| Index: chrome/installer/util/shell_util.cc
|
| diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc
|
| index 6a00618bac830d9c9c496d7c9653eca3bdbb3318..02c702b38aee209d9fddd073ebf8a6bc7722ec79 100644
|
| --- a/chrome/installer/util/shell_util.cc
|
| +++ b/chrome/installer/util/shell_util.cc
|
| @@ -31,6 +31,7 @@
|
| #include "base/path_service.h"
|
| #include "base/strings/string16.h"
|
| #include "base/strings/string_number_conversions.h"
|
| +#include "base/strings/string_piece.h"
|
| #include "base/strings/string_split.h"
|
| #include "base/strings/string_util.h"
|
| #include "base/strings/stringprintf.h"
|
| @@ -707,26 +708,45 @@ bool ElevateAndRegisterChrome(BrowserDistribution* dist,
|
| return false;
|
| }
|
|
|
| +// Returns the target used as a activate parameter when opening the settings
|
| +// pointing to the page that is the most relevant to a user trying to change the
|
| +// default handler for |protocol|.
|
| +base::string16 GetTargetForDefaultAppsSettings(const wchar_t* protocol) {
|
| + static const wchar_t kSystemSettingsDefaultAppsFormat[] =
|
| + L"SystemSettings_DefaultApps_%ls";
|
| +
|
| + if (base::EqualsCaseInsensitiveASCII(protocol, L"http"))
|
| + return base::StringPrintf(kSystemSettingsDefaultAppsFormat, L"Browser");
|
| + if (base::EqualsCaseInsensitiveASCII(protocol, L"mailto"))
|
| + return base::StringPrintf(kSystemSettingsDefaultAppsFormat, L"Email");
|
| + return L"SettingsPageAppsDefaultsProtocolView";
|
| +}
|
| +
|
| // Launches the Windows 'settings' modern app with the 'default apps' view
|
| // focused. This only works for Windows 8 and Windows 10. The appModelId
|
| -// looks arbitrary but it is the same in Win8 and Win10 previews. There
|
| -// is no easy way to retrieve the appModelId from the registry.
|
| -bool LaunchDefaultAppsSettingsModernDialog() {
|
| +// looks arbitrary but it is the same in Win8 and Win10. There is no easy way to
|
| +// retrieve the appModelId from the registry.
|
| +bool LaunchDefaultAppsSettingsModernDialog(const wchar_t* protocol) {
|
| + DCHECK(protocol);
|
| + static const wchar_t kControlPanelAppModelId[] =
|
| + L"windows.immersivecontrolpanel_cw5n1h2txyewy"
|
| + L"!microsoft.windows.immersivecontrolpanel";
|
| +
|
| base::win::ScopedComPtr<IApplicationActivationManager> activator;
|
| HRESULT hr = activator.CreateInstance(CLSID_ApplicationActivationManager);
|
| if (SUCCEEDED(hr)) {
|
| DWORD pid = 0;
|
| CoAllowSetForegroundWindow(activator.get(), nullptr);
|
| - hr = activator->ActivateApplication(
|
| - L"windows.immersivecontrolpanel_cw5n1h2txyewy"
|
| - L"!microsoft.windows.immersivecontrolpanel",
|
| - L"page=SettingsPageAppsDefaults", AO_NONE, &pid);
|
| + hr = activator->ActivateApplication(kControlPanelAppModelId,
|
| + L"page=SettingsPageAppsDefaults",
|
| + AO_NONE, &pid);
|
| if (SUCCEEDED(hr)) {
|
| hr = activator->ActivateApplication(
|
| - L"windows.immersivecontrolpanel_cw5n1h2txyewy"
|
| - L"!microsoft.windows.immersivecontrolpanel",
|
| - L"page=SettingsPageAppsDefaults"
|
| - L"&target=SystemSettings_DefaultApps_Browser", AO_NONE, &pid);
|
| + kControlPanelAppModelId,
|
| + base::StringPrintf(L"page=SettingsPageAppsDefaults&target=%ls",
|
| + GetTargetForDefaultAppsSettings(protocol).c_str())
|
| + .c_str(),
|
| + AO_NONE, &pid);
|
| }
|
| if (SUCCEEDED(hr))
|
| return true;
|
| @@ -1818,6 +1838,16 @@ bool ShellUtil::CanMakeChromeDefaultUnattended() {
|
| return base::win::GetVersion() < base::win::VERSION_WIN8;
|
| }
|
|
|
| +// static
|
| +ShellUtil::InteractiveSetDefaultMode ShellUtil::GetInteractiveSetDefaultMode() {
|
| + DCHECK(!CanMakeChromeDefaultUnattended());
|
| +
|
| + if (base::win::GetVersion() == base::win::VERSION_WIN8)
|
| + return InteractiveSetDefaultMode::INTENT_PICKER;
|
| +
|
| + return InteractiveSetDefaultMode::SYSTEM_SETTINGS;
|
| +}
|
| +
|
| bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist,
|
| int shell_change,
|
| const base::FilePath& chrome_exe,
|
| @@ -1891,7 +1921,7 @@ bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist,
|
| bool ShellUtil::ShowMakeChromeDefaultSystemUI(
|
| BrowserDistribution* dist,
|
| const base::FilePath& chrome_exe) {
|
| - DCHECK_GE(base::win::GetVersion(), base::win::VERSION_WIN8);
|
| + DCHECK(!CanMakeChromeDefaultUnattended());
|
| if (dist->GetDefaultBrowserControlPolicy() !=
|
| BrowserDistribution::DEFAULT_BROWSER_FULL_CONTROL) {
|
| return false;
|
| @@ -1903,22 +1933,25 @@ bool ShellUtil::ShowMakeChromeDefaultSystemUI(
|
| bool succeeded = true;
|
| bool is_default = (GetChromeDefaultState() == IS_DEFAULT);
|
| if (!is_default) {
|
| - if (base::win::GetVersion() < base::win::VERSION_WIN10) {
|
| - // 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, which is a mess, or pop the concise "How you want to
|
| - // open webpages?" dialog. We choose the latter.
|
| - ScopedUserProtocolEntry user_protocol_entry;
|
| - succeeded = LaunchSelectDefaultProtocolHandlerDialog(L"http");
|
| - } else {
|
| - // On Windows 10, you can't even launch the associations dialog.
|
| - // So we launch the settings dialog. Quoting from MSDN: "The Open With
|
| - // dialog box can no longer be used to change the default program used to
|
| - // open a file extension. You can only use SHOpenWithDialog to open
|
| - // a single file."
|
| - succeeded = LaunchDefaultAppsSettingsModernDialog();
|
| + switch (GetInteractiveSetDefaultMode()) {
|
| + case INTENT_PICKER: {
|
| + // 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, which is a mess, or pop the concise "How you want to
|
| + // open webpages?" dialog. We choose the latter.
|
| + ScopedUserProtocolEntry user_protocol_entry(L"http");
|
| + succeeded = LaunchSelectDefaultProtocolHandlerDialog(L"http");
|
| + } break;
|
| + case SYSTEM_SETTINGS:
|
| + // On Windows 10, you can't even launch the associations dialog.
|
| + // So we launch the settings dialog. Quoting from MSDN: "The Open With
|
| + // dialog box can no longer be used to change the default program used
|
| + // to open a file extension. You can only use SHOpenWithDialog to open
|
| + // a single file."
|
| + succeeded = LaunchDefaultAppsSettingsModernDialog(L"http");
|
| + break;
|
| }
|
| is_default = (succeeded && GetChromeDefaultState() == IS_DEFAULT);
|
| }
|
| @@ -1980,7 +2013,7 @@ bool ShellUtil::ShowMakeChromeDefaultProtocolClientSystemUI(
|
| BrowserDistribution* dist,
|
| const base::FilePath& chrome_exe,
|
| const base::string16& protocol) {
|
| - DCHECK_GE(base::win::GetVersion(), base::win::VERSION_WIN8);
|
| + DCHECK(!CanMakeChromeDefaultUnattended());
|
| if (dist->GetDefaultBrowserControlPolicy() !=
|
| BrowserDistribution::DEFAULT_BROWSER_FULL_CONTROL) {
|
| return false;
|
| @@ -1994,13 +2027,24 @@ bool ShellUtil::ShowMakeChromeDefaultProtocolClientSystemUI(
|
| bool is_default = (
|
| GetChromeDefaultProtocolClientState(protocol) == IS_DEFAULT);
|
| if (!is_default) {
|
| - // 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, which is a mess, or pop the concise "How you want to open
|
| - // links of this type (protocol)?" dialog. We choose the latter.
|
| - succeeded = LaunchSelectDefaultProtocolHandlerDialog(protocol.c_str());
|
| + switch (GetInteractiveSetDefaultMode()) {
|
| + case INTENT_PICKER: {
|
| + // 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, which is a mess, or pop the concise "How you want to
|
| + // open
|
| + // links of this type (protocol)?" dialog. We choose the latter.
|
| + ScopedUserProtocolEntry user_protocol_entry(protocol.c_str());
|
| + succeeded = LaunchSelectDefaultProtocolHandlerDialog(protocol.c_str());
|
| + } break;
|
| + case SYSTEM_SETTINGS:
|
| + // On Windows 10, you can't even launch the associations dialog.
|
| + // So we launch the settings dialog.
|
| + succeeded = LaunchDefaultAppsSettingsModernDialog(protocol.c_str());
|
| + break;
|
| + }
|
| is_default = (succeeded &&
|
| GetChromeDefaultProtocolClientState(protocol) == IS_DEFAULT);
|
| }
|
|
|