Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(437)

Side by Side Diff: chrome/installer/util/shell_util.cc

Issue 1294863006: Do not register Chrome's DelegateExecute on Win10+. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@d1_fix_debug_versioninfo
Patch Set: tweak IsChromeRegistered to support RemovalFlag Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/installer/setup/install_worker.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 // Note: Shell registration implies ProgId registration. 70 // Note: Shell registration implies ProgId registration.
71 CONFIRM_SHELL_REGISTRATION, 71 CONFIRM_SHELL_REGISTRATION,
72 // Same as CONFIRM_SHELL_REGISTRATION, but only look in HKLM (used when 72 // Same as CONFIRM_SHELL_REGISTRATION, but only look in HKLM (used when
73 // uninstalling to know whether elevation is required to clean up the 73 // uninstalling to know whether elevation is required to clean up the
74 // registry). 74 // registry).
75 CONFIRM_SHELL_REGISTRATION_IN_HKLM, 75 CONFIRM_SHELL_REGISTRATION_IN_HKLM,
76 }; 76 };
77 77
78 const wchar_t kReinstallCommand[] = L"ReinstallCommand"; 78 const wchar_t kReinstallCommand[] = L"ReinstallCommand";
79 79
80 // Returns true if Chrome Metro is supported on this OS (Win 8 8370 or greater). 80 // Returns true if Chrome Metro is supported on this version of Windows
81 // TODO(gab): Change this to a simple check for Win 8 once old Win8 builds 81 // (supported as of Win8; deprecated as of Win10).
82 // become irrelevant.
83 bool IsChromeMetroSupported() { 82 bool IsChromeMetroSupported() {
84 OSVERSIONINFOEX min_version_info = {}; 83 const base::win::Version win_version = base::win::GetVersion();
85 min_version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); 84 return win_version >= base::win::VERSION_WIN8 &&
86 min_version_info.dwMajorVersion = 6; 85 win_version < base::win::VERSION_WIN10;
87 min_version_info.dwMinorVersion = 2;
88 min_version_info.dwBuildNumber = 8370;
89 min_version_info.wServicePackMajor = 0;
90 min_version_info.wServicePackMinor = 0;
91
92 DWORDLONG condition_mask = 0;
93 VER_SET_CONDITION(condition_mask, VER_MAJORVERSION, VER_GREATER_EQUAL);
94 VER_SET_CONDITION(condition_mask, VER_MINORVERSION, VER_GREATER_EQUAL);
95 VER_SET_CONDITION(condition_mask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
96 VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
97 VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL);
98
99 DWORD type_mask = VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER |
100 VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR;
101
102 return VerifyVersionInfo(&min_version_info, type_mask, condition_mask) != 0;
103 } 86 }
104 87
105 // Returns the current (or installed) browser's ProgId (e.g. 88 // Returns the current (or installed) browser's ProgId (e.g.
106 // "ChromeHTML|suffix|"). 89 // "ChromeHTML|suffix|").
107 // |suffix| can be the empty string. 90 // |suffix| can be the empty string.
108 base::string16 GetBrowserProgId(const base::string16& suffix) { 91 base::string16 GetBrowserProgId(const base::string16& suffix) {
109 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 92 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
110 base::string16 chrome_html(dist->GetBrowserProgIdPrefix()); 93 base::string16 chrome_html(dist->GetBrowserProgIdPrefix());
111 chrome_html.append(suffix); 94 chrome_html.append(suffix);
112 95
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 // class. 168 // class.
186 class RegistryEntry { 169 class RegistryEntry {
187 public: 170 public:
188 // A bit-field enum of places to look for this key in the Windows registry. 171 // A bit-field enum of places to look for this key in the Windows registry.
189 enum LookForIn { 172 enum LookForIn {
190 LOOK_IN_HKCU = 1 << 0, 173 LOOK_IN_HKCU = 1 << 0,
191 LOOK_IN_HKLM = 1 << 1, 174 LOOK_IN_HKLM = 1 << 1,
192 LOOK_IN_HKCU_THEN_HKLM = LOOK_IN_HKCU | LOOK_IN_HKLM, 175 LOOK_IN_HKCU_THEN_HKLM = LOOK_IN_HKCU | LOOK_IN_HKLM,
193 }; 176 };
194 177
178 // Identifies the type of removal this RegistryEntry is flagged for, if any.
179 enum class RemovalFlag {
180 // Default case: install the key/value.
181 NONE,
182 // Registry value under |key_path_|\|name_| is flagged for deletion.
183 VALUE,
184 // Registry key under |key_path_| is flag for deletion.
185 KEY,
186 };
187
195 // Details about a Windows application, to be entered into the registry for 188 // Details about a Windows application, to be entered into the registry for
196 // the purpose of file associations. 189 // the purpose of file associations.
197 struct ApplicationInfo { 190 struct ApplicationInfo {
198 ApplicationInfo() : file_type_icon_index(0), application_icon_index(0) {} 191 ApplicationInfo() : file_type_icon_index(0), application_icon_index(0) {}
199 192
200 // The ProgId used by Windows for file associations with this application. 193 // The ProgId used by Windows for file associations with this application.
201 // Must not be empty or start with a '.'. 194 // Must not be empty or start with a '.'.
202 base::string16 prog_id; 195 base::string16 prog_id;
203 // The friendly name, and the path of the icon that will be used for files 196 // The friendly name, and the path of the icon that will be used for files
204 // of these types when associated with this application by default. (They 197 // of these types when associated with this application by default. (They
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 } 237 }
245 238
246 // Returns the Windows Default Programs capabilities key for Chrome. For 239 // Returns the Windows Default Programs capabilities key for Chrome. For
247 // example: 240 // example:
248 // "Software\Clients\StartMenuInternet\Chromium[.user]\Capabilities". 241 // "Software\Clients\StartMenuInternet\Chromium[.user]\Capabilities".
249 static base::string16 GetCapabilitiesKey(BrowserDistribution* dist, 242 static base::string16 GetCapabilitiesKey(BrowserDistribution* dist,
250 const base::string16& suffix) { 243 const base::string16& suffix) {
251 return GetBrowserClientKey(dist, suffix).append(L"\\Capabilities"); 244 return GetBrowserClientKey(dist, suffix).append(L"\\Capabilities");
252 } 245 }
253 246
247 // DelegateExecute ProgId. Needed for Chrome Metro in Windows 8. This is
248 // only needed for registring a web browser, not for general associations.
249 static ScopedVector<RegistryEntry> GetChromeDelegateExecuteEntries(
250 const base::FilePath& chrome_exe,
251 const ApplicationInfo& app_info) {
252 ScopedVector<RegistryEntry> entries;
253
254 base::string16 app_id_shell_key(ShellUtil::kRegClasses);
255 app_id_shell_key.push_back(base::FilePath::kSeparators[0]);
256 app_id_shell_key.append(app_info.app_id);
257 app_id_shell_key.append(ShellUtil::kRegExePath);
258 app_id_shell_key.append(ShellUtil::kRegShellPath);
259
260 // <root hkey>\Software\Classes\<app_id>\.exe\shell @=open
261 entries.push_back(
262 new RegistryEntry(app_id_shell_key, ShellUtil::kRegVerbOpen));
263
264 // The command to execute when opening this application via the Metro UI.
265 const base::string16 delegate_command(
266 ShellUtil::GetChromeDelegateCommand(chrome_exe));
267
268 // Each of Chrome's shortcuts has an appid; which, as of Windows 8, is
269 // registered to handle some verbs. This registration has the side-effect
270 // that these verbs now show up in the shortcut's context menu. We
271 // mitigate this side-effect by making the context menu entries
272 // user readable/localized strings. See relevant MSDN article:
273 // http://msdn.microsoft.com/en-US/library/windows/desktop/cc144171.aspx
274 static const struct {
275 const wchar_t* verb;
276 int name_id;
277 } verbs[] = {
278 {ShellUtil::kRegVerbOpen, -1},
279 {ShellUtil::kRegVerbOpenNewWindow, IDS_SHORTCUT_NEW_WINDOW_BASE},
280 };
281 for (const auto& verb_and_id : verbs) {
282 base::string16 sub_path(app_id_shell_key);
283 sub_path.push_back(base::FilePath::kSeparators[0]);
284 sub_path.append(verb_and_id.verb);
285
286 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb>
287 if (verb_and_id.name_id != -1) {
288 // TODO(grt): http://crbug.com/75152 Write a reference to a localized
289 // resource.
290 const base::string16 verb_name(
291 installer::GetLocalizedString(verb_and_id.name_id));
292 entries.push_back(new RegistryEntry(sub_path, verb_name.c_str()));
293 }
294 entries.push_back(
295 new RegistryEntry(sub_path, L"CommandId", L"Browser.Launch"));
296
297 sub_path.push_back(base::FilePath::kSeparators[0]);
298 sub_path.append(ShellUtil::kRegCommand);
299
300 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb>\command
301 entries.push_back(new RegistryEntry(sub_path, delegate_command));
302 entries.push_back(new RegistryEntry(
303 sub_path, ShellUtil::kRegDelegateExecute, app_info.delegate_clsid));
304 }
305
306 return entries.Pass();
307 }
308
254 // This method returns a list of all the registry entries that 309 // This method returns a list of all the registry entries that
255 // are needed to register this installation's ProgId and AppId. 310 // are needed to register this installation's ProgId and AppId.
256 // These entries need to be registered in HKLM prior to Win8. 311 // These entries need to be registered in HKLM prior to Win8.
257 static void GetChromeProgIdEntries(BrowserDistribution* dist, 312 static void GetChromeProgIdEntries(BrowserDistribution* dist,
258 const base::FilePath& chrome_exe, 313 const base::FilePath& chrome_exe,
259 const base::string16& suffix, 314 const base::string16& suffix,
260 ScopedVector<RegistryEntry>* entries) { 315 ScopedVector<RegistryEntry>* entries) {
261 int chrome_icon_index = 316 int chrome_icon_index =
262 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME); 317 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME);
263 318
264 ApplicationInfo app_info; 319 ApplicationInfo app_info;
265 app_info.prog_id = GetBrowserProgId(suffix); 320 app_info.prog_id = GetBrowserProgId(suffix);
266 app_info.file_type_name = dist->GetBrowserProgIdDesc(); 321 app_info.file_type_name = dist->GetBrowserProgIdDesc();
267 // File types associated with Chrome are just given the Chrome icon. 322 // File types associated with Chrome are just given the Chrome icon.
268 app_info.file_type_icon_path = chrome_exe; 323 app_info.file_type_icon_path = chrome_exe;
269 app_info.file_type_icon_index = chrome_icon_index; 324 app_info.file_type_icon_index = chrome_icon_index;
270 app_info.command_line = ShellUtil::GetChromeShellOpenCmd(chrome_exe); 325 app_info.command_line = ShellUtil::GetChromeShellOpenCmd(chrome_exe);
271 // For user-level installs: entries for the app id will be in HKCU; thus we 326 // For user-level installs: entries for the app id will be in HKCU; thus we
272 // do not need a suffix on those entries. 327 // do not need a suffix on those entries.
273 app_info.app_id = ShellUtil::GetBrowserModelId( 328 app_info.app_id = ShellUtil::GetBrowserModelId(
274 dist, InstallUtil::IsPerUserInstall(chrome_exe)); 329 dist, InstallUtil::IsPerUserInstall(chrome_exe));
275 330
276 // The command to execute when opening this application via the Metro UI.
277 base::string16 delegate_command(
278 ShellUtil::GetChromeDelegateCommand(chrome_exe));
279 bool set_delegate_execute =
280 IsChromeMetroSupported() &&
281 dist->GetCommandExecuteImplClsid(&app_info.delegate_clsid);
282
283 // TODO(grt): http://crbug.com/75152 Write a reference to a localized 331 // TODO(grt): http://crbug.com/75152 Write a reference to a localized
284 // resource for name, description, and company. 332 // resource for name, description, and company.
285 app_info.application_name = dist->GetDisplayName(); 333 app_info.application_name = dist->GetDisplayName();
286 app_info.application_icon_path = chrome_exe; 334 app_info.application_icon_path = chrome_exe;
287 app_info.application_icon_index = chrome_icon_index; 335 app_info.application_icon_index = chrome_icon_index;
288 app_info.application_description = dist->GetAppDescription(); 336 app_info.application_description = dist->GetAppDescription();
289 app_info.publisher_name = dist->GetPublisherName(); 337 app_info.publisher_name = dist->GetPublisherName();
290 338
339 dist->GetCommandExecuteImplClsid(&app_info.delegate_clsid);
340
291 GetProgIdEntries(app_info, entries); 341 GetProgIdEntries(app_info, entries);
292 342
293 // DelegateExecute ProgId. Needed for Chrome Metro in Windows 8. This is 343 if (!app_info.delegate_clsid.empty()) {
294 // only needed for registring a web browser, not for general associations. 344 ScopedVector<RegistryEntry> delegate_execute_entries =
295 if (set_delegate_execute) { 345 GetChromeDelegateExecuteEntries(chrome_exe, app_info);
296 base::string16 model_id_shell(ShellUtil::kRegClasses); 346 if (!IsChromeMetroSupported()) {
297 model_id_shell.push_back(base::FilePath::kSeparators[0]); 347 // Remove the keys (not only their values) so that Windows will continue
298 model_id_shell.append(app_info.app_id); 348 // to launch Chrome without a pesky association error.
299 model_id_shell.append(ShellUtil::kRegExePath); 349 for (RegistryEntry* entry : delegate_execute_entries)
300 model_id_shell.append(ShellUtil::kRegShellPath); 350 entry->set_removal_flag(RemovalFlag::KEY);
301
302 // <root hkey>\Software\Classes\<app_id>\.exe\shell @=open
303 entries->push_back(new RegistryEntry(model_id_shell,
304 ShellUtil::kRegVerbOpen));
305
306 // Each of Chrome's shortcuts has an appid; which, as of Windows 8, is
307 // registered to handle some verbs. This registration has the side-effect
308 // that these verbs now show up in the shortcut's context menu. We
309 // mitigate this side-effect by making the context menu entries
310 // user readable/localized strings. See relevant MSDN article:
311 // http://msdn.microsoft.com/en-US/library/windows/desktop/cc144171.aspx
312 const struct {
313 const wchar_t* verb;
314 int name_id;
315 } verbs[] = {
316 { ShellUtil::kRegVerbOpen, -1 },
317 { ShellUtil::kRegVerbOpenNewWindow, IDS_SHORTCUT_NEW_WINDOW_BASE },
318 };
319 for (size_t i = 0; i < arraysize(verbs); ++i) {
320 base::string16 sub_path(model_id_shell);
321 sub_path.push_back(base::FilePath::kSeparators[0]);
322 sub_path.append(verbs[i].verb);
323
324 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb>
325 if (verbs[i].name_id != -1) {
326 // TODO(grt): http://crbug.com/75152 Write a reference to a localized
327 // resource.
328 base::string16 verb_name(
329 installer::GetLocalizedString(verbs[i].name_id));
330 entries->push_back(new RegistryEntry(sub_path, verb_name.c_str()));
331 }
332 entries->push_back(new RegistryEntry(
333 sub_path, L"CommandId", L"Browser.Launch"));
334
335 sub_path.push_back(base::FilePath::kSeparators[0]);
336 sub_path.append(ShellUtil::kRegCommand);
337
338 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb>\command
339 entries->push_back(new RegistryEntry(sub_path, delegate_command));
340 entries->push_back(new RegistryEntry(
341 sub_path, ShellUtil::kRegDelegateExecute, app_info.delegate_clsid));
342 } 351 }
352 // Move |delegate_execute_entries| to |entries|.
353 entries->insert(entries->end(), delegate_execute_entries.begin(),
354 delegate_execute_entries.end());
355 delegate_execute_entries.weak_clear();
343 } 356 }
344 } 357 }
345 358
346 // Gets the registry entries to register an application in the Windows 359 // Gets the registry entries to register an application in the Windows
347 // registry. |app_info| provides all of the information needed. 360 // registry. |app_info| provides all of the information needed.
348 static void GetProgIdEntries(const ApplicationInfo& app_info, 361 static void GetProgIdEntries(const ApplicationInfo& app_info,
349 ScopedVector<RegistryEntry>* entries) { 362 ScopedVector<RegistryEntry>* entries) {
350 // Basic sanity checks. 363 // Basic sanity checks.
351 DCHECK(!app_info.prog_id.empty()); 364 DCHECK(!app_info.prog_id.empty());
352 DCHECK_NE(L'.', app_info.prog_id[0]); 365 DCHECK_NE(L'.', app_info.prog_id[0]);
353 366
354 // File association ProgId 367 // File association ProgId
355 base::string16 prog_id_path(ShellUtil::kRegClasses); 368 base::string16 prog_id_path(ShellUtil::kRegClasses);
356 prog_id_path.push_back(base::FilePath::kSeparators[0]); 369 prog_id_path.push_back(base::FilePath::kSeparators[0]);
357 prog_id_path.append(app_info.prog_id); 370 prog_id_path.append(app_info.prog_id);
358 entries->push_back( 371 entries->push_back(
359 new RegistryEntry(prog_id_path, app_info.file_type_name)); 372 new RegistryEntry(prog_id_path, app_info.file_type_name));
360 entries->push_back(new RegistryEntry( 373 entries->push_back(new RegistryEntry(
361 prog_id_path + ShellUtil::kRegDefaultIcon, 374 prog_id_path + ShellUtil::kRegDefaultIcon,
362 ShellUtil::FormatIconLocation(app_info.file_type_icon_path, 375 ShellUtil::FormatIconLocation(app_info.file_type_icon_path,
363 app_info.file_type_icon_index))); 376 app_info.file_type_icon_index)));
364 entries->push_back(new RegistryEntry( 377 entries->push_back(new RegistryEntry(
365 prog_id_path + ShellUtil::kRegShellOpen, app_info.command_line)); 378 prog_id_path + ShellUtil::kRegShellOpen, app_info.command_line));
366 if (!app_info.delegate_clsid.empty()) { 379 if (!app_info.delegate_clsid.empty()) {
367 entries->push_back( 380 entries->push_back(
368 new RegistryEntry(prog_id_path + ShellUtil::kRegShellOpen, 381 new RegistryEntry(prog_id_path + ShellUtil::kRegShellOpen,
369 ShellUtil::kRegDelegateExecute, 382 ShellUtil::kRegDelegateExecute,
370 app_info.delegate_clsid)); 383 app_info.delegate_clsid));
384 // If Metro is not supported, remove the DelegateExecute entry instead of
385 // adding it.
386 if (!IsChromeMetroSupported())
387 entries->back()->set_removal_flag(RemovalFlag::VALUE);
371 } 388 }
372 389
373 // The following entries are required as of Windows 8, but do not 390 // The following entries are required as of Windows 8, but do not
374 // depend on the DelegateExecute verb handler being set. 391 // depend on the DelegateExecute verb handler being set.
375 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { 392 if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
376 if (!app_info.app_id.empty()) { 393 if (!app_info.app_id.empty()) {
377 entries->push_back(new RegistryEntry( 394 entries->push_back(new RegistryEntry(
378 prog_id_path, ShellUtil::kRegAppUserModelId, app_info.app_id)); 395 prog_id_path, ShellUtil::kRegAppUserModelId, app_info.app_id));
379 } 396 }
380 397
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
639 GetXPStyleUserProtocolEntries(ShellUtil::kBrowserProtocolAssociations[i], 656 GetXPStyleUserProtocolEntries(ShellUtil::kBrowserProtocolAssociations[i],
640 chrome_icon, chrome_open, entries); 657 chrome_icon, chrome_open, entries);
641 } 658 }
642 659
643 // start->Internet shortcut. 660 // start->Internet shortcut.
644 base::string16 start_menu(ShellUtil::kRegStartMenuInternet); 661 base::string16 start_menu(ShellUtil::kRegStartMenuInternet);
645 base::string16 app_name = dist->GetBaseAppName() + suffix; 662 base::string16 app_name = dist->GetBaseAppName() + suffix;
646 entries->push_back(new RegistryEntry(start_menu, app_name)); 663 entries->push_back(new RegistryEntry(start_menu, app_name));
647 } 664 }
648 665
649 // Generate work_item tasks required to create current registry entry and 666 // Flags this RegistryKey with |removal_flag|, indicating that it should be
650 // add them to the given work item list. 667 // removed rather than created. Note that this will not result in cleaning up
668 // the entire registry hierarchy below RegistryEntry even if it is left empty
669 // by this operation (this should thus not be used for uninstall, but only to
670 // unregister keys that should explicitly no longer be active in the current
671 // configuration).
672 void set_removal_flag(RemovalFlag removal_flag) {
673 removal_flag_ = removal_flag;
674 }
675
676 // Generates work_item tasks required to create (or potentially delete based
677 // on |removal_flag_|) the current RegistryEntry and add them to the given
678 // work item list.
651 void AddToWorkItemList(HKEY root, WorkItemList *items) const { 679 void AddToWorkItemList(HKEY root, WorkItemList *items) const {
652 items->AddCreateRegKeyWorkItem(root, key_path_, WorkItem::kWow64Default); 680 if (removal_flag_ == RemovalFlag::VALUE) {
653 if (is_string_) { 681 items->AddDeleteRegValueWorkItem(root, key_path_, WorkItem::kWow64Default,
654 items->AddSetRegValueWorkItem( 682 name_);
655 root, key_path_, WorkItem::kWow64Default, name_, value_, true); 683 } else if (removal_flag_ == RemovalFlag::KEY) {
684 items->AddDeleteRegKeyWorkItem(root, key_path_, WorkItem::kWow64Default);
656 } else { 685 } else {
657 items->AddSetRegValueWorkItem( 686 DCHECK(removal_flag_ == RemovalFlag::NONE);
658 root, key_path_, WorkItem::kWow64Default, name_, int_value_, true); 687 items->AddCreateRegKeyWorkItem(root, key_path_, WorkItem::kWow64Default);
688 if (is_string_) {
689 items->AddSetRegValueWorkItem(root, key_path_, WorkItem::kWow64Default,
690 name_, value_, true);
691 } else {
692 items->AddSetRegValueWorkItem(root, key_path_, WorkItem::kWow64Default,
693 name_, int_value_, true);
694 }
659 } 695 }
660 } 696 }
661 697
698 // Returns true if this key is flagged for removal.
699 bool IsFlaggedForRemoval() const {
700 return removal_flag_ != RemovalFlag::NONE;
701 }
702
662 // Checks if the current registry entry exists in HKCU\|key_path_|\|name_| 703 // Checks if the current registry entry exists in HKCU\|key_path_|\|name_|
663 // and value is |value_|. If the key does NOT exist in HKCU, checks for 704 // and value is |value_|. If the key does NOT exist in HKCU, checks for
664 // the correct name and value in HKLM. 705 // the correct name and value in HKLM.
665 // |look_for_in| specifies roots (HKCU and/or HKLM) in which to look for the 706 // |look_for_in| specifies roots (HKCU and/or HKLM) in which to look for the
666 // key, unspecified roots are not looked into (i.e. the the key is assumed not 707 // key, unspecified roots are not looked into (i.e. the the key is assumed not
667 // to exist in them). 708 // to exist in them).
668 // |look_for_in| must at least specify one root to look into. 709 // |look_for_in| must at least specify one root to look into.
669 // If |look_for_in| is LOOK_IN_HKCU_THEN_HKLM, this method mimics Windows' 710 // If |look_for_in| is LOOK_IN_HKCU_THEN_HKLM, this method mimics Windows'
670 // behavior when searching in HKCR (HKCU takes precedence over HKLM). For 711 // behavior when searching in HKCR (HKCU takes precedence over HKLM). For
671 // registrations outside of HKCR on versions of Windows prior to Win8, 712 // registrations outside of HKCR on versions of Windows prior to Win8,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
703 // |name_| does not exist in the registry 744 // |name_| does not exist in the registry
704 DOES_NOT_EXIST, 745 DOES_NOT_EXIST,
705 // |name_| exists, but its value != |value_| 746 // |name_| exists, but its value != |value_|
706 DIFFERENT_VALUE, 747 DIFFERENT_VALUE,
707 // |name_| exists and its value is |value_| 748 // |name_| exists and its value is |value_|
708 SAME_VALUE, 749 SAME_VALUE,
709 }; 750 };
710 751
711 // Create a object that represent default value of a key 752 // Create a object that represent default value of a key
712 RegistryEntry(const base::string16& key_path, const base::string16& value) 753 RegistryEntry(const base::string16& key_path, const base::string16& value)
713 : key_path_(key_path), name_(), 754 : key_path_(key_path),
714 is_string_(true), value_(value), int_value_(0) { 755 name_(),
715 } 756 is_string_(true),
757 value_(value),
758 int_value_(0),
759 removal_flag_(RemovalFlag::NONE) {}
716 760
717 // Create a object that represent a key of type REG_SZ 761 // Create a object that represent a key of type REG_SZ
718 RegistryEntry(const base::string16& key_path, const base::string16& name, 762 RegistryEntry(const base::string16& key_path,
763 const base::string16& name,
719 const base::string16& value) 764 const base::string16& value)
720 : key_path_(key_path), name_(name), 765 : key_path_(key_path),
721 is_string_(true), value_(value), int_value_(0) { 766 name_(name),
722 } 767 is_string_(true),
768 value_(value),
769 int_value_(0),
770 removal_flag_(RemovalFlag::NONE) {}
723 771
724 // Create a object that represent a key of integer type 772 // Create a object that represent a key of integer type
725 RegistryEntry(const base::string16& key_path, const base::string16& name, 773 RegistryEntry(const base::string16& key_path,
774 const base::string16& name,
726 DWORD value) 775 DWORD value)
727 : key_path_(key_path), name_(name), 776 : key_path_(key_path),
728 is_string_(false), value_(), int_value_(value) { 777 name_(name),
729 } 778 is_string_(false),
779 value_(),
780 int_value_(value),
781 removal_flag_(RemovalFlag::NONE) {}
730 782
731 base::string16 key_path_; // key path for the registry entry 783 base::string16 key_path_; // key path for the registry entry
732 base::string16 name_; // name of the registry entry 784 base::string16 name_; // name of the registry entry
733 bool is_string_; // true if current registry entry is of type REG_SZ 785 bool is_string_; // true if current registry entry is of type REG_SZ
734 base::string16 value_; // string value (useful if is_string_ = true) 786 base::string16 value_; // string value (useful if is_string_ = true)
735 DWORD int_value_; // integer value (useful if is_string_ = false) 787 DWORD int_value_; // integer value (useful if is_string_ = false)
736 788
789 // Identifies whether this RegistryEntry is flagged for removal (i.e. no
790 // longer relevant on the configuration it was created under).
791 RemovalFlag removal_flag_;
792
737 // Helper function for ExistsInRegistry(). 793 // Helper function for ExistsInRegistry().
738 // Returns the RegistryStatus of the current registry entry in 794 // Returns the RegistryStatus of the current registry entry in
739 // |root|\|key_path_|\|name_|. 795 // |root|\|key_path_|\|name_|.
740 RegistryStatus StatusInRegistryUnderRoot(HKEY root) const { 796 RegistryStatus StatusInRegistryUnderRoot(HKEY root) const {
741 RegKey key(root, key_path_.c_str(), KEY_QUERY_VALUE); 797 RegKey key(root, key_path_.c_str(), KEY_QUERY_VALUE);
742 bool found = false; 798 bool found = false;
743 bool correct_value = false; 799 bool correct_value = false;
744 if (is_string_) { 800 if (is_string_) {
745 base::string16 read_value; 801 base::string16 read_value;
746 found = key.ReadValue(name_.c_str(), &read_value) == ERROR_SUCCESS; 802 found = key.ReadValue(name_.c_str(), &read_value) == ERROR_SUCCESS;
(...skipping 30 matching lines...) Expand all
777 (*itr)->AddToWorkItemList(root, items.get()); 833 (*itr)->AddToWorkItemList(root, items.get());
778 834
779 // Apply all the registry changes and if there is a problem, rollback 835 // Apply all the registry changes and if there is a problem, rollback
780 if (!items->Do()) { 836 if (!items->Do()) {
781 items->Rollback(); 837 items->Rollback();
782 return false; 838 return false;
783 } 839 }
784 return true; 840 return true;
785 } 841 }
786 842
787 // Checks that all |entries| are present on this computer. 843 // Checks that all |entries| are present on this computer (or absent if their
788 // |look_for_in| is passed to RegistryEntry::ExistsInRegistry(). Documentation 844 // |removal_flag_| is set). |look_for_in| is passed to
789 // for it can be found there. 845 // RegistryEntry::ExistsInRegistry(). Documentation for it can be found there.
790 bool AreEntriesRegistered(const ScopedVector<RegistryEntry>& entries, 846 bool AreEntriesAsDesired(const ScopedVector<RegistryEntry>& entries,
791 uint32 look_for_in) { 847 uint32 look_for_in) {
792 bool registered = true; 848 for (const auto* entry : entries) {
793 for (ScopedVector<RegistryEntry>::const_iterator itr = entries.begin(); 849 if (entry->ExistsInRegistry(look_for_in) != !entry->IsFlaggedForRemoval())
794 registered && itr != entries.end(); ++itr) { 850 return false;
795 // We do not need registered = registered && ... since the loop condition
796 // is set to exit early.
797 registered = (*itr)->ExistsInRegistry(look_for_in);
798 } 851 }
799 return registered; 852 return true;
800 } 853 }
801 854
802 // Checks that all required registry entries for Chrome are already present 855 // Checks that all required registry entries for Chrome are already present on
803 // on this computer. See RegistryEntry::ExistsInRegistry for the behavior of 856 // this computer (or absent if their |removal_flag_| is set).
804 // |look_for_in|. 857 // See RegistryEntry::ExistsInRegistry for the behavior of |look_for_in|.
805 // Note: between r133333 and r154145 we were registering parts of Chrome in HKCU 858 // Note: between r133333 and r154145 we were registering parts of Chrome in HKCU
806 // and parts in HKLM for user-level installs; we now always register everything 859 // and parts in HKLM for user-level installs; we now always register everything
807 // under a single registry root. Not doing so caused http://crbug.com/144910 for 860 // under a single registry root. Not doing so caused http://crbug.com/144910 for
808 // users who first-installed Chrome in that revision range (those users are 861 // users who first-installed Chrome in that revision range (those users are
809 // still impacted by http://crbug.com/144910). This method will keep returning 862 // still impacted by http://crbug.com/144910). This method will keep returning
810 // true for affected users (i.e. who have all the registrations, but over both 863 // true for affected users (i.e. who have all the registrations, but over both
811 // registry roots). 864 // registry roots).
812 bool IsChromeRegistered(BrowserDistribution* dist, 865 bool IsChromeRegistered(BrowserDistribution* dist,
813 const base::FilePath& chrome_exe, 866 const base::FilePath& chrome_exe,
814 const base::string16& suffix, 867 const base::string16& suffix,
815 uint32 look_for_in) { 868 uint32 look_for_in) {
816 ScopedVector<RegistryEntry> entries; 869 ScopedVector<RegistryEntry> entries;
817 RegistryEntry::GetChromeProgIdEntries(dist, chrome_exe, suffix, &entries); 870 RegistryEntry::GetChromeProgIdEntries(dist, chrome_exe, suffix, &entries);
818 RegistryEntry::GetShellIntegrationEntries(dist, chrome_exe, suffix, &entries); 871 RegistryEntry::GetShellIntegrationEntries(dist, chrome_exe, suffix, &entries);
819 RegistryEntry::GetChromeAppRegistrationEntries(chrome_exe, suffix, &entries); 872 RegistryEntry::GetChromeAppRegistrationEntries(chrome_exe, suffix, &entries);
820 return AreEntriesRegistered(entries, look_for_in); 873 return AreEntriesAsDesired(entries, look_for_in);
821 } 874 }
822 875
823 // This method checks if Chrome is already registered on the local machine 876 // This method checks if Chrome is already registered on the local machine
824 // for the requested protocol. It just checks the one value required for this. 877 // for the requested protocol. It just checks the one value required for this.
825 // See RegistryEntry::ExistsInRegistry for the behavior of |look_for_in|. 878 // See RegistryEntry::ExistsInRegistry for the behavior of |look_for_in|.
826 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist, 879 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist,
827 const base::string16& suffix, 880 const base::string16& suffix,
828 const base::string16& protocol, 881 const base::string16& protocol,
829 uint32 look_for_in) { 882 uint32 look_for_in) {
830 ScopedVector<RegistryEntry> entries; 883 ScopedVector<RegistryEntry> entries;
831 RegistryEntry::GetProtocolCapabilityEntries(dist, suffix, protocol, &entries); 884 RegistryEntry::GetProtocolCapabilityEntries(dist, suffix, protocol, &entries);
832 return AreEntriesRegistered(entries, look_for_in); 885 return AreEntriesAsDesired(entries, look_for_in);
833 } 886 }
834 887
835 // This method registers Chrome on Vista by launching an elevated setup.exe. 888 // This method registers Chrome on Vista by launching an elevated setup.exe.
836 // That will show the user the standard Vista elevation prompt. If the user 889 // That will show the user the standard Vista elevation prompt. If the user
837 // accepts it the new process will make the necessary changes and return SUCCESS 890 // accepts it the new process will make the necessary changes and return SUCCESS
838 // that we capture and return. 891 // that we capture and return.
839 // If protocol is non-empty we will also register Chrome as being capable of 892 // If protocol is non-empty we will also register Chrome as being capable of
840 // handling the protocol. 893 // handling the protocol.
841 bool ElevateAndRegisterChrome(BrowserDistribution* dist, 894 bool ElevateAndRegisterChrome(BrowserDistribution* dist,
842 const base::FilePath& chrome_exe, 895 const base::FilePath& chrome_exe,
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
1148 if (properties.has_dual_mode()) 1201 if (properties.has_dual_mode())
1149 shortcut_properties.set_dual_mode(properties.dual_mode); 1202 shortcut_properties.set_dual_mode(properties.dual_mode);
1150 1203
1151 return shortcut_properties; 1204 return shortcut_properties;
1152 } 1205 }
1153 1206
1154 // Cleans up an old verb (run) we used to register in 1207 // Cleans up an old verb (run) we used to register in
1155 // <root>\Software\Classes\Chrome<.suffix>\.exe\shell\run on Windows 8. 1208 // <root>\Software\Classes\Chrome<.suffix>\.exe\shell\run on Windows 8.
1156 void RemoveRunVerbOnWindows8(BrowserDistribution* dist, 1209 void RemoveRunVerbOnWindows8(BrowserDistribution* dist,
1157 const base::FilePath& chrome_exe) { 1210 const base::FilePath& chrome_exe) {
1158 if (IsChromeMetroSupported()) { 1211 if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
1159 bool is_per_user_install = InstallUtil::IsPerUserInstall(chrome_exe); 1212 bool is_per_user_install = InstallUtil::IsPerUserInstall(chrome_exe);
1160 HKEY root_key = DetermineRegistrationRoot(is_per_user_install); 1213 HKEY root_key = DetermineRegistrationRoot(is_per_user_install);
1161 // There's no need to rollback, so forgo the usual work item lists and just 1214 // There's no need to rollback, so forgo the usual work item lists and just
1162 // remove the key from the registry. 1215 // remove the key from the registry.
1163 base::string16 run_verb_key(ShellUtil::kRegClasses); 1216 base::string16 run_verb_key(ShellUtil::kRegClasses);
1164 run_verb_key.push_back(base::FilePath::kSeparators[0]); 1217 run_verb_key.push_back(base::FilePath::kSeparators[0]);
1165 run_verb_key.append(ShellUtil::GetBrowserModelId( 1218 run_verb_key.append(ShellUtil::GetBrowserModelId(
1166 dist, is_per_user_install)); 1219 dist, is_per_user_install));
1167 run_verb_key.append(ShellUtil::kRegExePath); 1220 run_verb_key.append(ShellUtil::kRegExePath);
1168 run_verb_key.append(ShellUtil::kRegShellPath); 1221 run_verb_key.append(ShellUtil::kRegShellPath);
(...skipping 1082 matching lines...) Expand 10 before | Expand all | Expand 10 after
2251 } else { 2304 } else {
2252 // If we got to this point then all we can do is create ProgId and basic app 2305 // If we got to this point then all we can do is create ProgId and basic app
2253 // registrations under HKCU. 2306 // registrations under HKCU.
2254 ScopedVector<RegistryEntry> entries; 2307 ScopedVector<RegistryEntry> entries;
2255 RegistryEntry::GetChromeProgIdEntries( 2308 RegistryEntry::GetChromeProgIdEntries(
2256 dist, chrome_exe, base::string16(), &entries); 2309 dist, chrome_exe, base::string16(), &entries);
2257 // Prefer to use |suffix|; unless Chrome's ProgIds are already registered 2310 // Prefer to use |suffix|; unless Chrome's ProgIds are already registered
2258 // with no suffix (as per the old registration style): in which case some 2311 // with no suffix (as per the old registration style): in which case some
2259 // other registry entries could refer to them and since we were not able to 2312 // other registry entries could refer to them and since we were not able to
2260 // set our HKLM entries above, we are better off not altering these here. 2313 // set our HKLM entries above, we are better off not altering these here.
2261 if (!AreEntriesRegistered(entries, RegistryEntry::LOOK_IN_HKCU)) { 2314 if (!AreEntriesAsDesired(entries, RegistryEntry::LOOK_IN_HKCU)) {
2262 if (!suffix.empty()) { 2315 if (!suffix.empty()) {
2263 entries.clear(); 2316 entries.clear();
2264 RegistryEntry::GetChromeProgIdEntries( 2317 RegistryEntry::GetChromeProgIdEntries(
2265 dist, chrome_exe, suffix, &entries); 2318 dist, chrome_exe, suffix, &entries);
2266 RegistryEntry::GetChromeAppRegistrationEntries( 2319 RegistryEntry::GetChromeAppRegistrationEntries(
2267 chrome_exe, suffix, &entries); 2320 chrome_exe, suffix, &entries);
2268 } 2321 }
2269 result = AddRegistryEntries(HKEY_CURRENT_USER, entries); 2322 result = AddRegistryEntries(HKEY_CURRENT_USER, entries);
2270 } else { 2323 } else {
2271 // The ProgId is registered unsuffixed in HKCU, also register the app with 2324 // The ProgId is registered unsuffixed in HKCU, also register the app with
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
2512 base::string16 key_path(ShellUtil::kRegClasses); 2565 base::string16 key_path(ShellUtil::kRegClasses);
2513 key_path.push_back(base::FilePath::kSeparators[0]); 2566 key_path.push_back(base::FilePath::kSeparators[0]);
2514 key_path.append(prog_id); 2567 key_path.append(prog_id);
2515 return InstallUtil::DeleteRegistryKey( 2568 return InstallUtil::DeleteRegistryKey(
2516 HKEY_CURRENT_USER, key_path, WorkItem::kWow64Default); 2569 HKEY_CURRENT_USER, key_path, WorkItem::kWow64Default);
2517 2570
2518 // TODO(mgiuca): Remove the extension association entries. This requires that 2571 // TODO(mgiuca): Remove the extension association entries. This requires that
2519 // the extensions associated with a particular prog_id are stored in that 2572 // the extensions associated with a particular prog_id are stored in that
2520 // prog_id's key. 2573 // prog_id's key.
2521 } 2574 }
OLDNEW
« no previous file with comments | « chrome/installer/setup/install_worker.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698