LCOV - code coverage report
Current view: top level - browser/app - nsBrowserApp.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 34 67 50.7 %
Date: 2017-07-14 16:53:18 Functions: 6 7 85.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "nsXULAppAPI.h"
       7             : #include "mozilla/XREAppData.h"
       8             : #include "application.ini.h"
       9             : #include "mozilla/Bootstrap.h"
      10             : #if defined(XP_WIN)
      11             : #include <windows.h>
      12             : #include <stdlib.h>
      13             : #elif defined(XP_UNIX)
      14             : #include <sys/resource.h>
      15             : #include <unistd.h>
      16             : #endif
      17             : 
      18             : #include <stdio.h>
      19             : #include <stdarg.h>
      20             : #include <time.h>
      21             : 
      22             : #include "nsCOMPtr.h"
      23             : #include "nsIFile.h"
      24             : 
      25             : #ifdef XP_WIN
      26             : #ifdef MOZ_ASAN
      27             : // ASAN requires firefox.exe to be built with -MD, and it's OK if we don't
      28             : // support Windows XP SP2 in ASAN builds.
      29             : #define XRE_DONT_SUPPORT_XPSP2
      30             : #endif
      31             : #define XRE_WANT_ENVIRON
      32             : #define strcasecmp _stricmp
      33             : #ifdef MOZ_SANDBOX
      34             : #include "mozilla/sandboxing/SandboxInitialization.h"
      35             : #endif
      36             : #endif
      37             : #include "BinaryPath.h"
      38             : 
      39             : #include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
      40             : 
      41             : #include "mozilla/Sprintf.h"
      42             : #include "mozilla/StartupTimeline.h"
      43             : #include "mozilla/WindowsDllBlocklist.h"
      44             : 
      45             : #ifdef LIBFUZZER
      46             : #include "FuzzerDefs.h"
      47             : #endif
      48             : 
      49             : #ifdef MOZ_LINUX_32_SSE2_STARTUP_ERROR
      50             : #include <cpuid.h>
      51             : #include "mozilla/Unused.h"
      52             : 
      53             : static bool
      54             : IsSSE2Available()
      55             : {
      56             :   // The rest of the app has been compiled to assume that SSE2 is present
      57             :   // unconditionally, so we can't use the normal copy of SSE.cpp here.
      58             :   // Since SSE.cpp caches the results and we need them only transiently,
      59             :   // instead of #including SSE.cpp here, let's just inline the specific check
      60             :   // that's needed.
      61             :   unsigned int level = 1u;
      62             :   unsigned int eax, ebx, ecx, edx;
      63             :   unsigned int bits = (1u<<26);
      64             :   unsigned int max = __get_cpuid_max(0, nullptr);
      65             :   if (level > max) {
      66             :     return false;
      67             :   }
      68             :   __cpuid_count(level, 0, eax, ebx, ecx, edx);
      69             :   return (edx & bits) == bits;
      70             : }
      71             : 
      72             : static const char sSSE2Message[] =
      73             :     "This browser version requires a processor with the SSE2 instruction "
      74             :     "set extension.\nYou may be able to obtain a version that does not "
      75             :     "require SSE2 from your Linux distribution.\n";
      76             : 
      77             : __attribute__((constructor))
      78             : static void
      79             : SSE2Check()
      80             : {
      81             :   if (IsSSE2Available()) {
      82             :     return;
      83             :   }
      84             :   // Using write() in order to avoid jemalloc-based buffering. Ignoring return
      85             :   // values, since there isn't much we could do on failure and there is no
      86             :   // point in trying to recover from errors.
      87             :   MOZ_UNUSED(write(STDERR_FILENO,
      88             :                    sSSE2Message,
      89             :                    MOZ_ARRAY_LENGTH(sSSE2Message) - 1));
      90             :   // _exit() instead of exit() to avoid running the usual "at exit" code.
      91             :   _exit(255);
      92             : }
      93             : #endif
      94             : 
      95             : #if !defined(MOZ_WIDGET_COCOA) && !defined(MOZ_WIDGET_ANDROID)
      96             : #define MOZ_BROWSER_CAN_BE_CONTENTPROC
      97             : #include "../../ipc/contentproc/plugin-container.cpp"
      98             : #endif
      99             : 
     100             : using namespace mozilla;
     101             : 
     102             : #ifdef XP_MACOSX
     103             : #define kOSXResourcesFolder "Resources"
     104             : #endif
     105             : #define kDesktopFolder "browser"
     106             : 
     107           0 : static MOZ_FORMAT_PRINTF(1, 2) void Output(const char *fmt, ... )
     108             : {
     109             :   va_list ap;
     110           0 :   va_start(ap, fmt);
     111             : 
     112             : #ifndef XP_WIN
     113           0 :   vfprintf(stderr, fmt, ap);
     114             : #else
     115             :   char msg[2048];
     116             :   vsnprintf_s(msg, _countof(msg), _TRUNCATE, fmt, ap);
     117             : 
     118             :   wchar_t wide_msg[2048];
     119             :   MultiByteToWideChar(CP_UTF8,
     120             :                       0,
     121             :                       msg,
     122             :                       -1,
     123             :                       wide_msg,
     124             :                       _countof(wide_msg));
     125             : #if MOZ_WINCONSOLE
     126             :   fwprintf_s(stderr, wide_msg);
     127             : #else
     128             :   // Linking user32 at load-time interferes with the DLL blocklist (bug 932100).
     129             :   // This is a rare codepath, so we can load user32 at run-time instead.
     130             :   HMODULE user32 = LoadLibraryW(L"user32.dll");
     131             :   if (user32) {
     132             :     decltype(MessageBoxW)* messageBoxW =
     133             :       (decltype(MessageBoxW)*) GetProcAddress(user32, "MessageBoxW");
     134             :     if (messageBoxW) {
     135             :       messageBoxW(nullptr, wide_msg, L"Firefox", MB_OK
     136             :                                                | MB_ICONERROR
     137             :                                                | MB_SETFOREGROUND);
     138             :     }
     139             :     FreeLibrary(user32);
     140             :   }
     141             : #endif
     142             : #endif
     143             : 
     144           0 :   va_end(ap);
     145           0 : }
     146             : 
     147             : /**
     148             :  * Return true if |arg| matches the given argument name.
     149             :  */
     150           5 : static bool IsArg(const char* arg, const char* s)
     151             : {
     152           5 :   if (*arg == '-')
     153             :   {
     154           5 :     if (*++arg == '-')
     155           3 :       ++arg;
     156           5 :     return !strcasecmp(arg, s);
     157             :   }
     158             : 
     159             : #if defined(XP_WIN)
     160             :   if (*arg == '/')
     161             :     return !strcasecmp(++arg, s);
     162             : #endif
     163             : 
     164           0 :   return false;
     165             : }
     166             : 
     167           3 : Bootstrap::UniquePtr gBootstrap;
     168             : 
     169           1 : static int do_main(int argc, char* argv[], char* envp[])
     170             : {
     171             :   // Allow firefox.exe to launch XULRunner apps via -app <application.ini>
     172             :   // Note that -app must be the *first* argument.
     173           1 :   const char *appDataFile = getenv("XUL_APP_FILE");
     174           1 :   if ((!appDataFile || !*appDataFile) &&
     175           1 :       (argc > 1 && IsArg(argv[1], "app"))) {
     176           0 :     if (argc == 2) {
     177           0 :       Output("Incorrect number of arguments passed to -app");
     178           0 :       return 255;
     179             :     }
     180           0 :     appDataFile = argv[2];
     181             : 
     182             :     char appEnv[MAXPATHLEN];
     183           0 :     SprintfLiteral(appEnv, "XUL_APP_FILE=%s", argv[2]);
     184           0 :     if (putenv(strdup(appEnv))) {
     185           0 :       Output("Couldn't set %s.\n", appEnv);
     186           0 :       return 255;
     187             :     }
     188           0 :     argv[2] = argv[0];
     189           0 :     argv += 2;
     190           0 :     argc -= 2;
     191           1 :   } else if (argc > 1 && IsArg(argv[1], "xpcshell")) {
     192           0 :     for (int i = 1; i < argc; i++) {
     193           0 :       argv[i] = argv[i + 1];
     194             :     }
     195             : 
     196             :     XREShellData shellData;
     197             : #if defined(XP_WIN) && defined(MOZ_SANDBOX)
     198             :     shellData.sandboxBrokerServices =
     199             :       sandboxing::GetInitializedBrokerServices();
     200             : #endif
     201             : 
     202           0 :     return gBootstrap->XRE_XPCShellMain(--argc, argv, envp, &shellData);
     203             :   }
     204             : 
     205             :   BootstrapConfig config;
     206             : 
     207           1 :   if (appDataFile && *appDataFile) {
     208           0 :     config.appData = nullptr;
     209           0 :     config.appDataPath = appDataFile;
     210             :   } else {
     211             :     // no -app flag so we use the compiled-in app data
     212           1 :     config.appData = &sAppData;
     213           1 :     config.appDataPath = kDesktopFolder;
     214             :   }
     215             : 
     216             : #if defined(XP_WIN) && defined(MOZ_SANDBOX)
     217             :   sandbox::BrokerServices* brokerServices =
     218             :     sandboxing::GetInitializedBrokerServices();
     219             :   sandboxing::PermissionsService* permissionsService =
     220             :     sandboxing::GetPermissionsService();
     221             : #if defined(MOZ_CONTENT_SANDBOX)
     222             :   if (!brokerServices) {
     223             :     Output("Couldn't initialize the broker services.\n");
     224             :     return 255;
     225             :   }
     226             : #endif
     227             :   config.sandboxBrokerServices = brokerServices;
     228             :   config.sandboxPermissionsService = permissionsService;
     229             : #endif
     230             : 
     231             : #ifdef LIBFUZZER
     232             :   if (getenv("LIBFUZZER"))
     233             :     gBootstrap->XRE_LibFuzzerSetDriver(fuzzer::FuzzerDriver);
     234             : #endif
     235             : 
     236           1 :   return gBootstrap->XRE_main(argc, argv, config);
     237             : }
     238             : 
     239             : static nsresult
     240           3 : InitXPCOMGlue(const char *argv0)
     241             : {
     242           6 :   UniqueFreePtr<char> exePath = BinaryPath::Get(argv0);
     243           3 :   if (!exePath) {
     244           0 :     Output("Couldn't find the application directory.\n");
     245           0 :     return NS_ERROR_FAILURE;
     246             :   }
     247             : 
     248           3 :   gBootstrap = mozilla::GetBootstrap(exePath.get());
     249           3 :   if (!gBootstrap) {
     250           0 :     Output("Couldn't load XPCOM.\n");
     251           0 :     return NS_ERROR_FAILURE;
     252             :   }
     253             : 
     254             :   // This will set this thread as the main thread.
     255           3 :   gBootstrap->NS_LogInit();
     256             : 
     257           3 :   return NS_OK;
     258             : }
     259             : 
     260           3 : int main(int argc, char* argv[], char* envp[])
     261             : {
     262           3 :   mozilla::TimeStamp start = mozilla::TimeStamp::Now();
     263             : 
     264             : #ifdef MOZ_BROWSER_CAN_BE_CONTENTPROC
     265             :   // We are launching as a content process, delegate to the appropriate
     266             :   // main
     267           3 :   if (argc > 1 && IsArg(argv[1], "contentproc")) {
     268             : #ifdef HAS_DLL_BLOCKLIST
     269             :     DllBlocklist_Initialize(eDllBlocklistInitFlagIsChildProcess);
     270             : #endif
     271             : #if defined(XP_WIN) && defined(MOZ_SANDBOX)
     272             :     // We need to initialize the sandbox TargetServices before InitXPCOMGlue
     273             :     // because we might need the sandbox broker to give access to some files.
     274             :     if (IsSandboxedProcess() && !sandboxing::GetInitializedTargetServices()) {
     275             :       Output("Failed to initialize the sandbox target services.");
     276             :       return 255;
     277             :     }
     278             : #endif
     279             : 
     280           2 :     nsresult rv = InitXPCOMGlue(argv[0]);
     281           2 :     if (NS_FAILED(rv)) {
     282           0 :       return 255;
     283             :     }
     284             : 
     285           2 :     int result = content_process_main(gBootstrap.get(), argc, argv);
     286             : 
     287             :     // InitXPCOMGlue calls NS_LogInit, so we need to balance it here.
     288           0 :     gBootstrap->NS_LogTerm();
     289             : 
     290           0 :     return result;
     291             :   }
     292             : #endif
     293             : 
     294             : #ifdef HAS_DLL_BLOCKLIST
     295             :   DllBlocklist_Initialize();
     296             : #endif
     297             : 
     298           1 :   nsresult rv = InitXPCOMGlue(argv[0]);
     299           1 :   if (NS_FAILED(rv)) {
     300           0 :     return 255;
     301             :   }
     302             : 
     303           1 :   gBootstrap->XRE_StartupTimelineRecord(mozilla::StartupTimeline::START, start);
     304             : 
     305             : #ifdef MOZ_BROWSER_CAN_BE_CONTENTPROC
     306           1 :   gBootstrap->XRE_EnableSameExecutableForContentProc();
     307             : #endif
     308             : 
     309           1 :   int result = do_main(argc, argv, envp);
     310             : 
     311           0 :   gBootstrap->NS_LogTerm();
     312             : 
     313             : #ifdef XP_MACOSX
     314             :   // Allow writes again. While we would like to catch writes from static
     315             :   // destructors to allow early exits to use _exit, we know that there is
     316             :   // at least one such write that we don't control (see bug 826029). For
     317             :   // now we enable writes again and early exits will have to use exit instead
     318             :   // of _exit.
     319             :   gBootstrap->XRE_StopLateWriteChecks();
     320             : #endif
     321             : 
     322           0 :   gBootstrap.reset();
     323             : 
     324           0 :   return result;
     325           9 : }

Generated by: LCOV version 1.13