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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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. | |
grt (UTC plus 2)
2015/08/24 15:08:20
"...for, if any."
gab
2015/08/27 20:51:07
Done.
| |
179 enum class RemovalFlag { | |
180 // Default case, no flag. | |
grt (UTC plus 2)
2015/08/24 15:08:19
// Default case: install the key/value.
gab
2015/08/27 20:51:07
Done.
| |
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 Loading... | |
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 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 (size_t i = 0; i < arraysize(verbs); ++i) { | |
grt (UTC plus 2)
2015/08/24 15:08:19
nit: for (const auto verb_and_id& : verbs) {
gab
2015/08/27 20:51:07
Woohoo C++11 in shell_util :-)!
| |
282 base::string16 sub_path(app_id_shell_key); | |
283 sub_path.push_back(base::FilePath::kSeparators[0]); | |
284 sub_path.append(verbs[i].verb); | |
285 | |
286 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb> | |
287 if (verbs[i].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(verbs[i].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. | 331 dist->GetCommandExecuteImplClsid(&app_info.delegate_clsid); |
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 | 332 |
283 // TODO(grt): http://crbug.com/75152 Write a reference to a localized | 333 // TODO(grt): http://crbug.com/75152 Write a reference to a localized |
284 // resource for name, description, and company. | 334 // resource for name, description, and company. |
285 app_info.application_name = dist->GetDisplayName(); | 335 app_info.application_name = dist->GetDisplayName(); |
286 app_info.application_icon_path = chrome_exe; | 336 app_info.application_icon_path = chrome_exe; |
287 app_info.application_icon_index = chrome_icon_index; | 337 app_info.application_icon_index = chrome_icon_index; |
288 app_info.application_description = dist->GetAppDescription(); | 338 app_info.application_description = dist->GetAppDescription(); |
289 app_info.publisher_name = dist->GetPublisherName(); | 339 app_info.publisher_name = dist->GetPublisherName(); |
290 | 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()) { |
grt (UTC plus 2)
2015/08/24 15:08:19
if (dist->GetCommandExecuteImplClsid(&app_info.del
gab
2015/08/27 20:51:07
Done.
gab
2015/08/27 21:48:53
Actually, no, GetProgIdEntries() needs app_info.de
grt (UTC plus 2)
2015/08/29 01:38:41
Ah! Subtle!
gab
2015/08/29 14:39:30
Ok will do.
| |
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 for (RegistryEntry* entry : delegate_execute_entries) { |
298 model_id_shell.append(app_info.app_id); | 348 // Need to get rid of the DelegateExecute keys (verbs, etc.) |
grt (UTC plus 2)
2015/08/24 15:08:19
nit: move the comment out of the loop body so the
gab
2015/08/27 20:51:07
Done.
| |
299 model_id_shell.append(ShellUtil::kRegExePath); | 349 // themselves (not only their values) or Chrome fails to launch as |
300 model_id_shell.append(ShellUtil::kRegShellPath); | 350 // Windows finds a registered verb hierarchy with no registered |
301 | 351 // commands underneath and reports "This file does not have a program |
302 // <root hkey>\Software\Classes\<app_id>\.exe\shell @=open | 352 // associated with it for performing this action. Please install a |
303 entries->push_back(new RegistryEntry(model_id_shell, | 353 // program or, if one is already installed, create an association in |
304 ShellUtil::kRegVerbOpen)); | 354 // the Default Programs control panel." |
305 | 355 entry->set_removal_flag(RemovalFlag::KEY); |
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 } | 356 } |
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 } | 357 } |
358 // Move |delegate_execute_entries| to |entries|. | |
359 entries->insert(entries->end(), delegate_execute_entries.begin(), | |
360 delegate_execute_entries.end()); | |
361 delegate_execute_entries.weak_clear(); | |
343 } | 362 } |
344 } | 363 } |
345 | 364 |
346 // Gets the registry entries to register an application in the Windows | 365 // Gets the registry entries to register an application in the Windows |
347 // registry. |app_info| provides all of the information needed. | 366 // registry. |app_info| provides all of the information needed. |
348 static void GetProgIdEntries(const ApplicationInfo& app_info, | 367 static void GetProgIdEntries(const ApplicationInfo& app_info, |
349 ScopedVector<RegistryEntry>* entries) { | 368 ScopedVector<RegistryEntry>* entries) { |
350 // Basic sanity checks. | 369 // Basic sanity checks. |
351 DCHECK(!app_info.prog_id.empty()); | 370 DCHECK(!app_info.prog_id.empty()); |
352 DCHECK_NE(L'.', app_info.prog_id[0]); | 371 DCHECK_NE(L'.', app_info.prog_id[0]); |
353 | 372 |
354 // File association ProgId | 373 // File association ProgId |
355 base::string16 prog_id_path(ShellUtil::kRegClasses); | 374 base::string16 prog_id_path(ShellUtil::kRegClasses); |
356 prog_id_path.push_back(base::FilePath::kSeparators[0]); | 375 prog_id_path.push_back(base::FilePath::kSeparators[0]); |
357 prog_id_path.append(app_info.prog_id); | 376 prog_id_path.append(app_info.prog_id); |
358 entries->push_back( | 377 entries->push_back( |
359 new RegistryEntry(prog_id_path, app_info.file_type_name)); | 378 new RegistryEntry(prog_id_path, app_info.file_type_name)); |
360 entries->push_back(new RegistryEntry( | 379 entries->push_back(new RegistryEntry( |
361 prog_id_path + ShellUtil::kRegDefaultIcon, | 380 prog_id_path + ShellUtil::kRegDefaultIcon, |
362 ShellUtil::FormatIconLocation(app_info.file_type_icon_path, | 381 ShellUtil::FormatIconLocation(app_info.file_type_icon_path, |
363 app_info.file_type_icon_index))); | 382 app_info.file_type_icon_index))); |
364 entries->push_back(new RegistryEntry( | 383 entries->push_back(new RegistryEntry( |
365 prog_id_path + ShellUtil::kRegShellOpen, app_info.command_line)); | 384 prog_id_path + ShellUtil::kRegShellOpen, app_info.command_line)); |
366 if (!app_info.delegate_clsid.empty()) { | 385 if (!app_info.delegate_clsid.empty()) { |
367 entries->push_back( | 386 scoped_ptr<RegistryEntry> delegate_execute_entry( |
368 new RegistryEntry(prog_id_path + ShellUtil::kRegShellOpen, | 387 new RegistryEntry(prog_id_path + ShellUtil::kRegShellOpen, |
369 ShellUtil::kRegDelegateExecute, | 388 ShellUtil::kRegDelegateExecute, |
370 app_info.delegate_clsid)); | 389 app_info.delegate_clsid)); |
390 if (!IsChromeMetroSupported()) | |
391 delegate_execute_entry->set_removal_flag(RemovalFlag::VALUE); | |
grt (UTC plus 2)
2015/08/24 15:08:20
do away with the delegate_execute_entry local var
gab
2015/08/27 20:51:07
Done.
| |
392 entries->push_back(delegate_execute_entry.Pass()); | |
371 } | 393 } |
372 | 394 |
373 // The following entries are required as of Windows 8, but do not | 395 // The following entries are required as of Windows 8, but do not |
374 // depend on the DelegateExecute verb handler being set. | 396 // depend on the DelegateExecute verb handler being set. |
375 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { | 397 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { |
376 if (!app_info.app_id.empty()) { | 398 if (!app_info.app_id.empty()) { |
377 entries->push_back(new RegistryEntry( | 399 entries->push_back(new RegistryEntry( |
378 prog_id_path, ShellUtil::kRegAppUserModelId, app_info.app_id)); | 400 prog_id_path, ShellUtil::kRegAppUserModelId, app_info.app_id)); |
379 } | 401 } |
380 | 402 |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
639 GetXPStyleUserProtocolEntries(ShellUtil::kBrowserProtocolAssociations[i], | 661 GetXPStyleUserProtocolEntries(ShellUtil::kBrowserProtocolAssociations[i], |
640 chrome_icon, chrome_open, entries); | 662 chrome_icon, chrome_open, entries); |
641 } | 663 } |
642 | 664 |
643 // start->Internet shortcut. | 665 // start->Internet shortcut. |
644 base::string16 start_menu(ShellUtil::kRegStartMenuInternet); | 666 base::string16 start_menu(ShellUtil::kRegStartMenuInternet); |
645 base::string16 app_name = dist->GetBaseAppName() + suffix; | 667 base::string16 app_name = dist->GetBaseAppName() + suffix; |
646 entries->push_back(new RegistryEntry(start_menu, app_name)); | 668 entries->push_back(new RegistryEntry(start_menu, app_name)); |
647 } | 669 } |
648 | 670 |
649 // Generate work_item tasks required to create current registry entry and | 671 // Flags this RegistryKey with |removal_flag|, indicating that it should be |
650 // add them to the given work item list. | 672 // removed rather than created. Note that this will not result in cleaning up |
673 // the entire registry hierarchy below RegistryEntry even if it is left empty | |
674 // by this operation (this should thus not be used for uninstall, but only to | |
675 // unregister keys that should explicitly no longer be active in the current | |
676 // configuration). | |
677 void set_removal_flag(RemovalFlag removal_flag) { | |
678 removal_flag_ = removal_flag; | |
679 } | |
680 | |
681 // Generate work_item tasks required to create (or potentially delete based on | |
grt (UTC plus 2)
2015/08/24 15:08:19
nit: Generates...
gab
2015/08/27 20:51:07
Done.
| |
682 // |removal_flag_|) the current RegistryEntry and add them to the given | |
683 // work item list. | |
651 void AddToWorkItemList(HKEY root, WorkItemList *items) const { | 684 void AddToWorkItemList(HKEY root, WorkItemList *items) const { |
652 items->AddCreateRegKeyWorkItem(root, key_path_, WorkItem::kWow64Default); | 685 if (removal_flag_ == RemovalFlag::VALUE) { |
653 if (is_string_) { | 686 items->AddDeleteRegValueWorkItem(root, key_path_, WorkItem::kWow64Default, |
654 items->AddSetRegValueWorkItem( | 687 name_); |
grt (UTC plus 2)
2015/08/24 15:08:20
this should be best-effort, no?
gab
2015/08/27 20:51:07
I don't think so, when I was figuring out what sho
grt (UTC plus 2)
2015/08/29 01:38:41
It looks like DeleteRegValueWorkItemTest.DeleteNon
gab
2015/08/29 14:39:30
Done in follow-up CL @ https://codereview.chromium
| |
655 root, key_path_, WorkItem::kWow64Default, name_, value_, true); | 688 } else if (removal_flag_ == RemovalFlag::KEY) { |
689 items->AddDeleteRegKeyWorkItem(root, key_path_, WorkItem::kWow64Default); | |
grt (UTC plus 2)
2015/08/24 15:08:19
and this?
gab
2015/08/27 20:51:07
Same thing.
| |
656 } else { | 690 } else { |
657 items->AddSetRegValueWorkItem( | 691 DCHECK(removal_flag_ == RemovalFlag::NONE); |
658 root, key_path_, WorkItem::kWow64Default, name_, int_value_, true); | 692 items->AddCreateRegKeyWorkItem(root, key_path_, WorkItem::kWow64Default); |
693 if (is_string_) { | |
694 items->AddSetRegValueWorkItem(root, key_path_, WorkItem::kWow64Default, | |
695 name_, value_, true); | |
696 } else { | |
697 items->AddSetRegValueWorkItem(root, key_path_, WorkItem::kWow64Default, | |
698 name_, int_value_, true); | |
699 } | |
659 } | 700 } |
660 } | 701 } |
661 | 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. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1148 if (properties.has_dual_mode()) | 1204 if (properties.has_dual_mode()) |
1149 shortcut_properties.set_dual_mode(properties.dual_mode); | 1205 shortcut_properties.set_dual_mode(properties.dual_mode); |
1150 | 1206 |
1151 return shortcut_properties; | 1207 return shortcut_properties; |
1152 } | 1208 } |
1153 | 1209 |
1154 // Cleans up an old verb (run) we used to register in | 1210 // Cleans up an old verb (run) we used to register in |
1155 // <root>\Software\Classes\Chrome<.suffix>\.exe\shell\run on Windows 8. | 1211 // <root>\Software\Classes\Chrome<.suffix>\.exe\shell\run on Windows 8. |
1156 void RemoveRunVerbOnWindows8(BrowserDistribution* dist, | 1212 void RemoveRunVerbOnWindows8(BrowserDistribution* dist, |
1157 const base::FilePath& chrome_exe) { | 1213 const base::FilePath& chrome_exe) { |
1158 if (IsChromeMetroSupported()) { | 1214 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { |
1159 bool is_per_user_install = InstallUtil::IsPerUserInstall(chrome_exe); | 1215 bool is_per_user_install = InstallUtil::IsPerUserInstall(chrome_exe); |
1160 HKEY root_key = DetermineRegistrationRoot(is_per_user_install); | 1216 HKEY root_key = DetermineRegistrationRoot(is_per_user_install); |
1161 // There's no need to rollback, so forgo the usual work item lists and just | 1217 // There's no need to rollback, so forgo the usual work item lists and just |
1162 // remove the key from the registry. | 1218 // remove the key from the registry. |
1163 base::string16 run_verb_key(ShellUtil::kRegClasses); | 1219 base::string16 run_verb_key(ShellUtil::kRegClasses); |
1164 run_verb_key.push_back(base::FilePath::kSeparators[0]); | 1220 run_verb_key.push_back(base::FilePath::kSeparators[0]); |
1165 run_verb_key.append(ShellUtil::GetBrowserModelId( | 1221 run_verb_key.append(ShellUtil::GetBrowserModelId( |
1166 dist, is_per_user_install)); | 1222 dist, is_per_user_install)); |
1167 run_verb_key.append(ShellUtil::kRegExePath); | 1223 run_verb_key.append(ShellUtil::kRegExePath); |
1168 run_verb_key.append(ShellUtil::kRegShellPath); | 1224 run_verb_key.append(ShellUtil::kRegShellPath); |
(...skipping 1343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2512 base::string16 key_path(ShellUtil::kRegClasses); | 2568 base::string16 key_path(ShellUtil::kRegClasses); |
2513 key_path.push_back(base::FilePath::kSeparators[0]); | 2569 key_path.push_back(base::FilePath::kSeparators[0]); |
2514 key_path.append(prog_id); | 2570 key_path.append(prog_id); |
2515 return InstallUtil::DeleteRegistryKey( | 2571 return InstallUtil::DeleteRegistryKey( |
2516 HKEY_CURRENT_USER, key_path, WorkItem::kWow64Default); | 2572 HKEY_CURRENT_USER, key_path, WorkItem::kWow64Default); |
2517 | 2573 |
2518 // TODO(mgiuca): Remove the extension association entries. This requires that | 2574 // TODO(mgiuca): Remove the extension association entries. This requires that |
2519 // the extensions associated with a particular prog_id are stored in that | 2575 // the extensions associated with a particular prog_id are stored in that |
2520 // prog_id's key. | 2576 // prog_id's key. |
2521 } | 2577 } |
OLD | NEW |