1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/b2g/app/nsBrowserApp.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,260 @@ 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 "application.ini.h" 1.11 +#include "nsXPCOMGlue.h" 1.12 +#if defined(XP_WIN) 1.13 +#include <windows.h> 1.14 +#include <stdlib.h> 1.15 +#elif defined(XP_UNIX) 1.16 +#include <sys/time.h> 1.17 +#include <sys/resource.h> 1.18 +#include <unistd.h> 1.19 +#endif 1.20 + 1.21 +#include <stdio.h> 1.22 +#include <stdarg.h> 1.23 + 1.24 +#include "nsCOMPtr.h" 1.25 +#include "nsIFile.h" 1.26 +#include "nsStringGlue.h" 1.27 + 1.28 +#ifdef XP_WIN 1.29 +// we want a wmain entry point 1.30 +#include "nsWindowsWMain.cpp" 1.31 +#define snprintf _snprintf 1.32 +#define strcasecmp _stricmp 1.33 +#endif 1.34 + 1.35 +#ifdef MOZ_WIDGET_GONK 1.36 +#include "GonkDisplay.h" 1.37 +#endif 1.38 + 1.39 +#include "BinaryPath.h" 1.40 + 1.41 +#include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL 1.42 + 1.43 +#ifdef MOZ_WIDGET_GONK 1.44 +# include <binder/ProcessState.h> 1.45 +#endif 1.46 + 1.47 +#include "mozilla/Telemetry.h" 1.48 +#include "mozilla/WindowsDllBlocklist.h" 1.49 + 1.50 +static void Output(const char *fmt, ... ) 1.51 +{ 1.52 + va_list ap; 1.53 + va_start(ap, fmt); 1.54 + 1.55 +#if defined(XP_WIN) && !MOZ_WINCONSOLE 1.56 + char16_t msg[2048]; 1.57 + _vsnwprintf(msg, sizeof(msg)/sizeof(msg[0]), NS_ConvertUTF8toUTF16(fmt).get(), ap); 1.58 + MessageBoxW(nullptr, msg, L"XULRunner", MB_OK | MB_ICONERROR); 1.59 +#else 1.60 + vfprintf(stderr, fmt, ap); 1.61 +#endif 1.62 + 1.63 + va_end(ap); 1.64 +} 1.65 + 1.66 +/** 1.67 + * Return true if |arg| matches the given argument name. 1.68 + */ 1.69 +static bool IsArg(const char* arg, const char* s) 1.70 +{ 1.71 + if (*arg == '-') 1.72 + { 1.73 + if (*++arg == '-') 1.74 + ++arg; 1.75 + return !strcasecmp(arg, s); 1.76 + } 1.77 + 1.78 +#if defined(XP_WIN) 1.79 + if (*arg == '/') 1.80 + return !strcasecmp(++arg, s); 1.81 +#endif 1.82 + 1.83 + return false; 1.84 +} 1.85 + 1.86 +/** 1.87 + * A helper class which calls NS_LogInit/NS_LogTerm in its scope. 1.88 + */ 1.89 +class ScopedLogging 1.90 +{ 1.91 +public: 1.92 + ScopedLogging() { NS_LogInit(); } 1.93 + ~ScopedLogging() { NS_LogTerm(); } 1.94 +}; 1.95 + 1.96 +XRE_GetFileFromPathType XRE_GetFileFromPath; 1.97 +XRE_CreateAppDataType XRE_CreateAppData; 1.98 +XRE_FreeAppDataType XRE_FreeAppData; 1.99 +XRE_TelemetryAccumulateType XRE_TelemetryAccumulate; 1.100 +XRE_mainType XRE_main; 1.101 + 1.102 +static const nsDynamicFunctionLoad kXULFuncs[] = { 1.103 + { "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath }, 1.104 + { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData }, 1.105 + { "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData }, 1.106 + { "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate }, 1.107 + { "XRE_main", (NSFuncPtr*) &XRE_main }, 1.108 + { nullptr, nullptr } 1.109 +}; 1.110 + 1.111 +static int do_main(int argc, char* argv[]) 1.112 +{ 1.113 + nsCOMPtr<nsIFile> appini; 1.114 + nsresult rv; 1.115 + 1.116 + // Allow firefox.exe to launch XULRunner apps via -app <application.ini> 1.117 + // Note that -app must be the *first* argument. 1.118 + const char *appDataFile = getenv("XUL_APP_FILE"); 1.119 + if (appDataFile && *appDataFile) { 1.120 + rv = XRE_GetFileFromPath(appDataFile, getter_AddRefs(appini)); 1.121 + if (NS_FAILED(rv)) { 1.122 + Output("Invalid path found: '%s'", appDataFile); 1.123 + return 255; 1.124 + } 1.125 + } 1.126 + else if (argc > 1 && IsArg(argv[1], "app")) { 1.127 + if (argc == 2) { 1.128 + Output("Incorrect number of arguments passed to -app"); 1.129 + return 255; 1.130 + } 1.131 + 1.132 + rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(appini)); 1.133 + if (NS_FAILED(rv)) { 1.134 + Output("application.ini path not recognized: '%s'", argv[2]); 1.135 + return 255; 1.136 + } 1.137 + 1.138 + char appEnv[MAXPATHLEN]; 1.139 + snprintf(appEnv, MAXPATHLEN, "XUL_APP_FILE=%s", argv[2]); 1.140 + if (putenv(appEnv)) { 1.141 + Output("Couldn't set %s.\n", appEnv); 1.142 + return 255; 1.143 + } 1.144 + argv[2] = argv[0]; 1.145 + argv += 2; 1.146 + argc -= 2; 1.147 + } 1.148 + 1.149 +#ifdef MOZ_WIDGET_GONK 1.150 + /* Called to start the boot animation */ 1.151 + (void) mozilla::GetGonkDisplay(); 1.152 +#endif 1.153 + 1.154 + if (appini) { 1.155 + nsXREAppData *appData; 1.156 + rv = XRE_CreateAppData(appini, &appData); 1.157 + if (NS_FAILED(rv)) { 1.158 + Output("Couldn't read application.ini"); 1.159 + return 255; 1.160 + } 1.161 + int result = XRE_main(argc, argv, appData, 0); 1.162 + XRE_FreeAppData(appData); 1.163 + return result; 1.164 + } 1.165 + 1.166 + return XRE_main(argc, argv, &sAppData, 0); 1.167 +} 1.168 + 1.169 +int main(int argc, char* argv[]) 1.170 +{ 1.171 + char exePath[MAXPATHLEN]; 1.172 + 1.173 +#ifdef MOZ_WIDGET_GONK 1.174 + // This creates a ThreadPool for binder ipc. A ThreadPool is necessary to 1.175 + // receive binder calls, though not necessary to send binder calls. 1.176 + // ProcessState::Self() also needs to be called once on the main thread to 1.177 + // register the main thread with the binder driver. 1.178 + android::ProcessState::self()->startThreadPool(); 1.179 +#endif 1.180 + 1.181 + nsresult rv = mozilla::BinaryPath::Get(argv[0], exePath); 1.182 + if (NS_FAILED(rv)) { 1.183 + Output("Couldn't calculate the application directory.\n"); 1.184 + return 255; 1.185 + } 1.186 + 1.187 + char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]); 1.188 + if (!lastSlash || ((lastSlash - exePath) + sizeof(XPCOM_DLL) + 1 > MAXPATHLEN)) 1.189 + return 255; 1.190 + 1.191 + strcpy(++lastSlash, XPCOM_DLL); 1.192 + 1.193 +#if defined(XP_UNIX) 1.194 + // If the b2g app is launched from adb shell, then the shell will wind 1.195 + // up being the process group controller. This means that we can't send 1.196 + // signals to the process group (useful for profiling). 1.197 + // We ignore the return value since setsid() fails if we're already the 1.198 + // process group controller (the normal situation). 1.199 + (void)setsid(); 1.200 +#endif 1.201 + 1.202 + int gotCounters; 1.203 +#if defined(XP_UNIX) 1.204 + struct rusage initialRUsage; 1.205 + gotCounters = !getrusage(RUSAGE_SELF, &initialRUsage); 1.206 +#elif defined(XP_WIN) 1.207 + IO_COUNTERS ioCounters; 1.208 + gotCounters = GetProcessIoCounters(GetCurrentProcess(), &ioCounters); 1.209 +#endif 1.210 + 1.211 +#ifdef HAS_DLL_BLOCKLIST 1.212 + DllBlocklist_Initialize(); 1.213 +#endif 1.214 + 1.215 + // We do this because of data in bug 771745 1.216 + XPCOMGlueEnablePreload(); 1.217 + 1.218 + rv = XPCOMGlueStartup(exePath); 1.219 + if (NS_FAILED(rv)) { 1.220 + Output("Couldn't load XPCOM.\n"); 1.221 + return 255; 1.222 + } 1.223 + // Reset exePath so that it is the directory name and not the xpcom dll name 1.224 + *lastSlash = 0; 1.225 + 1.226 + rv = XPCOMGlueLoadXULFunctions(kXULFuncs); 1.227 + if (NS_FAILED(rv)) { 1.228 + Output("Couldn't load XRE functions.\n"); 1.229 + return 255; 1.230 + } 1.231 + 1.232 + if (gotCounters) { 1.233 +#if defined(XP_WIN) 1.234 + XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_READ_OPS, 1.235 + int(ioCounters.ReadOperationCount)); 1.236 + XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_READ_TRANSFER, 1.237 + int(ioCounters.ReadTransferCount / 1024)); 1.238 + IO_COUNTERS newIoCounters; 1.239 + if (GetProcessIoCounters(GetCurrentProcess(), &newIoCounters)) { 1.240 + XRE_TelemetryAccumulate(mozilla::Telemetry::GLUESTARTUP_READ_OPS, 1.241 + int(newIoCounters.ReadOperationCount - ioCounters.ReadOperationCount)); 1.242 + XRE_TelemetryAccumulate(mozilla::Telemetry::GLUESTARTUP_READ_TRANSFER, 1.243 + int((newIoCounters.ReadTransferCount - ioCounters.ReadTransferCount) / 1024)); 1.244 + } 1.245 +#elif defined(XP_UNIX) 1.246 + XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_HARD_FAULTS, 1.247 + int(initialRUsage.ru_majflt)); 1.248 + struct rusage newRUsage; 1.249 + if (!getrusage(RUSAGE_SELF, &newRUsage)) { 1.250 + XRE_TelemetryAccumulate(mozilla::Telemetry::GLUESTARTUP_HARD_FAULTS, 1.251 + int(newRUsage.ru_majflt - initialRUsage.ru_majflt)); 1.252 + } 1.253 +#endif 1.254 + } 1.255 + 1.256 + int result; 1.257 + { 1.258 + ScopedLogging log; 1.259 + result = do_main(argc, argv); 1.260 + } 1.261 + 1.262 + return result; 1.263 +}