Improve the default browser settings dialog for Win10

On Win10 the current approach of SHOpenWithDialog is suboptimal. See
the bug for more details.

BUG=488774,489803

Review URL: https://codereview.chromium.org/1140293002

Cr-Commit-Position: refs/heads/master@{#330596}
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc
index acff489d..5dd804a 100644
--- a/chrome/installer/util/shell_util.cc
+++ b/chrome/installer/util/shell_util.cc
@@ -11,6 +11,7 @@
 
 #include <windows.h>
 #include <shlobj.h>
+#include <shobjidl.h>
 
 #include <limits>
 #include <string>
@@ -876,6 +877,25 @@
   return false;
 }
 
+// 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() {
+  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);
+    return SUCCEEDED(hr);
+  }
+  return false;
+}
+
 // Launches the Windows 7 and Windows 8 dialog for picking the application to
 // handle the given protocol. Most importantly, this is used to set the default
 // handler for http (and, implicitly with it, https). In that case it is also
@@ -2061,13 +2081,22 @@
   bool succeeded = true;
   bool is_default = (GetChromeDefaultState() == 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
-    // webpages?" dialog.  We choose the latter.
-    succeeded = LaunchSelectDefaultProtocolHandlerDialog(L"http");
+    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.
+      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();
+    }
     is_default = (succeeded && GetChromeDefaultState() == IS_DEFAULT);
   }
   if (succeeded && is_default)
diff --git a/chrome/installer/util/shell_util.h b/chrome/installer/util/shell_util.h
index 787e605..64e5848 100644
--- a/chrome/installer/util/shell_util.h
+++ b/chrome/installer/util/shell_util.h
@@ -445,11 +445,15 @@
                                 const base::FilePath& chrome_exe,
                                 bool elevate_if_not_admin);
 
-  // Shows and waits for the Windows 8 "How do you want to open webpages?"
+  // Windows 8: Shows and waits for the "How do you want to open webpages?"
   // dialog if Chrome is not already the default HTTP/HTTPS handler. Also does
   // XP-era registrations if Chrome is chosen or was already the default. Do
   // not use on pre-Win8 OSes.
   //
+  // Windows 10: The associations dialog cannot be launched so the settings
+  // dialog focused on default apps is launched. The function does not wait
+  // in this case.
+  //
   // |dist| gives the type of browser distribution currently in use.
   // |chrome_exe| The chrome.exe path to register as default browser.
   static bool ShowMakeChromeDefaultSystemUI(BrowserDistribution* dist,