1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 2002
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Brian Ryner <bryner@brianryner.com>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "nsXULAppAPI.h"
40 : #include "application.ini.h"
41 : #include "nsXPCOMGlue.h"
42 : #if defined(XP_WIN)
43 : #include <windows.h>
44 : #include <stdlib.h>
45 : #elif defined(XP_UNIX)
46 : #include <sys/time.h>
47 : #include <sys/resource.h>
48 : #endif
49 :
50 : #ifdef XP_MACOSX
51 : #include "MacQuirks.h"
52 : #endif
53 :
54 : #include <stdio.h>
55 : #include <stdarg.h>
56 :
57 : #include "nsCOMPtr.h"
58 : #include "nsILocalFile.h"
59 : #include "nsStringGlue.h"
60 :
61 : #ifdef XP_WIN
62 : // we want a wmain entry point
63 : #include "nsWindowsWMain.cpp"
64 : #define snprintf _snprintf
65 : #define strcasecmp _stricmp
66 : #endif
67 : #include "BinaryPath.h"
68 :
69 : #include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
70 :
71 : #include "mozilla/Telemetry.h"
72 :
73 0 : static void Output(const char *fmt, ... )
74 : {
75 : va_list ap;
76 0 : va_start(ap, fmt);
77 :
78 : #if defined(XP_WIN) && !MOZ_WINCONSOLE
79 : PRUnichar msg[2048];
80 : _vsnwprintf(msg, sizeof(msg)/sizeof(msg[0]), NS_ConvertUTF8toUTF16(fmt).get(), ap);
81 : MessageBoxW(NULL, msg, L"XULRunner", MB_OK | MB_ICONERROR);
82 : #else
83 0 : vfprintf(stderr, fmt, ap);
84 : #endif
85 :
86 0 : va_end(ap);
87 0 : }
88 :
89 : /**
90 : * Return true if |arg| matches the given argument name.
91 : */
92 46 : static bool IsArg(const char* arg, const char* s)
93 : {
94 46 : if (*arg == '-')
95 : {
96 46 : if (*++arg == '-')
97 0 : ++arg;
98 46 : return !strcasecmp(arg, s);
99 : }
100 :
101 : #if defined(XP_WIN) || defined(XP_OS2)
102 : if (*arg == '/')
103 : return !strcasecmp(++arg, s);
104 : #endif
105 :
106 0 : return false;
107 : }
108 :
109 : /**
110 : * A helper class which calls NS_LogInit/NS_LogTerm in its scope.
111 : */
112 : class ScopedLogging
113 : {
114 : public:
115 46 : ScopedLogging() { NS_LogInit(); }
116 23 : ~ScopedLogging() { NS_LogTerm(); }
117 : };
118 :
119 : XRE_GetFileFromPathType XRE_GetFileFromPath;
120 : XRE_CreateAppDataType XRE_CreateAppData;
121 : XRE_FreeAppDataType XRE_FreeAppData;
122 : #ifdef XRE_HAS_DLL_BLOCKLIST
123 : XRE_SetupDllBlocklistType XRE_SetupDllBlocklist;
124 : #endif
125 : XRE_TelemetryAccumulateType XRE_TelemetryAccumulate;
126 : XRE_mainType XRE_main;
127 :
128 : static const nsDynamicFunctionLoad kXULFuncs[] = {
129 : { "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
130 : { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
131 : { "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
132 : #ifdef XRE_HAS_DLL_BLOCKLIST
133 : { "XRE_SetupDllBlocklist", (NSFuncPtr*) &XRE_SetupDllBlocklist },
134 : #endif
135 : { "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
136 : { "XRE_main", (NSFuncPtr*) &XRE_main },
137 : { nsnull, nsnull }
138 : };
139 :
140 46 : static int do_main(int argc, char* argv[])
141 : {
142 69 : nsCOMPtr<nsILocalFile> appini;
143 : nsresult rv;
144 :
145 : // Allow firefox.exe to launch XULRunner apps via -app <application.ini>
146 : // Note that -app must be the *first* argument.
147 46 : const char *appDataFile = getenv("XUL_APP_FILE");
148 46 : if (appDataFile && *appDataFile) {
149 0 : rv = XRE_GetFileFromPath(appDataFile, getter_AddRefs(appini));
150 0 : if (NS_FAILED(rv)) {
151 0 : Output("Invalid path found: '%s'", appDataFile);
152 0 : return 255;
153 : }
154 : }
155 46 : else if (argc > 1 && IsArg(argv[1], "app")) {
156 0 : if (argc == 2) {
157 0 : Output("Incorrect number of arguments passed to -app");
158 0 : return 255;
159 : }
160 :
161 0 : rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(appini));
162 0 : if (NS_FAILED(rv)) {
163 0 : Output("application.ini path not recognized: '%s'", argv[2]);
164 0 : return 255;
165 : }
166 :
167 : char appEnv[MAXPATHLEN];
168 0 : snprintf(appEnv, MAXPATHLEN, "XUL_APP_FILE=%s", argv[2]);
169 0 : if (putenv(appEnv)) {
170 0 : Output("Couldn't set %s.\n", appEnv);
171 0 : return 255;
172 : }
173 0 : argv[2] = argv[0];
174 0 : argv += 2;
175 0 : argc -= 2;
176 : }
177 :
178 46 : if (appini) {
179 : nsXREAppData *appData;
180 0 : rv = XRE_CreateAppData(appini, &appData);
181 0 : if (NS_FAILED(rv)) {
182 0 : Output("Couldn't read application.ini");
183 0 : return 255;
184 : }
185 0 : int result = XRE_main(argc, argv, appData);
186 0 : XRE_FreeAppData(appData);
187 0 : return result;
188 : }
189 :
190 46 : return XRE_main(argc, argv, &sAppData);
191 : }
192 :
193 46 : int main(int argc, char* argv[])
194 : {
195 : char exePath[MAXPATHLEN];
196 :
197 : #ifdef XP_MACOSX
198 : TriggerQuirks();
199 : #endif
200 :
201 46 : nsresult rv = mozilla::BinaryPath::Get(argv[0], exePath);
202 46 : if (NS_FAILED(rv)) {
203 0 : Output("Couldn't calculate the application directory.\n");
204 0 : return 255;
205 : }
206 :
207 46 : char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
208 46 : if (!lastSlash || (lastSlash - exePath > MAXPATHLEN - sizeof(XPCOM_DLL) - 1))
209 0 : return 255;
210 :
211 46 : strcpy(++lastSlash, XPCOM_DLL);
212 :
213 : int gotCounters;
214 : #if defined(XP_UNIX)
215 : struct rusage initialRUsage;
216 46 : gotCounters = !getrusage(RUSAGE_SELF, &initialRUsage);
217 : #elif defined(XP_WIN)
218 : // GetProcessIoCounters().ReadOperationCount seems to have little to
219 : // do with actual read operations. It reports 0 or 1 at this stage
220 : // in the program. Luckily 1 coincides with when prefetch is
221 : // enabled. If Windows prefetch didn't happen we can do our own
222 : // faster dll preloading.
223 : IO_COUNTERS ioCounters;
224 : gotCounters = GetProcessIoCounters(GetCurrentProcess(), &ioCounters);
225 : if (gotCounters && !ioCounters.ReadOperationCount)
226 : #endif
227 : {
228 46 : XPCOMGlueEnablePreload();
229 : }
230 :
231 :
232 46 : rv = XPCOMGlueStartup(exePath);
233 46 : if (NS_FAILED(rv)) {
234 0 : Output("Couldn't load XPCOM.\n");
235 0 : return 255;
236 : }
237 : // Reset exePath so that it is the directory name and not the xpcom dll name
238 46 : *lastSlash = 0;
239 :
240 46 : rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
241 46 : if (NS_FAILED(rv)) {
242 0 : Output("Couldn't load XRE functions.\n");
243 0 : return 255;
244 : }
245 :
246 : #ifdef XRE_HAS_DLL_BLOCKLIST
247 : XRE_SetupDllBlocklist();
248 : #endif
249 :
250 46 : if (gotCounters) {
251 : #if defined(XP_WIN)
252 : XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_READ_OPS,
253 : int(ioCounters.ReadOperationCount));
254 : XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_READ_TRANSFER,
255 : int(ioCounters.ReadTransferCount / 1024));
256 : IO_COUNTERS newIoCounters;
257 : if (GetProcessIoCounters(GetCurrentProcess(), &newIoCounters)) {
258 : XRE_TelemetryAccumulate(mozilla::Telemetry::GLUESTARTUP_READ_OPS,
259 : int(newIoCounters.ReadOperationCount - ioCounters.ReadOperationCount));
260 : XRE_TelemetryAccumulate(mozilla::Telemetry::GLUESTARTUP_READ_TRANSFER,
261 : int((newIoCounters.ReadTransferCount - ioCounters.ReadTransferCount) / 1024));
262 : }
263 : #elif defined(XP_UNIX)
264 : XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_HARD_FAULTS,
265 46 : int(initialRUsage.ru_majflt));
266 : struct rusage newRUsage;
267 46 : if (!getrusage(RUSAGE_SELF, &newRUsage)) {
268 : XRE_TelemetryAccumulate(mozilla::Telemetry::GLUESTARTUP_HARD_FAULTS,
269 46 : int(newRUsage.ru_majflt - initialRUsage.ru_majflt));
270 : }
271 : #endif
272 : }
273 :
274 : int result;
275 : {
276 69 : ScopedLogging log;
277 46 : result = do_main(argc, argv);
278 : }
279 :
280 23 : XPCOMGlueShutdown();
281 23 : return result;
282 : }
|