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