toolkit/xre/MacQuirks.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #ifndef MacQuirks_h__
     8 #define MacQuirks_h__
    10 #include <sys/types.h>
    11 #include <sys/sysctl.h>
    12 #include "CoreFoundation/CoreFoundation.h"
    13 #include "CoreServices/CoreServices.h"
    14 #include "Carbon/Carbon.h"
    16 // This file is a copy and paste from existing methods from
    17 // libxul. This is intentional because this interpose
    18 // library does not link with libxul.
    20 struct VersionPart {
    21   int32_t     numA;
    23   const char *strB;    // NOT null-terminated, can be a null pointer
    24   uint32_t    strBlen;
    26   int32_t     numC;
    28   char       *extraD;  // null-terminated
    29 };
    31 /**
    32  * Parse a version part into a number and "extra text".
    33  *
    34  * @returns A pointer to the next versionpart, or null if none.
    35  */
    36 static char*
    37 ParseVP(char *part, VersionPart &result)
    38 {
    39   char *dot;
    41   result.numA = 0;
    42   result.strB = nullptr;
    43   result.strBlen = 0;
    44   result.numC = 0;
    45   result.extraD = nullptr;
    47   if (!part)
    48     return part;
    50   dot = strchr(part, '.');
    51   if (dot)
    52     *dot = '\0';
    54   if (part[0] == '*' && part[1] == '\0') {
    55     result.numA = INT32_MAX;
    56     result.strB = "";
    57   }
    58   else {
    59     result.numA = strtol(part, const_cast<char**>(&result.strB), 10);
    60   }
    62   if (!*result.strB) {
    63     result.strB = nullptr;
    64     result.strBlen = 0;
    65   }
    66   else {
    67     if (result.strB[0] == '+') {
    68       static const char kPre[] = "pre";
    70       ++result.numA;
    71       result.strB = kPre;
    72       result.strBlen = sizeof(kPre) - 1;
    73     }
    74     else {
    75       const char *numstart = strpbrk(result.strB, "0123456789+-");
    76       if (!numstart) {
    77   result.strBlen = strlen(result.strB);
    78       }
    79       else {
    80   result.strBlen = numstart - result.strB;
    82   result.numC = strtol(numstart, &result.extraD, 10);
    83   if (!*result.extraD)
    84     result.extraD = nullptr;
    85       }
    86     }
    87   }
    89   if (dot) {
    90     ++dot;
    92     if (!*dot)
    93       dot = nullptr;
    94   }
    96   return dot;
    97 }
   100 // compare two null-terminated strings, which may be null pointers
   101 static int32_t
   102 ns_strcmp(const char *str1, const char *str2)
   103 {
   104   // any string is *before* no string
   105   if (!str1)
   106     return str2 != 0;
   108   if (!str2)
   109     return -1;
   111   return strcmp(str1, str2);
   112 }
   114 // compare two length-specified string, which may be null pointers
   115 static int32_t
   116 ns_strnncmp(const char *str1, uint32_t len1, const char *str2, uint32_t len2)
   117 {
   118   // any string is *before* no string
   119   if (!str1)
   120     return str2 != 0;
   122   if (!str2)
   123     return -1;
   125   for (; len1 && len2; --len1, --len2, ++str1, ++str2) {
   126     if (*str1 < *str2)
   127       return -1;
   129     if (*str1 > *str2)
   130       return 1;
   131   }
   133   if (len1 == 0)
   134     return len2 == 0 ? 0 : -1;
   136   return 1;
   137 }
   139 // compare two int32_t
   140 static int32_t
   141 ns_cmp(int32_t n1, int32_t n2)
   142 {
   143   if (n1 < n2)
   144     return -1;
   146   return n1 != n2;
   147 }
   149 /**
   150  * Compares two VersionParts
   151  */
   152 static int32_t
   153 CompareVP(VersionPart &v1, VersionPart &v2)
   154 {
   155   int32_t r = ns_cmp(v1.numA, v2.numA);
   156   if (r)
   157     return r;
   159   r = ns_strnncmp(v1.strB, v1.strBlen, v2.strB, v2.strBlen);
   160   if (r)
   161     return r;
   163   r = ns_cmp(v1.numC, v2.numC);
   164   if (r)
   165     return r;
   167   return ns_strcmp(v1.extraD, v2.extraD);
   168 }
   170 /* this is intentionally not static so that we don't end up making copies
   171  * anywhere */
   172 int32_t
   173 NS_CompareVersions(const char *A, const char *B)
   174 {
   175   char *A2 = strdup(A);
   176   if (!A2)
   177     return 1;
   179   char *B2 = strdup(B);
   180   if (!B2) {
   181     free(A2);
   182     return 1;
   183   }
   185   int32_t result;
   186   char *a = A2, *b = B2;
   188   do {
   189     VersionPart va, vb;
   191     a = ParseVP(a, va);
   192     b = ParseVP(b, vb);
   194     result = CompareVP(va, vb);
   195     if (result)
   196       break;
   198   } while (a || b);
   200   free(A2);
   201   free(B2);
   203   return result;
   204 }
   207 static void
   208 TriggerQuirks()
   209 {
   210   int mib[2];
   212   mib[0] = CTL_KERN;
   213   mib[1] = KERN_OSRELEASE;
   214   // we won't support versions greater than 10.7.99
   215   char release[sizeof("10.7.99")];
   216   size_t len = sizeof(release);
   217   // sysctl will return ENOMEM if the release string is longer than sizeof(release)
   218   int ret = sysctl(mib, 2, release, &len, nullptr, 0);
   219   // we only want to trigger this on OS X 10.6, on versions 10.6.8 or newer
   220   // Darwin version 10 corresponds to OS X version 10.6, version 11 is 10.7
   221   // http://en.wikipedia.org/wiki/Darwin_(operating_system)#Release_history
   222   if (ret == 0 && NS_CompareVersions(release, "10.8.0") >= 0 && NS_CompareVersions(release, "11") < 0) {
   223     CFBundleRef mainBundle = CFBundleGetMainBundle();
   224     if (mainBundle) {
   225       CFRetain(mainBundle);
   227       CFStringRef bundleID = CFBundleGetIdentifier(mainBundle);
   228       if (bundleID) {
   229         CFRetain(bundleID);
   231         CFMutableDictionaryRef dict = (CFMutableDictionaryRef)CFBundleGetInfoDictionary(mainBundle);
   232         CFDictionarySetValue(dict, CFSTR("CFBundleIdentifier"), CFSTR("org.mozilla.firefox"));
   234         // Trigger a load of the quirks table for org.mozilla.firefox.
   235         // We use different function on 32/64bit because of how the APIs
   236         // behave to force a call to GetBugsForOurBundleIDFromCoreservicesd.
   237 #ifdef __i386__
   238         ProcessSerialNumber psn;
   239         ::GetCurrentProcess(&psn);
   240 #else
   241         SInt32 major;
   242         ::Gestalt(gestaltSystemVersionMajor, &major);
   243 #endif
   245         // restore the original id
   246         dict = (CFMutableDictionaryRef)CFBundleGetInfoDictionary(mainBundle);
   247         CFDictionarySetValue(dict, CFSTR("CFBundleIdentifier"), bundleID);
   249         CFRelease(bundleID);
   250       }
   251       CFRelease(mainBundle);
   252     }
   253   }
   254 }
   256 #endif //MacQuirks_h__

mercurial