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