Bug 1337530 - Fix Windows default browser detection. r?rstrong draft
authorMatt Howell <mhowell@mozilla.com>
Wed, 08 Feb 2017 08:37:20 -0800
changeset 480621 c90c157d09c2c2c4f7e66653c0c7ab495e54c347
parent 479958 e677ba018b22558fef1d07b74d416fd3a28a5dc3
child 545009 1e902a730cda2a85d2e95b2470de5f21c8f0c1a0
push id44601
push usermhowell@mozilla.com
push dateWed, 08 Feb 2017 16:42:47 +0000
reviewersrstrong
bugs1337530
milestone54.0a1
Bug 1337530 - Fix Windows default browser detection. r?rstrong MozReview-Commit-ID: 1I77ECJaOFk
browser/components/shell/nsWindowsShellService.cpp
--- a/browser/components/shell/nsWindowsShellService.cpp
+++ b/browser/components/shell/nsWindowsShellService.cpp
@@ -204,37 +204,37 @@ typedef struct {
 // handler to another application and still have Firefox check if it is the
 // default HTTP and HTTPS handler.
 // *** Do not add additional checks here unless you skip them when aForAllTypes
 // is false below***.
 static SETTING gSettings[] = {
   // File Handler Class
   // ***keep this as the first entry because when aForAllTypes is not set below
   // it will skip over this check.***
-  { MAKE_KEY_NAME1("FirefoxHTML", SOC), VAL_OPEN, OLD_VAL_OPEN },
+  { MAKE_KEY_NAME1("FirefoxHTML%PATHSUFFIX%", SOC), VAL_OPEN, OLD_VAL_OPEN },
 
   // Protocol Handler Class - for Vista and above
-  { MAKE_KEY_NAME1("FirefoxURL", SOC), VAL_OPEN, OLD_VAL_OPEN },
+  { MAKE_KEY_NAME1("FirefoxURL%PATHSUFFIX%", SOC), VAL_OPEN, OLD_VAL_OPEN },
 
   // Protocol Handlers
   { MAKE_KEY_NAME1("HTTP", DI), VAL_FILE_ICON },
   { MAKE_KEY_NAME1("HTTP", SOC), VAL_OPEN, OLD_VAL_OPEN },
   { MAKE_KEY_NAME1("HTTPS", DI), VAL_FILE_ICON },
   { MAKE_KEY_NAME1("HTTPS", SOC), VAL_OPEN, OLD_VAL_OPEN }
 };
 
 // The settings to disable DDE are separate from the default browser settings
 // since they are only checked when Firefox is the default browser and if they
 // are incorrect they are fixed without notifying the user.
 static SETTING gDDESettings[] = {
   // File Handler Class
-  { MAKE_KEY_NAME1("Software\\Classes\\FirefoxHTML", SOD) },
+  { MAKE_KEY_NAME1("Software\\Classes\\FirefoxHTML%PATHSUFFIX%", SOD) },
 
   // Protocol Handler Class - for Vista and above
-  { MAKE_KEY_NAME1("Software\\Classes\\FirefoxURL", SOD) },
+  { MAKE_KEY_NAME1("Software\\Classes\\FirefoxURL%PATHSUFFIX%", SOD) },
 
   // Protocol Handlers
   { MAKE_KEY_NAME1("Software\\Classes\\FTP", SOD) },
   { MAKE_KEY_NAME1("Software\\Classes\\HTTP", SOD) },
   { MAKE_KEY_NAME1("Software\\Classes\\HTTPS", SOD) }
 };
 
 nsresult
@@ -392,43 +392,54 @@ IsDefaultBrowserWin8(bool aCheckAllTypes
   }
   res = IsAARDefault(pAAR, L".html");
   if (*aIsDefaultBrowser && aCheckAllTypes) {
     *aIsDefaultBrowser = res;
   }
 }
 
 static nsresult
-GetAppRegName(nsAutoString &aAppRegName)
+GetAppPathHash(nsAutoString &aPathHash)
 {
   nsresult rv;
   nsCOMPtr<nsIProperties> dirSvc =
     do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIFile> exeFile;
   rv = dirSvc->Get(XRE_EXECUTABLE_FILE,
                    NS_GET_IID(nsIFile),
                    getter_AddRefs(exeFile));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIFile> appDir;
   rv = exeFile->GetParent(getter_AddRefs(appDir));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsAutoString path;
-  rv = appDir->GetPath(path);
+  nsAutoString appDirStr;
+  rv = appDir->GetPath(appDirStr);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  uint64_t hash = CityHash64(static_cast<const char *>(path.get()),
-                             path.Length() * sizeof(nsAutoString::char_type));
+  uint64_t hash = CityHash64(static_cast<const char *>(appDirStr.get()),
+                             appDirStr.Length() * sizeof(nsAutoString::char_type));
+  aPathHash.AppendInt((int)(hash >> 32), 16);
+  aPathHash.AppendInt((int)hash, 16);
+
+  return rv;
+}
+
+static nsresult
+GetAppRegName(nsAutoString &aAppRegName)
+{
+  nsAutoString pathHash;
+  nsresult rv = GetAppPathHash(pathHash);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   aAppRegName = APP_REG_NAME_BASE;
-  aAppRegName.AppendInt((int)hash, 16);
-  aAppRegName.AppendInt((int)(hash >> 32), 16);
+  aAppRegName.Append(pathHash);
 
   return rv;
 }
 
 /*
  * Query's the AAR for the default status.
  * This only checks for FirefoxURL and if aCheckAllTypes is set, then
  * it also checks for FirefoxHTML.  Note that those ProgIDs are shared
@@ -497,17 +508,37 @@ nsWindowsShellService::IsDefaultBrowser(
   SETTING* end = gSettings + sizeof(gSettings) / sizeof(SETTING);
 
   for (; settings < end; ++settings) {
     NS_ConvertUTF8toUTF16 keyName(settings->keyName);
     NS_ConvertUTF8toUTF16 valueData(settings->valueData);
     int32_t offset = valueData.Find("%APPPATH%");
     valueData.Replace(offset, 9, appLongPath);
 
+    // Check for the suffixed version of the key first, if both can exist.
+    offset = keyName.Find("%PATHSUFFIX%");
+    if (offset != -1) {
+      nsAutoString pathHash;
+      rv = GetAppPathHash(pathHash);
+      if (NS_FAILED(rv)) {
+        *aIsDefaultBrowser = false;
+        return NS_OK;
+      }
+      pathHash.Insert('-', 0);
+      keyName.Replace(offset, 12, pathHash);
+    }
+
     rv = OpenKeyForReading(HKEY_CLASSES_ROOT, keyName, &theKey);
+    if (NS_FAILED(rv) && offset != -1) {
+      // If the key we're after doesn't exist, maybe we need an
+      // unsuffixed version.
+      keyName.AssignASCII(settings->keyName);
+      keyName.Cut(offset, 12);
+      rv = OpenKeyForReading(HKEY_CLASSES_ROOT, keyName, &theKey);
+    }
     if (NS_FAILED(rv)) {
       *aIsDefaultBrowser = false;
       return NS_OK;
     }
 
     ::ZeroMemory(currValue, sizeof(currValue));
     DWORD len = sizeof currValue;
     res = ::RegQueryValueExW(theKey, L"", nullptr, nullptr,
@@ -566,17 +597,38 @@ nsWindowsShellService::IsDefaultBrowser(
   if (*aIsDefaultBrowser && aForAllTypes) {
     // Check ftp settings
 
     end = gDDESettings + sizeof(gDDESettings) / sizeof(SETTING);
 
     for (settings = gDDESettings; settings < end; ++settings) {
       NS_ConvertUTF8toUTF16 keyName(settings->keyName);
 
+      // Check for the suffixed version of the key first, if both can exist.
+      int32_t offset = keyName.Find("%PATHSUFFIX%");
+      if (offset != -1) {
+        nsAutoString pathHash;
+        rv = GetAppPathHash(pathHash);
+        if (NS_FAILED(rv)) {
+          ::RegCloseKey(theKey);
+          *aIsDefaultBrowser = false;
+          return NS_OK;
+        }
+        pathHash.Insert('-', 0);
+        keyName.Replace(offset, 12, pathHash);
+      }
+
       rv = OpenKeyForReading(HKEY_CURRENT_USER, keyName, &theKey);
+      if (NS_FAILED(rv) && offset != -1) {
+        // If the key we're after doesn't exist, maybe we need an
+        // unsuffixed version.
+        keyName.AssignASCII(settings->keyName);
+        keyName.Cut(offset, 12);
+        rv = OpenKeyForReading(HKEY_CURRENT_USER, keyName, &theKey);
+      }
       if (NS_FAILED(rv)) {
         ::RegCloseKey(theKey);
         // If disabling DDE fails try to disable it using the helper
         // application when setting Firefox as the default browser.
         *aIsDefaultBrowser = false;
         return NS_OK;
       }