Index: chrome/installer/util/shell_util.cc |
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc |
index 7753fc646e646d9b718a05314eb5e0f3a4d5ea6a..73e70a36377581fd311930ef55ebfb67b6deb0be 100644 |
--- a/chrome/installer/util/shell_util.cc |
+++ b/chrome/installer/util/shell_util.cc |
@@ -77,7 +77,6 @@ class RegistryEntry { |
// are needed to register Chromium ProgIds. |
// These entries should be registered in HKCU for user-level installs and in |
// HKLM for system-level installs. |
- // TODO (gab): Extract the Windows 8 only registrations out of this function. |
static bool GetProgIdEntries(BrowserDistribution* dist, |
const string16& chrome_exe, |
const string16& suffix, |
@@ -149,7 +148,7 @@ class RegistryEntry { |
} |
// The following entries are required as of Windows 8, but do not |
- // depend on the DelegateExecute. |
+ // depend on the DelegateExecute verb handler being set. |
if (base::win::GetVersion() >= base::win::VERSION_WIN8) { |
entries->push_front(new RegistryEntry( |
chrome_html_prog_id, ShellUtil::kRegAppUserModelId, app_id)); |
@@ -490,6 +489,10 @@ bool ElevateAndRegisterChrome(BrowserDistribution* dist, |
const string16& chrome_exe, |
const string16& suffix, |
const string16& protocol) { |
+ // Only user-level installs prior to Windows 8 should need to elevate to |
+ // register. |
+ DCHECK(InstallUtil::IsPerUserInstall(chrome_exe.c_str())); |
+ DCHECK_LT(base::win::GetVersion(), base::win::VERSION_WIN8); |
FilePath exe_path = |
FilePath::FromWStringHack(chrome_exe).DirName() |
.Append(installer::kSetupExe); |
@@ -589,12 +592,13 @@ bool AnotherUserHasDefaultBrowser(BrowserDistribution* dist, |
// Launches the Windows 7 and Windows 8 application association dialog, which |
// is the only documented way to make a browser the default browser on |
// Windows 8. |
-bool LaunchApplicationAssociationDialog(const string16& app_id) { |
- base::win::ScopedComPtr<IApplicationAssociationRegistrationUI> aarui; |
- HRESULT hr = aarui.CreateInstance(CLSID_ApplicationAssociationRegistrationUI); |
- if (FAILED(hr)) |
- return false; |
- hr = aarui->LaunchAdvancedAssociationUI(app_id.c_str()); |
+bool LaunchApplicationAssociationDialog() { |
+ const wchar_t* protocol = L"http"; |
+ OPENASINFO open_as_info = {}; |
+ open_as_info.pcszFile = protocol; |
+ open_as_info.oaifInFlags = |
+ OAIF_URL_PROTOCOL | OAIF_FORCE_REGISTRATION | OAIF_REGISTER_EXT; |
+ HRESULT hr = SHOpenWithDialog(NULL, &open_as_info); |
return SUCCEEDED(hr); |
} |
@@ -647,6 +651,14 @@ void RemoveBadWindows8RegistrationIfNeeded( |
} |
} |
+// Returns the root registry key (HKLM or HKCU) into which system registration |
+// for default protocols must be placed. As of Windows 8 everything can go in |
+// HKCU for per-user installs. |
+HKEY DetermineRegistrationRoot(bool is_per_user) { |
+ return is_per_user && base::win::GetVersion() >= base::win::VERSION_WIN8 ? |
+ HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; |
+} |
+ |
} // namespace |
const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon"; |
@@ -912,9 +924,17 @@ bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist, |
int shell_change, |
const string16& chrome_exe, |
bool elevate_if_not_admin) { |
+ DCHECK(!(shell_change & ShellUtil::SYSTEM_LEVEL) || IsUserAnAdmin()); |
+ |
if (!dist->CanSetAsDefault()) |
return false; |
+ // Windows 8 does not permit making a browser default just like that. |
+ // This process needs to be routed through the system's UI. Use |
+ // ShowMakeChromeDefaultSystemUI instead (below). |
+ if (base::win::GetVersion() >= base::win::VERSION_WIN8) |
+ return false; |
+ |
ShellUtil::RegisterChromeBrowser(dist, chrome_exe, L"", elevate_if_not_admin); |
bool ret = true; |
@@ -933,9 +953,12 @@ bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist, |
// control panel. This action does not require elevation and we |
// don't get to control window activation. More info at: |
// http://msdn.microsoft.com/en-us/library/cc144154(VS.85).aspx |
- return LaunchApplicationAssociationDialog(app_name.c_str()); |
+ // Since this will show a modal UI elementm this has been split into |
+ // a separate flow (see ShowMakeChromeDefaultSystemUI). |
+ return false; |
+ } |
- } else if (base::win::GetVersion() >= base::win::VERSION_VISTA) { |
+ if (base::win::GetVersion() >= base::win::VERSION_VISTA) { |
// On Windows Vista and Win7 we still can set ourselves via the |
// the IApplicationAssociationRegistration interface. |
VLOG(1) << "Registering Chrome as default browser on Vista."; |
@@ -997,6 +1020,24 @@ bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist, |
return ret; |
} |
+bool ShellUtil::ShowMakeChromeDefaultSystemUI( |
+ BrowserDistribution* dist, int shell_change, const string16& chrome_exe, |
+ bool elevate_if_not_admin) { |
+ if (!dist->CanSetAsDefault()) |
+ return false; |
+ |
+ ShellUtil::RegisterChromeBrowser(dist, chrome_exe, L"", elevate_if_not_admin); |
+ |
+ // On Windows 8, you can't set yourself as the default handler |
+ // programatically. In other words IApplicationAssociationRegistration |
+ // has been rendered useless. What you can do is to launch |
+ // "Set Program Associations" section of the "Default Programs" |
+ // control panel. This action does not require elevation and we |
+ // don't get to control window activation. More info at: |
+ // http://msdn.microsoft.com/en-us/library/cc144154(VS.85).aspx |
+ return LaunchApplicationAssociationDialog(); |
+} |
+ |
bool ShellUtil::MakeChromeDefaultProtocolClient(BrowserDistribution* dist, |
const string16& chrome_exe, |
const string16& protocol) { |
@@ -1077,29 +1118,34 @@ bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist, |
if (IsChromeRegistered(dist, chrome_exe, suffix)) |
return true; |
- // If user is an admin try to register and return the status. |
- if (IsUserAnAdmin()) { |
+ bool user_level = InstallUtil::IsPerUserInstall(chrome_exe.c_str()); |
+ HKEY root = DetermineRegistrationRoot(user_level); |
+ |
+ // 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*> sys_entries; |
STLElementDeleter<std::list<RegistryEntry*> > sys_deleter(&sys_entries); |
RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &progids); |
RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &sys_entries); |
- return AddRegistryEntries( |
- InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ? |
- HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, |
- progids) && |
- AddRegistryEntries(HKEY_LOCAL_MACHINE, sys_entries); |
+ return AddRegistryEntries(user_level ? HKEY_CURRENT_USER : |
+ HKEY_LOCAL_MACHINE, |
+ progids) && |
+ AddRegistryEntries(root, sys_entries); |
} |
- // If user is not an admin and OS is Vista, try to elevate and register. |
+ // If the user is not an admin and OS is between Vista and Windows 7 |
+ // inclusively, try to elevate and register. This is only intended for |
+ // user-level installs as system-level installs should always be run with |
+ // admin rights. |
if (elevate_if_not_admin && |
base::win::GetVersion() >= base::win::VERSION_VISTA && |
ElevateAndRegisterChrome(dist, chrome_exe, suffix, L"")) |
return true; |
- // If we got to this point then all we can do is create ProgIds under HKCU |
- // on XP as well as Vista. |
+ // If we got to this point then all we can do is create ProgIds under HKCU. |
std::list<RegistryEntry*> entries; |
STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); |
RegistryEntry::GetProgIdEntries(dist, chrome_exe, L"", &entries); |
@@ -1129,7 +1175,10 @@ bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist, |
if (IsChromeRegisteredForProtocol(dist, suffix, protocol)) |
return true; |
- if (IsUserAnAdmin()) { |
+ HKEY root = DetermineRegistrationRoot( |
+ InstallUtil::IsPerUserInstall(chrome_exe.c_str())); |
+ |
+ if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { |
// We can do this operation directly. |
// If we're not registered at all, try to register. If that fails |
// we should give up. |
@@ -1143,14 +1192,13 @@ bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist, |
STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); |
RegistryEntry::GetProtocolCapabilityEntries(dist, suffix, protocol, |
&entries); |
- return AddRegistryEntries(HKEY_LOCAL_MACHINE, entries); |
+ return AddRegistryEntries(root, entries); |
} else if (elevate_if_not_admin && |
base::win::GetVersion() >= base::win::VERSION_VISTA) { |
// Elevate to do the whole job |
return ElevateAndRegisterChrome(dist, chrome_exe, suffix, protocol); |
} else { |
- // we need admin rights to register our capability. If we don't |
- // have them and can't elevate, give up. |
+ // Admin rights are required to register capabilities before Windows 8. |
return false; |
} |
} |