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

Generated by: LCOV version 1.13-14-ga5dd952