xulrunner/stub/nsXULStub.cpp

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 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #include "nsXPCOMGlue.h"
michael@0 6 #include "nsINIParser.h"
michael@0 7 #include "nsXPCOMPrivate.h" // for XP MAXPATHLEN
michael@0 8 #include "nsXULAppAPI.h"
michael@0 9 #include "nsIFile.h"
michael@0 10
michael@0 11 #include <stdarg.h>
michael@0 12
michael@0 13 #ifdef XP_WIN
michael@0 14 #include <windows.h>
michael@0 15 #include <io.h>
michael@0 16 #define snprintf _snprintf
michael@0 17 #define vsnprintf _vsnprintf
michael@0 18 #define strcasecmp _stricmp
michael@0 19 #define PATH_SEPARATOR_CHAR '\\'
michael@0 20 #define R_OK 04
michael@0 21 #elif defined(XP_MACOSX)
michael@0 22 #include <unistd.h>
michael@0 23 #include <sys/stat.h>
michael@0 24 #include <CoreFoundation/CoreFoundation.h>
michael@0 25 #define PATH_SEPARATOR_CHAR '/'
michael@0 26 #else
michael@0 27 #include <unistd.h>
michael@0 28 #include <sys/types.h>
michael@0 29 #include <sys/stat.h>
michael@0 30 #define PATH_SEPARATOR_CHAR '/'
michael@0 31 #endif
michael@0 32
michael@0 33 #ifdef XP_WIN
michael@0 34 #define XRE_DONT_PROTECT_DLL_LOAD
michael@0 35 #include "nsWindowsWMain.cpp"
michael@0 36 #endif
michael@0 37
michael@0 38 #define VERSION_MAXLEN 128
michael@0 39
michael@0 40 static void Output(bool isError, const char *fmt, ... )
michael@0 41 {
michael@0 42 va_list ap;
michael@0 43 va_start(ap, fmt);
michael@0 44
michael@0 45 #if (defined(XP_WIN) && !MOZ_WINCONSOLE)
michael@0 46 char msg[2048];
michael@0 47
michael@0 48 vsnprintf(msg, sizeof(msg), fmt, ap);
michael@0 49
michael@0 50 UINT flags = MB_OK;
michael@0 51 if (isError)
michael@0 52 flags |= MB_ICONERROR;
michael@0 53 else
michael@0 54 flags |= MB_ICONINFORMATION;
michael@0 55
michael@0 56 wchar_t wide_msg[1024];
michael@0 57 MultiByteToWideChar(CP_ACP,
michael@0 58 0,
michael@0 59 msg,
michael@0 60 -1,
michael@0 61 wide_msg,
michael@0 62 sizeof(wide_msg) / sizeof(wchar_t));
michael@0 63
michael@0 64 MessageBoxW(nullptr, wide_msg, L"XULRunner", flags);
michael@0 65 #else
michael@0 66 vfprintf(stderr, fmt, ap);
michael@0 67 #endif
michael@0 68
michael@0 69 va_end(ap);
michael@0 70 }
michael@0 71
michael@0 72 /**
michael@0 73 * Return true if |arg| matches the given argument name.
michael@0 74 */
michael@0 75 static bool IsArg(const char* arg, const char* s)
michael@0 76 {
michael@0 77 if (*arg == '-')
michael@0 78 {
michael@0 79 if (*++arg == '-')
michael@0 80 ++arg;
michael@0 81 return !strcasecmp(arg, s);
michael@0 82 }
michael@0 83
michael@0 84 #if defined(XP_WIN)
michael@0 85 if (*arg == '/')
michael@0 86 return !strcasecmp(++arg, s);
michael@0 87 #endif
michael@0 88
michael@0 89 return false;
michael@0 90 }
michael@0 91
michael@0 92 /**
michael@0 93 * Return true if |aDir| is a valid file/directory.
michael@0 94 */
michael@0 95 static bool FolderExists(const char* aDir)
michael@0 96 {
michael@0 97 #ifdef XP_WIN
michael@0 98 wchar_t wideDir[MAX_PATH];
michael@0 99 MultiByteToWideChar(CP_UTF8, 0, aDir, -1, wideDir, MAX_PATH);
michael@0 100 DWORD fileAttrs = GetFileAttributesW(wideDir);
michael@0 101 return fileAttrs != INVALID_FILE_ATTRIBUTES;
michael@0 102 #else
michael@0 103 return access(aDir, R_OK) == 0;
michael@0 104 #endif
michael@0 105 }
michael@0 106
michael@0 107 static nsresult GetRealPath(const char* appDataFile, char* *aResult)
michael@0 108 {
michael@0 109 #ifdef XP_WIN
michael@0 110 wchar_t wAppDataFile[MAX_PATH];
michael@0 111 wchar_t wIniPath[MAX_PATH];
michael@0 112 MultiByteToWideChar(CP_UTF8, 0, appDataFile, -1, wAppDataFile, MAX_PATH);
michael@0 113 _wfullpath(wIniPath, wAppDataFile, MAX_PATH);
michael@0 114 WideCharToMultiByte(CP_UTF8, 0, wIniPath, -1, *aResult, MAX_PATH, 0, 0);
michael@0 115 #else
michael@0 116 struct stat fileStat;
michael@0 117 if (!realpath(appDataFile, *aResult) || stat(*aResult, &fileStat))
michael@0 118 return NS_ERROR_FAILURE;
michael@0 119 #endif
michael@0 120 if (!*aResult || !**aResult)
michael@0 121 return NS_ERROR_FAILURE;
michael@0 122
michael@0 123 return NS_OK;
michael@0 124 }
michael@0 125
michael@0 126 class AutoAppData
michael@0 127 {
michael@0 128 public:
michael@0 129 AutoAppData(nsIFile* aINIFile) : mAppData(nullptr) {
michael@0 130 nsresult rv = XRE_CreateAppData(aINIFile, &mAppData);
michael@0 131 if (NS_FAILED(rv))
michael@0 132 mAppData = nullptr;
michael@0 133 }
michael@0 134 ~AutoAppData() {
michael@0 135 if (mAppData)
michael@0 136 XRE_FreeAppData(mAppData);
michael@0 137 }
michael@0 138
michael@0 139 operator nsXREAppData*() const { return mAppData; }
michael@0 140 nsXREAppData* operator -> () const { return mAppData; }
michael@0 141
michael@0 142 private:
michael@0 143 nsXREAppData* mAppData;
michael@0 144 };
michael@0 145
michael@0 146 XRE_CreateAppDataType XRE_CreateAppData;
michael@0 147 XRE_FreeAppDataType XRE_FreeAppData;
michael@0 148 XRE_mainType XRE_main;
michael@0 149
michael@0 150 int
michael@0 151 main(int argc, char **argv)
michael@0 152 {
michael@0 153 nsresult rv;
michael@0 154 char *lastSlash;
michael@0 155
michael@0 156 char iniPath[MAXPATHLEN];
michael@0 157 char tmpPath[MAXPATHLEN];
michael@0 158 char greDir[MAXPATHLEN];
michael@0 159 bool greFound = false;
michael@0 160
michael@0 161 #if defined(XP_MACOSX)
michael@0 162 CFBundleRef appBundle = CFBundleGetMainBundle();
michael@0 163 if (!appBundle)
michael@0 164 return 1;
michael@0 165
michael@0 166 CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(appBundle);
michael@0 167 if (!resourcesURL)
michael@0 168 return 1;
michael@0 169
michael@0 170 CFURLRef absResourcesURL = CFURLCopyAbsoluteURL(resourcesURL);
michael@0 171 CFRelease(resourcesURL);
michael@0 172 if (!absResourcesURL)
michael@0 173 return 1;
michael@0 174
michael@0 175 CFURLRef iniFileURL =
michael@0 176 CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,
michael@0 177 absResourcesURL,
michael@0 178 CFSTR("application.ini"),
michael@0 179 false);
michael@0 180 CFRelease(absResourcesURL);
michael@0 181 if (!iniFileURL)
michael@0 182 return 1;
michael@0 183
michael@0 184 CFStringRef iniPathStr =
michael@0 185 CFURLCopyFileSystemPath(iniFileURL, kCFURLPOSIXPathStyle);
michael@0 186 CFRelease(iniFileURL);
michael@0 187 if (!iniPathStr)
michael@0 188 return 1;
michael@0 189
michael@0 190 CFStringGetCString(iniPathStr, iniPath, sizeof(iniPath),
michael@0 191 kCFStringEncodingUTF8);
michael@0 192 CFRelease(iniPathStr);
michael@0 193
michael@0 194 #else
michael@0 195
michael@0 196 #ifdef XP_WIN
michael@0 197 wchar_t wide_path[MAX_PATH];
michael@0 198 if (!::GetModuleFileNameW(nullptr, wide_path, MAX_PATH))
michael@0 199 return 1;
michael@0 200
michael@0 201 WideCharToMultiByte(CP_UTF8, 0, wide_path,-1,
michael@0 202 iniPath, MAX_PATH, nullptr, nullptr);
michael@0 203
michael@0 204 #else
michael@0 205 // on unix, there is no official way to get the path of the current binary.
michael@0 206 // instead of using the MOZILLA_FIVE_HOME hack, which doesn't scale to
michael@0 207 // multiple applications, we will try a series of techniques:
michael@0 208 //
michael@0 209 // 1) use realpath() on argv[0], which works unless we're loaded from the
michael@0 210 // PATH
michael@0 211 // 2) manually walk through the PATH and look for ourself
michael@0 212 // 3) give up
michael@0 213
michael@0 214 struct stat fileStat;
michael@0 215 strncpy(tmpPath, argv[0], sizeof(tmpPath));
michael@0 216 lastSlash = strrchr(tmpPath, '/');
michael@0 217 if (lastSlash) {
michael@0 218 *lastSlash = 0;
michael@0 219 realpath(tmpPath, iniPath);
michael@0 220 } else {
michael@0 221 const char *path = getenv("PATH");
michael@0 222 if (!path)
michael@0 223 return 1;
michael@0 224
michael@0 225 char *pathdup = strdup(path);
michael@0 226 if (!pathdup)
michael@0 227 return 1;
michael@0 228
michael@0 229 bool found = false;
michael@0 230 char *token = strtok(pathdup, ":");
michael@0 231 while (token) {
michael@0 232 sprintf(tmpPath, "%s/%s", token, argv[0]);
michael@0 233 if (stat(tmpPath, &fileStat) == 0) {
michael@0 234 found = true;
michael@0 235 lastSlash = strrchr(tmpPath, '/');
michael@0 236 *lastSlash = 0;
michael@0 237 realpath(tmpPath, iniPath);
michael@0 238 break;
michael@0 239 }
michael@0 240 token = strtok(nullptr, ":");
michael@0 241 }
michael@0 242 free (pathdup);
michael@0 243 if (!found)
michael@0 244 return 1;
michael@0 245 }
michael@0 246 lastSlash = iniPath + strlen(iniPath);
michael@0 247 *lastSlash = '/';
michael@0 248 #endif
michael@0 249
michael@0 250 #ifndef XP_UNIX
michael@0 251 lastSlash = strrchr(iniPath, PATH_SEPARATOR_CHAR);
michael@0 252 if (!lastSlash)
michael@0 253 return 1;
michael@0 254 #endif
michael@0 255
michael@0 256 *(++lastSlash) = '\0';
michael@0 257
michael@0 258 // On Linux/Win, look for XULRunner in appdir/xulrunner
michael@0 259
michael@0 260 snprintf(greDir, sizeof(greDir),
michael@0 261 "%sxulrunner" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL,
michael@0 262 iniPath);
michael@0 263
michael@0 264 greFound = FolderExists(greDir);
michael@0 265
michael@0 266 #ifdef XP_UNIX
michael@0 267 if (greFound) {
michael@0 268 char resolved_greDir[MAXPATHLEN] = "";
michael@0 269 if (realpath(greDir, resolved_greDir) && *resolved_greDir) {
michael@0 270 strncpy(greDir, resolved_greDir, MAXPATHLEN);
michael@0 271 }
michael@0 272 }
michael@0 273 #endif
michael@0 274
michael@0 275 strncpy(lastSlash, "application.ini", sizeof(iniPath) - (lastSlash - iniPath));
michael@0 276
michael@0 277 #endif
michael@0 278
michael@0 279 // If -app parameter was passed in, it is now time to take it under
michael@0 280 // consideration.
michael@0 281 const char *appDataFile;
michael@0 282 appDataFile = getenv("XUL_APP_FILE");
michael@0 283 if (!appDataFile || !*appDataFile)
michael@0 284 if (argc > 1 && IsArg(argv[1], "app")) {
michael@0 285 if (argc == 2) {
michael@0 286 Output(false, "specify APP-FILE (optional)\n");
michael@0 287 return 1;
michael@0 288 }
michael@0 289 argv[1] = argv[0];
michael@0 290 ++argv;
michael@0 291 --argc;
michael@0 292
michael@0 293 appDataFile = argv[1];
michael@0 294 argv[1] = argv[0];
michael@0 295 ++argv;
michael@0 296 --argc;
michael@0 297
michael@0 298 char kAppEnv[MAXPATHLEN];
michael@0 299 snprintf(kAppEnv, MAXPATHLEN, "XUL_APP_FILE=%s", appDataFile);
michael@0 300 if (putenv(kAppEnv))
michael@0 301 Output(false, "Couldn't set %s.\n", kAppEnv);
michael@0 302
michael@0 303 char *result = (char*) calloc(sizeof(char), MAXPATHLEN);
michael@0 304 if (NS_FAILED(GetRealPath(appDataFile, &result))) {
michael@0 305 Output(true, "Invalid application.ini path.\n");
michael@0 306 return 1;
michael@0 307 }
michael@0 308
michael@0 309 // We have a valid application.ini path passed in to the -app parameter
michael@0 310 // but not yet a valid greDir, so lets look for it also on the same folder
michael@0 311 // as the stub.
michael@0 312 if (!greFound) {
michael@0 313 lastSlash = strrchr(iniPath, PATH_SEPARATOR_CHAR);
michael@0 314 if (!lastSlash)
michael@0 315 return 1;
michael@0 316
michael@0 317 *(++lastSlash) = '\0';
michael@0 318
michael@0 319 snprintf(greDir, sizeof(greDir), "%s" XPCOM_DLL, iniPath);
michael@0 320 greFound = FolderExists(greDir);
michael@0 321 }
michael@0 322
michael@0 323 // copy it back.
michael@0 324 strcpy(iniPath, result);
michael@0 325 }
michael@0 326
michael@0 327 nsINIParser parser;
michael@0 328 rv = parser.Init(iniPath);
michael@0 329 if (NS_FAILED(rv)) {
michael@0 330 fprintf(stderr, "Could not read application.ini\n");
michael@0 331 return 1;
michael@0 332 }
michael@0 333
michael@0 334 if (!greFound) {
michael@0 335 #ifdef XP_MACOSX
michael@0 336 // Check for <bundle>/Contents/Frameworks/XUL.framework/Versions/Current/libmozglue.dylib
michael@0 337 CFURLRef fwurl = CFBundleCopyPrivateFrameworksURL(appBundle);
michael@0 338 CFURLRef absfwurl = nullptr;
michael@0 339 if (fwurl) {
michael@0 340 absfwurl = CFURLCopyAbsoluteURL(fwurl);
michael@0 341 CFRelease(fwurl);
michael@0 342 }
michael@0 343
michael@0 344 if (absfwurl) {
michael@0 345 CFURLRef xulurl =
michael@0 346 CFURLCreateCopyAppendingPathComponent(nullptr, absfwurl,
michael@0 347 CFSTR("XUL.framework/Versions/Current"),
michael@0 348 true);
michael@0 349
michael@0 350 if (xulurl) {
michael@0 351 CFURLRef xpcomurl =
michael@0 352 CFURLCreateCopyAppendingPathComponent(nullptr, xulurl,
michael@0 353 CFSTR("libmozglue.dylib"),
michael@0 354 false);
michael@0 355
michael@0 356 if (xpcomurl) {
michael@0 357 char tbuffer[MAXPATHLEN];
michael@0 358
michael@0 359 if (CFURLGetFileSystemRepresentation(xpcomurl, true,
michael@0 360 (UInt8*) tbuffer,
michael@0 361 sizeof(tbuffer)) &&
michael@0 362 access(tbuffer, R_OK | X_OK) == 0) {
michael@0 363 if (realpath(tbuffer, greDir)) {
michael@0 364 greFound = true;
michael@0 365 }
michael@0 366 else {
michael@0 367 greDir[0] = '\0';
michael@0 368 }
michael@0 369 }
michael@0 370
michael@0 371 CFRelease(xpcomurl);
michael@0 372 }
michael@0 373
michael@0 374 CFRelease(xulurl);
michael@0 375 }
michael@0 376
michael@0 377 CFRelease(absfwurl);
michael@0 378 }
michael@0 379 #endif
michael@0 380 if (!greFound) {
michael@0 381 Output(false, "Could not find the Mozilla runtime.\n");
michael@0 382 return 1;
michael@0 383 }
michael@0 384 }
michael@0 385
michael@0 386 rv = XPCOMGlueStartup(greDir);
michael@0 387 if (NS_FAILED(rv)) {
michael@0 388 if (rv == NS_ERROR_OUT_OF_MEMORY) {
michael@0 389 char applicationName[2000] = "this application";
michael@0 390 parser.GetString("App", "Name", applicationName, sizeof(applicationName));
michael@0 391 Output(true, "Not enough memory available to start %s.\n",
michael@0 392 applicationName);
michael@0 393 } else {
michael@0 394 Output(true, "Couldn't load XPCOM.\n");
michael@0 395 }
michael@0 396 return 1;
michael@0 397 }
michael@0 398
michael@0 399 static const nsDynamicFunctionLoad kXULFuncs[] = {
michael@0 400 { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
michael@0 401 { "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
michael@0 402 { "XRE_main", (NSFuncPtr*) &XRE_main },
michael@0 403 { nullptr, nullptr }
michael@0 404 };
michael@0 405
michael@0 406 rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
michael@0 407 if (NS_FAILED(rv)) {
michael@0 408 Output(true, "Couldn't load XRE functions.\n");
michael@0 409 return 1;
michael@0 410 }
michael@0 411
michael@0 412 NS_LogInit();
michael@0 413
michael@0 414 int retval;
michael@0 415
michael@0 416 { // Scope COMPtr and AutoAppData
michael@0 417 nsCOMPtr<nsIFile> iniFile;
michael@0 418 #ifdef XP_WIN
michael@0 419 // On Windows iniPath is UTF-8 encoded so we need to convert it.
michael@0 420 rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(iniPath), false,
michael@0 421 getter_AddRefs(iniFile));
michael@0 422 #else
michael@0 423 rv = NS_NewNativeLocalFile(nsDependentCString(iniPath), false,
michael@0 424 getter_AddRefs(iniFile));
michael@0 425 #endif
michael@0 426 if (NS_FAILED(rv)) {
michael@0 427 Output(true, "Couldn't find application.ini file.\n");
michael@0 428 return 1;
michael@0 429 }
michael@0 430
michael@0 431 AutoAppData appData(iniFile);
michael@0 432 if (!appData) {
michael@0 433 Output(true, "Error: couldn't parse application.ini.\n");
michael@0 434 return 1;
michael@0 435 }
michael@0 436
michael@0 437 NS_ASSERTION(appData->directory, "Failed to get app directory.");
michael@0 438
michael@0 439 if (!appData->xreDirectory) {
michael@0 440 // chop "libxul.so" off the GRE path
michael@0 441 lastSlash = strrchr(greDir, PATH_SEPARATOR_CHAR);
michael@0 442 if (lastSlash) {
michael@0 443 *lastSlash = '\0';
michael@0 444 }
michael@0 445 #ifdef XP_WIN
michael@0 446 // same as iniPath.
michael@0 447 NS_NewLocalFile(NS_ConvertUTF8toUTF16(greDir), false,
michael@0 448 &appData->xreDirectory);
michael@0 449 #else
michael@0 450 NS_NewNativeLocalFile(nsDependentCString(greDir), false,
michael@0 451 &appData->xreDirectory);
michael@0 452 #endif
michael@0 453 }
michael@0 454
michael@0 455 retval = XRE_main(argc, argv, appData, 0);
michael@0 456 }
michael@0 457
michael@0 458 NS_LogTerm();
michael@0 459
michael@0 460 return retval;
michael@0 461 }

mercurial