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.

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

mercurial