Chromium Code Reviews| Index: chrome/installer/util/shell_util.cc |
| diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc |
| index ad8ace3261ac290daa3197b91e34a8e213a3af77..fc31317e202ab411af0b66670145daca39e5b057 100644 |
| --- a/chrome/installer/util/shell_util.cc |
| +++ b/chrome/installer/util/shell_util.cc |
| @@ -204,10 +204,10 @@ class RegistryEntry { |
| } |
| // This method returns a list of all the registry entries that |
| - // are needed to register Chromium ProgIds. |
| + // are needed to register this installation's ProgId and AppId. |
| // These entries should be registered in HKCU for user-level installs and in |
| // HKLM for system-level installs. |
| - static bool GetProgIdEntries(BrowserDistribution* dist, |
| + static void GetProgIdEntries(BrowserDistribution* dist, |
| const string16& chrome_exe, |
| const string16& suffix, |
| std::list<RegistryEntry*>* entries) { |
| @@ -302,31 +302,31 @@ class RegistryEntry { |
| chrome_application, ShellUtil::kRegApplicationCompany, |
| dist->GetPublisherName())); |
| } |
| - |
| - return true; |
| } |
| // This method returns a list of the registry entries needed to declare a |
| // capability of handling a protocol on Windows. |
| - static bool GetProtocolCapabilityEntries(BrowserDistribution* dist, |
| + static void GetProtocolCapabilityEntries(BrowserDistribution* dist, |
| const string16& suffix, |
| const string16& protocol, |
| std::list<RegistryEntry*>* entries) { |
| entries->push_front(new RegistryEntry( |
| GetCapabilitiesKey(dist, suffix).append(L"\\URLAssociations"), |
| protocol, GetBrowserProgId(suffix))); |
| - return true; |
| } |
| - // This method returns a list of all the registry entries required to fully |
| - // integrate Chrome with Windows (i.e. StartMenuInternet, Default Programs, |
| - // AppPaths, etc.). This entries need to be registered in HKLM prior to Win8. |
| - static bool GetShellIntegrationEntries(BrowserDistribution* dist, |
| + // This method returns a list of the registry entries required to register |
| + // this installation in "RegisteredApplications" on Windows (to appear in |
| + // Default Programs, StartMenuInternet, etc.). |
| + // These entries need to be registered in HKLM prior to Win8. |
| + // If |suffix| is not empty, these entries are guaranteed to be unique on this |
| + // machine. |
| + static void GetShellIntegrationEntries(BrowserDistribution* dist, |
| const string16& chrome_exe, |
| const string16& suffix, |
| std::list<RegistryEntry*>* entries) { |
| - string16 icon_path = ShellUtil::GetChromeIcon(dist, chrome_exe); |
| - string16 quoted_exe_path = L"\"" + chrome_exe + L"\""; |
| + const string16 icon_path(ShellUtil::GetChromeIcon(dist, chrome_exe)); |
| + const string16 quoted_exe_path(L"\"" + chrome_exe + L"\""); |
| // Register for the Start Menu "Internet" link (pre-Win7). |
| const string16 start_menu_entry(GetBrowserClientKey(dist, suffix)); |
| @@ -355,9 +355,9 @@ class RegistryEntry { |
| entries->push_front(new RegistryEntry(install_info, L"IconsVisible", 1)); |
| // Register with Default Programs. |
| - string16 reg_app_name(dist->GetBaseAppName().append(suffix)); |
| + const string16 reg_app_name(dist->GetBaseAppName().append(suffix)); |
| // Tell Windows where to find Chrome's Default Programs info. |
| - string16 capabilities(GetCapabilitiesKey(dist, suffix)); |
| + const string16 capabilities(GetCapabilitiesKey(dist, suffix)); |
| entries->push_front(new RegistryEntry(ShellUtil::kRegRegisteredApplications, |
| reg_app_name, capabilities)); |
| // Write out Chrome's Default Programs info. |
| @@ -375,7 +375,7 @@ class RegistryEntry { |
| entries->push_front(new RegistryEntry(capabilities + L"\\Startmenu", |
| L"StartMenuInternet", reg_app_name)); |
| - string16 html_prog_id(GetBrowserProgId(suffix)); |
| + const string16 html_prog_id(GetBrowserProgId(suffix)); |
| for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { |
| entries->push_front(new RegistryEntry( |
| capabilities + L"\\FileAssociations", |
| @@ -387,9 +387,17 @@ class RegistryEntry { |
| capabilities + L"\\URLAssociations", |
| ShellUtil::kPotentialProtocolAssociations[i], html_prog_id)); |
| } |
| + } |
| - // Application Registration. |
| - FilePath chrome_path(chrome_exe); |
| + // This method returns a list of the registry entries required for this |
| + // installation to be registered in the Windows shell. |
| + // In particular: App Paths and File Associations. |
|
robertshield
2012/08/05 15:01:12
Please add links to http://msdn.microsoft.com/en-u
gab
2012/08/06 19:39:27
Done.
|
| + // These entries should be registered in HKCU for user-level installs and in |
| + // HKLM for system-level installs. |
| + static void GetAppRegistrationEntries(const string16& chrome_exe, |
| + const string16& suffix, |
| + std::list<RegistryEntry*>* entries) { |
|
robertshield
2012/08/05 15:01:12
any reason not to use base::ScopedVector here? it
gab
2012/08/06 19:39:27
shell_util has been using std::list forever, but I
|
| + const FilePath chrome_path(chrome_exe); |
| string16 app_path_key(ShellUtil::kAppPathsRegistryKey); |
| app_path_key.push_back(FilePath::kSeparators[0]); |
| app_path_key.append(chrome_path.BaseName().value()); |
| @@ -397,13 +405,20 @@ class RegistryEntry { |
| entries->push_front(new RegistryEntry(app_path_key, |
| ShellUtil::kAppPathsRegistryPathName, chrome_path.DirName().value())); |
| - // TODO: add chrome to open with list (Bug 16726). |
| - return true; |
| + const string16 html_prog_id(GetBrowserProgId(suffix)); |
| + for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { |
| + string16 key(ShellUtil::kRegClasses); |
| + key.push_back(FilePath::kSeparators[0]); |
| + key.append(ShellUtil::kFileAssociations[i]); |
| + key.push_back(FilePath::kSeparators[0]); |
| + key.append(ShellUtil::kRegOpenWithProgids); |
| + entries->push_front(new RegistryEntry(key, html_prog_id, string16())); |
| + } |
| } |
| // This method returns a list of all the user level registry entries that |
| // are needed to make Chromium the default handler for a protocol. |
| - static bool GetUserProtocolEntries(const string16& protocol, |
| + static void GetUserProtocolEntries(const string16& protocol, |
| const string16& chrome_icon, |
| const string16& chrome_open, |
| std::list<RegistryEntry*>* entries) { |
| @@ -433,16 +448,17 @@ class RegistryEntry { |
| // <root hkey>\Software\Classes\<protocol>\shell\@ |
| string16 protocol_shell_key = url_key + ShellUtil::kRegShellPath; |
| entries->push_front(new RegistryEntry(protocol_shell_key, L"open")); |
| - |
| - return true; |
| } |
| // This method returns a list of all the user level registry entries that |
| // are needed to make Chromium default browser. |
| - static bool GetUserEntries(BrowserDistribution* dist, |
| - const string16& chrome_exe, |
| - const string16& suffix, |
| - std::list<RegistryEntry*>* entries) { |
| + // Some of these entries are irrelevant in recent versions of Windows, but |
| + // we register them anyways as some legacy apps are hardcoded to lookup those |
| + // values. |
| + static void GetDefaultBrowserUserEntries(BrowserDistribution* dist, |
| + const string16& chrome_exe, |
| + const string16& suffix, |
| + std::list<RegistryEntry*>* entries) { |
|
robertshield
2012/08/05 15:01:12
same comment about base::ScopedVector
gab
2012/08/06 19:39:27
Done.
|
| // File extension associations. |
| string16 html_prog_id(GetBrowserProgId(suffix)); |
| for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { |
| @@ -464,7 +480,6 @@ class RegistryEntry { |
| string16 start_menu(ShellUtil::kRegStartMenuInternet); |
| string16 app_name = dist->GetBaseAppName() + suffix; |
| entries->push_front(new RegistryEntry(start_menu, app_name)); |
| - return true; |
| } |
| // Generate work_item tasks required to create current registry entry and |
| @@ -604,8 +619,8 @@ bool IsChromeRegistered(BrowserDistribution* dist, |
| std::list<RegistryEntry*> entries; |
| STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); |
| RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries); |
| - RegistryEntry::GetShellIntegrationEntries( |
| - dist, chrome_exe, suffix, &entries); |
| + RegistryEntry::GetShellIntegrationEntries(dist, chrome_exe, suffix, &entries); |
| + RegistryEntry::GetAppRegistrationEntries(chrome_exe, suffix, &entries); |
| return AreEntriesRegistered(entries, RegistryEntry::LOOK_IN_HKCU_THEN_HKLM); |
| } |
| @@ -868,6 +883,35 @@ HKEY DetermineShellIntegrationRoot(bool is_per_user) { |
| HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; |
| } |
| +// Associates Chrome with supported protocols and file associations. This should |
| +// not be required on Vista+ but since some applications still read |
| +// Software\Classes\http key directly, we have to do this on Vista+ as well. |
| +bool RegisterChromeAsDefaultForXP(BrowserDistribution* dist, |
| + int shell_change, |
| + const string16& chrome_exe) { |
| + bool ret = true; |
| + std::list<RegistryEntry*> entries; |
| + STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); |
| + RegistryEntry::GetDefaultBrowserUserEntries( |
| + dist, chrome_exe, |
| + ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe), &entries); |
| + // Change the default browser for current user. |
|
robertshield
2012/08/05 15:01:12
nit: imo should add a blank line before the commen
gab
2012/08/06 19:39:27
Done.
|
| + if ((shell_change & ShellUtil::CURRENT_USER) && |
| + !AddRegistryEntries(HKEY_CURRENT_USER, entries)) { |
| + ret = false; |
| + LOG(ERROR) << "Could not make Chrome default browser (XP/current user)."; |
| + } |
| + |
| + // Chrome as default browser at system level. |
| + if ((shell_change & ShellUtil::SYSTEM_LEVEL) && |
| + !AddRegistryEntries(HKEY_LOCAL_MACHINE, entries)) { |
| + ret = false; |
| + LOG(ERROR) << "Could not make Chrome default browser (XP/system level)."; |
| + } |
| + |
| + return ret; |
| +} |
| + |
| } // namespace |
| const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon"; |
| @@ -914,6 +958,7 @@ const wchar_t* ShellUtil::kRegVerbOpenNewWindow = L"opennewwindow"; |
| const wchar_t* ShellUtil::kRegVerbRun = L"run"; |
| const wchar_t* ShellUtil::kRegCommand = L"command"; |
| const wchar_t* ShellUtil::kRegDelegateExecute = L"DelegateExecute"; |
| +const wchar_t* ShellUtil::kRegOpenWithProgids = L"OpenWithProgids"; |
| bool ShellUtil::QuickIsChromeRegisteredInHKLM(BrowserDistribution* dist, |
| const string16& chrome_exe, |
| @@ -1288,29 +1333,8 @@ bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist, |
| } |
| } |
| - // Now use the old way to associate Chrome with supported protocols and file |
| - // associations. This should not be required on Vista but since some |
| - // applications still read Software\Classes\http key directly, we have to do |
| - // this on Vista also. |
| - |
| - std::list<RegistryEntry*> entries; |
| - STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); |
| - RegistryEntry::GetUserEntries( |
| - dist, chrome_exe, GetCurrentInstallationSuffix(dist, chrome_exe), |
| - &entries); |
| - // Change the default browser for current user. |
| - if ((shell_change & ShellUtil::CURRENT_USER) && |
| - !AddRegistryEntries(HKEY_CURRENT_USER, entries)) { |
| - ret = false; |
| - LOG(ERROR) << "Could not make Chrome default browser (XP/current user)."; |
| - } |
| - |
| - // Chrome as default browser at system level. |
| - if ((shell_change & ShellUtil::SYSTEM_LEVEL) && |
| - !AddRegistryEntries(HKEY_LOCAL_MACHINE, entries)) { |
| + if (!RegisterChromeAsDefaultForXP(dist, shell_change, chrome_exe)) |
| ret = false; |
| - LOG(ERROR) << "Could not make Chrome default browser (XP/system level)."; |
| - } |
| // Send Windows notification event so that it can update icons for |
| // file associations. |
| @@ -1334,7 +1358,16 @@ bool ShellUtil::ShowMakeChromeDefaultSystemUI(BrowserDistribution* dist, |
| // control panel, which is a mess, or pop the concise "How you want to open |
| // webpages?" dialog. We choose the latter. |
| // Return true only when the user took an action and there was no error. |
| - return LaunchSelectDefaultProtocolHandlerDialog(L"http"); |
| + const bool ret = LaunchSelectDefaultProtocolHandlerDialog(L"http"); |
| + |
| + if (ret) { |
| + const int shell_change = |
| + InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ? CURRENT_USER : |
| + SYSTEM_LEVEL; |
| + RegisterChromeAsDefaultForXP(dist, shell_change, chrome_exe); |
| + } |
| + |
| + return ret; |
| } |
| bool ShellUtil::MakeChromeDefaultProtocolClient(BrowserDistribution* dist, |
| @@ -1413,16 +1446,20 @@ bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist, |
| // Do the full registration if we can do it at user-level or if the user is an |
| // admin. |
| if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { |
| - std::list<RegistryEntry*> progids; |
| - STLElementDeleter<std::list<RegistryEntry*> > progids_deleter(&progids); |
| + std::list<RegistryEntry*> progid_and_appreg_entries; |
| + STLElementDeleter<std::list<RegistryEntry*> > progdid_and_appreg_deleter( |
| + &progid_and_appreg_entries); |
| std::list<RegistryEntry*> shell_entries; |
| STLElementDeleter<std::list<RegistryEntry*> > shell_deleter(&shell_entries); |
| - RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &progids); |
| + RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, |
| + &progid_and_appreg_entries); |
| + RegistryEntry::GetAppRegistrationEntries(chrome_exe, suffix, |
| + &progid_and_appreg_entries); |
| RegistryEntry::GetShellIntegrationEntries( |
| dist, chrome_exe, suffix, &shell_entries); |
| return AddRegistryEntries(user_level ? HKEY_CURRENT_USER : |
| HKEY_LOCAL_MACHINE, |
| - progids) && |
| + progid_and_appreg_entries) && |
| AddRegistryEntries(root, shell_entries); |
| } |
| @@ -1435,10 +1472,11 @@ bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist, |
| ElevateAndRegisterChrome(dist, chrome_exe, suffix, L"")) |
| return true; |
| - // If we got to this point then all we can do is create ProgIds under HKCU. |
| + // If we got to this point then all we can do is create ProgId and basic app |
| + // registrations under HKCU. |
| std::list<RegistryEntry*> entries; |
| STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); |
| - RegistryEntry::GetProgIdEntries(dist, chrome_exe, L"", &entries); |
| + RegistryEntry::GetProgIdEntries(dist, chrome_exe, string16(), &entries); |
| // Prefer to use |suffix|; unless Chrome's ProgIds are already registered with |
| // no suffix (as per the old registration style): in which case some other |
| // registry entries could refer to them and since we were not able to set our |
| @@ -1447,8 +1485,17 @@ bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist, |
| if (!suffix.empty()) { |
| STLDeleteElements(&entries); |
| RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries); |
| + RegistryEntry::GetAppRegistrationEntries(chrome_exe, suffix, &entries); |
| } |
| return AddRegistryEntries(HKEY_CURRENT_USER, entries); |
| + } else { |
| + // The ProgId is registered unsuffixed in HKCU, also register the app with |
| + // Windows in HKCU (this was not done in the old registration style and |
| + // thus needs to be done after the above check for the unsuffixed |
| + // registration). |
| + STLDeleteElements(&entries); |
| + RegistryEntry::GetAppRegistrationEntries(chrome_exe, string16(), &entries); |
| + return AddRegistryEntries(HKEY_CURRENT_USER, entries); |
| } |
| return true; |
| } |