OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 // | 4 // |
5 // This file defines functions that integrate Chrome in Windows shell. These | 5 // This file defines functions that integrate Chrome in Windows shell. These |
6 // functions can be used by Chrome as well as Chrome installer. All of the | 6 // functions can be used by Chrome as well as Chrome installer. All of the |
7 // work is done by the local functions defined in anonymous namespace in | 7 // work is done by the local functions defined in anonymous namespace in |
8 // this class. | 8 // this class. |
9 | 9 |
10 #include "chrome/installer/util/shell_util.h" | 10 #include "chrome/installer/util/shell_util.h" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 #include "base/win/windows_version.h" | 44 #include "base/win/windows_version.h" |
45 #include "chrome/common/chrome_constants.h" | 45 #include "chrome/common/chrome_constants.h" |
46 #include "chrome/common/chrome_switches.h" | 46 #include "chrome/common/chrome_switches.h" |
47 #include "chrome/installer/util/beacons.h" | 47 #include "chrome/installer/util/beacons.h" |
48 #include "chrome/installer/util/browser_distribution.h" | 48 #include "chrome/installer/util/browser_distribution.h" |
49 #include "chrome/installer/util/install_util.h" | 49 #include "chrome/installer/util/install_util.h" |
50 #include "chrome/installer/util/installer_util_strings.h" | 50 #include "chrome/installer/util/installer_util_strings.h" |
51 #include "chrome/installer/util/l10n_string_util.h" | 51 #include "chrome/installer/util/l10n_string_util.h" |
52 #include "chrome/installer/util/master_preferences.h" | 52 #include "chrome/installer/util/master_preferences.h" |
53 #include "chrome/installer/util/master_preferences_constants.h" | 53 #include "chrome/installer/util/master_preferences_constants.h" |
| 54 #include "chrome/installer/util/registry_entry.h" |
54 #include "chrome/installer/util/util_constants.h" | 55 #include "chrome/installer/util/util_constants.h" |
55 #include "chrome/installer/util/work_item.h" | 56 #include "chrome/installer/util/work_item.h" |
56 | 57 |
57 using base::win::RegKey; | 58 using base::win::RegKey; |
58 | 59 |
59 namespace { | 60 namespace { |
60 | 61 |
61 // An enum used to tell QuickIsChromeRegistered() which level of registration | 62 // An enum used to tell QuickIsChromeRegistered() which level of registration |
62 // the caller wants to confirm. | 63 // the caller wants to confirm. |
63 enum RegistrationConfirmationLevel { | 64 enum RegistrationConfirmationLevel { |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 base::string16 application_name; | 182 base::string16 application_name; |
182 base::FilePath application_icon_path; | 183 base::FilePath application_icon_path; |
183 int application_icon_index; | 184 int application_icon_index; |
184 base::string16 application_description; | 185 base::string16 application_description; |
185 base::string16 publisher_name; | 186 base::string16 publisher_name; |
186 | 187 |
187 // The CLSID for the application's DelegateExecute handler. May be empty. | 188 // The CLSID for the application's DelegateExecute handler. May be empty. |
188 base::string16 delegate_clsid; | 189 base::string16 delegate_clsid; |
189 }; | 190 }; |
190 | 191 |
191 // This class represents a single registry entry (a key and its value). A | |
192 // collection of registry entries should be collected into a list and written | |
193 // transactionally using a WorkItemList. This is preferred to writing to the | |
194 // registry directly, because if anything goes wrong, they can be rolled back. | |
195 class RegistryEntry { | |
196 public: | |
197 // A bit-field enum of places to look for this key in the Windows registry. | |
198 enum LookForIn { | |
199 LOOK_IN_HKCU = 1 << 0, | |
200 LOOK_IN_HKLM = 1 << 1, | |
201 LOOK_IN_HKCU_THEN_HKLM = LOOK_IN_HKCU | LOOK_IN_HKLM, | |
202 }; | |
203 | |
204 // Identifies the type of removal this RegistryEntry is flagged for, if any. | |
205 enum class RemovalFlag { | |
206 // Default case: install the key/value. | |
207 NONE, | |
208 // Registry value under |key_path_|\|name_| is flagged for deletion. | |
209 VALUE, | |
210 // Registry key under |key_path_| is flag for deletion. | |
211 KEY, | |
212 }; | |
213 | |
214 // Create an object that represent default value of a key. | |
215 RegistryEntry(const base::string16& key_path, const base::string16& value); | |
216 | |
217 // Create an object that represent a key of type REG_SZ. | |
218 RegistryEntry(const base::string16& key_path, | |
219 const base::string16& name, | |
220 const base::string16& value); | |
221 | |
222 // Create an object that represent a key of integer type. | |
223 RegistryEntry(const base::string16& key_path, | |
224 const base::string16& name, | |
225 DWORD value); | |
226 | |
227 // Flags this RegistryKey with |removal_flag|, indicating that it should be | |
228 // removed rather than created. Note that this will not result in cleaning up | |
229 // the entire registry hierarchy below RegistryEntry even if it is left empty | |
230 // by this operation (this should thus not be used for uninstall, but only to | |
231 // unregister keys that should explicitly no longer be active in the current | |
232 // configuration). | |
233 void set_removal_flag(RemovalFlag removal_flag) { | |
234 removal_flag_ = removal_flag; | |
235 } | |
236 | |
237 // Generates work_item tasks required to create (or potentially delete based | |
238 // on |removal_flag_|) the current RegistryEntry and add them to the given | |
239 // work item list. | |
240 void AddToWorkItemList(HKEY root, WorkItemList* items) const; | |
241 | |
242 // Returns true if this key is flagged for removal. | |
243 bool IsFlaggedForRemoval() const { | |
244 return removal_flag_ != RemovalFlag::NONE; | |
245 } | |
246 | |
247 // Checks if the current registry entry exists in HKCU\|key_path_|\|name_| | |
248 // and value is |value_|. If the key does NOT exist in HKCU, checks for | |
249 // the correct name and value in HKLM. | |
250 // |look_for_in| specifies roots (HKCU and/or HKLM) in which to look for the | |
251 // key, unspecified roots are not looked into (i.e. the the key is assumed not | |
252 // to exist in them). | |
253 // |look_for_in| must at least specify one root to look into. | |
254 // If |look_for_in| is LOOK_IN_HKCU_THEN_HKLM, this method mimics Windows' | |
255 // behavior when searching in HKCR (HKCU takes precedence over HKLM). For | |
256 // registrations outside of HKCR on versions of Windows prior to Win8, | |
257 // Chrome's values go in HKLM. This function will make unnecessary (but | |
258 // harmless) queries into HKCU in that case. | |
259 bool ExistsInRegistry(uint32 look_for_in) const; | |
260 | |
261 // Checks if the current registry entry exists in \|key_path_|\|name_|, | |
262 // regardless of value. Same lookup rules as ExistsInRegistry. | |
263 // Unlike ExistsInRegistry, this returns true if some other value is present | |
264 // with the same key. | |
265 bool KeyExistsInRegistry(uint32 look_for_in) const; | |
266 | |
267 private: | |
268 // States this RegistryKey can be in compared to the registry. | |
269 enum RegistryStatus { | |
270 // |name_| does not exist in the registry | |
271 DOES_NOT_EXIST, | |
272 // |name_| exists, but its value != |value_| | |
273 DIFFERENT_VALUE, | |
274 // |name_| exists and its value is |value_| | |
275 SAME_VALUE, | |
276 }; | |
277 | |
278 base::string16 key_path_; // key path for the registry entry | |
279 base::string16 name_; // name of the registry entry | |
280 bool is_string_; // true if current registry entry is of type REG_SZ | |
281 base::string16 value_; // string value (useful if is_string_ = true) | |
282 DWORD int_value_; // integer value (useful if is_string_ = false) | |
283 | |
284 // Identifies whether this RegistryEntry is flagged for removal (i.e. no | |
285 // longer relevant on the configuration it was created under). | |
286 RemovalFlag removal_flag_; | |
287 | |
288 // Helper function for ExistsInRegistry(). | |
289 // Returns the RegistryStatus of the current registry entry in | |
290 // |root|\|key_path_|\|name_|. | |
291 RegistryStatus StatusInRegistryUnderRoot(HKEY root) const; | |
292 | |
293 DISALLOW_COPY_AND_ASSIGN(RegistryEntry); | |
294 }; // class RegistryEntry | |
295 | |
296 RegistryEntry::RegistryEntry(const base::string16& key_path, | |
297 const base::string16& value) | |
298 : key_path_(key_path), | |
299 name_(), | |
300 is_string_(true), | |
301 value_(value), | |
302 int_value_(0), | |
303 removal_flag_(RemovalFlag::NONE) {} | |
304 | |
305 RegistryEntry::RegistryEntry(const base::string16& key_path, | |
306 const base::string16& name, | |
307 const base::string16& value) | |
308 : key_path_(key_path), | |
309 name_(name), | |
310 is_string_(true), | |
311 value_(value), | |
312 int_value_(0), | |
313 removal_flag_(RemovalFlag::NONE) {} | |
314 | |
315 RegistryEntry::RegistryEntry(const base::string16& key_path, | |
316 const base::string16& name, | |
317 DWORD value) | |
318 : key_path_(key_path), | |
319 name_(name), | |
320 is_string_(false), | |
321 value_(), | |
322 int_value_(value), | |
323 removal_flag_(RemovalFlag::NONE) {} | |
324 | |
325 void RegistryEntry::AddToWorkItemList(HKEY root, WorkItemList* items) const { | |
326 if (removal_flag_ == RemovalFlag::VALUE) { | |
327 items->AddDeleteRegValueWorkItem(root, key_path_, WorkItem::kWow64Default, | |
328 name_); | |
329 } else if (removal_flag_ == RemovalFlag::KEY) { | |
330 items->AddDeleteRegKeyWorkItem(root, key_path_, WorkItem::kWow64Default); | |
331 } else { | |
332 DCHECK(removal_flag_ == RemovalFlag::NONE); | |
333 items->AddCreateRegKeyWorkItem(root, key_path_, WorkItem::kWow64Default); | |
334 if (is_string_) { | |
335 items->AddSetRegValueWorkItem(root, key_path_, WorkItem::kWow64Default, | |
336 name_, value_, true); | |
337 } else { | |
338 items->AddSetRegValueWorkItem(root, key_path_, WorkItem::kWow64Default, | |
339 name_, int_value_, true); | |
340 } | |
341 } | |
342 } | |
343 | |
344 bool RegistryEntry::ExistsInRegistry(uint32 look_for_in) const { | |
345 DCHECK(look_for_in); | |
346 | |
347 RegistryStatus status = DOES_NOT_EXIST; | |
348 if (look_for_in & LOOK_IN_HKCU) | |
349 status = StatusInRegistryUnderRoot(HKEY_CURRENT_USER); | |
350 if (status == DOES_NOT_EXIST && (look_for_in & LOOK_IN_HKLM)) | |
351 status = StatusInRegistryUnderRoot(HKEY_LOCAL_MACHINE); | |
352 return status == SAME_VALUE; | |
353 } | |
354 | |
355 bool RegistryEntry::KeyExistsInRegistry(uint32 look_for_in) const { | |
356 DCHECK(look_for_in); | |
357 | |
358 RegistryStatus status = DOES_NOT_EXIST; | |
359 if (look_for_in & LOOK_IN_HKCU) | |
360 status = StatusInRegistryUnderRoot(HKEY_CURRENT_USER); | |
361 if (status == DOES_NOT_EXIST && (look_for_in & LOOK_IN_HKLM)) | |
362 status = StatusInRegistryUnderRoot(HKEY_LOCAL_MACHINE); | |
363 return status != DOES_NOT_EXIST; | |
364 } | |
365 | |
366 RegistryEntry::RegistryStatus RegistryEntry::StatusInRegistryUnderRoot( | |
367 HKEY root) const { | |
368 RegKey key(root, key_path_.c_str(), KEY_QUERY_VALUE); | |
369 bool found = false; | |
370 bool correct_value = false; | |
371 if (is_string_) { | |
372 base::string16 read_value; | |
373 found = key.ReadValue(name_.c_str(), &read_value) == ERROR_SUCCESS; | |
374 if (found) { | |
375 correct_value = | |
376 read_value.size() == value_.size() && | |
377 ::CompareString( | |
378 LOCALE_USER_DEFAULT, NORM_IGNORECASE, read_value.data(), | |
379 base::saturated_cast<int>(read_value.size()), value_.data(), | |
380 base::saturated_cast<int>(value_.size())) == CSTR_EQUAL; | |
381 } | |
382 } else { | |
383 DWORD read_value; | |
384 found = key.ReadValueDW(name_.c_str(), &read_value) == ERROR_SUCCESS; | |
385 if (found) | |
386 correct_value = read_value == int_value_; | |
387 } | |
388 return found ? (correct_value ? SAME_VALUE : DIFFERENT_VALUE) | |
389 : DOES_NOT_EXIST; | |
390 } | |
391 | |
392 // Returns the Windows browser client registration key for Chrome. For example: | 192 // Returns the Windows browser client registration key for Chrome. For example: |
393 // "Software\Clients\StartMenuInternet\Chromium[.user]". Strictly speaking, we | 193 // "Software\Clients\StartMenuInternet\Chromium[.user]". Strictly speaking, we |
394 // should use the name of the executable (e.g., "chrome.exe"), but that ship has | 194 // should use the name of the executable (e.g., "chrome.exe"), but that ship has |
395 // sailed. The cost of switching now is re-prompting users to make Chrome their | 195 // sailed. The cost of switching now is re-prompting users to make Chrome their |
396 // default browser, which isn't polite. |suffix| is the user-specific | 196 // default browser, which isn't polite. |suffix| is the user-specific |
397 // registration suffix; see GetUserSpecificDefaultBrowserSuffix in shell_util.h | 197 // registration suffix; see GetUserSpecificDefaultBrowserSuffix in shell_util.h |
398 // for details. | 198 // for details. |
399 base::string16 GetBrowserClientKey(BrowserDistribution* dist, | 199 base::string16 GetBrowserClientKey(BrowserDistribution* dist, |
400 const base::string16& suffix) { | 200 const base::string16& suffix) { |
401 DCHECK(suffix.empty() || suffix[0] == L'.'); | 201 DCHECK(suffix.empty() || suffix[0] == L'.'); |
(...skipping 2107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2509 base::string16 key_path(ShellUtil::kRegClasses); | 2309 base::string16 key_path(ShellUtil::kRegClasses); |
2510 key_path.push_back(base::FilePath::kSeparators[0]); | 2310 key_path.push_back(base::FilePath::kSeparators[0]); |
2511 key_path.append(prog_id); | 2311 key_path.append(prog_id); |
2512 return InstallUtil::DeleteRegistryKey( | 2312 return InstallUtil::DeleteRegistryKey( |
2513 HKEY_CURRENT_USER, key_path, WorkItem::kWow64Default); | 2313 HKEY_CURRENT_USER, key_path, WorkItem::kWow64Default); |
2514 | 2314 |
2515 // TODO(mgiuca): Remove the extension association entries. This requires that | 2315 // TODO(mgiuca): Remove the extension association entries. This requires that |
2516 // the extensions associated with a particular prog_id are stored in that | 2316 // the extensions associated with a particular prog_id are stored in that |
2517 // prog_id's key. | 2317 // prog_id's key. |
2518 } | 2318 } |
OLD | NEW |