| 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 |