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

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

Issue 623903002: Move shell_util's RegistryEntry class into a separate file. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@shell_util-generic-associations
Patch Set: Created 6 years, 2 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
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 29 matching lines...) Expand all
40 #include "base/win/shortcut.h" 40 #include "base/win/shortcut.h"
41 #include "base/win/win_util.h" 41 #include "base/win/win_util.h"
42 #include "base/win/windows_version.h" 42 #include "base/win/windows_version.h"
43 #include "chrome/common/chrome_constants.h" 43 #include "chrome/common/chrome_constants.h"
44 #include "chrome/common/chrome_switches.h" 44 #include "chrome/common/chrome_switches.h"
45 #include "chrome/installer/util/browser_distribution.h" 45 #include "chrome/installer/util/browser_distribution.h"
46 #include "chrome/installer/util/install_util.h" 46 #include "chrome/installer/util/install_util.h"
47 #include "chrome/installer/util/l10n_string_util.h" 47 #include "chrome/installer/util/l10n_string_util.h"
48 #include "chrome/installer/util/master_preferences.h" 48 #include "chrome/installer/util/master_preferences.h"
49 #include "chrome/installer/util/master_preferences_constants.h" 49 #include "chrome/installer/util/master_preferences_constants.h"
50 #include "chrome/installer/util/registry_entry.h"
50 #include "chrome/installer/util/util_constants.h" 51 #include "chrome/installer/util/util_constants.h"
51 #include "chrome/installer/util/work_item.h" 52 #include "chrome/installer/util/work_item.h"
52 53
53 #include "installer_util_strings.h" // NOLINT 54 #include "installer_util_strings.h" // NOLINT
54 55
55 using base::win::RegKey; 56 using base::win::RegKey;
56 57
57 namespace { 58 namespace {
58 59
59 // An enum used to tell QuickIsChromeRegistered() which level of registration 60 // An enum used to tell QuickIsChromeRegistered() which level of registration
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 171
171 bool UserSpecificRegistrySuffix::GetSuffix(base::string16* suffix) { 172 bool UserSpecificRegistrySuffix::GetSuffix(base::string16* suffix) {
172 if (suffix_.empty()) { 173 if (suffix_.empty()) {
173 NOTREACHED(); 174 NOTREACHED();
174 return false; 175 return false;
175 } 176 }
176 suffix->assign(suffix_); 177 suffix->assign(suffix_);
177 return true; 178 return true;
178 } 179 }
179 180
180 // This class represents a single registry entry. The objective is to 181 // Returns the Windows browser client registration key for Chrome. For example:
181 // encapsulate all the registry entries required for registering Chrome at one 182 // "Software\Clients\StartMenuInternet\Chromium[.user]". Strictly speaking, we
182 // place. This class can not be instantiated outside the class and the objects 183 // should use the name of the executable (e.g., "chrome.exe"), but that ship has
183 // of this class type can be obtained only by calling a static method of this 184 // sailed. The cost of switching now is re-prompting users to make Chrome their
184 // class. 185 // default browser, which isn't polite. |suffix| is the user-specific
185 class RegistryEntry { 186 // registration suffix; see GetUserSpecificDefaultBrowserSuffix in shell_util.h
186 public: 187 // for details.
187 // A bit-field enum of places to look for this key in the Windows registry. 188 base::string16 GetBrowserClientKey(BrowserDistribution* dist,
188 enum LookForIn { 189 const base::string16& suffix) {
189 LOOK_IN_HKCU = 1 << 0, 190 DCHECK(suffix.empty() || suffix[0] == L'.');
190 LOOK_IN_HKLM = 1 << 1, 191 return base::string16(ShellUtil::kRegStartMenuInternet)
191 LOOK_IN_HKCU_THEN_HKLM = LOOK_IN_HKCU | LOOK_IN_HKLM, 192 .append(1, L'\\')
192 }; 193 .append(dist->GetBaseAppName())
193 194 .append(suffix);
194 // Details about a Windows application, to be entered into the registry for 195 }
195 // the purpose of file associations. 196
196 struct ApplicationInfo { 197 // Returns the Windows Default Programs capabilities key for Chrome. For
197 ApplicationInfo() : file_type_icon_index(0), application_icon_index(0) {} 198 // example:
198 199 // "Software\Clients\StartMenuInternet\Chromium[.user]\Capabilities".
199 // The ProgId used by Windows for file associations with this application. 200 base::string16 GetCapabilitiesKey(BrowserDistribution* dist,
200 // Must not be empty or start with a '.'. 201 const base::string16& suffix) {
201 base::string16 prog_id; 202 return GetBrowserClientKey(dist, suffix).append(L"\\Capabilities");
202 // The friendly name, and the path of the icon that will be used for files 203 }
203 // of these types when associated with this application by default. (They 204
204 // are NOT the name/icon that will represent the application under the Open 205 // Details about a Windows application, to be entered into the registry for the
205 // With menu.) 206 // purpose of file associations.
206 base::string16 file_type_name; 207 struct ApplicationInfo {
207 // TODO(mgiuca): |file_type_icon_path| should be a base::FilePath. 208 ApplicationInfo() : file_type_icon_index(0), application_icon_index(0) {}
208 base::string16 file_type_icon_path; 209
209 int file_type_icon_index; 210 // The ProgId used by Windows for file associations with this application.
210 // The command to execute when opening a file via this association. It 211 // Must not be empty or start with a '.'.
211 // should contain "%1" (to tell Windows to pass the filename as an 212 base::string16 prog_id;
212 // argument). 213 // The friendly name, and the path of the icon that will be used for files of
213 // TODO(mgiuca): |command_line| should be a base::CommandLine. 214 // these types when associated with this application by default. (They are NOT
214 base::string16 command_line; 215 // the name/icon that will represent the application under the Open With
215 // The AppUserModelId used by Windows 8 for this application. Distinct from 216 // menu.)
216 // |prog_id|. 217 base::string16 file_type_name;
217 base::string16 app_id; 218 // TODO(mgiuca): |file_type_icon_path| should be a base::FilePath.
218 219 base::string16 file_type_icon_path;
219 // User-visible details about this application. Any of these may be empty. 220 int file_type_icon_index;
220 base::string16 application_name; 221 // The command to execute when opening a file via this association. It should
221 // TODO(mgiuca): |application_icon_path| should be a base::FilePath. 222 // contain "%1" (to tell Windows to pass the filename as an argument).
222 base::string16 application_icon_path; 223 // TODO(mgiuca): |command_line| should be a base::CommandLine.
223 int application_icon_index; 224 base::string16 command_line;
224 base::string16 application_description; 225 // The AppUserModelId used by Windows 8 for this application. Distinct from
225 base::string16 publisher_name; 226 // |prog_id|.
226 227 base::string16 app_id;
227 // The CLSID for the application's DelegateExecute handler. May be empty. 228
228 base::string16 delegate_clsid; 229 // User-visible details about this application. Any of these may be empty.
229 }; 230 base::string16 application_name;
230 231 // TODO(mgiuca): |application_icon_path| should be a base::FilePath.
231 // Returns the Windows browser client registration key for Chrome. For 232 base::string16 application_icon_path;
232 // example: "Software\Clients\StartMenuInternet\Chromium[.user]". Strictly 233 int application_icon_index;
233 // speaking, we should use the name of the executable (e.g., "chrome.exe"), 234 base::string16 application_description;
234 // but that ship has sailed. The cost of switching now is re-prompting users 235 base::string16 publisher_name;
235 // to make Chrome their default browser, which isn't polite. |suffix| is the 236
236 // user-specific registration suffix; see GetUserSpecificDefaultBrowserSuffix 237 // The CLSID for the application's DelegateExecute handler. May be empty.
237 // in shell_util.h for details. 238 base::string16 delegate_clsid;
238 static base::string16 GetBrowserClientKey(BrowserDistribution* dist, 239 };
239 const base::string16& suffix) { 240
240 DCHECK(suffix.empty() || suffix[0] == L'.'); 241 // Gets the registry entries to register an application in the Windows registry.
241 return base::string16(ShellUtil::kRegStartMenuInternet) 242 // |app_info| provides all of the information needed.
242 .append(1, L'\\') 243 void GetProgIdEntries(const ApplicationInfo& app_info,
243 .append(dist->GetBaseAppName()) 244 ScopedVector<RegistryEntry>* entries) {
244 .append(suffix); 245 // Basic sanity checks.
245 } 246 DCHECK(!app_info.prog_id.empty());
246 247 DCHECK_NE(L'.', app_info.prog_id[0]);
247 // Returns the Windows Default Programs capabilities key for Chrome. For 248
248 // example: 249 // File association ProgId
249 // "Software\Clients\StartMenuInternet\Chromium[.user]\Capabilities". 250 base::string16 prog_id_path(ShellUtil::kRegClasses);
250 static base::string16 GetCapabilitiesKey(BrowserDistribution* dist, 251 prog_id_path.push_back(base::FilePath::kSeparators[0]);
251 const base::string16& suffix) { 252 prog_id_path.append(app_info.prog_id);
252 return GetBrowserClientKey(dist, suffix).append(L"\\Capabilities"); 253 entries->push_back(new RegistryEntry(prog_id_path, app_info.file_type_name));
253 } 254 entries->push_back(new RegistryEntry(
254 255 prog_id_path + ShellUtil::kRegDefaultIcon,
255 // This method returns a list of all the registry entries that 256 ShellUtil::FormatIconLocation(app_info.file_type_icon_path,
256 // are needed to register this installation's ProgId and AppId. 257 app_info.file_type_icon_index)));
257 // These entries need to be registered in HKLM prior to Win8. 258 entries->push_back(new RegistryEntry(prog_id_path + ShellUtil::kRegShellOpen,
258 static void GetChromeProgIdEntries(BrowserDistribution* dist, 259 app_info.command_line));
259 const base::string16& chrome_exe, 260 if (!app_info.delegate_clsid.empty()) {
261 entries->push_back(
262 new RegistryEntry(prog_id_path + ShellUtil::kRegShellOpen,
263 ShellUtil::kRegDelegateExecute,
264 app_info.delegate_clsid));
265 }
266
267 // The following entries are required as of Windows 8, but do not
268 // depend on the DelegateExecute verb handler being set.
269 if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
270 if (!app_info.app_id.empty()) {
271 entries->push_back(new RegistryEntry(
272 prog_id_path, ShellUtil::kRegAppUserModelId, app_info.app_id));
273 }
274
275 // Add \Software\Classes\<prog_id>\Application entries
276 base::string16 application_path(prog_id_path + ShellUtil::kRegApplication);
277 if (!app_info.app_id.empty()) {
278 entries->push_back(new RegistryEntry(
279 application_path, ShellUtil::kRegAppUserModelId, app_info.app_id));
280 }
281 if (!app_info.application_icon_path.empty()) {
282 entries->push_back(new RegistryEntry(
283 application_path,
284 ShellUtil::kRegApplicationIcon,
285 ShellUtil::FormatIconLocation(app_info.application_icon_path,
286 app_info.application_icon_index)));
287 }
288 if (!app_info.application_name.empty()) {
289 entries->push_back(new RegistryEntry(application_path,
290 ShellUtil::kRegApplicationName,
291 app_info.application_name));
292 }
293 if (!app_info.application_description.empty()) {
294 entries->push_back(
295 new RegistryEntry(application_path,
296 ShellUtil::kRegApplicationDescription,
297 app_info.application_description));
298 }
299 if (!app_info.publisher_name.empty()) {
300 entries->push_back(new RegistryEntry(application_path,
301 ShellUtil::kRegApplicationCompany,
302 app_info.publisher_name));
303 }
304 }
305 }
306
307 // This method returns a list of all the registry entries that are needed to
308 // register this installation's ProgId and AppId. These entries need to be
309 // registered in HKLM prior to Win8.
310 void GetChromeProgIdEntries(BrowserDistribution* dist,
311 const base::string16& chrome_exe,
312 const base::string16& suffix,
313 ScopedVector<RegistryEntry>* entries) {
314 int chrome_icon_index =
315 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME);
316
317 ApplicationInfo app_info;
318 app_info.prog_id = GetBrowserProgId(suffix);
319 app_info.file_type_name = dist->GetBrowserProgIdDesc();
320 // File types associated with Chrome are just given the Chrome icon.
321 app_info.file_type_icon_path = chrome_exe;
322 app_info.file_type_icon_index = chrome_icon_index;
323 app_info.command_line = ShellUtil::GetChromeShellOpenCmd(chrome_exe);
324 // For user-level installs: entries for the app id will be in HKCU; thus we
325 // do not need a suffix on those entries.
326 app_info.app_id = ShellUtil::GetBrowserModelId(
327 dist, InstallUtil::IsPerUserInstall(chrome_exe.c_str()));
328
329 // The command to execute when opening this application via the Metro UI.
330 base::string16 delegate_command(
331 ShellUtil::GetChromeDelegateCommand(chrome_exe));
332 bool set_delegate_execute =
333 IsChromeMetroSupported() &&
334 dist->GetCommandExecuteImplClsid(&app_info.delegate_clsid);
335
336 // TODO(grt): http://crbug.com/75152 Write a reference to a localized
337 // resource for name, description, and company.
338 app_info.application_name = dist->GetDisplayName();
339 app_info.application_icon_path = chrome_exe;
340 app_info.application_icon_index = chrome_icon_index;
341 app_info.application_description = dist->GetAppDescription();
342 app_info.publisher_name = dist->GetPublisherName();
343
344 GetProgIdEntries(app_info, entries);
345
346 // DelegateExecute ProgId. Needed for Chrome Metro in Windows 8. This is
347 // only needed for registring a web browser, not for general associations.
348 if (set_delegate_execute) {
349 base::string16 model_id_shell(ShellUtil::kRegClasses);
350 model_id_shell.push_back(base::FilePath::kSeparators[0]);
351 model_id_shell.append(app_info.app_id);
352 model_id_shell.append(ShellUtil::kRegExePath);
353 model_id_shell.append(ShellUtil::kRegShellPath);
354
355 // <root hkey>\Software\Classes\<app_id>\.exe\shell @=open
356 entries->push_back(
357 new RegistryEntry(model_id_shell, ShellUtil::kRegVerbOpen));
358
359 // Each of Chrome's shortcuts has an appid; which, as of Windows 8, is
360 // registered to handle some verbs. This registration has the side-effect
361 // that these verbs now show up in the shortcut's context menu. We
362 // mitigate this side-effect by making the context menu entries
363 // user readable/localized strings. See relevant MSDN article:
364 // http://msdn.microsoft.com/en-US/library/windows/desktop/cc144171.aspx
365 const struct {
366 const wchar_t* verb;
367 int name_id;
368 } verbs[] = {
369 {ShellUtil::kRegVerbOpen, -1},
370 {ShellUtil::kRegVerbOpenNewWindow, IDS_SHORTCUT_NEW_WINDOW_BASE},
371 };
372 for (size_t i = 0; i < arraysize(verbs); ++i) {
373 base::string16 sub_path(model_id_shell);
374 sub_path.push_back(base::FilePath::kSeparators[0]);
375 sub_path.append(verbs[i].verb);
376
377 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb>
378 if (verbs[i].name_id != -1) {
379 // TODO(grt): http://crbug.com/75152 Write a reference to a localized
380 // resource.
381 base::string16 verb_name(
382 installer::GetLocalizedString(verbs[i].name_id));
383 entries->push_back(new RegistryEntry(sub_path, verb_name.c_str()));
384 }
385 entries->push_back(
386 new RegistryEntry(sub_path, L"CommandId", L"Browser.Launch"));
387
388 sub_path.push_back(base::FilePath::kSeparators[0]);
389 sub_path.append(ShellUtil::kRegCommand);
390
391 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb>\command
392 entries->push_back(new RegistryEntry(sub_path, delegate_command));
393 entries->push_back(new RegistryEntry(
394 sub_path, ShellUtil::kRegDelegateExecute, app_info.delegate_clsid));
395 }
396 }
397 }
398
399 // This method returns a list of the registry entries needed to declare a
400 // capability of handling a protocol on Windows.
401 void GetProtocolCapabilityEntries(BrowserDistribution* dist,
402 const base::string16& suffix,
403 const base::string16& protocol,
404 ScopedVector<RegistryEntry>* entries) {
405 entries->push_back(new RegistryEntry(
406 GetCapabilitiesKey(dist, suffix).append(L"\\URLAssociations"),
407 protocol,
408 GetBrowserProgId(suffix)));
409 }
410
411 // This method returns a list of the registry entries required to register this
412 // installation in "RegisteredApplications" on Windows (to appear in Default
413 // Programs, StartMenuInternet, etc.). These entries need to be registered in
414 // HKLM prior to Win8. If |suffix| is not empty, these entries are guaranteed to
415 // be unique on this machine.
416 void GetShellIntegrationEntries(BrowserDistribution* dist,
417 const base::string16& chrome_exe,
418 const base::string16& suffix,
419 ScopedVector<RegistryEntry>* entries) {
420 const base::string16 icon_path(ShellUtil::FormatIconLocation(
421 chrome_exe, dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME)));
422 const base::string16 quoted_exe_path(L"\"" + chrome_exe + L"\"");
423
424 // Register for the Start Menu "Internet" link (pre-Win7).
425 const base::string16 start_menu_entry(GetBrowserClientKey(dist, suffix));
426 // Register Chrome's display name.
427 // TODO(grt): http://crbug.com/75152 Also set LocalizedString; see
428 // http://msdn.microsoft.com/en-us/library/windows/desktop/cc144109(v=VS.85).a spx#registering_the_display_name
429 entries->push_back(
430 new RegistryEntry(start_menu_entry, dist->GetDisplayName()));
431 // Register the "open" verb for launching Chrome via the "Internet" link.
432 entries->push_back(new RegistryEntry(
433 start_menu_entry + ShellUtil::kRegShellOpen, quoted_exe_path));
434 // Register Chrome's icon for the Start Menu "Internet" link.
435 entries->push_back(new RegistryEntry(
436 start_menu_entry + ShellUtil::kRegDefaultIcon, icon_path));
437
438 // Register installation information.
439 base::string16 install_info(start_menu_entry + L"\\InstallInfo");
440 // Note: not using CommandLine since it has ambiguous rules for quoting
441 // strings.
442 entries->push_back(
443 new RegistryEntry(install_info,
444 kReinstallCommand,
445 quoted_exe_path + L" --" +
446 base::ASCIIToWide(switches::kMakeDefaultBrowser)));
447 entries->push_back(new RegistryEntry(
448 install_info,
449 L"HideIconsCommand",
450 quoted_exe_path + L" --" + base::ASCIIToWide(switches::kHideIcons)));
451 entries->push_back(new RegistryEntry(
452 install_info,
453 L"ShowIconsCommand",
454 quoted_exe_path + L" --" + base::ASCIIToWide(switches::kShowIcons)));
455 entries->push_back(new RegistryEntry(install_info, L"IconsVisible", 1));
456
457 // Register with Default Programs.
458 const base::string16 reg_app_name(dist->GetBaseAppName().append(suffix));
459 // Tell Windows where to find Chrome's Default Programs info.
460 const base::string16 capabilities(GetCapabilitiesKey(dist, suffix));
461 entries->push_back(new RegistryEntry(
462 ShellUtil::kRegRegisteredApplications, reg_app_name, capabilities));
463 // Write out Chrome's Default Programs info.
464 // TODO(grt): http://crbug.com/75152 Write a reference to a localized
465 // resource rather than this.
466 entries->push_back(new RegistryEntry(capabilities,
467 ShellUtil::kRegApplicationDescription,
468 dist->GetLongAppDescription()));
469 entries->push_back(new RegistryEntry(
470 capabilities, ShellUtil::kRegApplicationIcon, icon_path));
471 entries->push_back(new RegistryEntry(
472 capabilities, ShellUtil::kRegApplicationName, dist->GetDisplayName()));
473
474 entries->push_back(new RegistryEntry(
475 capabilities + L"\\Startmenu", L"StartMenuInternet", reg_app_name));
476
477 const base::string16 html_prog_id(GetBrowserProgId(suffix));
478 for (int i = 0; ShellUtil::kPotentialFileAssociations[i] != NULL; i++) {
479 entries->push_back(
480 new RegistryEntry(capabilities + L"\\FileAssociations",
481 ShellUtil::kPotentialFileAssociations[i],
482 html_prog_id));
483 }
484 for (int i = 0; ShellUtil::kPotentialProtocolAssociations[i] != NULL; i++) {
485 entries->push_back(
486 new RegistryEntry(capabilities + L"\\URLAssociations",
487 ShellUtil::kPotentialProtocolAssociations[i],
488 html_prog_id));
489 }
490 }
491
492 // Gets the registry entries to register an application as a handler for a
493 // particular file extension. |prog_id| is the ProgId used by Windows for the
494 // application. |ext| is the file extension, which must begin with a '.'.
495 void GetAppExtRegistrationEntries(const base::string16& prog_id,
496 const base::string16& ext,
497 ScopedVector<RegistryEntry>* entries) {
498 // In HKEY_CURRENT_USER\Software\Classes\EXT\OpenWithProgids, create an
499 // empty value with this class's ProgId.
500 base::string16 key_name(ShellUtil::kRegClasses);
501 key_name.push_back(base::FilePath::kSeparators[0]);
502 key_name.append(ext);
503 key_name.push_back(base::FilePath::kSeparators[0]);
504 key_name.append(ShellUtil::kRegOpenWithProgids);
505 entries->push_back(new RegistryEntry(key_name, prog_id, base::string16()));
506 }
507
508 // This method returns a list of the registry entries required for this
509 // installation to be registered in the Windows shell. In particular:
510 // - App Paths
511 // http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121
512 // - File Associations
513 // http://msdn.microsoft.com/en-us/library/bb166549
514 // These entries need to be registered in HKLM prior to Win8.
515 void GetChromeAppRegistrationEntries(const base::string16& chrome_exe,
260 const base::string16& suffix, 516 const base::string16& suffix,
261 ScopedVector<RegistryEntry>* entries) { 517 ScopedVector<RegistryEntry>* entries) {
262 int chrome_icon_index = 518 const base::FilePath chrome_path(chrome_exe);
263 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME); 519 base::string16 app_path_key(ShellUtil::kAppPathsRegistryKey);
264 520 app_path_key.push_back(base::FilePath::kSeparators[0]);
265 ApplicationInfo app_info; 521 app_path_key.append(chrome_path.BaseName().value());
266 app_info.prog_id = GetBrowserProgId(suffix); 522 entries->push_back(new RegistryEntry(app_path_key, chrome_exe));
267 app_info.file_type_name = dist->GetBrowserProgIdDesc(); 523 entries->push_back(new RegistryEntry(app_path_key,
268 // File types associated with Chrome are just given the Chrome icon. 524 ShellUtil::kAppPathsRegistryPathName,
269 app_info.file_type_icon_path = chrome_exe; 525 chrome_path.DirName().value()));
270 app_info.file_type_icon_index = chrome_icon_index; 526
271 app_info.command_line = ShellUtil::GetChromeShellOpenCmd(chrome_exe); 527 const base::string16 html_prog_id(GetBrowserProgId(suffix));
272 // For user-level installs: entries for the app id will be in HKCU; thus we 528 for (int i = 0; ShellUtil::kPotentialFileAssociations[i] != NULL; i++) {
273 // do not need a suffix on those entries. 529 GetAppExtRegistrationEntries(
274 app_info.app_id = ShellUtil::GetBrowserModelId( 530 html_prog_id, ShellUtil::kPotentialFileAssociations[i], entries);
275 dist, InstallUtil::IsPerUserInstall(chrome_exe.c_str())); 531 }
276 532 }
277 // The command to execute when opening this application via the Metro UI. 533
278 base::string16 delegate_command( 534 // Gets the registry entries to register an application as the default handler
279 ShellUtil::GetChromeDelegateCommand(chrome_exe)); 535 // for a particular file extension. |prog_id| is the ProgId used by Windows for
280 bool set_delegate_execute = 536 // the application. |ext| is the file extension, which must begin with a '.'. If
281 IsChromeMetroSupported() && 537 // |overwrite_existing|, always sets the default handler; otherwise only sets if
282 dist->GetCommandExecuteImplClsid(&app_info.delegate_clsid); 538 // there is no existing default.
283 539 //
284 // TODO(grt): http://crbug.com/75152 Write a reference to a localized 540 // This has no effect on Windows 8. Windows 8 ignores the default and lets the
285 // resource for name, description, and company. 541 // user choose. If there is only one handler for a file, it will automatically
286 app_info.application_name = dist->GetDisplayName(); 542 // become the default. Otherwise, the first time the user opens a file, they are
287 app_info.application_icon_path = chrome_exe; 543 // presented with the dialog to set the default handler. (This is roughly
288 app_info.application_icon_index = chrome_icon_index; 544 // equivalent to being called with |overwrite_existing| false.)
289 app_info.application_description = dist->GetAppDescription(); 545 void GetAppDefaultRegistrationEntries(const base::string16& prog_id,
290 app_info.publisher_name = dist->GetPublisherName(); 546 const base::string16& ext,
291 547 bool overwrite_existing,
292 GetProgIdEntries(app_info, entries); 548 ScopedVector<RegistryEntry>* entries) {
293 549 // Set the default value of HKEY_CURRENT_USER\Software\Classes\EXT to this
294 // DelegateExecute ProgId. Needed for Chrome Metro in Windows 8. This is 550 // class's name.
295 // only needed for registring a web browser, not for general associations. 551 base::string16 key_name(ShellUtil::kRegClasses);
296 if (set_delegate_execute) { 552 key_name.push_back(base::FilePath::kSeparators[0]);
297 base::string16 model_id_shell(ShellUtil::kRegClasses); 553 key_name.append(ext);
298 model_id_shell.push_back(base::FilePath::kSeparators[0]); 554 scoped_ptr<RegistryEntry> default_association(
299 model_id_shell.append(app_info.app_id); 555 new RegistryEntry(key_name, prog_id));
300 model_id_shell.append(ShellUtil::kRegExePath); 556 if (overwrite_existing ||
301 model_id_shell.append(ShellUtil::kRegShellPath); 557 !default_association->KeyExistsInRegistry(RegistryEntry::LOOK_IN_HKCU)) {
302 558 entries->push_back(default_association.release());
303 // <root hkey>\Software\Classes\<app_id>\.exe\shell @=open 559 }
304 entries->push_back(new RegistryEntry(model_id_shell, 560 }
305 ShellUtil::kRegVerbOpen)); 561
306 562 // This method returns a list of all the user level registry entries that are
307 // Each of Chrome's shortcuts has an appid; which, as of Windows 8, is 563 // needed to make Chromium the default handler for a protocol on XP.
308 // registered to handle some verbs. This registration has the side-effect 564 void GetXPStyleUserProtocolEntries(const base::string16& protocol,
309 // that these verbs now show up in the shortcut's context menu. We 565 const base::string16& chrome_icon,
310 // mitigate this side-effect by making the context menu entries 566 const base::string16& chrome_open,
311 // user readable/localized strings. See relevant MSDN article: 567 ScopedVector<RegistryEntry>* entries) {
312 // http://msdn.microsoft.com/en-US/library/windows/desktop/cc144171.aspx 568 // Protocols associations.
313 const struct { 569 base::string16 url_key(ShellUtil::kRegClasses);
314 const wchar_t* verb; 570 url_key.push_back(base::FilePath::kSeparators[0]);
315 int name_id; 571 url_key.append(protocol);
316 } verbs[] = { 572
317 { ShellUtil::kRegVerbOpen, -1 }, 573 // This registry value tells Windows that this 'class' is a URL scheme
318 { ShellUtil::kRegVerbOpenNewWindow, IDS_SHORTCUT_NEW_WINDOW_BASE }, 574 // so IE, explorer and other apps will route it to our handler.
319 }; 575 // <root hkey>\Software\Classes\<protocol>\URL Protocol
320 for (size_t i = 0; i < arraysize(verbs); ++i) { 576 entries->push_back(
321 base::string16 sub_path(model_id_shell); 577 new RegistryEntry(url_key, ShellUtil::kRegUrlProtocol, base::string16()));
322 sub_path.push_back(base::FilePath::kSeparators[0]); 578
323 sub_path.append(verbs[i].verb); 579 // <root hkey>\Software\Classes\<protocol>\DefaultIcon
324 580 base::string16 icon_key = url_key + ShellUtil::kRegDefaultIcon;
325 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb> 581 entries->push_back(new RegistryEntry(icon_key, chrome_icon));
326 if (verbs[i].name_id != -1) { 582
327 // TODO(grt): http://crbug.com/75152 Write a reference to a localized 583 // <root hkey>\Software\Classes\<protocol>\shell\open\command
328 // resource. 584 base::string16 shell_key = url_key + ShellUtil::kRegShellOpen;
329 base::string16 verb_name( 585 entries->push_back(new RegistryEntry(shell_key, chrome_open));
330 installer::GetLocalizedString(verbs[i].name_id)); 586
331 entries->push_back(new RegistryEntry(sub_path, verb_name.c_str())); 587 // <root hkey>\Software\Classes\<protocol>\shell\open\ddeexec
332 } 588 base::string16 dde_key = url_key + L"\\shell\\open\\ddeexec";
333 entries->push_back(new RegistryEntry( 589 entries->push_back(new RegistryEntry(dde_key, base::string16()));
334 sub_path, L"CommandId", L"Browser.Launch")); 590
335 591 // <root hkey>\Software\Classes\<protocol>\shell\@
336 sub_path.push_back(base::FilePath::kSeparators[0]); 592 base::string16 protocol_shell_key = url_key + ShellUtil::kRegShellPath;
337 sub_path.append(ShellUtil::kRegCommand); 593 entries->push_back(new RegistryEntry(protocol_shell_key, L"open"));
338 594 }
339 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb>\command 595
340 entries->push_back(new RegistryEntry(sub_path, delegate_command)); 596 // This method returns a list of all the user level registry entries that are
341 entries->push_back(new RegistryEntry( 597 // needed to make Chromium default browser on XP. Some of these entries are
342 sub_path, ShellUtil::kRegDelegateExecute, app_info.delegate_clsid)); 598 // irrelevant in recent versions of Windows, but we register them anyways as
343 } 599 // some legacy apps are hardcoded to lookup those values.
344 } 600 void GetXPStyleDefaultBrowserUserEntries(BrowserDistribution* dist,
345 }
346
347 // Gets the registry entries to register an application in the Windows
348 // registry. |app_info| provides all of the information needed.
349 static void GetProgIdEntries(const ApplicationInfo& app_info,
350 ScopedVector<RegistryEntry>* entries) {
351 // Basic sanity checks.
352 DCHECK(!app_info.prog_id.empty());
353 DCHECK_NE(L'.', app_info.prog_id[0]);
354
355 // File association ProgId
356 base::string16 prog_id_path(ShellUtil::kRegClasses);
357 prog_id_path.push_back(base::FilePath::kSeparators[0]);
358 prog_id_path.append(app_info.prog_id);
359 entries->push_back(
360 new RegistryEntry(prog_id_path, app_info.file_type_name));
361 entries->push_back(new RegistryEntry(
362 prog_id_path + ShellUtil::kRegDefaultIcon,
363 ShellUtil::FormatIconLocation(app_info.file_type_icon_path,
364 app_info.file_type_icon_index)));
365 entries->push_back(new RegistryEntry(
366 prog_id_path + ShellUtil::kRegShellOpen, app_info.command_line));
367 if (!app_info.delegate_clsid.empty()) {
368 entries->push_back(
369 new RegistryEntry(prog_id_path + ShellUtil::kRegShellOpen,
370 ShellUtil::kRegDelegateExecute,
371 app_info.delegate_clsid));
372 }
373
374 // The following entries are required as of Windows 8, but do not
375 // depend on the DelegateExecute verb handler being set.
376 if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
377 if (!app_info.app_id.empty()) {
378 entries->push_back(new RegistryEntry(
379 prog_id_path, ShellUtil::kRegAppUserModelId, app_info.app_id));
380 }
381
382 // Add \Software\Classes\<prog_id>\Application entries
383 base::string16 application_path(prog_id_path +
384 ShellUtil::kRegApplication);
385 if (!app_info.app_id.empty()) {
386 entries->push_back(new RegistryEntry(
387 application_path, ShellUtil::kRegAppUserModelId, app_info.app_id));
388 }
389 if (!app_info.application_icon_path.empty()) {
390 entries->push_back(new RegistryEntry(
391 application_path,
392 ShellUtil::kRegApplicationIcon,
393 ShellUtil::FormatIconLocation(app_info.application_icon_path,
394 app_info.application_icon_index)));
395 }
396 if (!app_info.application_name.empty()) {
397 entries->push_back(new RegistryEntry(application_path,
398 ShellUtil::kRegApplicationName,
399 app_info.application_name));
400 }
401 if (!app_info.application_description.empty()) {
402 entries->push_back(
403 new RegistryEntry(application_path,
404 ShellUtil::kRegApplicationDescription,
405 app_info.application_description));
406 }
407 if (!app_info.publisher_name.empty()) {
408 entries->push_back(new RegistryEntry(application_path,
409 ShellUtil::kRegApplicationCompany,
410 app_info.publisher_name));
411 }
412 }
413 }
414
415 // This method returns a list of the registry entries needed to declare a
416 // capability of handling a protocol on Windows.
417 static void GetProtocolCapabilityEntries(
418 BrowserDistribution* dist,
419 const base::string16& suffix,
420 const base::string16& protocol,
421 ScopedVector<RegistryEntry>* entries) {
422 entries->push_back(new RegistryEntry(
423 GetCapabilitiesKey(dist, suffix).append(L"\\URLAssociations"),
424 protocol, GetBrowserProgId(suffix)));
425 }
426
427 // This method returns a list of the registry entries required to register
428 // this installation in "RegisteredApplications" on Windows (to appear in
429 // Default Programs, StartMenuInternet, etc.).
430 // These entries need to be registered in HKLM prior to Win8.
431 // If |suffix| is not empty, these entries are guaranteed to be unique on this
432 // machine.
433 static void GetShellIntegrationEntries(BrowserDistribution* dist,
434 const base::string16& chrome_exe, 601 const base::string16& chrome_exe,
435 const base::string16& suffix, 602 const base::string16& suffix,
436 ScopedVector<RegistryEntry>* entries) { 603 ScopedVector<RegistryEntry>* entries) {
437 const base::string16 icon_path( 604 // File extension associations.
438 ShellUtil::FormatIconLocation( 605 base::string16 html_prog_id(GetBrowserProgId(suffix));
439 chrome_exe, 606 for (int i = 0; ShellUtil::kDefaultFileAssociations[i] != NULL; i++) {
440 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME))); 607 GetAppDefaultRegistrationEntries(
441 const base::string16 quoted_exe_path(L"\"" + chrome_exe + L"\""); 608 html_prog_id, ShellUtil::kDefaultFileAssociations[i], true, entries);
442 609 }
443 // Register for the Start Menu "Internet" link (pre-Win7). 610
444 const base::string16 start_menu_entry(GetBrowserClientKey(dist, suffix)); 611 // Protocols associations.
445 // Register Chrome's display name. 612 base::string16 chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe);
446 // TODO(grt): http://crbug.com/75152 Also set LocalizedString; see 613 base::string16 chrome_icon = ShellUtil::FormatIconLocation(
447 // http://msdn.microsoft.com/en-us/library/windows/desktop/cc144109(v=VS.85) .aspx#registering_the_display_name 614 chrome_exe, dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME));
448 entries->push_back(new RegistryEntry( 615 for (int i = 0; ShellUtil::kBrowserProtocolAssociations[i] != NULL; i++) {
449 start_menu_entry, dist->GetDisplayName())); 616 GetXPStyleUserProtocolEntries(ShellUtil::kBrowserProtocolAssociations[i],
450 // Register the "open" verb for launching Chrome via the "Internet" link. 617 chrome_icon,
451 entries->push_back(new RegistryEntry( 618 chrome_open,
452 start_menu_entry + ShellUtil::kRegShellOpen, quoted_exe_path)); 619 entries);
453 // Register Chrome's icon for the Start Menu "Internet" link. 620 }
454 entries->push_back(new RegistryEntry( 621
455 start_menu_entry + ShellUtil::kRegDefaultIcon, icon_path)); 622 // start->Internet shortcut.
456 623 base::string16 start_menu(ShellUtil::kRegStartMenuInternet);
457 // Register installation information. 624 base::string16 app_name = dist->GetBaseAppName() + suffix;
458 base::string16 install_info(start_menu_entry + L"\\InstallInfo"); 625 entries->push_back(new RegistryEntry(start_menu, app_name));
459 // Note: not using CommandLine since it has ambiguous rules for quoting 626 }
460 // strings.
461 entries->push_back(new RegistryEntry(install_info, kReinstallCommand,
462 quoted_exe_path + L" --" +
463 base::ASCIIToWide(switches::kMakeDefaultBrowser)));
464 entries->push_back(new RegistryEntry(install_info, L"HideIconsCommand",
465 quoted_exe_path + L" --" +
466 base::ASCIIToWide(switches::kHideIcons)));
467 entries->push_back(new RegistryEntry(install_info, L"ShowIconsCommand",
468 quoted_exe_path + L" --" +
469 base::ASCIIToWide(switches::kShowIcons)));
470 entries->push_back(new RegistryEntry(install_info, L"IconsVisible", 1));
471
472 // Register with Default Programs.
473 const base::string16 reg_app_name(dist->GetBaseAppName().append(suffix));
474 // Tell Windows where to find Chrome's Default Programs info.
475 const base::string16 capabilities(GetCapabilitiesKey(dist, suffix));
476 entries->push_back(new RegistryEntry(ShellUtil::kRegRegisteredApplications,
477 reg_app_name, capabilities));
478 // Write out Chrome's Default Programs info.
479 // TODO(grt): http://crbug.com/75152 Write a reference to a localized
480 // resource rather than this.
481 entries->push_back(new RegistryEntry(
482 capabilities, ShellUtil::kRegApplicationDescription,
483 dist->GetLongAppDescription()));
484 entries->push_back(new RegistryEntry(
485 capabilities, ShellUtil::kRegApplicationIcon, icon_path));
486 entries->push_back(new RegistryEntry(
487 capabilities, ShellUtil::kRegApplicationName,
488 dist->GetDisplayName()));
489
490 entries->push_back(new RegistryEntry(capabilities + L"\\Startmenu",
491 L"StartMenuInternet", reg_app_name));
492
493 const base::string16 html_prog_id(GetBrowserProgId(suffix));
494 for (int i = 0; ShellUtil::kPotentialFileAssociations[i] != NULL; i++) {
495 entries->push_back(new RegistryEntry(
496 capabilities + L"\\FileAssociations",
497 ShellUtil::kPotentialFileAssociations[i], html_prog_id));
498 }
499 for (int i = 0; ShellUtil::kPotentialProtocolAssociations[i] != NULL;
500 i++) {
501 entries->push_back(new RegistryEntry(
502 capabilities + L"\\URLAssociations",
503 ShellUtil::kPotentialProtocolAssociations[i], html_prog_id));
504 }
505 }
506
507 // This method returns a list of the registry entries required for this
508 // installation to be registered in the Windows shell.
509 // In particular:
510 // - App Paths
511 // http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121
512 // - File Associations
513 // http://msdn.microsoft.com/en-us/library/bb166549
514 // These entries need to be registered in HKLM prior to Win8.
515 static void GetChromeAppRegistrationEntries(
516 const base::string16& chrome_exe,
517 const base::string16& suffix,
518 ScopedVector<RegistryEntry>* entries) {
519 const base::FilePath chrome_path(chrome_exe);
520 base::string16 app_path_key(ShellUtil::kAppPathsRegistryKey);
521 app_path_key.push_back(base::FilePath::kSeparators[0]);
522 app_path_key.append(chrome_path.BaseName().value());
523 entries->push_back(new RegistryEntry(app_path_key, chrome_exe));
524 entries->push_back(new RegistryEntry(app_path_key,
525 ShellUtil::kAppPathsRegistryPathName, chrome_path.DirName().value()));
526
527 const base::string16 html_prog_id(GetBrowserProgId(suffix));
528 for (int i = 0; ShellUtil::kPotentialFileAssociations[i] != NULL; i++) {
529 GetAppExtRegistrationEntries(
530 html_prog_id, ShellUtil::kPotentialFileAssociations[i], entries);
531 }
532 }
533
534 // Gets the registry entries to register an application as a handler for a
535 // particular file extension. |prog_id| is the ProgId used by Windows for the
536 // application. |ext| is the file extension, which must begin with a '.'.
537 static void GetAppExtRegistrationEntries(
538 const base::string16& prog_id,
539 const base::string16& ext,
540 ScopedVector<RegistryEntry>* entries) {
541 // In HKEY_CURRENT_USER\Software\Classes\EXT\OpenWithProgids, create an
542 // empty value with this class's ProgId.
543 base::string16 key_name(ShellUtil::kRegClasses);
544 key_name.push_back(base::FilePath::kSeparators[0]);
545 key_name.append(ext);
546 key_name.push_back(base::FilePath::kSeparators[0]);
547 key_name.append(ShellUtil::kRegOpenWithProgids);
548 entries->push_back(new RegistryEntry(key_name, prog_id, base::string16()));
549 }
550
551 // Gets the registry entries to register an application as the default handler
552 // for a particular file extension. |prog_id| is the ProgId used by Windows
553 // for the application. |ext| is the file extension, which must begin with a
554 // '.'. If |overwrite_existing|, always sets the default handler; otherwise
555 // only sets if there is no existing default.
556 //
557 // This has no effect on Windows 8. Windows 8 ignores the default and lets the
558 // user choose. If there is only one handler for a file, it will automatically
559 // become the default. Otherwise, the first time the user opens a file, they
560 // are presented with the dialog to set the default handler. (This is roughly
561 // equivalent to being called with |overwrite_existing| false.)
562 static void GetAppDefaultRegistrationEntries(
563 const base::string16& prog_id,
564 const base::string16& ext,
565 bool overwrite_existing,
566 ScopedVector<RegistryEntry>* entries) {
567 // Set the default value of HKEY_CURRENT_USER\Software\Classes\EXT to this
568 // class's name.
569 base::string16 key_name(ShellUtil::kRegClasses);
570 key_name.push_back(base::FilePath::kSeparators[0]);
571 key_name.append(ext);
572 scoped_ptr<RegistryEntry> default_association(
573 new RegistryEntry(key_name, prog_id));
574 if (overwrite_existing ||
575 !default_association->KeyExistsInRegistry(
576 RegistryEntry::LOOK_IN_HKCU)) {
577 entries->push_back(default_association.release());
578 }
579 }
580
581 // This method returns a list of all the user level registry entries that
582 // are needed to make Chromium the default handler for a protocol on XP.
583 static void GetXPStyleUserProtocolEntries(
584 const base::string16& protocol,
585 const base::string16& chrome_icon,
586 const base::string16& chrome_open,
587 ScopedVector<RegistryEntry>* entries) {
588 // Protocols associations.
589 base::string16 url_key(ShellUtil::kRegClasses);
590 url_key.push_back(base::FilePath::kSeparators[0]);
591 url_key.append(protocol);
592
593 // This registry value tells Windows that this 'class' is a URL scheme
594 // so IE, explorer and other apps will route it to our handler.
595 // <root hkey>\Software\Classes\<protocol>\URL Protocol
596 entries->push_back(new RegistryEntry(url_key,
597 ShellUtil::kRegUrlProtocol, base::string16()));
598
599 // <root hkey>\Software\Classes\<protocol>\DefaultIcon
600 base::string16 icon_key = url_key + ShellUtil::kRegDefaultIcon;
601 entries->push_back(new RegistryEntry(icon_key, chrome_icon));
602
603 // <root hkey>\Software\Classes\<protocol>\shell\open\command
604 base::string16 shell_key = url_key + ShellUtil::kRegShellOpen;
605 entries->push_back(new RegistryEntry(shell_key, chrome_open));
606
607 // <root hkey>\Software\Classes\<protocol>\shell\open\ddeexec
608 base::string16 dde_key = url_key + L"\\shell\\open\\ddeexec";
609 entries->push_back(new RegistryEntry(dde_key, base::string16()));
610
611 // <root hkey>\Software\Classes\<protocol>\shell\@
612 base::string16 protocol_shell_key = url_key + ShellUtil::kRegShellPath;
613 entries->push_back(new RegistryEntry(protocol_shell_key, L"open"));
614 }
615
616 // This method returns a list of all the user level registry entries that
617 // are needed to make Chromium default browser on XP.
618 // Some of these entries are irrelevant in recent versions of Windows, but
619 // we register them anyways as some legacy apps are hardcoded to lookup those
620 // values.
621 static void GetXPStyleDefaultBrowserUserEntries(
622 BrowserDistribution* dist,
623 const base::string16& chrome_exe,
624 const base::string16& suffix,
625 ScopedVector<RegistryEntry>* entries) {
626 // File extension associations.
627 base::string16 html_prog_id(GetBrowserProgId(suffix));
628 for (int i = 0; ShellUtil::kDefaultFileAssociations[i] != NULL; i++) {
629 GetAppDefaultRegistrationEntries(
630 html_prog_id, ShellUtil::kDefaultFileAssociations[i], true, entries);
631 }
632
633 // Protocols associations.
634 base::string16 chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe);
635 base::string16 chrome_icon =
636 ShellUtil::FormatIconLocation(
637 chrome_exe,
638 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME));
639 for (int i = 0; ShellUtil::kBrowserProtocolAssociations[i] != NULL; i++) {
640 GetXPStyleUserProtocolEntries(ShellUtil::kBrowserProtocolAssociations[i],
641 chrome_icon, chrome_open, entries);
642 }
643
644 // start->Internet shortcut.
645 base::string16 start_menu(ShellUtil::kRegStartMenuInternet);
646 base::string16 app_name = dist->GetBaseAppName() + suffix;
647 entries->push_back(new RegistryEntry(start_menu, app_name));
648 }
649
650 // Generate work_item tasks required to create current registry entry and
651 // add them to the given work item list.
652 void AddToWorkItemList(HKEY root, WorkItemList *items) const {
653 items->AddCreateRegKeyWorkItem(root, key_path_, WorkItem::kWow64Default);
654 if (is_string_) {
655 items->AddSetRegValueWorkItem(
656 root, key_path_, WorkItem::kWow64Default, name_, value_, true);
657 } else {
658 items->AddSetRegValueWorkItem(
659 root, key_path_, WorkItem::kWow64Default, name_, int_value_, true);
660 }
661 }
662
663 // Checks if the current registry entry exists in HKCU\|key_path_|\|name_|
664 // and value is |value_|. If the key does NOT exist in HKCU, checks for
665 // the correct name and value in HKLM.
666 // |look_for_in| specifies roots (HKCU and/or HKLM) in which to look for the
667 // key, unspecified roots are not looked into (i.e. the the key is assumed not
668 // to exist in them).
669 // |look_for_in| must at least specify one root to look into.
670 // If |look_for_in| is LOOK_IN_HKCU_THEN_HKLM, this method mimics Windows'
671 // behavior when searching in HKCR (HKCU takes precedence over HKLM). For
672 // registrations outside of HKCR on versions of Windows prior to Win8,
673 // Chrome's values go in HKLM. This function will make unnecessary (but
674 // harmless) queries into HKCU in that case.
675 bool ExistsInRegistry(uint32 look_for_in) const {
676 DCHECK(look_for_in);
677
678 RegistryStatus status = DOES_NOT_EXIST;
679 if (look_for_in & LOOK_IN_HKCU)
680 status = StatusInRegistryUnderRoot(HKEY_CURRENT_USER);
681 if (status == DOES_NOT_EXIST && (look_for_in & LOOK_IN_HKLM))
682 status = StatusInRegistryUnderRoot(HKEY_LOCAL_MACHINE);
683 return status == SAME_VALUE;
684 }
685
686 // Checks if the current registry entry exists in \|key_path_|\|name_|,
687 // regardless of value. Same lookup rules as ExistsInRegistry.
688 // Unlike ExistsInRegistry, this returns true if some other value is present
689 // with the same key.
690 bool KeyExistsInRegistry(uint32 look_for_in) const {
691 DCHECK(look_for_in);
692
693 RegistryStatus status = DOES_NOT_EXIST;
694 if (look_for_in & LOOK_IN_HKCU)
695 status = StatusInRegistryUnderRoot(HKEY_CURRENT_USER);
696 if (status == DOES_NOT_EXIST && (look_for_in & LOOK_IN_HKLM))
697 status = StatusInRegistryUnderRoot(HKEY_LOCAL_MACHINE);
698 return status != DOES_NOT_EXIST;
699 }
700
701 private:
702 // States this RegistryKey can be in compared to the registry.
703 enum RegistryStatus {
704 // |name_| does not exist in the registry
705 DOES_NOT_EXIST,
706 // |name_| exists, but its value != |value_|
707 DIFFERENT_VALUE,
708 // |name_| exists and its value is |value_|
709 SAME_VALUE,
710 };
711
712 // Create a object that represent default value of a key
713 RegistryEntry(const base::string16& key_path, const base::string16& value)
714 : key_path_(key_path), name_(),
715 is_string_(true), value_(value), int_value_(0) {
716 }
717
718 // Create a object that represent a key of type REG_SZ
719 RegistryEntry(const base::string16& key_path, const base::string16& name,
720 const base::string16& value)
721 : key_path_(key_path), name_(name),
722 is_string_(true), value_(value), int_value_(0) {
723 }
724
725 // Create a object that represent a key of integer type
726 RegistryEntry(const base::string16& key_path, const base::string16& name,
727 DWORD value)
728 : key_path_(key_path), name_(name),
729 is_string_(false), value_(), int_value_(value) {
730 }
731
732 base::string16 key_path_; // key path for the registry entry
733 base::string16 name_; // name of the registry entry
734 bool is_string_; // true if current registry entry is of type REG_SZ
735 base::string16 value_; // string value (useful if is_string_ = true)
736 DWORD int_value_; // integer value (useful if is_string_ = false)
737
738 // Helper function for ExistsInRegistry().
739 // Returns the RegistryStatus of the current registry entry in
740 // |root|\|key_path_|\|name_|.
741 RegistryStatus StatusInRegistryUnderRoot(HKEY root) const {
742 RegKey key(root, key_path_.c_str(), KEY_QUERY_VALUE);
743 bool found = false;
744 bool correct_value = false;
745 if (is_string_) {
746 base::string16 read_value;
747 found = key.ReadValue(name_.c_str(), &read_value) == ERROR_SUCCESS;
748 if (found) {
749 correct_value = read_value.size() == value_.size() &&
750 std::equal(value_.begin(), value_.end(), read_value.begin(),
751 base::CaseInsensitiveCompare<wchar_t>());
752 }
753 } else {
754 DWORD read_value;
755 found = key.ReadValueDW(name_.c_str(), &read_value) == ERROR_SUCCESS;
756 if (found)
757 correct_value = read_value == int_value_;
758 }
759 return found ?
760 (correct_value ? SAME_VALUE : DIFFERENT_VALUE) : DOES_NOT_EXIST;
761 }
762
763 DISALLOW_COPY_AND_ASSIGN(RegistryEntry);
764 }; // class RegistryEntry
765
766 627
767 // This method converts all the RegistryEntries from the given list to 628 // This method converts all the RegistryEntries from the given list to
768 // Set/CreateRegWorkItems and runs them using WorkItemList. 629 // Set/CreateRegWorkItems and runs them using WorkItemList.
769 bool AddRegistryEntries(HKEY root, const ScopedVector<RegistryEntry>& entries) { 630 bool AddRegistryEntries(HKEY root, const ScopedVector<RegistryEntry>& entries) {
770 scoped_ptr<WorkItemList> items(WorkItem::CreateWorkItemList()); 631 scoped_ptr<WorkItemList> items(WorkItem::CreateWorkItemList());
771 632
772 for (ScopedVector<RegistryEntry>::const_iterator itr = entries.begin(); 633 for (ScopedVector<RegistryEntry>::const_iterator itr = entries.begin();
773 itr != entries.end(); ++itr) 634 itr != entries.end(); ++itr)
774 (*itr)->AddToWorkItemList(root, items.get()); 635 (*itr)->AddToWorkItemList(root, items.get());
775 636
(...skipping 28 matching lines...) Expand all
804 // under a single registry root. Not doing so caused http://crbug.com/144910 for 665 // under a single registry root. Not doing so caused http://crbug.com/144910 for
805 // users who first-installed Chrome in that revision range (those users are 666 // users who first-installed Chrome in that revision range (those users are
806 // still impacted by http://crbug.com/144910). This method will keep returning 667 // still impacted by http://crbug.com/144910). This method will keep returning
807 // true for affected users (i.e. who have all the registrations, but over both 668 // true for affected users (i.e. who have all the registrations, but over both
808 // registry roots). 669 // registry roots).
809 bool IsChromeRegistered(BrowserDistribution* dist, 670 bool IsChromeRegistered(BrowserDistribution* dist,
810 const base::string16& chrome_exe, 671 const base::string16& chrome_exe,
811 const base::string16& suffix, 672 const base::string16& suffix,
812 uint32 look_for_in) { 673 uint32 look_for_in) {
813 ScopedVector<RegistryEntry> entries; 674 ScopedVector<RegistryEntry> entries;
814 RegistryEntry::GetChromeProgIdEntries(dist, chrome_exe, suffix, &entries); 675 GetChromeProgIdEntries(dist, chrome_exe, suffix, &entries);
815 RegistryEntry::GetShellIntegrationEntries(dist, chrome_exe, suffix, &entries); 676 GetShellIntegrationEntries(dist, chrome_exe, suffix, &entries);
816 RegistryEntry::GetChromeAppRegistrationEntries(chrome_exe, suffix, &entries); 677 GetChromeAppRegistrationEntries(chrome_exe, suffix, &entries);
817 return AreEntriesRegistered(entries, look_for_in); 678 return AreEntriesRegistered(entries, look_for_in);
818 } 679 }
819 680
820 // This method checks if Chrome is already registered on the local machine 681 // This method checks if Chrome is already registered on the local machine
821 // for the requested protocol. It just checks the one value required for this. 682 // for the requested protocol. It just checks the one value required for this.
822 // See RegistryEntry::ExistsInRegistry for the behavior of |look_for_in|. 683 // See RegistryEntry::ExistsInRegistry for the behavior of |look_for_in|.
823 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist, 684 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist,
824 const base::string16& suffix, 685 const base::string16& suffix,
825 const base::string16& protocol, 686 const base::string16& protocol,
826 uint32 look_for_in) { 687 uint32 look_for_in) {
827 ScopedVector<RegistryEntry> entries; 688 ScopedVector<RegistryEntry> entries;
828 RegistryEntry::GetProtocolCapabilityEntries(dist, suffix, protocol, &entries); 689 GetProtocolCapabilityEntries(dist, suffix, protocol, &entries);
829 return AreEntriesRegistered(entries, look_for_in); 690 return AreEntriesRegistered(entries, look_for_in);
830 } 691 }
831 692
832 // This method registers Chrome on Vista by launching an elevated setup.exe. 693 // This method registers Chrome on Vista by launching an elevated setup.exe.
833 // That will show the user the standard Vista elevation prompt. If the user 694 // That will show the user the standard Vista elevation prompt. If the user
834 // accepts it the new process will make the necessary changes and return SUCCESS 695 // accepts it the new process will make the necessary changes and return SUCCESS
835 // that we capture and return. 696 // that we capture and return.
836 // If protocol is non-empty we will also register Chrome as being capable of 697 // If protocol is non-empty we will also register Chrome as being capable of
837 // handling the protocol. 698 // handling the protocol.
838 bool ElevateAndRegisterChrome(BrowserDistribution* dist, 699 bool ElevateAndRegisterChrome(BrowserDistribution* dist,
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
932 case CONFIRM_PROGID_REGISTRATION: 793 case CONFIRM_PROGID_REGISTRATION:
933 // Software\Classes\ChromeHTML|suffix| 794 // Software\Classes\ChromeHTML|suffix|
934 reg_key = ShellUtil::kRegClasses; 795 reg_key = ShellUtil::kRegClasses;
935 reg_key.push_back(base::FilePath::kSeparators[0]); 796 reg_key.push_back(base::FilePath::kSeparators[0]);
936 reg_key.append(dist->GetBrowserProgIdPrefix()); 797 reg_key.append(dist->GetBrowserProgIdPrefix());
937 reg_key.append(suffix); 798 reg_key.append(suffix);
938 break; 799 break;
939 case CONFIRM_SHELL_REGISTRATION: 800 case CONFIRM_SHELL_REGISTRATION:
940 case CONFIRM_SHELL_REGISTRATION_IN_HKLM: 801 case CONFIRM_SHELL_REGISTRATION_IN_HKLM:
941 // Software\Clients\StartMenuInternet\Google Chrome|suffix| 802 // Software\Clients\StartMenuInternet\Google Chrome|suffix|
942 reg_key = RegistryEntry::GetBrowserClientKey(dist, suffix); 803 reg_key = GetBrowserClientKey(dist, suffix);
943 break; 804 break;
944 default: 805 default:
945 NOTREACHED(); 806 NOTREACHED();
946 break; 807 break;
947 } 808 }
948 reg_key.append(ShellUtil::kRegShellOpen); 809 reg_key.append(ShellUtil::kRegShellOpen);
949 810
950 // ProgId registrations are allowed to reside in HKCU for user-level installs 811 // ProgId registrations are allowed to reside in HKCU for user-level installs
951 // (and values there have priority over values in HKLM). The same is true for 812 // (and values there have priority over values in HKLM). The same is true for
952 // shell integration entries as of Windows 8. 813 // shell integration entries as of Windows 8.
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1018 } 879 }
1019 880
1020 // Associates Chrome with supported protocols and file associations. This should 881 // Associates Chrome with supported protocols and file associations. This should
1021 // not be required on Vista+ but since some applications still read 882 // not be required on Vista+ but since some applications still read
1022 // Software\Classes\http key directly, we have to do this on Vista+ as well. 883 // Software\Classes\http key directly, we have to do this on Vista+ as well.
1023 bool RegisterChromeAsDefaultXPStyle(BrowserDistribution* dist, 884 bool RegisterChromeAsDefaultXPStyle(BrowserDistribution* dist,
1024 int shell_change, 885 int shell_change,
1025 const base::string16& chrome_exe) { 886 const base::string16& chrome_exe) {
1026 bool ret = true; 887 bool ret = true;
1027 ScopedVector<RegistryEntry> entries; 888 ScopedVector<RegistryEntry> entries;
1028 RegistryEntry::GetXPStyleDefaultBrowserUserEntries( 889 GetXPStyleDefaultBrowserUserEntries(
1029 dist, chrome_exe, 890 dist,
1030 ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe), &entries); 891 chrome_exe,
892 ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe),
893 &entries);
1031 894
1032 // Change the default browser for current user. 895 // Change the default browser for current user.
1033 if ((shell_change & ShellUtil::CURRENT_USER) && 896 if ((shell_change & ShellUtil::CURRENT_USER) &&
1034 !AddRegistryEntries(HKEY_CURRENT_USER, entries)) { 897 !AddRegistryEntries(HKEY_CURRENT_USER, entries)) {
1035 ret = false; 898 ret = false;
1036 LOG(ERROR) << "Could not make Chrome default browser (XP/current user)."; 899 LOG(ERROR) << "Could not make Chrome default browser (XP/current user).";
1037 } 900 }
1038 901
1039 // Chrome as default browser at system level. 902 // Chrome as default browser at system level.
1040 if ((shell_change & ShellUtil::SYSTEM_LEVEL) && 903 if ((shell_change & ShellUtil::SYSTEM_LEVEL) &&
(...skipping 13 matching lines...) Expand all
1054 BrowserDistribution* dist, 917 BrowserDistribution* dist,
1055 const base::string16& chrome_exe, 918 const base::string16& chrome_exe,
1056 const base::string16& protocol) { 919 const base::string16& protocol) {
1057 ScopedVector<RegistryEntry> entries; 920 ScopedVector<RegistryEntry> entries;
1058 const base::string16 chrome_open( 921 const base::string16 chrome_open(
1059 ShellUtil::GetChromeShellOpenCmd(chrome_exe)); 922 ShellUtil::GetChromeShellOpenCmd(chrome_exe));
1060 const base::string16 chrome_icon( 923 const base::string16 chrome_icon(
1061 ShellUtil::FormatIconLocation( 924 ShellUtil::FormatIconLocation(
1062 chrome_exe, 925 chrome_exe,
1063 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME))); 926 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME)));
1064 RegistryEntry::GetXPStyleUserProtocolEntries(protocol, chrome_icon, 927 GetXPStyleUserProtocolEntries(protocol, chrome_icon, chrome_open, &entries);
1065 chrome_open, &entries);
1066 // Change the default protocol handler for current user. 928 // Change the default protocol handler for current user.
1067 if (!AddRegistryEntries(HKEY_CURRENT_USER, entries)) { 929 if (!AddRegistryEntries(HKEY_CURRENT_USER, entries)) {
1068 LOG(ERROR) << "Could not make Chrome default protocol client (XP)."; 930 LOG(ERROR) << "Could not make Chrome default protocol client (XP).";
1069 return false; 931 return false;
1070 } 932 }
1071 933
1072 return true; 934 return true;
1073 } 935 }
1074 936
1075 // Returns |properties.shortcut_name| if the property is set, otherwise it 937 // Returns |properties.shortcut_name| if the property is set, otherwise it
(...skipping 1115 matching lines...) Expand 10 before | Expand all | Expand 10 after
2191 // Check if chrome is already registered with this suffix. 2053 // Check if chrome is already registered with this suffix.
2192 if (IsChromeRegistered(dist, chrome_exe, suffix, look_for_in)) 2054 if (IsChromeRegistered(dist, chrome_exe, suffix, look_for_in))
2193 return true; 2055 return true;
2194 2056
2195 bool result = true; 2057 bool result = true;
2196 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { 2058 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) {
2197 // Do the full registration if we can do it at user-level or if the user is 2059 // Do the full registration if we can do it at user-level or if the user is
2198 // an admin. 2060 // an admin.
2199 ScopedVector<RegistryEntry> progid_and_appreg_entries; 2061 ScopedVector<RegistryEntry> progid_and_appreg_entries;
2200 ScopedVector<RegistryEntry> shell_entries; 2062 ScopedVector<RegistryEntry> shell_entries;
2201 RegistryEntry::GetChromeProgIdEntries( 2063 GetChromeProgIdEntries(
2202 dist, chrome_exe, suffix, &progid_and_appreg_entries); 2064 dist, chrome_exe, suffix, &progid_and_appreg_entries);
2203 RegistryEntry::GetChromeAppRegistrationEntries( 2065 GetChromeAppRegistrationEntries(
2204 chrome_exe, suffix, &progid_and_appreg_entries); 2066 chrome_exe, suffix, &progid_and_appreg_entries);
2205 RegistryEntry::GetShellIntegrationEntries( 2067 GetShellIntegrationEntries(dist, chrome_exe, suffix, &shell_entries);
2206 dist, chrome_exe, suffix, &shell_entries);
2207 result = (AddRegistryEntries(root, progid_and_appreg_entries) && 2068 result = (AddRegistryEntries(root, progid_and_appreg_entries) &&
2208 AddRegistryEntries(root, shell_entries)); 2069 AddRegistryEntries(root, shell_entries));
2209 } else if (elevate_if_not_admin && 2070 } else if (elevate_if_not_admin &&
2210 base::win::GetVersion() >= base::win::VERSION_VISTA && 2071 base::win::GetVersion() >= base::win::VERSION_VISTA &&
2211 ElevateAndRegisterChrome(dist, chrome_exe, suffix, base::string16())) { 2072 ElevateAndRegisterChrome(dist, chrome_exe, suffix, base::string16())) {
2212 // If the user is not an admin and OS is between Vista and Windows 7 2073 // If the user is not an admin and OS is between Vista and Windows 7
2213 // inclusively, try to elevate and register. This is only intended for 2074 // inclusively, try to elevate and register. This is only intended for
2214 // user-level installs as system-level installs should always be run with 2075 // user-level installs as system-level installs should always be run with
2215 // admin rights. 2076 // admin rights.
2216 result = true; 2077 result = true;
2217 } else { 2078 } else {
2218 // If we got to this point then all we can do is create ProgId and basic app 2079 // If we got to this point then all we can do is create ProgId and basic app
2219 // registrations under HKCU. 2080 // registrations under HKCU.
2220 ScopedVector<RegistryEntry> entries; 2081 ScopedVector<RegistryEntry> entries;
2221 RegistryEntry::GetChromeProgIdEntries( 2082 GetChromeProgIdEntries(dist, chrome_exe, base::string16(), &entries);
2222 dist, chrome_exe, base::string16(), &entries);
2223 // Prefer to use |suffix|; unless Chrome's ProgIds are already registered 2083 // Prefer to use |suffix|; unless Chrome's ProgIds are already registered
2224 // with no suffix (as per the old registration style): in which case some 2084 // with no suffix (as per the old registration style): in which case some
2225 // other registry entries could refer to them and since we were not able to 2085 // other registry entries could refer to them and since we were not able to
2226 // set our HKLM entries above, we are better off not altering these here. 2086 // set our HKLM entries above, we are better off not altering these here.
2227 if (!AreEntriesRegistered(entries, RegistryEntry::LOOK_IN_HKCU)) { 2087 if (!AreEntriesRegistered(entries, RegistryEntry::LOOK_IN_HKCU)) {
2228 if (!suffix.empty()) { 2088 if (!suffix.empty()) {
2229 entries.clear(); 2089 entries.clear();
2230 RegistryEntry::GetChromeProgIdEntries( 2090 GetChromeProgIdEntries(dist, chrome_exe, suffix, &entries);
2231 dist, chrome_exe, suffix, &entries); 2091 GetChromeAppRegistrationEntries(chrome_exe, suffix, &entries);
2232 RegistryEntry::GetChromeAppRegistrationEntries(
2233 chrome_exe, suffix, &entries);
2234 } 2092 }
2235 result = AddRegistryEntries(HKEY_CURRENT_USER, entries); 2093 result = AddRegistryEntries(HKEY_CURRENT_USER, entries);
2236 } else { 2094 } else {
2237 // The ProgId is registered unsuffixed in HKCU, also register the app with 2095 // The ProgId is registered unsuffixed in HKCU, also register the app with
2238 // Windows in HKCU (this was not done in the old registration style and 2096 // Windows in HKCU (this was not done in the old registration style and
2239 // thus needs to be done after the above check for the unsuffixed 2097 // thus needs to be done after the above check for the unsuffixed
2240 // registration). 2098 // registration).
2241 entries.clear(); 2099 entries.clear();
2242 RegistryEntry::GetChromeAppRegistrationEntries( 2100 GetChromeAppRegistrationEntries(chrome_exe, base::string16(), &entries);
2243 chrome_exe, base::string16(), &entries);
2244 result = AddRegistryEntries(HKEY_CURRENT_USER, entries); 2101 result = AddRegistryEntries(HKEY_CURRENT_USER, entries);
2245 } 2102 }
2246 } 2103 }
2247 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); 2104 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
2248 return result; 2105 return result;
2249 } 2106 }
2250 2107
2251 bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist, 2108 bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist,
2252 const base::string16& chrome_exe, 2109 const base::string16& chrome_exe,
2253 const base::string16& unique_suffix, 2110 const base::string16& unique_suffix,
(...skipping 26 matching lines...) Expand all
2280 return true; 2137 return true;
2281 2138
2282 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { 2139 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) {
2283 // We can do this operation directly. 2140 // We can do this operation directly.
2284 // First, make sure Chrome is fully registered on this machine. 2141 // First, make sure Chrome is fully registered on this machine.
2285 if (!RegisterChromeBrowser(dist, chrome_exe, suffix, false)) 2142 if (!RegisterChromeBrowser(dist, chrome_exe, suffix, false))
2286 return false; 2143 return false;
2287 2144
2288 // Write in the capabillity for the protocol. 2145 // Write in the capabillity for the protocol.
2289 ScopedVector<RegistryEntry> entries; 2146 ScopedVector<RegistryEntry> entries;
2290 RegistryEntry::GetProtocolCapabilityEntries(dist, suffix, protocol, 2147 GetProtocolCapabilityEntries(dist, suffix, protocol, &entries);
2291 &entries);
2292 return AddRegistryEntries(root, entries); 2148 return AddRegistryEntries(root, entries);
2293 } else if (elevate_if_not_admin && 2149 } else if (elevate_if_not_admin &&
2294 base::win::GetVersion() >= base::win::VERSION_VISTA) { 2150 base::win::GetVersion() >= base::win::VERSION_VISTA) {
2295 // Elevate to do the whole job 2151 // Elevate to do the whole job
2296 return ElevateAndRegisterChrome(dist, chrome_exe, suffix, protocol); 2152 return ElevateAndRegisterChrome(dist, chrome_exe, suffix, protocol);
2297 } else { 2153 } else {
2298 // Admin rights are required to register capabilities before Windows 8. 2154 // Admin rights are required to register capabilities before Windows 8.
2299 return false; 2155 return false;
2300 } 2156 }
2301 } 2157 }
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
2433 // static 2289 // static
2434 bool ShellUtil::AddFileAssociations( 2290 bool ShellUtil::AddFileAssociations(
2435 const base::string16& prog_id, 2291 const base::string16& prog_id,
2436 const base::CommandLine& command_line, 2292 const base::CommandLine& command_line,
2437 const base::string16& file_type_name, 2293 const base::string16& file_type_name,
2438 const base::FilePath& icon_path, 2294 const base::FilePath& icon_path,
2439 const std::set<base::string16>& file_extensions) { 2295 const std::set<base::string16>& file_extensions) {
2440 ScopedVector<RegistryEntry> entries; 2296 ScopedVector<RegistryEntry> entries;
2441 2297
2442 // Create a class for this app. 2298 // Create a class for this app.
2443 RegistryEntry::ApplicationInfo app_info; 2299 ApplicationInfo app_info;
2444 app_info.prog_id = prog_id; 2300 app_info.prog_id = prog_id;
2445 app_info.file_type_name = file_type_name; 2301 app_info.file_type_name = file_type_name;
2446 app_info.file_type_icon_path = icon_path.value(); 2302 app_info.file_type_icon_path = icon_path.value();
2447 app_info.file_type_icon_index = 0; 2303 app_info.file_type_icon_index = 0;
2448 app_info.command_line = command_line.GetCommandLineString(); 2304 app_info.command_line = command_line.GetCommandLineString();
2449 RegistryEntry::GetProgIdEntries(app_info, &entries); 2305 GetProgIdEntries(app_info, &entries);
2450 2306
2451 // Associate each extension that the app can handle with the class. Set this 2307 // Associate each extension that the app can handle with the class. Set this
2452 // app as the default handler if and only if there is no existing default. 2308 // app as the default handler if and only if there is no existing default.
2453 for (std::set<base::string16>::const_iterator it = file_extensions.begin(); 2309 for (std::set<base::string16>::const_iterator it = file_extensions.begin();
2454 it != file_extensions.end(); 2310 it != file_extensions.end();
2455 ++it) { 2311 ++it) {
2456 // Do not allow empty file extensions, or extensions beginning with a '.'. 2312 // Do not allow empty file extensions, or extensions beginning with a '.'.
2457 DCHECK(!it->empty()); 2313 DCHECK(!it->empty());
2458 DCHECK_NE(L'.', (*it)[0]); 2314 DCHECK_NE(L'.', (*it)[0]);
2459 base::string16 ext(1, L'.'); 2315 base::string16 ext(1, L'.');
2460 ext.append(*it); 2316 ext.append(*it);
2461 RegistryEntry::GetAppExtRegistrationEntries(prog_id, ext, &entries); 2317 GetAppExtRegistrationEntries(prog_id, ext, &entries);
2462 2318
2463 // Regstering as the default will have no effect on Windows 8 (see 2319 // Regstering as the default will have no effect on Windows 8 (see
2464 // documentation for GetAppDefaultRegistrationEntries). However, if our app 2320 // documentation for GetAppDefaultRegistrationEntries). However, if our app
2465 // is the only handler, it will automatically become the default, so the 2321 // is the only handler, it will automatically become the default, so the
2466 // same effect is achieved. 2322 // same effect is achieved.
2467 RegistryEntry::GetAppDefaultRegistrationEntries( 2323 GetAppDefaultRegistrationEntries(prog_id, ext, false, &entries);
2468 prog_id, ext, false, &entries);
2469 } 2324 }
2470 2325
2471 return AddRegistryEntries(HKEY_CURRENT_USER, entries); 2326 return AddRegistryEntries(HKEY_CURRENT_USER, entries);
2472 } 2327 }
2473 2328
2474 // static 2329 // static
2475 bool ShellUtil::DeleteFileAssociations(const base::string16& prog_id) { 2330 bool ShellUtil::DeleteFileAssociations(const base::string16& prog_id) {
2476 // Delete the key HKEY_CURRENT_USER\Software\Classes\PROGID. 2331 // Delete the key HKEY_CURRENT_USER\Software\Classes\PROGID.
2477 base::string16 key_path(ShellUtil::kRegClasses); 2332 base::string16 key_path(ShellUtil::kRegClasses);
2478 key_path.push_back(base::FilePath::kSeparators[0]); 2333 key_path.push_back(base::FilePath::kSeparators[0]);
2479 key_path.append(prog_id); 2334 key_path.append(prog_id);
2480 return InstallUtil::DeleteRegistryKey( 2335 return InstallUtil::DeleteRegistryKey(
2481 HKEY_CURRENT_USER, key_path, WorkItem::kWow64Default); 2336 HKEY_CURRENT_USER, key_path, WorkItem::kWow64Default);
2482 2337
2483 // TODO(mgiuca): Remove the extension association entries. This requires that 2338 // TODO(mgiuca): Remove the extension association entries. This requires that
2484 // the extensions associated with a particular prog_id are stored in that 2339 // the extensions associated with a particular prog_id are stored in that
2485 // prog_id's key. 2340 // prog_id's key.
2486 } 2341 }
OLDNEW
« chrome/installer/util/registry_entry.cc ('K') | « chrome/installer/util/registry_entry.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698