michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsXULAppAPI.h" michael@0: #include "mozilla/AppData.h" michael@0: #include "application.ini.h" michael@0: #include "nsXPCOMGlue.h" michael@0: #if defined(XP_WIN) michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #elif defined(XP_UNIX) michael@0: #include michael@0: #include michael@0: #include michael@0: #endif michael@0: michael@0: #ifdef XP_MACOSX michael@0: #include michael@0: #include "MacQuirks.h" michael@0: #endif michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: #include "nsCOMPtr.h" michael@0: #include "nsIFile.h" michael@0: #include "nsStringGlue.h" michael@0: michael@0: // Easy access to a five second startup delay used to get michael@0: // a debugger attached in the metro environment. michael@0: // #define DEBUG_delay_start_metro michael@0: michael@0: #ifdef XP_WIN michael@0: // we want a wmain entry point michael@0: #include "nsWindowsWMain.cpp" michael@0: #define snprintf _snprintf michael@0: #define strcasecmp _stricmp michael@0: #endif michael@0: #include "BinaryPath.h" michael@0: michael@0: #include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL michael@0: michael@0: #include "mozilla/Telemetry.h" michael@0: #include "mozilla/WindowsDllBlocklist.h" michael@0: michael@0: using namespace mozilla; michael@0: michael@0: #define kDesktopFolder "browser" michael@0: #define kMetroFolder "metro" michael@0: #define kMetroAppIniFilename "metroapp.ini" michael@0: #ifdef XP_WIN michael@0: #define kMetroTestFile "tests.ini" michael@0: const char* kMetroConsoleIdParam = "testconsoleid="; michael@0: #endif michael@0: michael@0: static void Output(const char *fmt, ... ) michael@0: { michael@0: va_list ap; michael@0: va_start(ap, fmt); michael@0: michael@0: #ifndef XP_WIN michael@0: vfprintf(stderr, fmt, ap); michael@0: #else michael@0: char msg[2048]; michael@0: vsnprintf_s(msg, _countof(msg), _TRUNCATE, fmt, ap); michael@0: michael@0: wchar_t wide_msg[2048]; michael@0: MultiByteToWideChar(CP_UTF8, michael@0: 0, michael@0: msg, michael@0: -1, michael@0: wide_msg, michael@0: _countof(wide_msg)); michael@0: #if MOZ_WINCONSOLE michael@0: fwprintf_s(stderr, wide_msg); michael@0: #else michael@0: // Linking user32 at load-time interferes with the DLL blocklist (bug 932100). michael@0: // This is a rare codepath, so we can load user32 at run-time instead. michael@0: HMODULE user32 = LoadLibraryW(L"user32.dll"); michael@0: if (user32) { michael@0: decltype(MessageBoxW)* messageBoxW = michael@0: (decltype(MessageBoxW)*) GetProcAddress(user32, "MessageBoxW"); michael@0: if (messageBoxW) { michael@0: messageBoxW(nullptr, wide_msg, L"Firefox", MB_OK michael@0: | MB_ICONERROR michael@0: | MB_SETFOREGROUND); michael@0: } michael@0: FreeLibrary(user32); michael@0: } michael@0: #endif michael@0: #endif michael@0: michael@0: va_end(ap); michael@0: } michael@0: michael@0: /** michael@0: * Return true if |arg| matches the given argument name. michael@0: */ michael@0: static bool IsArg(const char* arg, const char* s) michael@0: { michael@0: if (*arg == '-') michael@0: { michael@0: if (*++arg == '-') michael@0: ++arg; michael@0: return !strcasecmp(arg, s); michael@0: } michael@0: michael@0: #if defined(XP_WIN) michael@0: if (*arg == '/') michael@0: return !strcasecmp(++arg, s); michael@0: #endif michael@0: michael@0: return false; michael@0: } michael@0: michael@0: #ifdef XP_WIN michael@0: /* michael@0: * AttachToTestHarness - Windows helper for when we are running michael@0: * in the immersive environment. Firefox is launched by Windows in michael@0: * response to a request by metrotestharness, which is launched by michael@0: * runtests.py. As such stdout in fx doesn't point to the right michael@0: * stream. This helper touches up stdout such that test output gets michael@0: * routed to a named pipe metrotestharness creates and dumps to its michael@0: * stdout. michael@0: */ michael@0: static void AttachToTestHarness() michael@0: { michael@0: // attach to the metrotestharness named logging pipe michael@0: HANDLE winOut = CreateFileA("\\\\.\\pipe\\metrotestharness", michael@0: GENERIC_WRITE, michael@0: FILE_SHARE_WRITE, 0, michael@0: OPEN_EXISTING, 0, 0); michael@0: michael@0: if (winOut == INVALID_HANDLE_VALUE) { michael@0: OutputDebugStringW(L"Could not create named logging pipe.\n"); michael@0: return; michael@0: } michael@0: michael@0: // Set the c runtime handle michael@0: int stdOut = _open_osfhandle((intptr_t)winOut, _O_APPEND); michael@0: if (stdOut == -1) { michael@0: OutputDebugStringW(L"Could not open c-runtime handle.\n"); michael@0: return; michael@0: } michael@0: FILE *fp = _fdopen(stdOut, "a"); michael@0: *stdout = *fp; michael@0: } michael@0: #endif michael@0: michael@0: XRE_GetFileFromPathType XRE_GetFileFromPath; michael@0: XRE_CreateAppDataType XRE_CreateAppData; michael@0: XRE_FreeAppDataType XRE_FreeAppData; michael@0: XRE_TelemetryAccumulateType XRE_TelemetryAccumulate; michael@0: XRE_StartupTimelineRecordType XRE_StartupTimelineRecord; michael@0: XRE_mainType XRE_main; michael@0: XRE_StopLateWriteChecksType XRE_StopLateWriteChecks; michael@0: michael@0: static const nsDynamicFunctionLoad kXULFuncs[] = { michael@0: { "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath }, michael@0: { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData }, michael@0: { "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData }, michael@0: { "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate }, michael@0: { "XRE_StartupTimelineRecord", (NSFuncPtr*) &XRE_StartupTimelineRecord }, michael@0: { "XRE_main", (NSFuncPtr*) &XRE_main }, michael@0: { "XRE_StopLateWriteChecks", (NSFuncPtr*) &XRE_StopLateWriteChecks }, michael@0: { nullptr, nullptr } michael@0: }; michael@0: michael@0: static int do_main(int argc, char* argv[], nsIFile *xreDirectory) michael@0: { michael@0: nsCOMPtr appini; michael@0: nsresult rv; michael@0: uint32_t mainFlags = 0; michael@0: michael@0: // Allow firefox.exe to launch XULRunner apps via -app michael@0: // Note that -app must be the *first* argument. michael@0: const char *appDataFile = getenv("XUL_APP_FILE"); michael@0: if (appDataFile && *appDataFile) { michael@0: rv = XRE_GetFileFromPath(appDataFile, getter_AddRefs(appini)); michael@0: if (NS_FAILED(rv)) { michael@0: Output("Invalid path found: '%s'", appDataFile); michael@0: return 255; michael@0: } michael@0: } michael@0: else if (argc > 1 && IsArg(argv[1], "app")) { michael@0: if (argc == 2) { michael@0: Output("Incorrect number of arguments passed to -app"); michael@0: return 255; michael@0: } michael@0: michael@0: rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(appini)); michael@0: if (NS_FAILED(rv)) { michael@0: Output("application.ini path not recognized: '%s'", argv[2]); michael@0: return 255; michael@0: } michael@0: michael@0: char appEnv[MAXPATHLEN]; michael@0: snprintf(appEnv, MAXPATHLEN, "XUL_APP_FILE=%s", argv[2]); michael@0: if (putenv(appEnv)) { michael@0: Output("Couldn't set %s.\n", appEnv); michael@0: return 255; michael@0: } michael@0: argv[2] = argv[0]; michael@0: argv += 2; michael@0: argc -= 2; michael@0: } michael@0: michael@0: if (appini) { michael@0: nsXREAppData *appData; michael@0: rv = XRE_CreateAppData(appini, &appData); michael@0: if (NS_FAILED(rv)) { michael@0: Output("Couldn't read application.ini"); michael@0: return 255; michael@0: } michael@0: // xreDirectory already has a refcount from NS_NewLocalFile michael@0: appData->xreDirectory = xreDirectory; michael@0: int result = XRE_main(argc, argv, appData, mainFlags); michael@0: XRE_FreeAppData(appData); michael@0: return result; michael@0: } michael@0: michael@0: bool metroOnDesktop = false; michael@0: michael@0: #ifdef MOZ_METRO michael@0: if (argc > 1) { michael@0: // This command-line flag is passed to our executable when it is to be michael@0: // launched in metro mode (i.e. our EXE is registered as the default michael@0: // browser and the user has tapped our EXE's tile) michael@0: if (IsArg(argv[1], "ServerName:DefaultBrowserServer")) { michael@0: mainFlags = XRE_MAIN_FLAG_USE_METRO; michael@0: argv[1] = argv[0]; michael@0: argv++; michael@0: argc--; michael@0: } else if (IsArg(argv[1], "BackgroundSessionClosed")) { michael@0: // This command line flag is used for indirect shutdowns, the OS michael@0: // relaunches Metro Firefox with this command line arg. michael@0: mainFlags = XRE_MAIN_FLAG_USE_METRO; michael@0: } else { michael@0: #ifndef RELEASE_BUILD michael@0: // This command-line flag is used to test the metro browser in a desktop michael@0: // environment. michael@0: for (int idx = 1; idx < argc; idx++) { michael@0: if (IsArg(argv[idx], "metrodesktop")) { michael@0: metroOnDesktop = true; michael@0: // Disable crash reporting when running in metrodesktop mode. michael@0: char crashSwitch[] = "MOZ_CRASHREPORTER_DISABLE=1"; michael@0: putenv(crashSwitch); michael@0: break; michael@0: } michael@0: } michael@0: #endif michael@0: } michael@0: } michael@0: #endif michael@0: michael@0: // Desktop browser launch michael@0: if (mainFlags != XRE_MAIN_FLAG_USE_METRO && !metroOnDesktop) { michael@0: ScopedAppData appData(&sAppData); michael@0: nsCOMPtr exeFile; michael@0: rv = mozilla::BinaryPath::GetFile(argv[0], getter_AddRefs(exeFile)); michael@0: if (NS_FAILED(rv)) { michael@0: Output("Couldn't find the application directory.\n"); michael@0: return 255; michael@0: } michael@0: michael@0: nsCOMPtr greDir; michael@0: exeFile->GetParent(getter_AddRefs(greDir)); michael@0: michael@0: nsCOMPtr appSubdir; michael@0: greDir->Clone(getter_AddRefs(appSubdir)); michael@0: appSubdir->Append(NS_LITERAL_STRING(kDesktopFolder)); michael@0: michael@0: SetStrongPtr(appData.directory, static_cast(appSubdir.get())); michael@0: // xreDirectory already has a refcount from NS_NewLocalFile michael@0: appData.xreDirectory = xreDirectory; michael@0: michael@0: return XRE_main(argc, argv, &appData, mainFlags); michael@0: } michael@0: michael@0: // Metro browser launch michael@0: #ifdef MOZ_METRO michael@0: nsCOMPtr iniFile, appSubdir; michael@0: michael@0: xreDirectory->Clone(getter_AddRefs(iniFile)); michael@0: xreDirectory->Clone(getter_AddRefs(appSubdir)); michael@0: michael@0: iniFile->Append(NS_LITERAL_STRING(kMetroFolder)); michael@0: iniFile->Append(NS_LITERAL_STRING(kMetroAppIniFilename)); michael@0: michael@0: appSubdir->Append(NS_LITERAL_STRING(kMetroFolder)); michael@0: michael@0: nsAutoCString path; michael@0: if (NS_FAILED(iniFile->GetNativePath(path))) { michael@0: Output("Couldn't get ini file path.\n"); michael@0: return 255; michael@0: } michael@0: michael@0: nsXREAppData *appData; michael@0: rv = XRE_CreateAppData(iniFile, &appData); michael@0: if (NS_FAILED(rv) || !appData) { michael@0: Output("Couldn't read application.ini"); michael@0: return 255; michael@0: } michael@0: michael@0: SetStrongPtr(appData->directory, static_cast(appSubdir.get())); michael@0: // xreDirectory already has a refcount from NS_NewLocalFile michael@0: appData->xreDirectory = xreDirectory; michael@0: michael@0: #ifdef XP_WIN michael@0: if (!metroOnDesktop) { michael@0: nsCOMPtr testFile; michael@0: michael@0: xreDirectory->Clone(getter_AddRefs(testFile)); michael@0: testFile->Append(NS_LITERAL_STRING(kMetroTestFile)); michael@0: michael@0: nsAutoCString path; michael@0: if (NS_FAILED(testFile->GetNativePath(path))) { michael@0: Output("Couldn't get test file path.\n"); michael@0: return 255; michael@0: } michael@0: michael@0: // Check for a metro test harness command line args file michael@0: HANDLE hTestFile = CreateFileA(path.get(), michael@0: GENERIC_READ, michael@0: 0, nullptr, OPEN_EXISTING, michael@0: FILE_ATTRIBUTE_NORMAL, michael@0: nullptr); michael@0: if (hTestFile != INVALID_HANDLE_VALUE) { michael@0: // Typical test harness command line args string is around 100 bytes. michael@0: char buffer[1024]; michael@0: memset(buffer, 0, sizeof(buffer)); michael@0: DWORD bytesRead = 0; michael@0: if (!ReadFile(hTestFile, (VOID*)buffer, sizeof(buffer)-1, michael@0: &bytesRead, nullptr) || !bytesRead) { michael@0: CloseHandle(hTestFile); michael@0: printf("failed to read test file '%s'", testFile); michael@0: return -1; michael@0: } michael@0: CloseHandle(hTestFile); michael@0: michael@0: // Build new args array michael@0: char* newArgv[20]; michael@0: int newArgc = 1; michael@0: michael@0: memset(newArgv, 0, sizeof(newArgv)); michael@0: michael@0: char* ptr = buffer; michael@0: newArgv[0] = ptr; michael@0: while (*ptr != '\0' && michael@0: (ptr - buffer) < sizeof(buffer) && michael@0: newArgc < ARRAYSIZE(newArgv)) { michael@0: if (isspace(*ptr)) { michael@0: *ptr = '\0'; michael@0: ptr++; michael@0: newArgv[newArgc] = ptr; michael@0: newArgc++; michael@0: continue; michael@0: } michael@0: ptr++; michael@0: } michael@0: if (ptr == newArgv[newArgc-1]) michael@0: newArgc--; michael@0: michael@0: // attach browser stdout to metrotestharness stdout michael@0: AttachToTestHarness(); michael@0: michael@0: int result = XRE_main(newArgc, newArgv, appData, mainFlags); michael@0: XRE_FreeAppData(appData); michael@0: return result; michael@0: } michael@0: } michael@0: #endif michael@0: michael@0: int result = XRE_main(argc, argv, appData, mainFlags); michael@0: XRE_FreeAppData(appData); michael@0: return result; michael@0: #endif michael@0: michael@0: NS_NOTREACHED("browser do_main failed to pickup proper initialization"); michael@0: return 255; michael@0: } michael@0: michael@0: #ifdef XP_WIN michael@0: michael@0: /** michael@0: * Used only when GetTickCount64 is not available on the platform. michael@0: * Last result of GetTickCount call. Kept in [ms]. michael@0: */ michael@0: static DWORD sLastGTCResult = 0; michael@0: michael@0: /** michael@0: * Higher part of the 64-bit value of MozGetTickCount64, michael@0: * incremented atomically. michael@0: */ michael@0: static DWORD sLastGTCRollover = 0; michael@0: michael@0: /** michael@0: * Function protecting GetTickCount result from rolling over. The original michael@0: * code comes from the Windows implementation of the TimeStamp class minus the michael@0: * locking harness which isn't needed here. michael@0: * michael@0: * @returns The current time in milliseconds michael@0: */ michael@0: static ULONGLONG WINAPI michael@0: MozGetTickCount64() michael@0: { michael@0: DWORD GTC = ::GetTickCount(); michael@0: michael@0: /* Pull the rollover counter forward only if new value of GTC goes way michael@0: * down under the last saved result */ michael@0: if ((sLastGTCResult > GTC) && ((sLastGTCResult - GTC) > (1UL << 30))) michael@0: ++sLastGTCRollover; michael@0: michael@0: sLastGTCResult = GTC; michael@0: return (ULONGLONG)sLastGTCRollover << 32 | sLastGTCResult; michael@0: } michael@0: michael@0: typedef ULONGLONG (WINAPI* GetTickCount64_t)(); michael@0: static GetTickCount64_t sGetTickCount64 = nullptr; michael@0: michael@0: #endif michael@0: michael@0: /** michael@0: * Local TimeStamp::Now()-compatible implementation used to record timestamps michael@0: * which will be passed to XRE_StartupTimelineRecord(). michael@0: */ michael@0: static uint64_t michael@0: TimeStamp_Now() michael@0: { michael@0: #ifdef XP_WIN michael@0: LARGE_INTEGER freq; michael@0: ::QueryPerformanceFrequency(&freq); michael@0: michael@0: HMODULE kernelDLL = GetModuleHandleW(L"kernel32.dll"); michael@0: sGetTickCount64 = reinterpret_cast michael@0: (GetProcAddress(kernelDLL, "GetTickCount64")); michael@0: michael@0: if (!sGetTickCount64) { michael@0: /* If the platform does not support the GetTickCount64 (Windows XP doesn't), michael@0: * then use our fallback implementation based on GetTickCount. */ michael@0: sGetTickCount64 = MozGetTickCount64; michael@0: } michael@0: michael@0: return sGetTickCount64() * freq.QuadPart; michael@0: #elif defined(XP_MACOSX) michael@0: return mach_absolute_time(); michael@0: #elif defined(HAVE_CLOCK_MONOTONIC) michael@0: struct timespec ts; michael@0: int rv = clock_gettime(CLOCK_MONOTONIC, &ts); michael@0: michael@0: if (rv != 0) { michael@0: return 0; michael@0: } michael@0: michael@0: uint64_t baseNs = (uint64_t)ts.tv_sec * 1000000000; michael@0: return baseNs + (uint64_t)ts.tv_nsec; michael@0: #endif michael@0: } michael@0: michael@0: static bool michael@0: FileExists(const char *path) michael@0: { michael@0: #ifdef XP_WIN michael@0: wchar_t wideDir[MAX_PATH]; michael@0: MultiByteToWideChar(CP_UTF8, 0, path, -1, wideDir, MAX_PATH); michael@0: DWORD fileAttrs = GetFileAttributesW(wideDir); michael@0: return fileAttrs != INVALID_FILE_ATTRIBUTES; michael@0: #else michael@0: return access(path, R_OK) == 0; michael@0: #endif michael@0: } michael@0: michael@0: #ifdef LIBXUL_SDK michael@0: # define XPCOM_PATH "xulrunner" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL michael@0: #else michael@0: # define XPCOM_PATH XPCOM_DLL michael@0: #endif michael@0: static nsresult michael@0: InitXPCOMGlue(const char *argv0, nsIFile **xreDirectory) michael@0: { michael@0: char exePath[MAXPATHLEN]; michael@0: michael@0: nsresult rv = mozilla::BinaryPath::Get(argv0, exePath); michael@0: if (NS_FAILED(rv)) { michael@0: Output("Couldn't find the application directory.\n"); michael@0: return rv; michael@0: } michael@0: michael@0: char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]); michael@0: if (!lastSlash || (size_t(lastSlash - exePath) > MAXPATHLEN - sizeof(XPCOM_PATH) - 1)) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: strcpy(lastSlash + 1, XPCOM_PATH); michael@0: lastSlash += sizeof(XPCOM_PATH) - sizeof(XPCOM_DLL); michael@0: michael@0: if (!FileExists(exePath)) { michael@0: #if defined(LIBXUL_SDK) && defined(XP_MACOSX) michael@0: // Check for /Contents/Frameworks/XUL.framework/libxpcom.dylib michael@0: bool greFound = false; michael@0: CFBundleRef appBundle = CFBundleGetMainBundle(); michael@0: if (!appBundle) michael@0: return NS_ERROR_FAILURE; michael@0: CFURLRef fwurl = CFBundleCopyPrivateFrameworksURL(appBundle); michael@0: CFURLRef absfwurl = nullptr; michael@0: if (fwurl) { michael@0: absfwurl = CFURLCopyAbsoluteURL(fwurl); michael@0: CFRelease(fwurl); michael@0: } michael@0: if (absfwurl) { michael@0: CFURLRef xulurl = michael@0: CFURLCreateCopyAppendingPathComponent(nullptr, absfwurl, michael@0: CFSTR("XUL.framework"), michael@0: true); michael@0: michael@0: if (xulurl) { michael@0: CFURLRef xpcomurl = michael@0: CFURLCreateCopyAppendingPathComponent(nullptr, xulurl, michael@0: CFSTR("libxpcom.dylib"), michael@0: false); michael@0: michael@0: if (xpcomurl) { michael@0: if (CFURLGetFileSystemRepresentation(xpcomurl, true, michael@0: (UInt8*) exePath, michael@0: sizeof(exePath)) && michael@0: access(tbuffer, R_OK | X_OK) == 0) { michael@0: if (realpath(tbuffer, exePath)) { michael@0: greFound = true; michael@0: } michael@0: } michael@0: CFRelease(xpcomurl); michael@0: } michael@0: CFRelease(xulurl); michael@0: } michael@0: CFRelease(absfwurl); michael@0: } michael@0: } michael@0: if (!greFound) { michael@0: #endif michael@0: Output("Could not find the Mozilla runtime.\n"); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: // We do this because of data in bug 771745 michael@0: XPCOMGlueEnablePreload(); michael@0: michael@0: rv = XPCOMGlueStartup(exePath); michael@0: if (NS_FAILED(rv)) { michael@0: Output("Couldn't load XPCOM.\n"); michael@0: return rv; michael@0: } michael@0: michael@0: rv = XPCOMGlueLoadXULFunctions(kXULFuncs); michael@0: if (NS_FAILED(rv)) { michael@0: Output("Couldn't load XRE functions.\n"); michael@0: return rv; michael@0: } michael@0: michael@0: NS_LogInit(); michael@0: michael@0: // chop XPCOM_DLL off exePath michael@0: *lastSlash = '\0'; michael@0: #ifdef XP_WIN michael@0: rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), false, michael@0: xreDirectory); michael@0: #else michael@0: rv = NS_NewNativeLocalFile(nsDependentCString(exePath), false, michael@0: xreDirectory); michael@0: #endif michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: int main(int argc, char* argv[]) michael@0: { michael@0: #ifdef DEBUG_delay_start_metro michael@0: Sleep(5000); michael@0: #endif michael@0: uint64_t start = TimeStamp_Now(); michael@0: michael@0: #ifdef XP_MACOSX michael@0: TriggerQuirks(); michael@0: #endif michael@0: michael@0: int gotCounters; michael@0: #if defined(XP_UNIX) michael@0: struct rusage initialRUsage; michael@0: gotCounters = !getrusage(RUSAGE_SELF, &initialRUsage); michael@0: #elif defined(XP_WIN) michael@0: IO_COUNTERS ioCounters; michael@0: gotCounters = GetProcessIoCounters(GetCurrentProcess(), &ioCounters); michael@0: #endif michael@0: michael@0: nsIFile *xreDirectory; michael@0: michael@0: #ifdef HAS_DLL_BLOCKLIST michael@0: DllBlocklist_Initialize(); michael@0: michael@0: #ifdef DEBUG michael@0: // In order to be effective against AppInit DLLs, the blocklist must be michael@0: // initialized before user32.dll is loaded into the process (bug 932100). michael@0: if (GetModuleHandleA("user32.dll")) { michael@0: fprintf(stderr, "DLL blocklist was unable to intercept AppInit DLLs.\n"); michael@0: } michael@0: #endif michael@0: #endif michael@0: michael@0: nsresult rv = InitXPCOMGlue(argv[0], &xreDirectory); michael@0: if (NS_FAILED(rv)) { michael@0: return 255; michael@0: } michael@0: michael@0: XRE_StartupTimelineRecord(mozilla::StartupTimeline::START, start); michael@0: michael@0: if (gotCounters) { michael@0: #if defined(XP_WIN) michael@0: XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_READ_OPS, michael@0: int(ioCounters.ReadOperationCount)); michael@0: XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_READ_TRANSFER, michael@0: int(ioCounters.ReadTransferCount / 1024)); michael@0: IO_COUNTERS newIoCounters; michael@0: if (GetProcessIoCounters(GetCurrentProcess(), &newIoCounters)) { michael@0: XRE_TelemetryAccumulate(mozilla::Telemetry::GLUESTARTUP_READ_OPS, michael@0: int(newIoCounters.ReadOperationCount - ioCounters.ReadOperationCount)); michael@0: XRE_TelemetryAccumulate(mozilla::Telemetry::GLUESTARTUP_READ_TRANSFER, michael@0: int((newIoCounters.ReadTransferCount - ioCounters.ReadTransferCount) / 1024)); michael@0: } michael@0: #elif defined(XP_UNIX) michael@0: XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_HARD_FAULTS, michael@0: int(initialRUsage.ru_majflt)); michael@0: struct rusage newRUsage; michael@0: if (!getrusage(RUSAGE_SELF, &newRUsage)) { michael@0: XRE_TelemetryAccumulate(mozilla::Telemetry::GLUESTARTUP_HARD_FAULTS, michael@0: int(newRUsage.ru_majflt - initialRUsage.ru_majflt)); michael@0: } michael@0: #endif michael@0: } michael@0: michael@0: int result = do_main(argc, argv, xreDirectory); michael@0: michael@0: NS_LogTerm(); michael@0: michael@0: #ifdef XP_MACOSX michael@0: // Allow writes again. While we would like to catch writes from static michael@0: // destructors to allow early exits to use _exit, we know that there is michael@0: // at least one such write that we don't control (see bug 826029). For michael@0: // now we enable writes again and early exits will have to use exit instead michael@0: // of _exit. michael@0: XRE_StopLateWriteChecks(); michael@0: #endif michael@0: michael@0: return result; michael@0: }