toolkit/xre/MacQuirks.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/xre/MacQuirks.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,256 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +
    1.10 +#ifndef MacQuirks_h__
    1.11 +#define MacQuirks_h__
    1.12 +
    1.13 +#include <sys/types.h>
    1.14 +#include <sys/sysctl.h>
    1.15 +#include "CoreFoundation/CoreFoundation.h"
    1.16 +#include "CoreServices/CoreServices.h"
    1.17 +#include "Carbon/Carbon.h"
    1.18 +
    1.19 +// This file is a copy and paste from existing methods from
    1.20 +// libxul. This is intentional because this interpose
    1.21 +// library does not link with libxul.
    1.22 +
    1.23 +struct VersionPart {
    1.24 +  int32_t     numA;
    1.25 +
    1.26 +  const char *strB;    // NOT null-terminated, can be a null pointer
    1.27 +  uint32_t    strBlen;
    1.28 +
    1.29 +  int32_t     numC;
    1.30 +
    1.31 +  char       *extraD;  // null-terminated
    1.32 +};
    1.33 +
    1.34 +/**
    1.35 + * Parse a version part into a number and "extra text".
    1.36 + *
    1.37 + * @returns A pointer to the next versionpart, or null if none.
    1.38 + */
    1.39 +static char*
    1.40 +ParseVP(char *part, VersionPart &result)
    1.41 +{
    1.42 +  char *dot;
    1.43 +
    1.44 +  result.numA = 0;
    1.45 +  result.strB = nullptr;
    1.46 +  result.strBlen = 0;
    1.47 +  result.numC = 0;
    1.48 +  result.extraD = nullptr;
    1.49 +
    1.50 +  if (!part)
    1.51 +    return part;
    1.52 +
    1.53 +  dot = strchr(part, '.');
    1.54 +  if (dot)
    1.55 +    *dot = '\0';
    1.56 +
    1.57 +  if (part[0] == '*' && part[1] == '\0') {
    1.58 +    result.numA = INT32_MAX;
    1.59 +    result.strB = "";
    1.60 +  }
    1.61 +  else {
    1.62 +    result.numA = strtol(part, const_cast<char**>(&result.strB), 10);
    1.63 +  }
    1.64 +
    1.65 +  if (!*result.strB) {
    1.66 +    result.strB = nullptr;
    1.67 +    result.strBlen = 0;
    1.68 +  }
    1.69 +  else {
    1.70 +    if (result.strB[0] == '+') {
    1.71 +      static const char kPre[] = "pre";
    1.72 +
    1.73 +      ++result.numA;
    1.74 +      result.strB = kPre;
    1.75 +      result.strBlen = sizeof(kPre) - 1;
    1.76 +    }
    1.77 +    else {
    1.78 +      const char *numstart = strpbrk(result.strB, "0123456789+-");
    1.79 +      if (!numstart) {
    1.80 +  result.strBlen = strlen(result.strB);
    1.81 +      }
    1.82 +      else {
    1.83 +  result.strBlen = numstart - result.strB;
    1.84 +
    1.85 +  result.numC = strtol(numstart, &result.extraD, 10);
    1.86 +  if (!*result.extraD)
    1.87 +    result.extraD = nullptr;
    1.88 +      }
    1.89 +    }
    1.90 +  }
    1.91 +
    1.92 +  if (dot) {
    1.93 +    ++dot;
    1.94 +
    1.95 +    if (!*dot)
    1.96 +      dot = nullptr;
    1.97 +  }
    1.98 +
    1.99 +  return dot;
   1.100 +}
   1.101 +
   1.102 +
   1.103 +// compare two null-terminated strings, which may be null pointers
   1.104 +static int32_t
   1.105 +ns_strcmp(const char *str1, const char *str2)
   1.106 +{
   1.107 +  // any string is *before* no string
   1.108 +  if (!str1)
   1.109 +    return str2 != 0;
   1.110 +
   1.111 +  if (!str2)
   1.112 +    return -1;
   1.113 +
   1.114 +  return strcmp(str1, str2);
   1.115 +}
   1.116 +
   1.117 +// compare two length-specified string, which may be null pointers
   1.118 +static int32_t
   1.119 +ns_strnncmp(const char *str1, uint32_t len1, const char *str2, uint32_t len2)
   1.120 +{
   1.121 +  // any string is *before* no string
   1.122 +  if (!str1)
   1.123 +    return str2 != 0;
   1.124 +
   1.125 +  if (!str2)
   1.126 +    return -1;
   1.127 +
   1.128 +  for (; len1 && len2; --len1, --len2, ++str1, ++str2) {
   1.129 +    if (*str1 < *str2)
   1.130 +      return -1;
   1.131 +
   1.132 +    if (*str1 > *str2)
   1.133 +      return 1;
   1.134 +  }
   1.135 +
   1.136 +  if (len1 == 0)
   1.137 +    return len2 == 0 ? 0 : -1;
   1.138 +
   1.139 +  return 1;
   1.140 +}
   1.141 +
   1.142 +// compare two int32_t
   1.143 +static int32_t
   1.144 +ns_cmp(int32_t n1, int32_t n2)
   1.145 +{
   1.146 +  if (n1 < n2)
   1.147 +    return -1;
   1.148 +
   1.149 +  return n1 != n2;
   1.150 +}
   1.151 +
   1.152 +/**
   1.153 + * Compares two VersionParts
   1.154 + */
   1.155 +static int32_t
   1.156 +CompareVP(VersionPart &v1, VersionPart &v2)
   1.157 +{
   1.158 +  int32_t r = ns_cmp(v1.numA, v2.numA);
   1.159 +  if (r)
   1.160 +    return r;
   1.161 +
   1.162 +  r = ns_strnncmp(v1.strB, v1.strBlen, v2.strB, v2.strBlen);
   1.163 +  if (r)
   1.164 +    return r;
   1.165 +
   1.166 +  r = ns_cmp(v1.numC, v2.numC);
   1.167 +  if (r)
   1.168 +    return r;
   1.169 +
   1.170 +  return ns_strcmp(v1.extraD, v2.extraD);
   1.171 +}
   1.172 +
   1.173 +/* this is intentionally not static so that we don't end up making copies
   1.174 + * anywhere */
   1.175 +int32_t
   1.176 +NS_CompareVersions(const char *A, const char *B)
   1.177 +{
   1.178 +  char *A2 = strdup(A);
   1.179 +  if (!A2)
   1.180 +    return 1;
   1.181 +
   1.182 +  char *B2 = strdup(B);
   1.183 +  if (!B2) {
   1.184 +    free(A2);
   1.185 +    return 1;
   1.186 +  }
   1.187 +
   1.188 +  int32_t result;
   1.189 +  char *a = A2, *b = B2;
   1.190 +
   1.191 +  do {
   1.192 +    VersionPart va, vb;
   1.193 +
   1.194 +    a = ParseVP(a, va);
   1.195 +    b = ParseVP(b, vb);
   1.196 +
   1.197 +    result = CompareVP(va, vb);
   1.198 +    if (result)
   1.199 +      break;
   1.200 +
   1.201 +  } while (a || b);
   1.202 +
   1.203 +  free(A2);
   1.204 +  free(B2);
   1.205 +
   1.206 +  return result;
   1.207 +}
   1.208 +
   1.209 +
   1.210 +static void
   1.211 +TriggerQuirks()
   1.212 +{
   1.213 +  int mib[2];
   1.214 +
   1.215 +  mib[0] = CTL_KERN;
   1.216 +  mib[1] = KERN_OSRELEASE;
   1.217 +  // we won't support versions greater than 10.7.99
   1.218 +  char release[sizeof("10.7.99")];
   1.219 +  size_t len = sizeof(release);
   1.220 +  // sysctl will return ENOMEM if the release string is longer than sizeof(release)
   1.221 +  int ret = sysctl(mib, 2, release, &len, nullptr, 0);
   1.222 +  // we only want to trigger this on OS X 10.6, on versions 10.6.8 or newer
   1.223 +  // Darwin version 10 corresponds to OS X version 10.6, version 11 is 10.7
   1.224 +  // http://en.wikipedia.org/wiki/Darwin_(operating_system)#Release_history
   1.225 +  if (ret == 0 && NS_CompareVersions(release, "10.8.0") >= 0 && NS_CompareVersions(release, "11") < 0) {
   1.226 +    CFBundleRef mainBundle = CFBundleGetMainBundle();
   1.227 +    if (mainBundle) {
   1.228 +      CFRetain(mainBundle);
   1.229 +
   1.230 +      CFStringRef bundleID = CFBundleGetIdentifier(mainBundle);
   1.231 +      if (bundleID) {
   1.232 +        CFRetain(bundleID);
   1.233 +
   1.234 +        CFMutableDictionaryRef dict = (CFMutableDictionaryRef)CFBundleGetInfoDictionary(mainBundle);
   1.235 +        CFDictionarySetValue(dict, CFSTR("CFBundleIdentifier"), CFSTR("org.mozilla.firefox"));
   1.236 +
   1.237 +        // Trigger a load of the quirks table for org.mozilla.firefox.
   1.238 +        // We use different function on 32/64bit because of how the APIs
   1.239 +        // behave to force a call to GetBugsForOurBundleIDFromCoreservicesd.
   1.240 +#ifdef __i386__
   1.241 +        ProcessSerialNumber psn;
   1.242 +        ::GetCurrentProcess(&psn);
   1.243 +#else
   1.244 +        SInt32 major;
   1.245 +        ::Gestalt(gestaltSystemVersionMajor, &major);
   1.246 +#endif
   1.247 +
   1.248 +        // restore the original id
   1.249 +        dict = (CFMutableDictionaryRef)CFBundleGetInfoDictionary(mainBundle);
   1.250 +        CFDictionarySetValue(dict, CFSTR("CFBundleIdentifier"), bundleID);
   1.251 +
   1.252 +        CFRelease(bundleID);
   1.253 +      }
   1.254 +      CFRelease(mainBundle);
   1.255 +    }
   1.256 +  }
   1.257 +}
   1.258 +
   1.259 +#endif //MacQuirks_h__

mercurial