Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / shell_integration_win.cc
index 3b8ac54..68e23b8 100644 (file)
@@ -5,6 +5,7 @@
 #include "chrome/browser/shell_integration.h"
 
 #include <windows.h>
+#include <shlwapi.h>
 #include <shobjidl.h>
 #include <propkey.h>
 
@@ -176,6 +177,58 @@ void MigrateChromiumShortcutsCallback() {
   }
 }
 
+// Windows 8 introduced a new protocol->executable binding system which cannot
+// be retrieved in the HKCR registry subkey method implemented below. We call
+// AssocQueryString with the new Win8-only flag ASSOCF_IS_PROTOCOL instead.
+base::string16 GetAppForProtocolUsingAssocQuery(const GURL& url) {
+  base::string16 url_scheme = base::ASCIIToWide(url.scheme());
+  // Don't attempt to query protocol association on an empty string.
+  if (url_scheme.empty())
+    return base::string16();
+
+  // Query AssocQueryString for a human-readable description of the program
+  // that will be invoked given the provided URL spec. This is used only to
+  // populate the external protocol dialog box the user sees when invoking
+  // an unknown external protocol.
+  wchar_t out_buffer[1024];
+  DWORD buffer_size = arraysize(out_buffer);
+  HRESULT hr = AssocQueryString(ASSOCF_IS_PROTOCOL,
+                                ASSOCSTR_FRIENDLYAPPNAME,
+                                url_scheme.c_str(),
+                                NULL,
+                                out_buffer,
+                                &buffer_size);
+  if (FAILED(hr)) {
+    DLOG(WARNING) << "AssocQueryString failed!";
+    return base::string16();
+  }
+  return base::string16(out_buffer);
+}
+
+base::string16 GetAppForProtocolUsingRegistry(const GURL& url) {
+  base::string16 url_spec = base::ASCIIToWide(url.possibly_invalid_spec());
+  const base::string16 cmd_key_path =
+      base::ASCIIToWide(url.scheme() + "\\shell\\open\\command");
+  base::win::RegKey cmd_key(HKEY_CLASSES_ROOT,
+                            cmd_key_path.c_str(),
+                            KEY_READ);
+  size_t split_offset = url_spec.find(L':');
+  if (split_offset == base::string16::npos)
+    return base::string16();
+  const base::string16 parameters = url_spec.substr(split_offset + 1,
+                                                    url_spec.length() - 1);
+  base::string16 application_to_launch;
+  if (cmd_key.ReadValue(NULL, &application_to_launch) == ERROR_SUCCESS) {
+    ReplaceSubstringsAfterOffset(&application_to_launch,
+                                 0,
+                                 L"%1",
+                                 parameters);
+    return application_to_launch;
+  }
+  return base::string16();
+}
+
+
 ShellIntegration::DefaultWebClientState
     GetDefaultWebClientStateFromShellUtilDefaultState(
         ShellUtil::DefaultState default_state) {
@@ -296,23 +349,13 @@ ShellIntegration::DefaultWebClientState
           base::UTF8ToUTF16(protocol)));
 }
 
-base::string16 ShellIntegration::GetApplicationForProtocol(const GURL& url) {
-  std::wstring url_spec = base::ASCIIToWide(url.possibly_invalid_spec());
-  std::wstring cmd_key_path =
-      base::ASCIIToWide(url.scheme() + "\\shell\\open\\command");
-  base::win::RegKey cmd_key(HKEY_CLASSES_ROOT, cmd_key_path.c_str(), KEY_READ);
-  size_t split_offset = url_spec.find(L':');
-  if (split_offset == std::wstring::npos)
-    return std::wstring();
-  std::wstring parameters = url_spec.substr(split_offset + 1,
-                                            url_spec.length() - 1);
-  std::wstring application_to_launch;
-  if (cmd_key.ReadValue(NULL, &application_to_launch) == ERROR_SUCCESS) {
-    ReplaceSubstringsAfterOffset(&application_to_launch, 0, L"%1", parameters);
-    return application_to_launch;
-  }
-
-  return std::wstring();
+base::string16 ShellIntegration::GetApplicationNameForProtocol(
+    const GURL& url) {
+  // Windows 8 or above requires a new protocol association query.
+  if (base::win::GetVersion() >= base::win::VERSION_WIN8)
+    return GetAppForProtocolUsingAssocQuery(url);
+  else
+    return GetAppForProtocolUsingRegistry(url);
 }
 
 // There is no reliable way to say which browser is default on a machine (each
@@ -341,7 +384,8 @@ bool ShellIntegration::IsFirefoxDefaultBrowser() {
     base::win::RegKey key(HKEY_CLASSES_ROOT, key_path.c_str(), KEY_READ);
     base::string16 app_cmd;
     if (key.Valid() && (key.ReadValue(L"", &app_cmd) == ERROR_SUCCESS) &&
-        base::string16::npos != StringToLowerASCII(app_cmd).find(L"firefox"))
+        base::string16::npos !=
+        base::StringToLowerASCII(app_cmd).find(L"firefox"))
       ff_default = true;
   }
   return ff_default;