1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/app/nsBrowserApp.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,657 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 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 +#include "nsXULAppAPI.h" 1.10 +#include "mozilla/AppData.h" 1.11 +#include "application.ini.h" 1.12 +#include "nsXPCOMGlue.h" 1.13 +#if defined(XP_WIN) 1.14 +#include <windows.h> 1.15 +#include <stdlib.h> 1.16 +#include <io.h> 1.17 +#include <fcntl.h> 1.18 +#elif defined(XP_UNIX) 1.19 +#include <sys/resource.h> 1.20 +#include <time.h> 1.21 +#include <unistd.h> 1.22 +#endif 1.23 + 1.24 +#ifdef XP_MACOSX 1.25 +#include <mach/mach_time.h> 1.26 +#include "MacQuirks.h" 1.27 +#endif 1.28 + 1.29 +#include <stdio.h> 1.30 +#include <stdarg.h> 1.31 +#include <time.h> 1.32 + 1.33 +#include "nsCOMPtr.h" 1.34 +#include "nsIFile.h" 1.35 +#include "nsStringGlue.h" 1.36 + 1.37 +// Easy access to a five second startup delay used to get 1.38 +// a debugger attached in the metro environment. 1.39 +// #define DEBUG_delay_start_metro 1.40 + 1.41 +#ifdef XP_WIN 1.42 +// we want a wmain entry point 1.43 +#include "nsWindowsWMain.cpp" 1.44 +#define snprintf _snprintf 1.45 +#define strcasecmp _stricmp 1.46 +#endif 1.47 +#include "BinaryPath.h" 1.48 + 1.49 +#include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL 1.50 + 1.51 +#include "mozilla/Telemetry.h" 1.52 +#include "mozilla/WindowsDllBlocklist.h" 1.53 + 1.54 +using namespace mozilla; 1.55 + 1.56 +#define kDesktopFolder "browser" 1.57 +#define kMetroFolder "metro" 1.58 +#define kMetroAppIniFilename "metroapp.ini" 1.59 +#ifdef XP_WIN 1.60 +#define kMetroTestFile "tests.ini" 1.61 +const char* kMetroConsoleIdParam = "testconsoleid="; 1.62 +#endif 1.63 + 1.64 +static void Output(const char *fmt, ... ) 1.65 +{ 1.66 + va_list ap; 1.67 + va_start(ap, fmt); 1.68 + 1.69 +#ifndef XP_WIN 1.70 + vfprintf(stderr, fmt, ap); 1.71 +#else 1.72 + char msg[2048]; 1.73 + vsnprintf_s(msg, _countof(msg), _TRUNCATE, fmt, ap); 1.74 + 1.75 + wchar_t wide_msg[2048]; 1.76 + MultiByteToWideChar(CP_UTF8, 1.77 + 0, 1.78 + msg, 1.79 + -1, 1.80 + wide_msg, 1.81 + _countof(wide_msg)); 1.82 +#if MOZ_WINCONSOLE 1.83 + fwprintf_s(stderr, wide_msg); 1.84 +#else 1.85 + // Linking user32 at load-time interferes with the DLL blocklist (bug 932100). 1.86 + // This is a rare codepath, so we can load user32 at run-time instead. 1.87 + HMODULE user32 = LoadLibraryW(L"user32.dll"); 1.88 + if (user32) { 1.89 + decltype(MessageBoxW)* messageBoxW = 1.90 + (decltype(MessageBoxW)*) GetProcAddress(user32, "MessageBoxW"); 1.91 + if (messageBoxW) { 1.92 + messageBoxW(nullptr, wide_msg, L"Firefox", MB_OK 1.93 + | MB_ICONERROR 1.94 + | MB_SETFOREGROUND); 1.95 + } 1.96 + FreeLibrary(user32); 1.97 + } 1.98 +#endif 1.99 +#endif 1.100 + 1.101 + va_end(ap); 1.102 +} 1.103 + 1.104 +/** 1.105 + * Return true if |arg| matches the given argument name. 1.106 + */ 1.107 +static bool IsArg(const char* arg, const char* s) 1.108 +{ 1.109 + if (*arg == '-') 1.110 + { 1.111 + if (*++arg == '-') 1.112 + ++arg; 1.113 + return !strcasecmp(arg, s); 1.114 + } 1.115 + 1.116 +#if defined(XP_WIN) 1.117 + if (*arg == '/') 1.118 + return !strcasecmp(++arg, s); 1.119 +#endif 1.120 + 1.121 + return false; 1.122 +} 1.123 + 1.124 +#ifdef XP_WIN 1.125 +/* 1.126 + * AttachToTestHarness - Windows helper for when we are running 1.127 + * in the immersive environment. Firefox is launched by Windows in 1.128 + * response to a request by metrotestharness, which is launched by 1.129 + * runtests.py. As such stdout in fx doesn't point to the right 1.130 + * stream. This helper touches up stdout such that test output gets 1.131 + * routed to a named pipe metrotestharness creates and dumps to its 1.132 + * stdout. 1.133 + */ 1.134 +static void AttachToTestHarness() 1.135 +{ 1.136 + // attach to the metrotestharness named logging pipe 1.137 + HANDLE winOut = CreateFileA("\\\\.\\pipe\\metrotestharness", 1.138 + GENERIC_WRITE, 1.139 + FILE_SHARE_WRITE, 0, 1.140 + OPEN_EXISTING, 0, 0); 1.141 + 1.142 + if (winOut == INVALID_HANDLE_VALUE) { 1.143 + OutputDebugStringW(L"Could not create named logging pipe.\n"); 1.144 + return; 1.145 + } 1.146 + 1.147 + // Set the c runtime handle 1.148 + int stdOut = _open_osfhandle((intptr_t)winOut, _O_APPEND); 1.149 + if (stdOut == -1) { 1.150 + OutputDebugStringW(L"Could not open c-runtime handle.\n"); 1.151 + return; 1.152 + } 1.153 + FILE *fp = _fdopen(stdOut, "a"); 1.154 + *stdout = *fp; 1.155 +} 1.156 +#endif 1.157 + 1.158 +XRE_GetFileFromPathType XRE_GetFileFromPath; 1.159 +XRE_CreateAppDataType XRE_CreateAppData; 1.160 +XRE_FreeAppDataType XRE_FreeAppData; 1.161 +XRE_TelemetryAccumulateType XRE_TelemetryAccumulate; 1.162 +XRE_StartupTimelineRecordType XRE_StartupTimelineRecord; 1.163 +XRE_mainType XRE_main; 1.164 +XRE_StopLateWriteChecksType XRE_StopLateWriteChecks; 1.165 + 1.166 +static const nsDynamicFunctionLoad kXULFuncs[] = { 1.167 + { "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath }, 1.168 + { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData }, 1.169 + { "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData }, 1.170 + { "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate }, 1.171 + { "XRE_StartupTimelineRecord", (NSFuncPtr*) &XRE_StartupTimelineRecord }, 1.172 + { "XRE_main", (NSFuncPtr*) &XRE_main }, 1.173 + { "XRE_StopLateWriteChecks", (NSFuncPtr*) &XRE_StopLateWriteChecks }, 1.174 + { nullptr, nullptr } 1.175 +}; 1.176 + 1.177 +static int do_main(int argc, char* argv[], nsIFile *xreDirectory) 1.178 +{ 1.179 + nsCOMPtr<nsIFile> appini; 1.180 + nsresult rv; 1.181 + uint32_t mainFlags = 0; 1.182 + 1.183 + // Allow firefox.exe to launch XULRunner apps via -app <application.ini> 1.184 + // Note that -app must be the *first* argument. 1.185 + const char *appDataFile = getenv("XUL_APP_FILE"); 1.186 + if (appDataFile && *appDataFile) { 1.187 + rv = XRE_GetFileFromPath(appDataFile, getter_AddRefs(appini)); 1.188 + if (NS_FAILED(rv)) { 1.189 + Output("Invalid path found: '%s'", appDataFile); 1.190 + return 255; 1.191 + } 1.192 + } 1.193 + else if (argc > 1 && IsArg(argv[1], "app")) { 1.194 + if (argc == 2) { 1.195 + Output("Incorrect number of arguments passed to -app"); 1.196 + return 255; 1.197 + } 1.198 + 1.199 + rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(appini)); 1.200 + if (NS_FAILED(rv)) { 1.201 + Output("application.ini path not recognized: '%s'", argv[2]); 1.202 + return 255; 1.203 + } 1.204 + 1.205 + char appEnv[MAXPATHLEN]; 1.206 + snprintf(appEnv, MAXPATHLEN, "XUL_APP_FILE=%s", argv[2]); 1.207 + if (putenv(appEnv)) { 1.208 + Output("Couldn't set %s.\n", appEnv); 1.209 + return 255; 1.210 + } 1.211 + argv[2] = argv[0]; 1.212 + argv += 2; 1.213 + argc -= 2; 1.214 + } 1.215 + 1.216 + if (appini) { 1.217 + nsXREAppData *appData; 1.218 + rv = XRE_CreateAppData(appini, &appData); 1.219 + if (NS_FAILED(rv)) { 1.220 + Output("Couldn't read application.ini"); 1.221 + return 255; 1.222 + } 1.223 + // xreDirectory already has a refcount from NS_NewLocalFile 1.224 + appData->xreDirectory = xreDirectory; 1.225 + int result = XRE_main(argc, argv, appData, mainFlags); 1.226 + XRE_FreeAppData(appData); 1.227 + return result; 1.228 + } 1.229 + 1.230 + bool metroOnDesktop = false; 1.231 + 1.232 +#ifdef MOZ_METRO 1.233 + if (argc > 1) { 1.234 + // This command-line flag is passed to our executable when it is to be 1.235 + // launched in metro mode (i.e. our EXE is registered as the default 1.236 + // browser and the user has tapped our EXE's tile) 1.237 + if (IsArg(argv[1], "ServerName:DefaultBrowserServer")) { 1.238 + mainFlags = XRE_MAIN_FLAG_USE_METRO; 1.239 + argv[1] = argv[0]; 1.240 + argv++; 1.241 + argc--; 1.242 + } else if (IsArg(argv[1], "BackgroundSessionClosed")) { 1.243 + // This command line flag is used for indirect shutdowns, the OS 1.244 + // relaunches Metro Firefox with this command line arg. 1.245 + mainFlags = XRE_MAIN_FLAG_USE_METRO; 1.246 + } else { 1.247 +#ifndef RELEASE_BUILD 1.248 + // This command-line flag is used to test the metro browser in a desktop 1.249 + // environment. 1.250 + for (int idx = 1; idx < argc; idx++) { 1.251 + if (IsArg(argv[idx], "metrodesktop")) { 1.252 + metroOnDesktop = true; 1.253 + // Disable crash reporting when running in metrodesktop mode. 1.254 + char crashSwitch[] = "MOZ_CRASHREPORTER_DISABLE=1"; 1.255 + putenv(crashSwitch); 1.256 + break; 1.257 + } 1.258 + } 1.259 +#endif 1.260 + } 1.261 + } 1.262 +#endif 1.263 + 1.264 + // Desktop browser launch 1.265 + if (mainFlags != XRE_MAIN_FLAG_USE_METRO && !metroOnDesktop) { 1.266 + ScopedAppData appData(&sAppData); 1.267 + nsCOMPtr<nsIFile> exeFile; 1.268 + rv = mozilla::BinaryPath::GetFile(argv[0], getter_AddRefs(exeFile)); 1.269 + if (NS_FAILED(rv)) { 1.270 + Output("Couldn't find the application directory.\n"); 1.271 + return 255; 1.272 + } 1.273 + 1.274 + nsCOMPtr<nsIFile> greDir; 1.275 + exeFile->GetParent(getter_AddRefs(greDir)); 1.276 + 1.277 + nsCOMPtr<nsIFile> appSubdir; 1.278 + greDir->Clone(getter_AddRefs(appSubdir)); 1.279 + appSubdir->Append(NS_LITERAL_STRING(kDesktopFolder)); 1.280 + 1.281 + SetStrongPtr(appData.directory, static_cast<nsIFile*>(appSubdir.get())); 1.282 + // xreDirectory already has a refcount from NS_NewLocalFile 1.283 + appData.xreDirectory = xreDirectory; 1.284 + 1.285 + return XRE_main(argc, argv, &appData, mainFlags); 1.286 + } 1.287 + 1.288 + // Metro browser launch 1.289 +#ifdef MOZ_METRO 1.290 + nsCOMPtr<nsIFile> iniFile, appSubdir; 1.291 + 1.292 + xreDirectory->Clone(getter_AddRefs(iniFile)); 1.293 + xreDirectory->Clone(getter_AddRefs(appSubdir)); 1.294 + 1.295 + iniFile->Append(NS_LITERAL_STRING(kMetroFolder)); 1.296 + iniFile->Append(NS_LITERAL_STRING(kMetroAppIniFilename)); 1.297 + 1.298 + appSubdir->Append(NS_LITERAL_STRING(kMetroFolder)); 1.299 + 1.300 + nsAutoCString path; 1.301 + if (NS_FAILED(iniFile->GetNativePath(path))) { 1.302 + Output("Couldn't get ini file path.\n"); 1.303 + return 255; 1.304 + } 1.305 + 1.306 + nsXREAppData *appData; 1.307 + rv = XRE_CreateAppData(iniFile, &appData); 1.308 + if (NS_FAILED(rv) || !appData) { 1.309 + Output("Couldn't read application.ini"); 1.310 + return 255; 1.311 + } 1.312 + 1.313 + SetStrongPtr(appData->directory, static_cast<nsIFile*>(appSubdir.get())); 1.314 + // xreDirectory already has a refcount from NS_NewLocalFile 1.315 + appData->xreDirectory = xreDirectory; 1.316 + 1.317 +#ifdef XP_WIN 1.318 + if (!metroOnDesktop) { 1.319 + nsCOMPtr<nsIFile> testFile; 1.320 + 1.321 + xreDirectory->Clone(getter_AddRefs(testFile)); 1.322 + testFile->Append(NS_LITERAL_STRING(kMetroTestFile)); 1.323 + 1.324 + nsAutoCString path; 1.325 + if (NS_FAILED(testFile->GetNativePath(path))) { 1.326 + Output("Couldn't get test file path.\n"); 1.327 + return 255; 1.328 + } 1.329 + 1.330 + // Check for a metro test harness command line args file 1.331 + HANDLE hTestFile = CreateFileA(path.get(), 1.332 + GENERIC_READ, 1.333 + 0, nullptr, OPEN_EXISTING, 1.334 + FILE_ATTRIBUTE_NORMAL, 1.335 + nullptr); 1.336 + if (hTestFile != INVALID_HANDLE_VALUE) { 1.337 + // Typical test harness command line args string is around 100 bytes. 1.338 + char buffer[1024]; 1.339 + memset(buffer, 0, sizeof(buffer)); 1.340 + DWORD bytesRead = 0; 1.341 + if (!ReadFile(hTestFile, (VOID*)buffer, sizeof(buffer)-1, 1.342 + &bytesRead, nullptr) || !bytesRead) { 1.343 + CloseHandle(hTestFile); 1.344 + printf("failed to read test file '%s'", testFile); 1.345 + return -1; 1.346 + } 1.347 + CloseHandle(hTestFile); 1.348 + 1.349 + // Build new args array 1.350 + char* newArgv[20]; 1.351 + int newArgc = 1; 1.352 + 1.353 + memset(newArgv, 0, sizeof(newArgv)); 1.354 + 1.355 + char* ptr = buffer; 1.356 + newArgv[0] = ptr; 1.357 + while (*ptr != '\0' && 1.358 + (ptr - buffer) < sizeof(buffer) && 1.359 + newArgc < ARRAYSIZE(newArgv)) { 1.360 + if (isspace(*ptr)) { 1.361 + *ptr = '\0'; 1.362 + ptr++; 1.363 + newArgv[newArgc] = ptr; 1.364 + newArgc++; 1.365 + continue; 1.366 + } 1.367 + ptr++; 1.368 + } 1.369 + if (ptr == newArgv[newArgc-1]) 1.370 + newArgc--; 1.371 + 1.372 + // attach browser stdout to metrotestharness stdout 1.373 + AttachToTestHarness(); 1.374 + 1.375 + int result = XRE_main(newArgc, newArgv, appData, mainFlags); 1.376 + XRE_FreeAppData(appData); 1.377 + return result; 1.378 + } 1.379 + } 1.380 +#endif 1.381 + 1.382 + int result = XRE_main(argc, argv, appData, mainFlags); 1.383 + XRE_FreeAppData(appData); 1.384 + return result; 1.385 +#endif 1.386 + 1.387 + NS_NOTREACHED("browser do_main failed to pickup proper initialization"); 1.388 + return 255; 1.389 +} 1.390 + 1.391 +#ifdef XP_WIN 1.392 + 1.393 +/** 1.394 + * Used only when GetTickCount64 is not available on the platform. 1.395 + * Last result of GetTickCount call. Kept in [ms]. 1.396 + */ 1.397 +static DWORD sLastGTCResult = 0; 1.398 + 1.399 +/** 1.400 + * Higher part of the 64-bit value of MozGetTickCount64, 1.401 + * incremented atomically. 1.402 + */ 1.403 +static DWORD sLastGTCRollover = 0; 1.404 + 1.405 +/** 1.406 + * Function protecting GetTickCount result from rolling over. The original 1.407 + * code comes from the Windows implementation of the TimeStamp class minus the 1.408 + * locking harness which isn't needed here. 1.409 + * 1.410 + * @returns The current time in milliseconds 1.411 + */ 1.412 +static ULONGLONG WINAPI 1.413 +MozGetTickCount64() 1.414 +{ 1.415 + DWORD GTC = ::GetTickCount(); 1.416 + 1.417 + /* Pull the rollover counter forward only if new value of GTC goes way 1.418 + * down under the last saved result */ 1.419 + if ((sLastGTCResult > GTC) && ((sLastGTCResult - GTC) > (1UL << 30))) 1.420 + ++sLastGTCRollover; 1.421 + 1.422 + sLastGTCResult = GTC; 1.423 + return (ULONGLONG)sLastGTCRollover << 32 | sLastGTCResult; 1.424 +} 1.425 + 1.426 +typedef ULONGLONG (WINAPI* GetTickCount64_t)(); 1.427 +static GetTickCount64_t sGetTickCount64 = nullptr; 1.428 + 1.429 +#endif 1.430 + 1.431 +/** 1.432 + * Local TimeStamp::Now()-compatible implementation used to record timestamps 1.433 + * which will be passed to XRE_StartupTimelineRecord(). 1.434 + */ 1.435 +static uint64_t 1.436 +TimeStamp_Now() 1.437 +{ 1.438 +#ifdef XP_WIN 1.439 + LARGE_INTEGER freq; 1.440 + ::QueryPerformanceFrequency(&freq); 1.441 + 1.442 + HMODULE kernelDLL = GetModuleHandleW(L"kernel32.dll"); 1.443 + sGetTickCount64 = reinterpret_cast<GetTickCount64_t> 1.444 + (GetProcAddress(kernelDLL, "GetTickCount64")); 1.445 + 1.446 + if (!sGetTickCount64) { 1.447 + /* If the platform does not support the GetTickCount64 (Windows XP doesn't), 1.448 + * then use our fallback implementation based on GetTickCount. */ 1.449 + sGetTickCount64 = MozGetTickCount64; 1.450 + } 1.451 + 1.452 + return sGetTickCount64() * freq.QuadPart; 1.453 +#elif defined(XP_MACOSX) 1.454 + return mach_absolute_time(); 1.455 +#elif defined(HAVE_CLOCK_MONOTONIC) 1.456 + struct timespec ts; 1.457 + int rv = clock_gettime(CLOCK_MONOTONIC, &ts); 1.458 + 1.459 + if (rv != 0) { 1.460 + return 0; 1.461 + } 1.462 + 1.463 + uint64_t baseNs = (uint64_t)ts.tv_sec * 1000000000; 1.464 + return baseNs + (uint64_t)ts.tv_nsec; 1.465 +#endif 1.466 +} 1.467 + 1.468 +static bool 1.469 +FileExists(const char *path) 1.470 +{ 1.471 +#ifdef XP_WIN 1.472 + wchar_t wideDir[MAX_PATH]; 1.473 + MultiByteToWideChar(CP_UTF8, 0, path, -1, wideDir, MAX_PATH); 1.474 + DWORD fileAttrs = GetFileAttributesW(wideDir); 1.475 + return fileAttrs != INVALID_FILE_ATTRIBUTES; 1.476 +#else 1.477 + return access(path, R_OK) == 0; 1.478 +#endif 1.479 +} 1.480 + 1.481 +#ifdef LIBXUL_SDK 1.482 +# define XPCOM_PATH "xulrunner" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL 1.483 +#else 1.484 +# define XPCOM_PATH XPCOM_DLL 1.485 +#endif 1.486 +static nsresult 1.487 +InitXPCOMGlue(const char *argv0, nsIFile **xreDirectory) 1.488 +{ 1.489 + char exePath[MAXPATHLEN]; 1.490 + 1.491 + nsresult rv = mozilla::BinaryPath::Get(argv0, exePath); 1.492 + if (NS_FAILED(rv)) { 1.493 + Output("Couldn't find the application directory.\n"); 1.494 + return rv; 1.495 + } 1.496 + 1.497 + char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]); 1.498 + if (!lastSlash || (size_t(lastSlash - exePath) > MAXPATHLEN - sizeof(XPCOM_PATH) - 1)) 1.499 + return NS_ERROR_FAILURE; 1.500 + 1.501 + strcpy(lastSlash + 1, XPCOM_PATH); 1.502 + lastSlash += sizeof(XPCOM_PATH) - sizeof(XPCOM_DLL); 1.503 + 1.504 + if (!FileExists(exePath)) { 1.505 +#if defined(LIBXUL_SDK) && defined(XP_MACOSX) 1.506 + // Check for <bundle>/Contents/Frameworks/XUL.framework/libxpcom.dylib 1.507 + bool greFound = false; 1.508 + CFBundleRef appBundle = CFBundleGetMainBundle(); 1.509 + if (!appBundle) 1.510 + return NS_ERROR_FAILURE; 1.511 + CFURLRef fwurl = CFBundleCopyPrivateFrameworksURL(appBundle); 1.512 + CFURLRef absfwurl = nullptr; 1.513 + if (fwurl) { 1.514 + absfwurl = CFURLCopyAbsoluteURL(fwurl); 1.515 + CFRelease(fwurl); 1.516 + } 1.517 + if (absfwurl) { 1.518 + CFURLRef xulurl = 1.519 + CFURLCreateCopyAppendingPathComponent(nullptr, absfwurl, 1.520 + CFSTR("XUL.framework"), 1.521 + true); 1.522 + 1.523 + if (xulurl) { 1.524 + CFURLRef xpcomurl = 1.525 + CFURLCreateCopyAppendingPathComponent(nullptr, xulurl, 1.526 + CFSTR("libxpcom.dylib"), 1.527 + false); 1.528 + 1.529 + if (xpcomurl) { 1.530 + if (CFURLGetFileSystemRepresentation(xpcomurl, true, 1.531 + (UInt8*) exePath, 1.532 + sizeof(exePath)) && 1.533 + access(tbuffer, R_OK | X_OK) == 0) { 1.534 + if (realpath(tbuffer, exePath)) { 1.535 + greFound = true; 1.536 + } 1.537 + } 1.538 + CFRelease(xpcomurl); 1.539 + } 1.540 + CFRelease(xulurl); 1.541 + } 1.542 + CFRelease(absfwurl); 1.543 + } 1.544 + } 1.545 + if (!greFound) { 1.546 +#endif 1.547 + Output("Could not find the Mozilla runtime.\n"); 1.548 + return NS_ERROR_FAILURE; 1.549 + } 1.550 + 1.551 + // We do this because of data in bug 771745 1.552 + XPCOMGlueEnablePreload(); 1.553 + 1.554 + rv = XPCOMGlueStartup(exePath); 1.555 + if (NS_FAILED(rv)) { 1.556 + Output("Couldn't load XPCOM.\n"); 1.557 + return rv; 1.558 + } 1.559 + 1.560 + rv = XPCOMGlueLoadXULFunctions(kXULFuncs); 1.561 + if (NS_FAILED(rv)) { 1.562 + Output("Couldn't load XRE functions.\n"); 1.563 + return rv; 1.564 + } 1.565 + 1.566 + NS_LogInit(); 1.567 + 1.568 + // chop XPCOM_DLL off exePath 1.569 + *lastSlash = '\0'; 1.570 +#ifdef XP_WIN 1.571 + rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), false, 1.572 + xreDirectory); 1.573 +#else 1.574 + rv = NS_NewNativeLocalFile(nsDependentCString(exePath), false, 1.575 + xreDirectory); 1.576 +#endif 1.577 + 1.578 + return rv; 1.579 +} 1.580 + 1.581 +int main(int argc, char* argv[]) 1.582 +{ 1.583 +#ifdef DEBUG_delay_start_metro 1.584 + Sleep(5000); 1.585 +#endif 1.586 + uint64_t start = TimeStamp_Now(); 1.587 + 1.588 +#ifdef XP_MACOSX 1.589 + TriggerQuirks(); 1.590 +#endif 1.591 + 1.592 + int gotCounters; 1.593 +#if defined(XP_UNIX) 1.594 + struct rusage initialRUsage; 1.595 + gotCounters = !getrusage(RUSAGE_SELF, &initialRUsage); 1.596 +#elif defined(XP_WIN) 1.597 + IO_COUNTERS ioCounters; 1.598 + gotCounters = GetProcessIoCounters(GetCurrentProcess(), &ioCounters); 1.599 +#endif 1.600 + 1.601 + nsIFile *xreDirectory; 1.602 + 1.603 +#ifdef HAS_DLL_BLOCKLIST 1.604 + DllBlocklist_Initialize(); 1.605 + 1.606 +#ifdef DEBUG 1.607 + // In order to be effective against AppInit DLLs, the blocklist must be 1.608 + // initialized before user32.dll is loaded into the process (bug 932100). 1.609 + if (GetModuleHandleA("user32.dll")) { 1.610 + fprintf(stderr, "DLL blocklist was unable to intercept AppInit DLLs.\n"); 1.611 + } 1.612 +#endif 1.613 +#endif 1.614 + 1.615 + nsresult rv = InitXPCOMGlue(argv[0], &xreDirectory); 1.616 + if (NS_FAILED(rv)) { 1.617 + return 255; 1.618 + } 1.619 + 1.620 + XRE_StartupTimelineRecord(mozilla::StartupTimeline::START, start); 1.621 + 1.622 + if (gotCounters) { 1.623 +#if defined(XP_WIN) 1.624 + XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_READ_OPS, 1.625 + int(ioCounters.ReadOperationCount)); 1.626 + XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_READ_TRANSFER, 1.627 + int(ioCounters.ReadTransferCount / 1024)); 1.628 + IO_COUNTERS newIoCounters; 1.629 + if (GetProcessIoCounters(GetCurrentProcess(), &newIoCounters)) { 1.630 + XRE_TelemetryAccumulate(mozilla::Telemetry::GLUESTARTUP_READ_OPS, 1.631 + int(newIoCounters.ReadOperationCount - ioCounters.ReadOperationCount)); 1.632 + XRE_TelemetryAccumulate(mozilla::Telemetry::GLUESTARTUP_READ_TRANSFER, 1.633 + int((newIoCounters.ReadTransferCount - ioCounters.ReadTransferCount) / 1024)); 1.634 + } 1.635 +#elif defined(XP_UNIX) 1.636 + XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_HARD_FAULTS, 1.637 + int(initialRUsage.ru_majflt)); 1.638 + struct rusage newRUsage; 1.639 + if (!getrusage(RUSAGE_SELF, &newRUsage)) { 1.640 + XRE_TelemetryAccumulate(mozilla::Telemetry::GLUESTARTUP_HARD_FAULTS, 1.641 + int(newRUsage.ru_majflt - initialRUsage.ru_majflt)); 1.642 + } 1.643 +#endif 1.644 + } 1.645 + 1.646 + int result = do_main(argc, argv, xreDirectory); 1.647 + 1.648 + NS_LogTerm(); 1.649 + 1.650 +#ifdef XP_MACOSX 1.651 + // Allow writes again. While we would like to catch writes from static 1.652 + // destructors to allow early exits to use _exit, we know that there is 1.653 + // at least one such write that we don't control (see bug 826029). For 1.654 + // now we enable writes again and early exits will have to use exit instead 1.655 + // of _exit. 1.656 + XRE_StopLateWriteChecks(); 1.657 +#endif 1.658 + 1.659 + return result; 1.660 +}