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 Communicator client 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) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
24 : * Benjamin Smedberg <benjamin@smedbergs.us>
25 : * Ben Goodger <ben@mozilla.org>
26 : * Fredrik Holmqvist <thesuckiestemail@yahoo.se>
27 : * Ben Turner <mozilla@songbirdnest.com>
28 : * Sergei Dolgov <sergei_d@fi.tartu.ee>
29 : *
30 : * Alternatively, the contents of this file may be used under the terms of
31 : * either the GNU General Public License Version 2 or later (the "GPL"), or
32 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 : * in which case the provisions of the GPL or the LGPL are applicable instead
34 : * of those above. If you wish to allow use of your version of this file only
35 : * under the terms of either the GPL or the LGPL, and not to allow others to
36 : * use your version of this file under the terms of the MPL, indicate your
37 : * decision by deleting the provisions above and replace them with the notice
38 : * and other provisions required by the GPL or the LGPL. If you do not delete
39 : * the provisions above, a recipient may use your version of this file under
40 : * the terms of any one of the MPL, the GPL or the LGPL.
41 : *
42 : * ***** END LICENSE BLOCK ***** */
43 :
44 : #if defined(XP_OS2) && defined(MOZ_OS2_HIGH_MEMORY)
45 : // os2safe.h has to be included before os2.h, needed for high mem
46 : #include <os2safe.h>
47 : #endif
48 :
49 : #define XPCOM_TRANSLATE_NSGM_ENTRY_POINT 1
50 :
51 : #if defined(MOZ_WIDGET_QT)
52 : #include <QtGui/QApplication>
53 : #include "nsQAppInstance.h"
54 : #include <QtGui/QInputContextFactory>
55 : #include <QtGui/QInputContext>
56 : #endif // MOZ_WIDGET_QT
57 :
58 : #include "mozilla/dom/ContentParent.h"
59 : #include "mozilla/dom/ContentChild.h"
60 :
61 : #include "mozilla/Util.h"
62 :
63 : #include "nsAppRunner.h"
64 : #include "nsUpdateDriver.h"
65 :
66 : #ifdef MOZ_INSTRUMENT_EVENT_LOOP
67 : #include "EventTracer.h"
68 : #endif
69 :
70 : #ifdef XP_MACOSX
71 : #include "nsVersionComparator.h"
72 : #include "MacLaunchHelper.h"
73 : #include "MacApplicationDelegate.h"
74 : #include "MacAutoreleasePool.h"
75 : // these are needed for sysctl
76 : #include <sys/types.h>
77 : #include <sys/sysctl.h>
78 : #endif
79 :
80 : #ifdef XP_OS2
81 : #include "private/pprthred.h"
82 : #endif
83 : #include "prmem.h"
84 : #include "prnetdb.h"
85 : #include "prprf.h"
86 : #include "prproces.h"
87 : #include "prenv.h"
88 :
89 : #include "nsIAppShellService.h"
90 : #include "nsIAppStartup.h"
91 : #include "nsIAppStartupNotifier.h"
92 : #include "nsIMutableArray.h"
93 : #include "nsICategoryManager.h"
94 : #include "nsIChromeRegistry.h"
95 : #include "nsICommandLineRunner.h"
96 : #include "nsIComponentManager.h"
97 : #include "nsIComponentRegistrar.h"
98 : #include "nsIContentHandler.h"
99 : #include "nsIDialogParamBlock.h"
100 : #include "nsIDOMWindow.h"
101 : #include "mozilla/ModuleUtils.h"
102 : #include "nsIIOService2.h"
103 : #include "nsIObserverService.h"
104 : #include "nsINativeAppSupport.h"
105 : #include "nsIProcess.h"
106 : #include "nsIProfileUnlocker.h"
107 : #include "nsIPromptService.h"
108 : #include "nsIServiceManager.h"
109 : #include "nsIStringBundle.h"
110 : #include "nsISupportsPrimitives.h"
111 : #include "nsIToolkitChromeRegistry.h"
112 : #include "nsIToolkitProfile.h"
113 : #include "nsIToolkitProfileService.h"
114 : #include "nsIURI.h"
115 : #include "nsIWindowCreator.h"
116 : #include "nsIWindowMediator.h"
117 : #include "nsIWindowWatcher.h"
118 : #include "nsIXULAppInfo.h"
119 : #include "nsIXULRuntime.h"
120 : #include "nsPIDOMWindow.h"
121 : #include "nsIBaseWindow.h"
122 : #include "nsIWidget.h"
123 : #include "nsIDocShell.h"
124 : #include "nsAppShellCID.h"
125 :
126 : #include "mozilla/FunctionTimer.h"
127 : #include "mozilla/unused.h"
128 :
129 : using namespace mozilla;
130 : using mozilla::unused;
131 :
132 : #ifdef XP_WIN
133 : #include "nsIWinAppHelper.h"
134 : #include <windows.h>
135 : #include "cairo/cairo-features.h"
136 :
137 : #ifndef PROCESS_DEP_ENABLE
138 : #define PROCESS_DEP_ENABLE 0x1
139 : #endif
140 : #endif
141 :
142 : #include "nsCRT.h"
143 : #include "nsCOMPtr.h"
144 : #include "nsDirectoryServiceDefs.h"
145 : #include "nsDirectoryServiceUtils.h"
146 : #include "nsEmbedCID.h"
147 : #include "nsNetUtil.h"
148 : #include "nsReadableUtils.h"
149 : #include "nsStaticComponents.h"
150 : #include "nsXPCOM.h"
151 : #include "nsXPCOMCIDInternal.h"
152 : #include "nsXPIDLString.h"
153 : #include "nsPrintfCString.h"
154 : #include "nsVersionComparator.h"
155 :
156 : #include "nsAppDirectoryServiceDefs.h"
157 : #include "nsXULAppAPI.h"
158 : #include "nsXREDirProvider.h"
159 : #include "nsToolkitCompsCID.h"
160 :
161 : #include "nsINIParser.h"
162 : #include "mozilla/Omnijar.h"
163 : #include "mozilla/StartupTimeline.h"
164 :
165 : #include <stdlib.h>
166 :
167 : #ifdef XP_UNIX
168 : #include <sys/stat.h>
169 : #include <unistd.h>
170 : #include <pwd.h>
171 : #endif
172 :
173 : #ifdef XP_WIN
174 : #include <process.h>
175 : #include <shlobj.h>
176 : #include "nsThreadUtils.h"
177 : #endif
178 :
179 : #ifdef XP_MACOSX
180 : #include "nsILocalFileMac.h"
181 : #include "nsCommandLineServiceMac.h"
182 : #endif
183 :
184 : // for X remote support
185 : #ifdef MOZ_ENABLE_XREMOTE
186 : #include "XRemoteClient.h"
187 : #include "nsIRemoteService.h"
188 : #endif
189 :
190 : #ifdef NS_TRACE_MALLOC
191 : #include "nsTraceMalloc.h"
192 : #endif
193 :
194 : #if defined(DEBUG) && defined(XP_WIN32)
195 : #include <malloc.h>
196 : #endif
197 :
198 : #if defined (XP_MACOSX)
199 : #include <Carbon/Carbon.h>
200 : #endif
201 :
202 : #ifdef DEBUG
203 : #include "prlog.h"
204 : #endif
205 :
206 : #ifdef MOZ_JPROF
207 : #include "jprof.h"
208 : #endif
209 :
210 : #ifdef MOZ_CRASHREPORTER
211 : #include "nsExceptionHandler.h"
212 : #include "nsICrashReporter.h"
213 : #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
214 : #include "nsIPrefService.h"
215 : #endif
216 :
217 : #include "base/command_line.h"
218 :
219 : #include "mozilla/FunctionTimer.h"
220 :
221 : #ifdef MOZ_WIDGET_ANDROID
222 : #include "AndroidBridge.h"
223 : #endif
224 :
225 : extern PRUint32 gRestartMode;
226 : extern void InstallSignalHandlers(const char *ProgramName);
227 : #include "nsX11ErrorHandler.h"
228 :
229 : #define FILE_COMPATIBILITY_INFO NS_LITERAL_CSTRING("compatibility.ini")
230 : #define FILE_INVALIDATE_CACHES NS_LITERAL_CSTRING(".purgecaches")
231 :
232 : int gArgc;
233 : char **gArgv;
234 :
235 : static const char gToolkitVersion[] = NS_STRINGIFY(GRE_MILESTONE);
236 : static const char gToolkitBuildID[] = NS_STRINGIFY(GRE_BUILDID);
237 :
238 : static nsIProfileLock* gProfileLock;
239 :
240 : static int gRestartArgc;
241 : static char **gRestartArgv;
242 :
243 : #ifdef MOZ_WIDGET_QT
244 : static int gQtOnlyArgc;
245 : static char **gQtOnlyArgv;
246 : #endif
247 :
248 : #if defined(MOZ_WIDGET_GTK2)
249 : #if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) \
250 : || defined(NS_TRACE_MALLOC)
251 : #define CLEANUP_MEMORY 1
252 : #define PANGO_ENABLE_BACKEND
253 : #include <pango/pangofc-fontmap.h>
254 : #endif
255 : #include <gtk/gtk.h>
256 : #ifdef MOZ_X11
257 : #include <gdk/gdkx.h>
258 : #endif /* MOZ_X11 */
259 : #include "nsGTKToolkit.h"
260 : #endif
261 : #include "BinaryPath.h"
262 :
263 : using mozilla::dom::ContentParent;
264 : using mozilla::dom::ContentChild;
265 :
266 : // Save literal putenv string to environment variable.
267 : static void
268 69 : SaveToEnv(const char *putenv)
269 : {
270 69 : char *expr = strdup(putenv);
271 69 : if (expr)
272 69 : PR_SetEnv(expr);
273 : // We intentionally leak |expr| here since it is required by PR_SetEnv.
274 69 : }
275 :
276 : // Tests that an environment variable exists and has a value
277 : static bool
278 46 : EnvHasValue(const char *name)
279 : {
280 46 : const char *val = PR_GetEnv(name);
281 46 : return (val && *val);
282 : }
283 :
284 : // Save the given word to the specified environment variable.
285 : static void
286 22 : SaveWordToEnv(const char *name, const nsACString & word)
287 : {
288 22 : char *expr = PR_smprintf("%s=%s", name, PromiseFlatCString(word).get());
289 22 : if (expr)
290 22 : PR_SetEnv(expr);
291 : // We intentionally leak |expr| here since it is required by PR_SetEnv.
292 22 : }
293 :
294 : // Save the path of the given file to the specified environment variable.
295 : static void
296 0 : SaveFileToEnv(const char *name, nsIFile *file)
297 : {
298 : #ifdef XP_WIN
299 : nsAutoString path;
300 : file->GetPath(path);
301 : SetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(), path.get());
302 : #else
303 0 : nsCAutoString path;
304 0 : file->GetNativePath(path);
305 0 : SaveWordToEnv(name, path);
306 : #endif
307 0 : }
308 :
309 : // Load the path of a file saved with SaveFileToEnv
310 : static already_AddRefed<nsILocalFile>
311 0 : GetFileFromEnv(const char *name)
312 : {
313 : nsresult rv;
314 0 : nsILocalFile *file = nsnull;
315 :
316 : #ifdef XP_WIN
317 : WCHAR path[_MAX_PATH];
318 : if (!GetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(),
319 : path, _MAX_PATH))
320 : return nsnull;
321 :
322 : rv = NS_NewLocalFile(nsDependentString(path), true, &file);
323 : if (NS_FAILED(rv))
324 : return nsnull;
325 :
326 : return file;
327 : #else
328 0 : const char *arg = PR_GetEnv(name);
329 0 : if (!arg || !*arg)
330 0 : return nsnull;
331 :
332 0 : rv = NS_NewNativeLocalFile(nsDependentCString(arg), true, &file);
333 0 : if (NS_FAILED(rv))
334 0 : return nsnull;
335 :
336 0 : return file;
337 : #endif
338 : }
339 :
340 : // Save the path of the given word to the specified environment variable
341 : // provided the environment variable does not have a value.
342 : static void
343 0 : SaveWordToEnvIfUnset(const char *name, const nsACString & word)
344 : {
345 0 : if (!EnvHasValue(name))
346 0 : SaveWordToEnv(name, word);
347 0 : }
348 :
349 : // Save the path of the given file to the specified environment variable
350 : // provided the environment variable does not have a value.
351 : static void
352 0 : SaveFileToEnvIfUnset(const char *name, nsIFile *file)
353 : {
354 0 : if (!EnvHasValue(name))
355 0 : SaveFileToEnv(name, file);
356 0 : }
357 :
358 : static bool
359 369 : strimatch(const char* lowerstr, const char* mixedstr)
360 : {
361 949 : while(*lowerstr) {
362 557 : if (!*mixedstr) return false; // mixedstr is shorter
363 557 : if (tolower(*mixedstr) != *lowerstr) return false; // no match
364 :
365 211 : ++lowerstr;
366 211 : ++mixedstr;
367 : }
368 :
369 23 : if (*mixedstr) return false; // lowerstr is shorter
370 :
371 23 : return true;
372 : }
373 :
374 : /**
375 : * Output a string to the user. This method is really only meant to be used to
376 : * output last-ditch error messages designed for developers NOT END USERS.
377 : *
378 : * @param isError
379 : * Pass true to indicate severe errors.
380 : * @param fmt
381 : * printf-style format string followed by arguments.
382 : */
383 0 : static void Output(bool isError, const char *fmt, ... )
384 : {
385 : va_list ap;
386 0 : va_start(ap, fmt);
387 :
388 : #if defined(XP_WIN) && !MOZ_WINCONSOLE
389 : char *msg = PR_vsmprintf(fmt, ap);
390 : if (msg)
391 : {
392 : UINT flags = MB_OK;
393 : if (isError)
394 : flags |= MB_ICONERROR;
395 : else
396 : flags |= MB_ICONINFORMATION;
397 :
398 : wchar_t wide_msg[1024];
399 : MultiByteToWideChar(CP_ACP,
400 : 0,
401 : msg,
402 : -1,
403 : wide_msg,
404 : sizeof(wide_msg) / sizeof(wchar_t));
405 :
406 : MessageBoxW(NULL, wide_msg, L"XULRunner", flags);
407 : PR_smprintf_free(msg);
408 : }
409 : #else
410 0 : vfprintf(stderr, fmt, ap);
411 : #endif
412 :
413 0 : va_end(ap);
414 0 : }
415 :
416 : enum RemoteResult {
417 : REMOTE_NOT_FOUND = 0,
418 : REMOTE_FOUND = 1,
419 : REMOTE_ARG_BAD = 2
420 : };
421 :
422 : enum ArgResult {
423 : ARG_NONE = 0,
424 : ARG_FOUND = 1,
425 : ARG_BAD = 2 // you wanted a param, but there isn't one
426 : };
427 :
428 92 : static void RemoveArg(char **argv)
429 : {
430 92 : do {
431 92 : *argv = *(argv + 1);
432 92 : ++argv;
433 : } while (*argv);
434 :
435 23 : --gArgc;
436 23 : }
437 :
438 : /**
439 : * Check for a commandline flag. If the flag takes a parameter, the
440 : * parameter is returned in aParam. Flags may be in the form -arg or
441 : * --arg (or /arg on win32/OS2).
442 : *
443 : * @param aArg the parameter to check. Must be lowercase.
444 : * @param aCheckOSInt if true returns ARG_BAD if the osint argument is present
445 : * when aArg is also present.
446 : * @param if non-null, the -arg <data> will be stored in this pointer. This is *not*
447 : * allocated, but rather a pointer to the argv data.
448 : */
449 : static ArgResult
450 300 : CheckArg(const char* aArg, bool aCheckOSInt = false, const char **aParam = nsnull, bool aRemArg = true)
451 : {
452 300 : NS_ABORT_IF_FALSE(gArgv, "gArgv must be initialized before CheckArg()");
453 :
454 300 : char **curarg = gArgv + 1; // skip argv[0]
455 300 : ArgResult ar = ARG_NONE;
456 :
457 1477 : while (*curarg) {
458 900 : char *arg = curarg[0];
459 :
460 900 : if (arg[0] == '-'
461 : #if defined(XP_WIN) || defined(XP_OS2)
462 : || *arg == '/'
463 : #endif
464 : ) {
465 369 : ++arg;
466 369 : if (*arg == '-')
467 0 : ++arg;
468 :
469 369 : if (strimatch(aArg, arg)) {
470 23 : if (aRemArg)
471 23 : RemoveArg(curarg);
472 23 : if (!aParam) {
473 23 : ar = ARG_FOUND;
474 23 : break;
475 : }
476 :
477 0 : if (*curarg) {
478 0 : if (**curarg == '-'
479 : #if defined(XP_WIN) || defined(XP_OS2)
480 : || **curarg == '/'
481 : #endif
482 : )
483 0 : return ARG_BAD;
484 :
485 0 : *aParam = *curarg;
486 0 : if (aRemArg)
487 0 : RemoveArg(curarg);
488 0 : ar = ARG_FOUND;
489 0 : break;
490 : }
491 0 : return ARG_BAD;
492 : }
493 : }
494 :
495 877 : ++curarg;
496 : }
497 :
498 300 : if (aCheckOSInt && ar == ARG_FOUND) {
499 23 : ArgResult arOSInt = CheckArg("osint");
500 23 : if (arOSInt == ARG_FOUND) {
501 0 : ar = ARG_BAD;
502 0 : PR_fprintf(PR_STDERR, "Error: argument -osint is invalid\n");
503 : }
504 : }
505 :
506 300 : return ar;
507 : }
508 :
509 : #if defined(XP_WIN)
510 : /**
511 : * Check for a commandline flag from the windows shell and remove it from the
512 : * argv used when restarting. Flags MUST be in the form -arg.
513 : *
514 : * @param aArg the parameter to check. Must be lowercase.
515 : */
516 : static ArgResult
517 : CheckArgShell(const char* aArg)
518 : {
519 : char **curarg = gRestartArgv + 1; // skip argv[0]
520 :
521 : while (*curarg) {
522 : char *arg = curarg[0];
523 :
524 : if (arg[0] == '-') {
525 : ++arg;
526 :
527 : if (strimatch(aArg, arg)) {
528 : do {
529 : *curarg = *(curarg + 1);
530 : ++curarg;
531 : } while (*curarg);
532 :
533 : --gRestartArgc;
534 :
535 : return ARG_FOUND;
536 : }
537 : }
538 :
539 : ++curarg;
540 : }
541 :
542 : return ARG_NONE;
543 : }
544 :
545 : /**
546 : * Enabled Native App Support to process DDE messages when the app needs to
547 : * restart and the app has been launched by the Windows shell to open an url.
548 : * When aWait is false this will process the DDE events manually. This prevents
549 : * Windows from displaying an error message due to the DDE message not being
550 : * acknowledged.
551 : */
552 : static void
553 : ProcessDDE(nsINativeAppSupport* aNative, bool aWait)
554 : {
555 : // When the app is launched by the windows shell the windows shell
556 : // expects the app to be available for DDE messages and if it isn't
557 : // windows displays an error dialog. To prevent the error the DDE server
558 : // is enabled and pending events are processed when the app needs to
559 : // restart after it was launched by the shell with the requestpending
560 : // argument. The requestpending pending argument is removed to
561 : // differentiate it from being launched when an app restart is not
562 : // required.
563 : ArgResult ar;
564 : ar = CheckArgShell("requestpending");
565 : if (ar == ARG_FOUND) {
566 : aNative->Enable(); // enable win32 DDE responses
567 : if (aWait) {
568 : nsIThread *thread = NS_GetCurrentThread();
569 : // This is just a guesstimate based on testing different values.
570 : // If count is 8 or less windows will display an error dialog.
571 : PRInt32 count = 20;
572 : while(--count >= 0) {
573 : NS_ProcessNextEvent(thread);
574 : PR_Sleep(PR_MillisecondsToInterval(1));
575 : }
576 : }
577 : }
578 : }
579 : #endif
580 :
581 : bool gSafeMode = false;
582 :
583 : /**
584 : * The nsXULAppInfo object implements nsIFactory so that it can be its own
585 : * singleton.
586 : */
587 : class nsXULAppInfo : public nsIXULAppInfo,
588 : #ifdef XP_WIN
589 : public nsIWinAppHelper,
590 : #endif
591 : #ifdef MOZ_CRASHREPORTER
592 : public nsICrashReporter,
593 : #endif
594 : public nsIXULRuntime
595 :
596 : {
597 : public:
598 1464 : nsXULAppInfo() {}
599 : NS_DECL_ISUPPORTS_INHERITED
600 : NS_DECL_NSIXULAPPINFO
601 : NS_DECL_NSIXULRUNTIME
602 : #ifdef MOZ_CRASHREPORTER
603 : NS_DECL_NSICRASHREPORTER
604 : #endif
605 : #ifdef XP_WIN
606 : NS_DECL_NSIWINAPPHELPER
607 : #endif
608 : };
609 :
610 110381 : NS_INTERFACE_MAP_BEGIN(nsXULAppInfo)
611 110381 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULRuntime)
612 107528 : NS_INTERFACE_MAP_ENTRY(nsIXULRuntime)
613 : #ifdef XP_WIN
614 : NS_INTERFACE_MAP_ENTRY(nsIWinAppHelper)
615 : #endif
616 : #ifdef MOZ_CRASHREPORTER
617 102807 : NS_INTERFACE_MAP_ENTRY(nsICrashReporter)
618 : #endif
619 98648 : NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIXULAppInfo, gAppData ||
620 : XRE_GetProcessType() == GeckoProcessType_Content)
621 98648 : NS_INTERFACE_MAP_END
622 :
623 : NS_IMETHODIMP_(nsrefcnt)
624 99380 : nsXULAppInfo::AddRef()
625 : {
626 99380 : return 1;
627 : }
628 :
629 : NS_IMETHODIMP_(nsrefcnt)
630 99380 : nsXULAppInfo::Release()
631 : {
632 99380 : return 1;
633 : }
634 :
635 : NS_IMETHODIMP
636 0 : nsXULAppInfo::GetVendor(nsACString& aResult)
637 : {
638 0 : if (XRE_GetProcessType() == GeckoProcessType_Content) {
639 0 : NS_WARNING("Attempt to get unavailable information in content process.");
640 0 : return NS_ERROR_NOT_AVAILABLE;
641 : }
642 0 : aResult.Assign(gAppData->vendor);
643 :
644 0 : return NS_OK;
645 : }
646 :
647 : NS_IMETHODIMP
648 0 : nsXULAppInfo::GetName(nsACString& aResult)
649 : {
650 0 : if (XRE_GetProcessType() == GeckoProcessType_Content) {
651 0 : NS_WARNING("Attempt to get unavailable information in content process.");
652 0 : return NS_ERROR_NOT_AVAILABLE;
653 : }
654 0 : aResult.Assign(gAppData->name);
655 :
656 0 : return NS_OK;
657 : }
658 :
659 : NS_IMETHODIMP
660 0 : nsXULAppInfo::GetID(nsACString& aResult)
661 : {
662 0 : if (XRE_GetProcessType() == GeckoProcessType_Content) {
663 0 : NS_WARNING("Attempt to get unavailable information in content process.");
664 0 : return NS_ERROR_NOT_AVAILABLE;
665 : }
666 0 : aResult.Assign(gAppData->ID);
667 :
668 0 : return NS_OK;
669 : }
670 :
671 : NS_IMETHODIMP
672 0 : nsXULAppInfo::GetVersion(nsACString& aResult)
673 : {
674 0 : if (XRE_GetProcessType() == GeckoProcessType_Content) {
675 0 : ContentChild* cc = ContentChild::GetSingleton();
676 0 : aResult = cc->GetAppInfo().version;
677 0 : return NS_OK;
678 : }
679 0 : aResult.Assign(gAppData->version);
680 :
681 0 : return NS_OK;
682 : }
683 :
684 : NS_IMETHODIMP
685 0 : nsXULAppInfo::GetPlatformVersion(nsACString& aResult)
686 : {
687 0 : aResult.Assign(gToolkitVersion);
688 :
689 0 : return NS_OK;
690 : }
691 :
692 : NS_IMETHODIMP
693 0 : nsXULAppInfo::GetAppBuildID(nsACString& aResult)
694 : {
695 0 : if (XRE_GetProcessType() == GeckoProcessType_Content) {
696 0 : ContentChild* cc = ContentChild::GetSingleton();
697 0 : aResult = cc->GetAppInfo().buildID;
698 0 : return NS_OK;
699 : }
700 0 : aResult.Assign(gAppData->buildID);
701 :
702 0 : return NS_OK;
703 : }
704 :
705 : NS_IMETHODIMP
706 0 : nsXULAppInfo::GetPlatformBuildID(nsACString& aResult)
707 : {
708 0 : aResult.Assign(gToolkitBuildID);
709 :
710 0 : return NS_OK;
711 : }
712 :
713 : NS_IMETHODIMP
714 0 : nsXULAppInfo::GetLogConsoleErrors(bool *aResult)
715 : {
716 0 : *aResult = gLogConsoleErrors;
717 0 : return NS_OK;
718 : }
719 :
720 : NS_IMETHODIMP
721 0 : nsXULAppInfo::SetLogConsoleErrors(bool aValue)
722 : {
723 0 : gLogConsoleErrors = aValue;
724 0 : return NS_OK;
725 : }
726 :
727 : NS_IMETHODIMP
728 1419 : nsXULAppInfo::GetInSafeMode(bool *aResult)
729 : {
730 1419 : *aResult = gSafeMode;
731 1419 : return NS_OK;
732 : }
733 :
734 : NS_IMETHODIMP
735 22 : nsXULAppInfo::GetOS(nsACString& aResult)
736 : {
737 22 : aResult.AssignLiteral(OS_TARGET);
738 22 : return NS_OK;
739 : }
740 :
741 : NS_IMETHODIMP
742 166 : nsXULAppInfo::GetXPCOMABI(nsACString& aResult)
743 : {
744 : #ifdef TARGET_XPCOM_ABI
745 166 : aResult.AssignLiteral(TARGET_XPCOM_ABI);
746 166 : return NS_OK;
747 : #else
748 : return NS_ERROR_NOT_AVAILABLE;
749 : #endif
750 : }
751 :
752 : NS_IMETHODIMP
753 0 : nsXULAppInfo::GetWidgetToolkit(nsACString& aResult)
754 : {
755 0 : aResult.AssignLiteral(MOZ_WIDGET_TOOLKIT);
756 0 : return NS_OK;
757 : }
758 :
759 : // Ensure that the GeckoProcessType enum, defined in xpcom/build/nsXULAppAPI.h,
760 : // is synchronized with the const unsigned longs defined in
761 : // xpcom/system/nsIXULRuntime.idl.
762 : #define SYNC_ENUMS(a,b) \
763 : PR_STATIC_ASSERT(nsIXULRuntime::PROCESS_TYPE_ ## a == \
764 : static_cast<int>(GeckoProcessType_ ## b));
765 :
766 : SYNC_ENUMS(DEFAULT, Default)
767 : SYNC_ENUMS(PLUGIN, Plugin)
768 : SYNC_ENUMS(CONTENT, Content)
769 : SYNC_ENUMS(IPDLUNITTEST, IPDLUnitTest)
770 :
771 : // .. and ensure that that is all of them:
772 : PR_STATIC_ASSERT(GeckoProcessType_IPDLUnitTest + 1 == GeckoProcessType_End);
773 :
774 : NS_IMETHODIMP
775 1684 : nsXULAppInfo::GetProcessType(PRUint32* aResult)
776 : {
777 1684 : NS_ENSURE_ARG_POINTER(aResult);
778 1684 : *aResult = XRE_GetProcessType();
779 1684 : return NS_OK;
780 : }
781 :
782 : NS_IMETHODIMP
783 0 : nsXULAppInfo::EnsureContentProcess()
784 : {
785 0 : if (XRE_GetProcessType() != GeckoProcessType_Default)
786 0 : return NS_ERROR_NOT_AVAILABLE;
787 :
788 0 : unused << ContentParent::GetNewOrUsed();
789 0 : return NS_OK;
790 : }
791 :
792 : NS_IMETHODIMP
793 0 : nsXULAppInfo::InvalidateCachesOnRestart()
794 : {
795 0 : nsCOMPtr<nsIFile> file;
796 : nsresult rv = NS_GetSpecialDirectory(NS_APP_PROFILE_DIR_STARTUP,
797 0 : getter_AddRefs(file));
798 0 : if (NS_FAILED(rv))
799 0 : return rv;
800 0 : if (!file)
801 0 : return NS_ERROR_NOT_AVAILABLE;
802 :
803 0 : file->AppendNative(FILE_COMPATIBILITY_INFO);
804 :
805 0 : nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
806 0 : nsINIParser parser;
807 0 : rv = parser.Init(localFile);
808 0 : if (NS_FAILED(rv)) {
809 : // This fails if compatibility.ini is not there, so we'll
810 : // flush the caches on the next restart anyways.
811 0 : return NS_OK;
812 : }
813 :
814 0 : nsCAutoString buf;
815 0 : rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
816 :
817 0 : if (NS_FAILED(rv)) {
818 0 : PRFileDesc *fd = nsnull;
819 0 : localFile->OpenNSPRFileDesc(PR_RDWR | PR_APPEND, 0600, &fd);
820 0 : if (!fd) {
821 0 : NS_ERROR("could not create output stream");
822 0 : return NS_ERROR_NOT_AVAILABLE;
823 : }
824 : static const char kInvalidationHeader[] = NS_LINEBREAK "InvalidateCaches=1" NS_LINEBREAK;
825 0 : rv = PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1);
826 0 : PR_Close(fd);
827 :
828 0 : if (NS_FAILED(rv))
829 0 : return rv;
830 : }
831 0 : return NS_OK;
832 : }
833 :
834 : NS_IMETHODIMP
835 0 : nsXULAppInfo::GetReplacedLockTime(PRInt64 *aReplacedLockTime)
836 : {
837 0 : if (!gProfileLock)
838 0 : return NS_ERROR_NOT_AVAILABLE;
839 0 : gProfileLock->GetReplacedLockTime(aReplacedLockTime);
840 0 : return NS_OK;
841 : }
842 :
843 : #ifdef XP_WIN
844 : // Matches the enum in WinNT.h for the Vista SDK but renamed so that we can
845 : // safely build with the Vista SDK and without it.
846 : typedef enum
847 : {
848 : VistaTokenElevationTypeDefault = 1,
849 : VistaTokenElevationTypeFull,
850 : VistaTokenElevationTypeLimited
851 : } VISTA_TOKEN_ELEVATION_TYPE;
852 :
853 : // avoid collision with TokeElevationType enum in WinNT.h
854 : // of the Vista SDK
855 : #define VistaTokenElevationType static_cast< TOKEN_INFORMATION_CLASS >( 18 )
856 :
857 : NS_IMETHODIMP
858 : nsXULAppInfo::GetUserCanElevate(bool *aUserCanElevate)
859 : {
860 : HANDLE hToken;
861 :
862 : VISTA_TOKEN_ELEVATION_TYPE elevationType;
863 : DWORD dwSize;
864 :
865 : if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) ||
866 : !GetTokenInformation(hToken, VistaTokenElevationType, &elevationType,
867 : sizeof(elevationType), &dwSize)) {
868 : *aUserCanElevate = false;
869 : }
870 : else {
871 : // The possible values returned for elevationType and their meanings are:
872 : // TokenElevationTypeDefault: The token does not have a linked token
873 : // (e.g. UAC disabled or a standard user, so they can't be elevated)
874 : // TokenElevationTypeFull: The token is linked to an elevated token
875 : // (e.g. UAC is enabled and the user is already elevated so they can't
876 : // be elevated again)
877 : // TokenElevationTypeLimited: The token is linked to a limited token
878 : // (e.g. UAC is enabled and the user is not elevated, so they can be
879 : // elevated)
880 : *aUserCanElevate = (elevationType == VistaTokenElevationTypeLimited);
881 : }
882 :
883 : if (hToken)
884 : CloseHandle(hToken);
885 :
886 : return NS_OK;
887 : }
888 : #endif
889 :
890 : #ifdef MOZ_CRASHREPORTER
891 : NS_IMETHODIMP
892 0 : nsXULAppInfo::GetEnabled(bool *aEnabled)
893 : {
894 0 : *aEnabled = CrashReporter::GetEnabled();
895 0 : return NS_OK;
896 : }
897 :
898 : NS_IMETHODIMP
899 2773 : nsXULAppInfo::SetEnabled(bool aEnabled)
900 : {
901 2773 : if (aEnabled) {
902 1386 : if (CrashReporter::GetEnabled())
903 : // no point in erroring for double-enabling
904 0 : return NS_OK;
905 :
906 2772 : nsCOMPtr<nsILocalFile> xreDirectory;
907 1386 : if (gAppData) {
908 0 : xreDirectory = gAppData->xreDirectory;
909 : }
910 : else {
911 : // We didn't get started through XRE_Main, probably
912 2772 : nsCOMPtr<nsIFile> greDir;
913 1386 : NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(greDir));
914 1386 : if (!greDir)
915 0 : return NS_ERROR_FAILURE;
916 :
917 1386 : xreDirectory = do_QueryInterface(greDir);
918 1386 : if (!xreDirectory)
919 0 : return NS_ERROR_FAILURE;
920 : }
921 1386 : return CrashReporter::SetExceptionHandler(xreDirectory, true);
922 : }
923 : else {
924 1387 : if (!CrashReporter::GetEnabled())
925 : // no point in erroring for double-disabling
926 1 : return NS_OK;
927 :
928 1386 : return CrashReporter::UnsetExceptionHandler();
929 : }
930 : }
931 :
932 : NS_IMETHODIMP
933 0 : nsXULAppInfo::GetServerURL(nsIURL** aServerURL)
934 : {
935 0 : if (!CrashReporter::GetEnabled())
936 0 : return NS_ERROR_NOT_INITIALIZED;
937 :
938 0 : nsCAutoString data;
939 0 : if (!CrashReporter::GetServerURL(data)) {
940 0 : return NS_ERROR_FAILURE;
941 : }
942 0 : nsCOMPtr<nsIURI> uri;
943 0 : NS_NewURI(getter_AddRefs(uri), data);
944 0 : if (!uri)
945 0 : return NS_ERROR_FAILURE;
946 :
947 0 : nsCOMPtr<nsIURL> url;
948 0 : url = do_QueryInterface(uri);
949 0 : NS_ADDREF(*aServerURL = url);
950 :
951 0 : return NS_OK;
952 : }
953 :
954 : NS_IMETHODIMP
955 0 : nsXULAppInfo::SetServerURL(nsIURL* aServerURL)
956 : {
957 : bool schemeOk;
958 : // only allow https or http URLs
959 0 : nsresult rv = aServerURL->SchemeIs("https", &schemeOk);
960 0 : NS_ENSURE_SUCCESS(rv, rv);
961 0 : if (!schemeOk) {
962 0 : rv = aServerURL->SchemeIs("http", &schemeOk);
963 0 : NS_ENSURE_SUCCESS(rv, rv);
964 :
965 0 : if (!schemeOk)
966 0 : return NS_ERROR_INVALID_ARG;
967 : }
968 0 : nsCAutoString spec;
969 0 : rv = aServerURL->GetSpec(spec);
970 0 : NS_ENSURE_SUCCESS(rv, rv);
971 :
972 0 : return CrashReporter::SetServerURL(spec);
973 : }
974 :
975 : NS_IMETHODIMP
976 0 : nsXULAppInfo::GetMinidumpPath(nsILocalFile** aMinidumpPath)
977 : {
978 0 : if (!CrashReporter::GetEnabled())
979 0 : return NS_ERROR_NOT_INITIALIZED;
980 :
981 0 : nsAutoString path;
982 0 : if (!CrashReporter::GetMinidumpPath(path))
983 0 : return NS_ERROR_FAILURE;
984 :
985 0 : nsresult rv = NS_NewLocalFile(path, false, aMinidumpPath);
986 0 : NS_ENSURE_SUCCESS(rv, rv);
987 0 : return NS_OK;
988 : }
989 :
990 : NS_IMETHODIMP
991 1386 : nsXULAppInfo::SetMinidumpPath(nsILocalFile* aMinidumpPath)
992 : {
993 2772 : nsAutoString path;
994 1386 : nsresult rv = aMinidumpPath->GetPath(path);
995 1386 : NS_ENSURE_SUCCESS(rv, rv);
996 1386 : return CrashReporter::SetMinidumpPath(path);
997 : }
998 :
999 : NS_IMETHODIMP
1000 0 : nsXULAppInfo::AnnotateCrashReport(const nsACString& key,
1001 : const nsACString& data)
1002 : {
1003 0 : return CrashReporter::AnnotateCrashReport(key, data);
1004 : }
1005 :
1006 : NS_IMETHODIMP
1007 0 : nsXULAppInfo::AppendAppNotesToCrashReport(const nsACString& data)
1008 : {
1009 0 : return CrashReporter::AppendAppNotesToCrashReport(data);
1010 : }
1011 :
1012 : NS_IMETHODIMP
1013 0 : nsXULAppInfo::RegisterAppMemory(PRUint64 pointer,
1014 : PRUint64 len)
1015 : {
1016 0 : return CrashReporter::RegisterAppMemory((void *)pointer, len);
1017 : }
1018 :
1019 : NS_IMETHODIMP
1020 0 : nsXULAppInfo::WriteMinidumpForException(void* aExceptionInfo)
1021 : {
1022 : #ifdef XP_WIN32
1023 : return CrashReporter::WriteMinidumpForException(static_cast<EXCEPTION_POINTERS*>(aExceptionInfo));
1024 : #else
1025 0 : return NS_ERROR_NOT_IMPLEMENTED;
1026 : #endif
1027 : }
1028 :
1029 : NS_IMETHODIMP
1030 0 : nsXULAppInfo::AppendObjCExceptionInfoToAppNotes(void* aException)
1031 : {
1032 : #ifdef XP_MACOSX
1033 : return CrashReporter::AppendObjCExceptionInfoToAppNotes(aException);
1034 : #else
1035 0 : return NS_ERROR_NOT_IMPLEMENTED;
1036 : #endif
1037 : }
1038 :
1039 : NS_IMETHODIMP
1040 0 : nsXULAppInfo::GetSubmitReports(bool* aEnabled)
1041 : {
1042 0 : return CrashReporter::GetSubmitReports(aEnabled);
1043 : }
1044 :
1045 : NS_IMETHODIMP
1046 0 : nsXULAppInfo::SetSubmitReports(bool aEnabled)
1047 : {
1048 0 : return CrashReporter::SetSubmitReports(aEnabled);
1049 : }
1050 :
1051 : #endif
1052 :
1053 1464 : static const nsXULAppInfo kAppInfo;
1054 8514 : static nsresult AppInfoConstructor(nsISupports* aOuter,
1055 : REFNSIID aIID, void **aResult)
1056 : {
1057 8514 : NS_ENSURE_NO_AGGREGATION(aOuter);
1058 :
1059 : return const_cast<nsXULAppInfo*>(&kAppInfo)->
1060 8514 : QueryInterface(aIID, aResult);
1061 : }
1062 :
1063 : bool gLogConsoleErrors
1064 : #ifdef DEBUG
1065 : = true;
1066 : #else
1067 : = false;
1068 : #endif
1069 :
1070 : #define NS_ENSURE_TRUE_LOG(x, ret) \
1071 : PR_BEGIN_MACRO \
1072 : if (NS_UNLIKELY(!(x))) { \
1073 : NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \
1074 : gLogConsoleErrors = true; \
1075 : return ret; \
1076 : } \
1077 : PR_END_MACRO
1078 :
1079 : #define NS_ENSURE_SUCCESS_LOG(res, ret) \
1080 : NS_ENSURE_TRUE_LOG(NS_SUCCEEDED(res), ret)
1081 :
1082 : /**
1083 : * Because we're starting/stopping XPCOM several times in different scenarios,
1084 : * this class is a stack-based critter that makes sure that XPCOM is shut down
1085 : * during early returns.
1086 : */
1087 :
1088 : class ScopedXPCOMStartup
1089 : {
1090 : public:
1091 0 : ScopedXPCOMStartup() :
1092 0 : mServiceManager(nsnull) { }
1093 : ~ScopedXPCOMStartup();
1094 :
1095 : nsresult Initialize();
1096 : nsresult SetWindowCreator(nsINativeAppSupport* native);
1097 :
1098 : static nsresult CreateAppSupport(nsISupports* aOuter, REFNSIID aIID, void** aResult);
1099 :
1100 : private:
1101 : nsIServiceManager* mServiceManager;
1102 : static nsINativeAppSupport* gNativeAppSupport;
1103 : };
1104 :
1105 0 : ScopedXPCOMStartup::~ScopedXPCOMStartup()
1106 : {
1107 0 : NS_IF_RELEASE(gNativeAppSupport);
1108 :
1109 0 : if (mServiceManager) {
1110 : #ifdef XP_MACOSX
1111 : // On OS X, we need a pool to catch cocoa objects that are autoreleased
1112 : // during teardown.
1113 : mozilla::MacAutoreleasePool pool;
1114 : #endif
1115 :
1116 0 : nsCOMPtr<nsIAppStartup> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID));
1117 0 : if (appStartup)
1118 0 : appStartup->DestroyHiddenWindow();
1119 :
1120 0 : gDirServiceProvider->DoShutdown();
1121 :
1122 0 : WriteConsoleLog();
1123 :
1124 0 : NS_ShutdownXPCOM(mServiceManager);
1125 0 : mServiceManager = nsnull;
1126 : }
1127 0 : }
1128 :
1129 : // {95d89e3e-a169-41a3-8e56-719978e15b12}
1130 : #define APPINFO_CID \
1131 : { 0x95d89e3e, 0xa169, 0x41a3, { 0x8e, 0x56, 0x71, 0x99, 0x78, 0xe1, 0x5b, 0x12 } }
1132 :
1133 : // {0C4A446C-EE82-41f2-8D04-D366D2C7A7D4}
1134 : static const nsCID kNativeAppSupportCID =
1135 : { 0xc4a446c, 0xee82, 0x41f2, { 0x8d, 0x4, 0xd3, 0x66, 0xd2, 0xc7, 0xa7, 0xd4 } };
1136 :
1137 : // {5F5E59CE-27BC-47eb-9D1F-B09CA9049836}
1138 : static const nsCID kProfileServiceCID =
1139 : { 0x5f5e59ce, 0x27bc, 0x47eb, { 0x9d, 0x1f, 0xb0, 0x9c, 0xa9, 0x4, 0x98, 0x36 } };
1140 :
1141 : static already_AddRefed<nsIFactory>
1142 0 : ProfileServiceFactoryConstructor(const mozilla::Module& module, const mozilla::Module::CIDEntry& entry)
1143 : {
1144 0 : nsCOMPtr<nsIFactory> factory;
1145 0 : NS_NewToolkitProfileFactory(getter_AddRefs(factory));
1146 0 : return factory.forget();
1147 : }
1148 :
1149 : NS_DEFINE_NAMED_CID(APPINFO_CID);
1150 :
1151 : static const mozilla::Module::CIDEntry kXRECIDs[] = {
1152 : { &kAPPINFO_CID, false, NULL, AppInfoConstructor },
1153 : { &kProfileServiceCID, false, ProfileServiceFactoryConstructor, NULL },
1154 : { &kNativeAppSupportCID, false, NULL, ScopedXPCOMStartup::CreateAppSupport },
1155 : { NULL }
1156 : };
1157 :
1158 : static const mozilla::Module::ContractIDEntry kXREContracts[] = {
1159 : { XULAPPINFO_SERVICE_CONTRACTID, &kAPPINFO_CID },
1160 : { XULRUNTIME_SERVICE_CONTRACTID, &kAPPINFO_CID },
1161 : #ifdef MOZ_CRASHREPORTER
1162 : { NS_CRASHREPORTER_CONTRACTID, &kAPPINFO_CID },
1163 : #endif
1164 : { NS_PROFILESERVICE_CONTRACTID, &kProfileServiceCID },
1165 : { NS_NATIVEAPPSUPPORT_CONTRACTID, &kNativeAppSupportCID },
1166 : { NULL }
1167 : };
1168 :
1169 : static const mozilla::Module kXREModule = {
1170 : mozilla::Module::kVersion,
1171 : kXRECIDs,
1172 : kXREContracts
1173 : };
1174 :
1175 : NSMODULE_DEFN(Apprunner) = &kXREModule;
1176 :
1177 : nsresult
1178 0 : ScopedXPCOMStartup::Initialize()
1179 : {
1180 0 : NS_ASSERTION(gDirServiceProvider, "Should not get here!");
1181 :
1182 : nsresult rv;
1183 :
1184 : rv = NS_InitXPCOM2(&mServiceManager, gDirServiceProvider->GetAppDir(),
1185 0 : gDirServiceProvider);
1186 0 : if (NS_FAILED(rv)) {
1187 0 : NS_ERROR("Couldn't start xpcom!");
1188 0 : mServiceManager = nsnull;
1189 : }
1190 : else {
1191 : nsCOMPtr<nsIComponentRegistrar> reg =
1192 0 : do_QueryInterface(mServiceManager);
1193 0 : NS_ASSERTION(reg, "Service Manager doesn't QI to Registrar.");
1194 : }
1195 :
1196 0 : return rv;
1197 : }
1198 :
1199 : /**
1200 : * This is a little factory class that serves as a singleton-service-factory
1201 : * for the nativeappsupport object.
1202 : */
1203 : class nsSingletonFactory : public nsIFactory
1204 : {
1205 : public:
1206 : NS_DECL_ISUPPORTS
1207 : NS_DECL_NSIFACTORY
1208 :
1209 : nsSingletonFactory(nsISupports* aSingleton);
1210 0 : ~nsSingletonFactory() { }
1211 :
1212 : private:
1213 : nsCOMPtr<nsISupports> mSingleton;
1214 : };
1215 :
1216 0 : nsSingletonFactory::nsSingletonFactory(nsISupports* aSingleton)
1217 0 : : mSingleton(aSingleton)
1218 : {
1219 0 : NS_ASSERTION(mSingleton, "Singleton was null!");
1220 0 : }
1221 :
1222 0 : NS_IMPL_ISUPPORTS1(nsSingletonFactory, nsIFactory)
1223 :
1224 : NS_IMETHODIMP
1225 0 : nsSingletonFactory::CreateInstance(nsISupports* aOuter,
1226 : const nsIID& aIID,
1227 : void* *aResult)
1228 : {
1229 0 : NS_ENSURE_NO_AGGREGATION(aOuter);
1230 :
1231 0 : return mSingleton->QueryInterface(aIID, aResult);
1232 : }
1233 :
1234 : NS_IMETHODIMP
1235 0 : nsSingletonFactory::LockFactory(bool)
1236 : {
1237 0 : return NS_OK;
1238 : }
1239 :
1240 : /**
1241 : * Set our windowcreator on the WindowWatcher service.
1242 : */
1243 : nsresult
1244 0 : ScopedXPCOMStartup::SetWindowCreator(nsINativeAppSupport* native)
1245 : {
1246 : NS_TIME_FUNCTION;
1247 : nsresult rv;
1248 :
1249 0 : NS_IF_ADDREF(gNativeAppSupport = native);
1250 :
1251 : // Inform the chrome registry about OS accessibility
1252 : nsCOMPtr<nsIToolkitChromeRegistry> cr =
1253 0 : mozilla::services::GetToolkitChromeRegistryService();
1254 : NS_TIME_FUNCTION_MARK("Got ToolkitChromeRegistry service");
1255 :
1256 0 : if (cr)
1257 0 : cr->CheckForOSAccessibility();
1258 :
1259 : NS_TIME_FUNCTION_MARK("OS Accessibility check");
1260 :
1261 0 : nsCOMPtr<nsIWindowCreator> creator (do_GetService(NS_APPSTARTUP_CONTRACTID));
1262 0 : if (!creator) return NS_ERROR_UNEXPECTED;
1263 :
1264 : NS_TIME_FUNCTION_MARK("Got AppStartup service");
1265 :
1266 : nsCOMPtr<nsIWindowWatcher> wwatch
1267 0 : (do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
1268 0 : NS_ENSURE_SUCCESS(rv, rv);
1269 :
1270 : NS_TIME_FUNCTION_MARK("Got WindowWatcher service");
1271 :
1272 0 : return wwatch->SetWindowCreator(creator);
1273 : }
1274 :
1275 : /* static */ nsresult
1276 0 : ScopedXPCOMStartup::CreateAppSupport(nsISupports* aOuter, REFNSIID aIID, void** aResult)
1277 : {
1278 0 : if (aOuter)
1279 0 : return NS_ERROR_NO_AGGREGATION;
1280 :
1281 0 : if (!gNativeAppSupport)
1282 0 : return NS_ERROR_NOT_INITIALIZED;
1283 :
1284 0 : return gNativeAppSupport->QueryInterface(aIID, aResult);
1285 : }
1286 :
1287 : nsINativeAppSupport* ScopedXPCOMStartup::gNativeAppSupport;
1288 :
1289 : /**
1290 : * A helper class which calls NS_LogInit/NS_LogTerm in its scope.
1291 : */
1292 : class ScopedLogging
1293 : {
1294 : public:
1295 23 : ScopedLogging() { NS_LogInit(); }
1296 23 : ~ScopedLogging() { NS_LogTerm(); }
1297 : };
1298 :
1299 0 : static void DumpArbitraryHelp()
1300 : {
1301 : nsresult rv;
1302 :
1303 0 : ScopedLogging log;
1304 :
1305 : {
1306 0 : ScopedXPCOMStartup xpcom;
1307 0 : xpcom.Initialize();
1308 :
1309 : nsCOMPtr<nsICommandLineRunner> cmdline
1310 0 : (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
1311 0 : if (!cmdline)
1312 : return;
1313 :
1314 0 : nsCString text;
1315 0 : rv = cmdline->GetHelpText(text);
1316 0 : if (NS_SUCCEEDED(rv))
1317 0 : printf("%s", text.get());
1318 : }
1319 : }
1320 :
1321 : // English text needs to go into a dtd file.
1322 : // But when this is called we have no components etc. These strings must either be
1323 : // here, or in a native resource file.
1324 : static void
1325 0 : DumpHelp()
1326 : {
1327 : printf("Usage: %s [ options ... ] [URL]\n"
1328 0 : " where options include:\n\n", gArgv[0]);
1329 :
1330 : #ifdef MOZ_X11
1331 : printf("X11 options\n"
1332 : " --display=DISPLAY X display to use\n"
1333 0 : " --sync Make X calls synchronous\n");
1334 : #endif
1335 : #ifdef XP_UNIX
1336 : printf(" --g-fatal-warnings Make all warnings fatal\n"
1337 0 : "\n%s options\n", gAppData->name);
1338 : #endif
1339 :
1340 : printf(" -h or -help Print this message.\n"
1341 : " -v or -version Print %s version.\n"
1342 : " -P <profile> Start with <profile>.\n"
1343 : " -migration Start with migration wizard.\n"
1344 : " -ProfileManager Start with ProfileManager.\n"
1345 : " -no-remote Do not accept or send remote commands; implies -new-instance.\n"
1346 : " -new-instance Open new instance, not a new window in running instance.\n"
1347 : " -UILocale <locale> Start with <locale> resources as UI Locale.\n"
1348 0 : " -safe-mode Disables extensions and themes for this session.\n", gAppData->name);
1349 :
1350 : #if defined(XP_WIN) || defined(XP_OS2)
1351 : printf(" -console Start %s with a debugging console.\n", gAppData->name);
1352 : #endif
1353 :
1354 : // this works, but only after the components have registered. so if you drop in a new command line handler, -help
1355 : // won't not until the second run.
1356 : // out of the bug, because we ship a component.reg file, it works correctly.
1357 0 : DumpArbitraryHelp();
1358 0 : }
1359 :
1360 : #ifdef DEBUG_warren
1361 : #ifdef XP_WIN
1362 : #define _CRTDBG_MAP_ALLOC
1363 : #include <crtdbg.h>
1364 : #endif
1365 : #endif
1366 :
1367 : #if defined(FREEBSD)
1368 : // pick up fpsetmask prototype.
1369 : #include <ieeefp.h>
1370 : #endif
1371 :
1372 : static inline void
1373 0 : DumpVersion()
1374 : {
1375 : printf("%s %s %s",
1376 0 : gAppData->vendor ? gAppData->vendor : "", gAppData->name, gAppData->version);
1377 0 : if (gAppData->copyright)
1378 0 : printf(", %s", gAppData->copyright);
1379 0 : printf("\n");
1380 0 : }
1381 :
1382 : #ifdef MOZ_ENABLE_XREMOTE
1383 : // use int here instead of a PR type since it will be returned
1384 : // from main - just to keep types consistent
1385 : static int
1386 0 : HandleRemoteArgument(const char* remote, const char* aDesktopStartupID)
1387 : {
1388 : nsresult rv;
1389 : ArgResult ar;
1390 :
1391 0 : const char *profile = 0;
1392 0 : nsCAutoString program(gAppData->name);
1393 0 : ToLowerCase(program);
1394 0 : const char *username = getenv("LOGNAME");
1395 :
1396 0 : ar = CheckArg("p", false, &profile);
1397 0 : if (ar == ARG_BAD) {
1398 0 : PR_fprintf(PR_STDERR, "Error: argument -p requires a profile name\n");
1399 0 : return 1;
1400 : }
1401 :
1402 0 : const char *temp = nsnull;
1403 0 : ar = CheckArg("a", false, &temp);
1404 0 : if (ar == ARG_BAD) {
1405 0 : PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
1406 0 : return 1;
1407 0 : } else if (ar == ARG_FOUND) {
1408 0 : program.Assign(temp);
1409 : }
1410 :
1411 0 : ar = CheckArg("u", false, &username);
1412 0 : if (ar == ARG_BAD) {
1413 0 : PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
1414 0 : return 1;
1415 : }
1416 :
1417 0 : XRemoteClient client;
1418 0 : rv = client.Init();
1419 0 : if (NS_FAILED(rv)) {
1420 0 : PR_fprintf(PR_STDERR, "Error: Failed to connect to X server.\n");
1421 0 : return 1;
1422 : }
1423 :
1424 0 : nsXPIDLCString response;
1425 0 : bool success = false;
1426 : rv = client.SendCommand(program.get(), username, profile, remote,
1427 0 : aDesktopStartupID, getter_Copies(response), &success);
1428 : // did the command fail?
1429 0 : if (NS_FAILED(rv)) {
1430 : PR_fprintf(PR_STDERR, "Error: Failed to send command: %s\n",
1431 0 : response ? response.get() : "No response included");
1432 0 : return 1;
1433 : }
1434 :
1435 0 : if (!success) {
1436 0 : PR_fprintf(PR_STDERR, "Error: No running window found\n");
1437 0 : return 2;
1438 : }
1439 :
1440 0 : return 0;
1441 : }
1442 :
1443 : static RemoteResult
1444 0 : RemoteCommandLine(const char* aDesktopStartupID)
1445 : {
1446 : nsresult rv;
1447 : ArgResult ar;
1448 :
1449 0 : nsCAutoString program(gAppData->name);
1450 0 : ToLowerCase(program);
1451 0 : const char *username = getenv("LOGNAME");
1452 :
1453 0 : const char *temp = nsnull;
1454 0 : ar = CheckArg("a", true, &temp);
1455 0 : if (ar == ARG_BAD) {
1456 0 : PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
1457 0 : return REMOTE_ARG_BAD;
1458 0 : } else if (ar == ARG_FOUND) {
1459 0 : program.Assign(temp);
1460 : }
1461 :
1462 0 : ar = CheckArg("u", true, &username);
1463 0 : if (ar == ARG_BAD) {
1464 0 : PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
1465 0 : return REMOTE_ARG_BAD;
1466 : }
1467 :
1468 0 : XRemoteClient client;
1469 0 : rv = client.Init();
1470 0 : if (NS_FAILED(rv))
1471 0 : return REMOTE_NOT_FOUND;
1472 :
1473 0 : nsXPIDLCString response;
1474 0 : bool success = false;
1475 : rv = client.SendCommandLine(program.get(), username, nsnull,
1476 : gArgc, gArgv, aDesktopStartupID,
1477 0 : getter_Copies(response), &success);
1478 : // did the command fail?
1479 0 : if (NS_FAILED(rv) || !success)
1480 0 : return REMOTE_NOT_FOUND;
1481 :
1482 0 : return REMOTE_FOUND;
1483 : }
1484 : #endif // MOZ_ENABLE_XREMOTE
1485 :
1486 : void
1487 0 : XRE_InitOmnijar(nsILocalFile* greOmni, nsILocalFile* appOmni)
1488 : {
1489 0 : mozilla::Omnijar::Init(greOmni, appOmni);
1490 0 : }
1491 :
1492 : nsresult
1493 1434 : XRE_GetBinaryPath(const char* argv0, nsILocalFile* *aResult)
1494 : {
1495 1434 : return mozilla::BinaryPath::GetFile(argv0, aResult);
1496 : }
1497 :
1498 : #define NS_ERROR_LAUNCHED_CHILD_PROCESS NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_PROFILE, 200)
1499 :
1500 : #ifdef XP_WIN
1501 : #include "nsWindowsRestart.cpp"
1502 : #include <shellapi.h>
1503 :
1504 : typedef BOOL (WINAPI* SetProcessDEPPolicyFunc)(DWORD dwFlags);
1505 : #endif
1506 :
1507 : #if defined(XP_OS2) && (__KLIBC__ == 0 && __KLIBC_MINOR__ >= 6) // broken kLibc
1508 : // Copy the environment maintained by the C library into an ASCIIZ array
1509 : // that can be used to pass it on to the OS/2 Dos* APIs (which otherwise
1510 : // don't know anything about the stuff set by PR_SetEnv() or setenv()).
1511 : char *createEnv()
1512 : {
1513 : // just allocate the maximum amount (24 kB = 0x60000 bytes), to be able to
1514 : // copy the existing environment
1515 : char *env = (char *)calloc(0x6000, sizeof(char));
1516 : if (!env) {
1517 : return NULL;
1518 : }
1519 :
1520 : // walk along the environ string array of the C library and copy
1521 : // everything (that fits) into the output environment array, leaving
1522 : // null bytes between the entries
1523 : char *penv = env; // movable pointer to result environment ASCIIZ array
1524 : int i = 0, space = 0x6000;
1525 : while (environ[i] && environ[i][0]) {
1526 : int len = strlen(environ[i]);
1527 : if (space - len <= 0) {
1528 : break;
1529 : }
1530 : strcpy(penv, environ[i]);
1531 : i++; // next environment variable
1532 : penv += len + 1; // jump to after next null byte
1533 : space -= len - 1; // subtract consumed length from usable space
1534 : }
1535 :
1536 : return env;
1537 : }
1538 :
1539 : // OS2LaunchChild() is there to replace _execv() which is broken in the C
1540 : // runtime library that comes with GCC 3.3.5 on OS/2. It uses createEnv()
1541 : // to copy the process environment and add necessary variables
1542 : //
1543 : // returns -1 on failure and 0 on success
1544 : int OS2LaunchChild(const char *aExePath, int aArgc, char **aArgv)
1545 : {
1546 : // find total length of aArgv
1547 : int len = 0;
1548 : for (int i = 0; i < aArgc; i++) {
1549 : len += strlen(aArgv[i]) + 1; // plus space in between
1550 : }
1551 : len++; // leave space for null byte at end
1552 : // allocate enough space for all strings and nulls,
1553 : // calloc helpfully initializes to null
1554 : char *args = (char *)calloc(len, sizeof(char));
1555 : if (!args) {
1556 : return -1;
1557 : }
1558 : char *pargs = args; // extra pointer to after the last argument
1559 : // build argument list in the format the DosStartSession() wants,
1560 : // adding spaces between the arguments
1561 : for (int i = 0; i < aArgc; i++, *pargs++ = ' ') {
1562 : strcpy(pargs, aArgv[i]);
1563 : pargs += strlen(aArgv[i]);
1564 : }
1565 : if (aArgc > 1) {
1566 : *(pargs-1) = '\0'; // replace last space
1567 : }
1568 : *pargs = '\0';
1569 : // make sure that the program is separated by null byte
1570 : pargs = strchr(args, ' ');
1571 : if (pargs) {
1572 : *pargs = '\0';
1573 : }
1574 :
1575 : char *env = createEnv();
1576 :
1577 : char error[CCHMAXPATH] = { 0 };
1578 : RESULTCODES crc = { 0 };
1579 : ULONG rc = DosExecPgm(error, sizeof(error), EXEC_ASYNC, args, env,
1580 : &crc, (PSZ)aExePath);
1581 : free(args); // done with the arguments
1582 : if (env) {
1583 : free(env);
1584 : }
1585 : if (rc != NO_ERROR) {
1586 : return -1;
1587 : }
1588 :
1589 : return 0;
1590 : }
1591 : #endif
1592 :
1593 : // If aBlankCommandLine is true, then the application will be launched with a
1594 : // blank command line instead of being launched with the same command line that
1595 : // it was initially started with.
1596 0 : static nsresult LaunchChild(nsINativeAppSupport* aNative,
1597 : bool aBlankCommandLine = false)
1598 : {
1599 0 : aNative->Quit(); // release DDE mutex, if we're holding it
1600 :
1601 : // Restart this process by exec'ing it into the current process
1602 : // if supported by the platform. Otherwise, use NSPR.
1603 :
1604 : #ifdef MOZ_JPROF
1605 : // make sure JPROF doesn't think we're E10s
1606 : unsetenv("JPROF_SLAVE");
1607 : #endif
1608 :
1609 0 : if (aBlankCommandLine) {
1610 : #if defined(MOZ_WIDGET_QT)
1611 : // Remove only arguments not given to Qt
1612 : gRestartArgc = gQtOnlyArgc;
1613 : gRestartArgv = gQtOnlyArgv;
1614 : #else
1615 0 : gRestartArgc = 1;
1616 0 : gRestartArgv[gRestartArgc] = nsnull;
1617 : #endif
1618 : }
1619 :
1620 0 : SaveToEnv("MOZ_LAUNCHED_CHILD=1");
1621 :
1622 : #if defined(MOZ_WIDGET_ANDROID)
1623 : mozilla::AndroidBridge::Bridge()->ScheduleRestart();
1624 : #else
1625 : #if defined(XP_MACOSX)
1626 : CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
1627 : PRUint32 restartMode = 0;
1628 : restartMode = gRestartMode;
1629 : LaunchChildMac(gRestartArgc, gRestartArgv, restartMode);
1630 : #else
1631 0 : nsCOMPtr<nsILocalFile> lf;
1632 0 : nsresult rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
1633 0 : if (NS_FAILED(rv))
1634 0 : return rv;
1635 :
1636 : #if defined(XP_WIN)
1637 : nsAutoString exePath;
1638 : rv = lf->GetPath(exePath);
1639 : if (NS_FAILED(rv))
1640 : return rv;
1641 :
1642 : if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv))
1643 : return NS_ERROR_FAILURE;
1644 :
1645 : #else
1646 0 : nsCAutoString exePath;
1647 0 : rv = lf->GetNativePath(exePath);
1648 0 : if (NS_FAILED(rv))
1649 0 : return rv;
1650 :
1651 : #if defined(XP_OS2) && (__KLIBC__ == 0 && __KLIBC_MINOR__ >= 6)
1652 : // implementation of _execv() is broken with kLibc 0.6.x and later
1653 : if (OS2LaunchChild(exePath.get(), gRestartArgc, gRestartArgv) == -1)
1654 : return NS_ERROR_FAILURE;
1655 : #elif defined(XP_OS2)
1656 : if (_execv(exePath.get(), gRestartArgv) == -1)
1657 : return NS_ERROR_FAILURE;
1658 : #elif defined(XP_UNIX)
1659 0 : if (execv(exePath.get(), gRestartArgv) == -1)
1660 0 : return NS_ERROR_FAILURE;
1661 : #else
1662 : PRProcess* process = PR_CreateProcess(exePath.get(), gRestartArgv,
1663 : nsnull, nsnull);
1664 : if (!process) return NS_ERROR_FAILURE;
1665 :
1666 : PRInt32 exitCode;
1667 : PRStatus failed = PR_WaitProcess(process, &exitCode);
1668 : if (failed || exitCode)
1669 : return NS_ERROR_FAILURE;
1670 : #endif // XP_OS2 series
1671 : #endif // WP_WIN
1672 : #endif // WP_MACOSX
1673 : #endif // MOZ_WIDGET_ANDROID
1674 :
1675 0 : return NS_ERROR_LAUNCHED_CHILD_PROCESS;
1676 : }
1677 :
1678 : static const char kProfileProperties[] =
1679 : "chrome://mozapps/locale/profile/profileSelection.properties";
1680 :
1681 : static nsresult
1682 0 : ProfileLockedDialog(nsILocalFile* aProfileDir, nsILocalFile* aProfileLocalDir,
1683 : nsIProfileUnlocker* aUnlocker,
1684 : nsINativeAppSupport* aNative, nsIProfileLock* *aResult)
1685 : {
1686 : nsresult rv;
1687 :
1688 0 : ScopedXPCOMStartup xpcom;
1689 0 : rv = xpcom.Initialize();
1690 0 : NS_ENSURE_SUCCESS(rv, rv);
1691 :
1692 0 : rv = xpcom.SetWindowCreator(aNative);
1693 0 : NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
1694 :
1695 : { //extra scoping is needed so we release these components before xpcom shutdown
1696 : nsCOMPtr<nsIStringBundleService> sbs =
1697 0 : mozilla::services::GetStringBundleService();
1698 0 : NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE);
1699 :
1700 0 : nsCOMPtr<nsIStringBundle> sb;
1701 0 : sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
1702 0 : NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE);
1703 :
1704 0 : NS_ConvertUTF8toUTF16 appName(gAppData->name);
1705 0 : const PRUnichar* params[] = {appName.get(), appName.get()};
1706 :
1707 0 : nsXPIDLString killMessage;
1708 : #ifndef XP_MACOSX
1709 : static const PRUnichar kRestartNoUnlocker[] = {'r','e','s','t','a','r','t','M','e','s','s','a','g','e','N','o','U','n','l','o','c','k','e','r','\0'}; // "restartMessageNoUnlocker"
1710 : static const PRUnichar kRestartUnlocker[] = {'r','e','s','t','a','r','t','M','e','s','s','a','g','e','U','n','l','o','c','k','e','r','\0'}; // "restartMessageUnlocker"
1711 : #else
1712 : static const PRUnichar kRestartNoUnlocker[] = {'r','e','s','t','a','r','t','M','e','s','s','a','g','e','N','o','U','n','l','o','c','k','e','r','M','a','c','\0'}; // "restartMessageNoUnlockerMac"
1713 : static const PRUnichar kRestartUnlocker[] = {'r','e','s','t','a','r','t','M','e','s','s','a','g','e','U','n','l','o','c','k','e','r','M','a','c','\0'}; // "restartMessageUnlockerMac"
1714 : #endif
1715 :
1716 0 : sb->FormatStringFromName(aUnlocker ? kRestartUnlocker : kRestartNoUnlocker,
1717 0 : params, 2, getter_Copies(killMessage));
1718 :
1719 0 : nsXPIDLString killTitle;
1720 0 : sb->FormatStringFromName(NS_LITERAL_STRING("restartTitle").get(),
1721 0 : params, 1, getter_Copies(killTitle));
1722 :
1723 0 : if (!killMessage || !killTitle)
1724 0 : return NS_ERROR_FAILURE;
1725 :
1726 : nsCOMPtr<nsIPromptService> ps
1727 0 : (do_GetService(NS_PROMPTSERVICE_CONTRACTID));
1728 0 : NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE);
1729 :
1730 0 : if (aUnlocker) {
1731 : const PRUint32 flags =
1732 : (nsIPromptService::BUTTON_TITLE_CANCEL *
1733 : nsIPromptService::BUTTON_POS_0) +
1734 : (nsIPromptService::BUTTON_TITLE_IS_STRING *
1735 : nsIPromptService::BUTTON_POS_1) +
1736 0 : nsIPromptService::BUTTON_POS_1_DEFAULT;
1737 :
1738 : PRInt32 button;
1739 : // The actual value is irrelevant but we shouldn't be handing out
1740 : // malformed JSBools to XPConnect.
1741 0 : bool checkState = false;
1742 0 : rv = ps->ConfirmEx(nsnull, killTitle, killMessage, flags,
1743 : killTitle, nsnull, nsnull, nsnull,
1744 0 : &checkState, &button);
1745 0 : NS_ENSURE_SUCCESS_LOG(rv, rv);
1746 :
1747 0 : if (button == 1) {
1748 0 : rv = aUnlocker->Unlock(nsIProfileUnlocker::FORCE_QUIT);
1749 0 : if (NS_FAILED(rv))
1750 0 : return rv;
1751 :
1752 : return NS_LockProfilePath(aProfileDir, aProfileLocalDir,
1753 0 : nsnull, aResult);
1754 : }
1755 : } else {
1756 0 : rv = ps->Alert(nsnull, killTitle, killMessage);
1757 0 : NS_ENSURE_SUCCESS_LOG(rv, rv);
1758 : }
1759 :
1760 0 : return NS_ERROR_ABORT;
1761 : }
1762 : }
1763 :
1764 : static nsresult
1765 0 : ProfileMissingDialog(nsINativeAppSupport* aNative)
1766 : {
1767 : nsresult rv;
1768 :
1769 0 : ScopedXPCOMStartup xpcom;
1770 0 : rv = xpcom.Initialize();
1771 0 : NS_ENSURE_SUCCESS(rv, rv);
1772 :
1773 0 : rv = xpcom.SetWindowCreator(aNative);
1774 0 : NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
1775 :
1776 : { //extra scoping is needed so we release these components before xpcom shutdown
1777 : nsCOMPtr<nsIStringBundleService> sbs =
1778 0 : mozilla::services::GetStringBundleService();
1779 0 : NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE);
1780 :
1781 0 : nsCOMPtr<nsIStringBundle> sb;
1782 0 : sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
1783 0 : NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE);
1784 :
1785 0 : NS_ConvertUTF8toUTF16 appName(gAppData->name);
1786 0 : const PRUnichar* params[] = {appName.get(), appName.get()};
1787 :
1788 0 : nsXPIDLString missingMessage;
1789 :
1790 : // profileMissing
1791 : static const PRUnichar kMissing[] = {'p','r','o','f','i','l','e','M','i','s','s','i','n','g','\0'};
1792 0 : sb->FormatStringFromName(kMissing, params, 2, getter_Copies(missingMessage));
1793 :
1794 0 : nsXPIDLString missingTitle;
1795 0 : sb->FormatStringFromName(NS_LITERAL_STRING("profileMissingTitle").get(),
1796 0 : params, 1, getter_Copies(missingTitle));
1797 :
1798 0 : if (missingMessage && missingTitle) {
1799 : nsCOMPtr<nsIPromptService> ps
1800 0 : (do_GetService(NS_PROMPTSERVICE_CONTRACTID));
1801 0 : NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE);
1802 :
1803 0 : ps->Alert(nsnull, missingTitle, missingMessage);
1804 : }
1805 :
1806 0 : return NS_ERROR_ABORT;
1807 : }
1808 : }
1809 :
1810 : static const char kProfileManagerURL[] =
1811 : "chrome://mozapps/content/profile/profileSelection.xul";
1812 :
1813 : static nsresult
1814 0 : ShowProfileManager(nsIToolkitProfileService* aProfileSvc,
1815 : nsINativeAppSupport* aNative)
1816 : {
1817 : nsresult rv;
1818 :
1819 0 : nsCOMPtr<nsILocalFile> profD, profLD;
1820 : PRUnichar* profileNamePtr;
1821 0 : nsCAutoString profileName;
1822 :
1823 : {
1824 0 : ScopedXPCOMStartup xpcom;
1825 0 : rv = xpcom.Initialize();
1826 0 : NS_ENSURE_SUCCESS(rv, rv);
1827 :
1828 0 : rv = xpcom.SetWindowCreator(aNative);
1829 0 : NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
1830 :
1831 : #ifdef XP_MACOSX
1832 : CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
1833 : #endif
1834 :
1835 : #ifdef XP_WIN
1836 : // we don't have to wait here because profile manager window will pump
1837 : // and DDE message will be handled
1838 : ProcessDDE(aNative, false);
1839 : #endif
1840 :
1841 : { //extra scoping is needed so we release these components before xpcom shutdown
1842 : nsCOMPtr<nsIWindowWatcher> windowWatcher
1843 0 : (do_GetService(NS_WINDOWWATCHER_CONTRACTID));
1844 : nsCOMPtr<nsIDialogParamBlock> ioParamBlock
1845 0 : (do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID));
1846 0 : nsCOMPtr<nsIMutableArray> dlgArray (do_CreateInstance(NS_ARRAY_CONTRACTID));
1847 0 : NS_ENSURE_TRUE(windowWatcher && ioParamBlock && dlgArray, NS_ERROR_FAILURE);
1848 :
1849 0 : ioParamBlock->SetObjects(dlgArray);
1850 :
1851 : nsCOMPtr<nsIAppStartup> appStartup
1852 0 : (do_GetService(NS_APPSTARTUP_CONTRACTID));
1853 0 : NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE);
1854 :
1855 0 : nsCOMPtr<nsIDOMWindow> newWindow;
1856 0 : rv = windowWatcher->OpenWindow(nsnull,
1857 : kProfileManagerURL,
1858 : "_blank",
1859 : "centerscreen,chrome,modal,titlebar",
1860 : ioParamBlock,
1861 0 : getter_AddRefs(newWindow));
1862 :
1863 0 : NS_ENSURE_SUCCESS_LOG(rv, rv);
1864 :
1865 0 : aProfileSvc->Flush();
1866 :
1867 : PRInt32 dialogConfirmed;
1868 0 : rv = ioParamBlock->GetInt(0, &dialogConfirmed);
1869 0 : if (NS_FAILED(rv) || dialogConfirmed == 0) return NS_ERROR_ABORT;
1870 :
1871 0 : nsCOMPtr<nsIProfileLock> lock;
1872 0 : rv = dlgArray->QueryElementAt(0, NS_GET_IID(nsIProfileLock),
1873 0 : getter_AddRefs(lock));
1874 0 : NS_ENSURE_SUCCESS_LOG(rv, rv);
1875 :
1876 0 : rv = lock->GetDirectory(getter_AddRefs(profD));
1877 0 : NS_ENSURE_SUCCESS(rv, rv);
1878 :
1879 0 : rv = lock->GetLocalDirectory(getter_AddRefs(profLD));
1880 0 : NS_ENSURE_SUCCESS(rv, rv);
1881 :
1882 0 : rv = ioParamBlock->GetString(0, &profileNamePtr);
1883 0 : NS_ENSURE_SUCCESS(rv, rv);
1884 :
1885 0 : CopyUTF16toUTF8(profileNamePtr, profileName);
1886 0 : NS_Free(profileNamePtr);
1887 :
1888 0 : lock->Unlock();
1889 : }
1890 : }
1891 :
1892 0 : SaveFileToEnv("XRE_PROFILE_PATH", profD);
1893 0 : SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", profLD);
1894 0 : SaveWordToEnv("XRE_PROFILE_NAME", profileName);
1895 :
1896 0 : bool offline = false;
1897 0 : aProfileSvc->GetStartOffline(&offline);
1898 0 : if (offline) {
1899 0 : SaveToEnv("XRE_START_OFFLINE=1");
1900 : }
1901 :
1902 0 : return LaunchChild(aNative);
1903 : }
1904 :
1905 : // Pick a profile. We need to end up with a profile lock.
1906 : //
1907 : // 1) check for -profile <path>
1908 : // 2) check for -P <name>
1909 : // 3) check for -ProfileManager
1910 : // 4) use the default profile, if there is one
1911 : // 5) if there are *no* profiles, set up profile-migration
1912 : // 6) display the profile-manager UI
1913 :
1914 : static bool gDoMigration = false;
1915 : static bool gDoProfileReset = false;
1916 :
1917 : /**
1918 : * Creates a new profile with a timestamp in the name to use for profile reset.
1919 : */
1920 : static nsresult
1921 0 : ResetProfile(nsIToolkitProfileService* aProfileSvc, nsIToolkitProfile* *aNewProfile)
1922 : {
1923 0 : NS_ENSURE_ARG_POINTER(aProfileSvc);
1924 :
1925 0 : nsCOMPtr<nsIToolkitProfile> newProfile;
1926 : // Make the new profile "default-" + the time in seconds since epoch for uniqueness.
1927 0 : nsCAutoString newProfileName("default-");
1928 0 : newProfileName.Append(nsPrintfCString("%lld", PR_Now() / 1000));
1929 : nsresult rv = aProfileSvc->CreateProfile(nsnull, // choose a default dir for us
1930 : nsnull, // choose a default dir for us
1931 : newProfileName,
1932 0 : getter_AddRefs(newProfile));
1933 0 : NS_ENSURE_SUCCESS(rv, rv);
1934 :
1935 0 : rv = aProfileSvc->Flush();
1936 0 : NS_ENSURE_SUCCESS(rv, rv);
1937 :
1938 0 : NS_IF_ADDREF(*aNewProfile = newProfile);
1939 :
1940 0 : return NS_OK;
1941 : }
1942 :
1943 : /**
1944 : * Set the currently running profile as the default/selected one.
1945 : *
1946 : * @param aCurrentProfileRoot The root directory of the current profile.
1947 : * @return an error if aCurrentProfileRoot is not found or the profile could not
1948 : * be set as the default.
1949 : */
1950 : static nsresult
1951 0 : SetCurrentProfileAsDefault(nsIToolkitProfileService* aProfileSvc,
1952 : nsILocalFile* aCurrentProfileRoot)
1953 : {
1954 0 : NS_ENSURE_ARG_POINTER(aProfileSvc);
1955 :
1956 0 : nsCOMPtr<nsISimpleEnumerator> profiles;
1957 0 : nsresult rv = aProfileSvc->GetProfiles(getter_AddRefs(profiles));
1958 0 : if (NS_FAILED(rv))
1959 0 : return rv;
1960 :
1961 0 : bool foundMatchingProfile = false;
1962 0 : nsCOMPtr<nsIToolkitProfile> profile;
1963 0 : rv = profiles->GetNext(getter_AddRefs(profile));
1964 0 : while (NS_SUCCEEDED(rv)) {
1965 0 : nsCOMPtr<nsILocalFile> profileRoot;
1966 0 : profile->GetRootDir(getter_AddRefs(profileRoot));
1967 0 : profileRoot->Equals(aCurrentProfileRoot, &foundMatchingProfile);
1968 0 : if (foundMatchingProfile && profile) {
1969 0 : rv = aProfileSvc->SetSelectedProfile(profile);
1970 0 : if (NS_SUCCEEDED(rv))
1971 0 : rv = aProfileSvc->Flush();
1972 0 : return rv;
1973 : }
1974 0 : rv = profiles->GetNext(getter_AddRefs(profile));
1975 : }
1976 0 : return rv;
1977 : }
1978 :
1979 : static nsresult
1980 0 : SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, nsINativeAppSupport* aNative,
1981 : bool* aStartOffline, nsACString* aProfileName)
1982 : {
1983 : nsresult rv;
1984 : ArgResult ar;
1985 : const char* arg;
1986 0 : *aResult = nsnull;
1987 0 : *aStartOffline = false;
1988 :
1989 0 : ar = CheckArg("offline", true);
1990 0 : if (ar == ARG_BAD) {
1991 0 : PR_fprintf(PR_STDERR, "Error: argument -offline is invalid when argument -osint is specified\n");
1992 0 : return NS_ERROR_FAILURE;
1993 : }
1994 :
1995 0 : if (ar || EnvHasValue("XRE_START_OFFLINE"))
1996 0 : *aStartOffline = true;
1997 :
1998 0 : if (EnvHasValue("MOZ_RESET_PROFILE_RESTART")) {
1999 0 : gDoProfileReset = true;
2000 0 : gDoMigration = true;
2001 0 : SaveToEnv("MOZ_RESET_PROFILE_RESTART=");
2002 : }
2003 :
2004 : // reset-profile and migration args need to be checked before any profiles are chosen below.
2005 0 : ar = CheckArg("reset-profile", true);
2006 0 : if (ar == ARG_BAD) {
2007 0 : PR_fprintf(PR_STDERR, "Error: argument -reset-profile is invalid when argument -osint is specified\n");
2008 0 : return NS_ERROR_FAILURE;
2009 0 : } else if (ar == ARG_FOUND) {
2010 0 : gDoProfileReset = true;
2011 : }
2012 :
2013 0 : ar = CheckArg("migration", true);
2014 0 : if (ar == ARG_BAD) {
2015 0 : PR_fprintf(PR_STDERR, "Error: argument -migration is invalid when argument -osint is specified\n");
2016 0 : return NS_ERROR_FAILURE;
2017 0 : } else if (ar == ARG_FOUND) {
2018 0 : gDoMigration = true;
2019 : }
2020 :
2021 0 : nsCOMPtr<nsILocalFile> lf = GetFileFromEnv("XRE_PROFILE_PATH");
2022 0 : if (lf) {
2023 : nsCOMPtr<nsILocalFile> localDir =
2024 0 : GetFileFromEnv("XRE_PROFILE_LOCAL_PATH");
2025 0 : if (!localDir) {
2026 0 : localDir = lf;
2027 : }
2028 :
2029 0 : arg = PR_GetEnv("XRE_PROFILE_NAME");
2030 0 : if (arg && *arg && aProfileName)
2031 0 : aProfileName->Assign(nsDependentCString(arg));
2032 :
2033 : // Clear out flags that we handled (or should have handled!) last startup.
2034 : const char *dummy;
2035 0 : CheckArg("p", false, &dummy);
2036 0 : CheckArg("profile", false, &dummy);
2037 0 : CheckArg("profilemanager");
2038 :
2039 0 : if (gDoProfileReset) {
2040 : // If we're resetting a profile, create a new one and use it to startup.
2041 0 : nsCOMPtr<nsIToolkitProfile> newProfile;
2042 0 : rv = ResetProfile(aProfileSvc, getter_AddRefs(newProfile));
2043 0 : if (NS_SUCCEEDED(rv)) {
2044 0 : rv = newProfile->GetRootDir(getter_AddRefs(lf));
2045 0 : NS_ENSURE_SUCCESS(rv, rv);
2046 0 : SaveFileToEnv("XRE_PROFILE_PATH", lf);
2047 :
2048 0 : rv = newProfile->GetLocalDir(getter_AddRefs(localDir));
2049 0 : NS_ENSURE_SUCCESS(rv, rv);
2050 0 : SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", localDir);
2051 :
2052 0 : rv = newProfile->GetName(*aProfileName);
2053 0 : if (NS_FAILED(rv))
2054 0 : aProfileName->Truncate(0);
2055 0 : SaveWordToEnv("XRE_PROFILE_NAME", *aProfileName);
2056 : } else {
2057 0 : NS_WARNING("Profile reset failed.");
2058 0 : gDoProfileReset = false;
2059 : }
2060 : }
2061 :
2062 0 : return NS_LockProfilePath(lf, localDir, nsnull, aResult);
2063 : }
2064 :
2065 0 : ar = CheckArg("profile", true, &arg);
2066 0 : if (ar == ARG_BAD) {
2067 0 : PR_fprintf(PR_STDERR, "Error: argument -profile requires a path\n");
2068 0 : return NS_ERROR_FAILURE;
2069 : }
2070 0 : if (ar) {
2071 0 : if (gDoProfileReset) {
2072 0 : NS_WARNING("Profile reset is only supported for the default profile.");
2073 0 : gDoProfileReset = false;
2074 : }
2075 :
2076 0 : nsCOMPtr<nsILocalFile> lf;
2077 0 : rv = XRE_GetFileFromPath(arg, getter_AddRefs(lf));
2078 0 : NS_ENSURE_SUCCESS(rv, rv);
2079 :
2080 0 : nsCOMPtr<nsIProfileUnlocker> unlocker;
2081 :
2082 : // Check if the profile path exists and it's a directory.
2083 : bool exists;
2084 0 : lf->Exists(&exists);
2085 0 : if (!exists) {
2086 0 : rv = lf->Create(nsIFile::DIRECTORY_TYPE, 0700);
2087 0 : NS_ENSURE_SUCCESS(rv, rv);
2088 : }
2089 :
2090 : // If a profile path is specified directory on the command line, then
2091 : // assume that the temp directory is the same as the given directory.
2092 0 : rv = NS_LockProfilePath(lf, lf, getter_AddRefs(unlocker), aResult);
2093 0 : if (NS_SUCCEEDED(rv))
2094 0 : return rv;
2095 :
2096 0 : return ProfileLockedDialog(lf, lf, unlocker, aNative, aResult);
2097 : }
2098 :
2099 0 : ar = CheckArg("createprofile", true, &arg);
2100 0 : if (ar == ARG_BAD) {
2101 0 : PR_fprintf(PR_STDERR, "Error: argument -createprofile requires a profile name\n");
2102 0 : return NS_ERROR_FAILURE;
2103 : }
2104 0 : if (ar) {
2105 0 : nsCOMPtr<nsIToolkitProfile> profile;
2106 :
2107 0 : const char* delim = strchr(arg, ' ');
2108 0 : if (delim) {
2109 0 : nsCOMPtr<nsILocalFile> lf;
2110 0 : rv = NS_NewNativeLocalFile(nsDependentCString(delim + 1),
2111 0 : true, getter_AddRefs(lf));
2112 0 : if (NS_FAILED(rv)) {
2113 0 : PR_fprintf(PR_STDERR, "Error: profile path not valid.\n");
2114 0 : return rv;
2115 : }
2116 :
2117 : // As with -profile, assume that the given path will be used for both the
2118 : // main profile directory and the temp profile directory.
2119 0 : rv = aProfileSvc->CreateProfile(lf, lf, nsDependentCSubstring(arg, delim),
2120 0 : getter_AddRefs(profile));
2121 : } else {
2122 0 : rv = aProfileSvc->CreateProfile(nsnull, nsnull, nsDependentCString(arg),
2123 0 : getter_AddRefs(profile));
2124 : }
2125 : // Some pathological arguments can make it this far
2126 0 : if (NS_FAILED(rv)) {
2127 0 : PR_fprintf(PR_STDERR, "Error creating profile.\n");
2128 0 : return rv;
2129 : }
2130 0 : rv = NS_ERROR_ABORT;
2131 0 : aProfileSvc->Flush();
2132 :
2133 : // XXXben need to ensure prefs.js exists here so the tinderboxes will
2134 : // not go orange.
2135 0 : nsCOMPtr<nsILocalFile> prefsJSFile;
2136 0 : profile->GetRootDir(getter_AddRefs(prefsJSFile));
2137 0 : prefsJSFile->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
2138 0 : nsCAutoString pathStr;
2139 0 : prefsJSFile->GetNativePath(pathStr);
2140 0 : PR_fprintf(PR_STDERR, "Success: created profile '%s' at '%s'\n", arg, pathStr.get());
2141 : bool exists;
2142 0 : prefsJSFile->Exists(&exists);
2143 0 : if (!exists)
2144 0 : prefsJSFile->Create(nsIFile::NORMAL_FILE_TYPE, 0644);
2145 : // XXXdarin perhaps 0600 would be better?
2146 :
2147 0 : return rv;
2148 : }
2149 :
2150 : PRUint32 count;
2151 0 : rv = aProfileSvc->GetProfileCount(&count);
2152 0 : NS_ENSURE_SUCCESS(rv, rv);
2153 :
2154 0 : ar = CheckArg("p", false, &arg);
2155 0 : if (ar == ARG_BAD) {
2156 0 : ar = CheckArg("osint");
2157 0 : if (ar == ARG_FOUND) {
2158 0 : PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument -osint is specified\n");
2159 0 : return NS_ERROR_FAILURE;
2160 : }
2161 0 : return ShowProfileManager(aProfileSvc, aNative);
2162 : }
2163 0 : if (ar) {
2164 0 : ar = CheckArg("osint");
2165 0 : if (ar == ARG_FOUND) {
2166 0 : PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument -osint is specified\n");
2167 0 : return NS_ERROR_FAILURE;
2168 : }
2169 0 : nsCOMPtr<nsIToolkitProfile> profile;
2170 0 : rv = aProfileSvc->GetProfileByName(nsDependentCString(arg),
2171 0 : getter_AddRefs(profile));
2172 0 : if (NS_SUCCEEDED(rv)) {
2173 : // If we're resetting a profile, create a new one and use it to startup.
2174 0 : if (gDoProfileReset) {
2175 0 : NS_WARNING("Profile reset is only supported for the default profile.");
2176 0 : gDoProfileReset = false;
2177 : }
2178 :
2179 0 : nsCOMPtr<nsIProfileUnlocker> unlocker;
2180 0 : rv = profile->Lock(nsnull, aResult);
2181 0 : if (NS_SUCCEEDED(rv)) {
2182 0 : if (aProfileName)
2183 0 : aProfileName->Assign(nsDependentCString(arg));
2184 0 : return NS_OK;
2185 : }
2186 :
2187 0 : nsCOMPtr<nsILocalFile> profileDir;
2188 0 : rv = profile->GetRootDir(getter_AddRefs(profileDir));
2189 0 : NS_ENSURE_SUCCESS(rv, rv);
2190 :
2191 0 : nsCOMPtr<nsILocalFile> profileLocalDir;
2192 0 : rv = profile->GetLocalDir(getter_AddRefs(profileLocalDir));
2193 0 : NS_ENSURE_SUCCESS(rv, rv);
2194 :
2195 : return ProfileLockedDialog(profileDir, profileLocalDir, unlocker,
2196 0 : aNative, aResult);
2197 : }
2198 :
2199 0 : return ShowProfileManager(aProfileSvc, aNative);
2200 : }
2201 :
2202 0 : ar = CheckArg("profilemanager", true);
2203 0 : if (ar == ARG_BAD) {
2204 0 : PR_fprintf(PR_STDERR, "Error: argument -profilemanager is invalid when argument -osint is specified\n");
2205 0 : return NS_ERROR_FAILURE;
2206 0 : } else if (ar == ARG_FOUND) {
2207 0 : return ShowProfileManager(aProfileSvc, aNative);
2208 : }
2209 :
2210 0 : if (!count) {
2211 0 : gDoMigration = true;
2212 0 : gDoProfileReset = false;
2213 :
2214 : // create a default profile
2215 0 : nsCOMPtr<nsIToolkitProfile> profile;
2216 : nsresult rv = aProfileSvc->CreateProfile(nsnull, // choose a default dir for us
2217 : nsnull, // choose a default dir for us
2218 0 : NS_LITERAL_CSTRING("default"),
2219 0 : getter_AddRefs(profile));
2220 0 : if (NS_SUCCEEDED(rv)) {
2221 0 : aProfileSvc->Flush();
2222 0 : rv = profile->Lock(nsnull, aResult);
2223 0 : if (NS_SUCCEEDED(rv)) {
2224 0 : if (aProfileName)
2225 0 : aProfileName->Assign(NS_LITERAL_CSTRING("default"));
2226 0 : return NS_OK;
2227 : }
2228 : }
2229 : }
2230 :
2231 0 : bool useDefault = true;
2232 0 : if (count > 1)
2233 0 : aProfileSvc->GetStartWithLastProfile(&useDefault);
2234 :
2235 0 : if (useDefault) {
2236 0 : nsCOMPtr<nsIToolkitProfile> profile;
2237 : // GetSelectedProfile will auto-select the only profile if there's just one
2238 0 : aProfileSvc->GetSelectedProfile(getter_AddRefs(profile));
2239 0 : if (profile) {
2240 : // If we're resetting a profile, create a new one and use it to startup.
2241 0 : if (gDoProfileReset) {
2242 0 : nsCOMPtr<nsIToolkitProfile> newProfile;
2243 0 : rv = ResetProfile(aProfileSvc, getter_AddRefs(newProfile));
2244 0 : if (NS_SUCCEEDED(rv))
2245 0 : profile = newProfile;
2246 : else
2247 0 : gDoProfileReset = false;
2248 : }
2249 0 : nsCOMPtr<nsIProfileUnlocker> unlocker;
2250 0 : rv = profile->Lock(getter_AddRefs(unlocker), aResult);
2251 0 : if (NS_SUCCEEDED(rv)) {
2252 : // Try to grab the profile name.
2253 0 : if (aProfileName) {
2254 0 : rv = profile->GetName(*aProfileName);
2255 0 : if (NS_FAILED(rv))
2256 0 : aProfileName->Truncate(0);
2257 : }
2258 0 : return NS_OK;
2259 : }
2260 :
2261 0 : nsCOMPtr<nsILocalFile> profileDir;
2262 0 : rv = profile->GetRootDir(getter_AddRefs(profileDir));
2263 0 : NS_ENSURE_SUCCESS(rv, rv);
2264 :
2265 0 : nsCOMPtr<nsILocalFile> profileLocalDir;
2266 0 : rv = profile->GetRootDir(getter_AddRefs(profileLocalDir));
2267 0 : NS_ENSURE_SUCCESS(rv, rv);
2268 :
2269 : return ProfileLockedDialog(profileDir, profileLocalDir, unlocker,
2270 0 : aNative, aResult);
2271 : }
2272 : }
2273 :
2274 0 : return ShowProfileManager(aProfileSvc, aNative);
2275 : }
2276 :
2277 : /**
2278 : * Checks the compatibility.ini file to see if we have updated our application
2279 : * or otherwise invalidated our caches. If the application has been updated,
2280 : * we return false; otherwise, we return true. We also write the status
2281 : * of the caches (valid/invalid) into the return param aCachesOK. The aCachesOK
2282 : * is always invalid if the application has been updated.
2283 : */
2284 : static bool
2285 0 : CheckCompatibility(nsIFile* aProfileDir, const nsCString& aVersion,
2286 : const nsCString& aOSABI, nsIFile* aXULRunnerDir,
2287 : nsIFile* aAppDir, nsILocalFile* aFlagFile,
2288 : bool* aCachesOK)
2289 : {
2290 0 : *aCachesOK = false;
2291 0 : nsCOMPtr<nsIFile> file;
2292 0 : aProfileDir->Clone(getter_AddRefs(file));
2293 0 : if (!file)
2294 0 : return false;
2295 0 : file->AppendNative(FILE_COMPATIBILITY_INFO);
2296 :
2297 0 : nsINIParser parser;
2298 0 : nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
2299 0 : nsresult rv = parser.Init(localFile);
2300 0 : if (NS_FAILED(rv))
2301 0 : return false;
2302 :
2303 0 : nsCAutoString buf;
2304 0 : rv = parser.GetString("Compatibility", "LastVersion", buf);
2305 0 : if (NS_FAILED(rv) || !aVersion.Equals(buf))
2306 0 : return false;
2307 :
2308 0 : rv = parser.GetString("Compatibility", "LastOSABI", buf);
2309 0 : if (NS_FAILED(rv) || !aOSABI.Equals(buf))
2310 0 : return false;
2311 :
2312 0 : rv = parser.GetString("Compatibility", "LastPlatformDir", buf);
2313 0 : if (NS_FAILED(rv))
2314 0 : return false;
2315 :
2316 0 : nsCOMPtr<nsILocalFile> lf;
2317 : rv = NS_NewNativeLocalFile(buf, false,
2318 0 : getter_AddRefs(lf));
2319 0 : if (NS_FAILED(rv))
2320 0 : return false;
2321 :
2322 : bool eq;
2323 0 : rv = lf->Equals(aXULRunnerDir, &eq);
2324 0 : if (NS_FAILED(rv) || !eq)
2325 0 : return false;
2326 :
2327 0 : if (aAppDir) {
2328 0 : rv = parser.GetString("Compatibility", "LastAppDir", buf);
2329 0 : if (NS_FAILED(rv))
2330 0 : return false;
2331 :
2332 : rv = NS_NewNativeLocalFile(buf, false,
2333 0 : getter_AddRefs(lf));
2334 0 : if (NS_FAILED(rv))
2335 0 : return false;
2336 :
2337 0 : rv = lf->Equals(aAppDir, &eq);
2338 0 : if (NS_FAILED(rv) || !eq)
2339 0 : return false;
2340 : }
2341 :
2342 : // If we see this flag, caches are invalid.
2343 0 : rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
2344 0 : *aCachesOK = (NS_FAILED(rv) || !buf.EqualsLiteral("1"));
2345 :
2346 0 : bool purgeCaches = false;
2347 0 : if (aFlagFile) {
2348 0 : aFlagFile->Exists(&purgeCaches);
2349 : }
2350 :
2351 0 : *aCachesOK = !purgeCaches && *aCachesOK;
2352 0 : return true;
2353 : }
2354 :
2355 0 : static void BuildVersion(nsCString &aBuf)
2356 : {
2357 0 : aBuf.Assign(gAppData->version);
2358 0 : aBuf.Append('_');
2359 0 : aBuf.Append(gAppData->buildID);
2360 0 : aBuf.Append('/');
2361 0 : aBuf.Append(gToolkitBuildID);
2362 0 : }
2363 :
2364 : static void
2365 0 : WriteVersion(nsIFile* aProfileDir, const nsCString& aVersion,
2366 : const nsCString& aOSABI, nsIFile* aXULRunnerDir,
2367 : nsIFile* aAppDir)
2368 : {
2369 0 : nsCOMPtr<nsIFile> file;
2370 0 : aProfileDir->Clone(getter_AddRefs(file));
2371 0 : if (!file)
2372 : return;
2373 0 : file->AppendNative(FILE_COMPATIBILITY_INFO);
2374 :
2375 0 : nsCOMPtr<nsILocalFile> lf = do_QueryInterface(file);
2376 :
2377 0 : nsCAutoString platformDir;
2378 0 : aXULRunnerDir->GetNativePath(platformDir);
2379 :
2380 0 : nsCAutoString appDir;
2381 0 : if (aAppDir)
2382 0 : aAppDir->GetNativePath(appDir);
2383 :
2384 0 : PRFileDesc *fd = nsnull;
2385 0 : lf->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0600, &fd);
2386 0 : if (!fd) {
2387 0 : NS_ERROR("could not create output stream");
2388 : return;
2389 : }
2390 :
2391 : static const char kHeader[] = "[Compatibility]" NS_LINEBREAK
2392 : "LastVersion=";
2393 :
2394 0 : PR_Write(fd, kHeader, sizeof(kHeader) - 1);
2395 0 : PR_Write(fd, aVersion.get(), aVersion.Length());
2396 :
2397 : static const char kOSABIHeader[] = NS_LINEBREAK "LastOSABI=";
2398 0 : PR_Write(fd, kOSABIHeader, sizeof(kOSABIHeader) - 1);
2399 0 : PR_Write(fd, aOSABI.get(), aOSABI.Length());
2400 :
2401 : static const char kPlatformDirHeader[] = NS_LINEBREAK "LastPlatformDir=";
2402 :
2403 0 : PR_Write(fd, kPlatformDirHeader, sizeof(kPlatformDirHeader) - 1);
2404 0 : PR_Write(fd, platformDir.get(), platformDir.Length());
2405 :
2406 : static const char kAppDirHeader[] = NS_LINEBREAK "LastAppDir=";
2407 0 : if (aAppDir) {
2408 0 : PR_Write(fd, kAppDirHeader, sizeof(kAppDirHeader) - 1);
2409 0 : PR_Write(fd, appDir.get(), appDir.Length());
2410 : }
2411 :
2412 : static const char kNL[] = NS_LINEBREAK;
2413 0 : PR_Write(fd, kNL, sizeof(kNL) - 1);
2414 :
2415 0 : PR_Close(fd);
2416 : }
2417 :
2418 0 : static void RemoveComponentRegistries(nsIFile* aProfileDir, nsIFile* aLocalProfileDir,
2419 : bool aRemoveEMFiles)
2420 : {
2421 0 : nsCOMPtr<nsIFile> file;
2422 0 : aProfileDir->Clone(getter_AddRefs(file));
2423 0 : if (!file)
2424 : return;
2425 :
2426 0 : if (aRemoveEMFiles) {
2427 0 : file->SetNativeLeafName(NS_LITERAL_CSTRING("extensions.ini"));
2428 0 : file->Remove(false);
2429 : }
2430 :
2431 0 : aLocalProfileDir->Clone(getter_AddRefs(file));
2432 0 : if (!file)
2433 : return;
2434 :
2435 : #if defined(XP_UNIX) || defined(XP_BEOS)
2436 : #define PLATFORM_FASL_SUFFIX ".mfasl"
2437 : #elif defined(XP_WIN) || defined(XP_OS2)
2438 : #define PLATFORM_FASL_SUFFIX ".mfl"
2439 : #endif
2440 :
2441 0 : file->AppendNative(NS_LITERAL_CSTRING("XUL" PLATFORM_FASL_SUFFIX));
2442 0 : file->Remove(false);
2443 :
2444 0 : file->SetNativeLeafName(NS_LITERAL_CSTRING("XPC" PLATFORM_FASL_SUFFIX));
2445 0 : file->Remove(false);
2446 :
2447 0 : file->SetNativeLeafName(NS_LITERAL_CSTRING("startupCache"));
2448 0 : file->Remove(true);
2449 : }
2450 :
2451 : // To support application initiated restart via nsIAppStartup.quit, we
2452 : // need to save various environment variables, and then restore them
2453 : // before re-launching the application.
2454 :
2455 : static struct SavedVar {
2456 : const char *name;
2457 : char *value;
2458 : } gSavedVars[] = {
2459 : {"XUL_APP_FILE", nsnull}
2460 : };
2461 :
2462 0 : static void SaveStateForAppInitiatedRestart()
2463 : {
2464 0 : for (size_t i = 0; i < ArrayLength(gSavedVars); ++i) {
2465 0 : const char *s = PR_GetEnv(gSavedVars[i].name);
2466 0 : if (s)
2467 0 : gSavedVars[i].value = PR_smprintf("%s=%s", gSavedVars[i].name, s);
2468 : }
2469 0 : }
2470 :
2471 0 : static void RestoreStateForAppInitiatedRestart()
2472 : {
2473 0 : for (size_t i = 0; i < ArrayLength(gSavedVars); ++i) {
2474 0 : if (gSavedVars[i].value)
2475 0 : PR_SetEnv(gSavedVars[i].value);
2476 : }
2477 0 : }
2478 :
2479 : #ifdef MOZ_CRASHREPORTER
2480 : // When we first initialize the crash reporter we don't have a profile,
2481 : // so we set the minidump path to $TEMP. Once we have a profile,
2482 : // we set it to $PROFILE/minidumps, creating the directory
2483 : // if needed.
2484 0 : static void MakeOrSetMinidumpPath(nsIFile* profD)
2485 : {
2486 0 : nsCOMPtr<nsIFile> dumpD;
2487 0 : nsresult rv = profD->Clone(getter_AddRefs(dumpD));
2488 :
2489 0 : if(dumpD) {
2490 : bool fileExists;
2491 : //XXX: do some more error checking here
2492 0 : dumpD->Append(NS_LITERAL_STRING("minidumps"));
2493 0 : rv = dumpD->Exists(&fileExists);
2494 0 : if(!fileExists) {
2495 0 : dumpD->Create(nsIFile::DIRECTORY_TYPE, 0700);
2496 : }
2497 :
2498 0 : nsAutoString pathStr;
2499 0 : if(NS_SUCCEEDED(dumpD->GetPath(pathStr)))
2500 0 : CrashReporter::SetMinidumpPath(pathStr);
2501 : }
2502 0 : }
2503 : #endif
2504 :
2505 : const nsXREAppData* gAppData = nsnull;
2506 :
2507 : #if defined(XP_OS2)
2508 : // because we use early returns, we use a stack-based helper to un-set the OS2 FP handler
2509 : class ScopedFPHandler {
2510 : private:
2511 : EXCEPTIONREGISTRATIONRECORD excpreg;
2512 :
2513 : public:
2514 : ScopedFPHandler() { PR_OS2_SetFloatExcpHandler(&excpreg); }
2515 : ~ScopedFPHandler() { PR_OS2_UnsetFloatExcpHandler(&excpreg); }
2516 : };
2517 : #endif
2518 :
2519 : #ifdef MOZ_WIDGET_GTK2
2520 : #include "prlink.h"
2521 : typedef void (*_g_set_application_name_fn)(const gchar *application_name);
2522 : typedef void (*_gtk_window_set_auto_startup_notification_fn)(gboolean setting);
2523 :
2524 0 : static PRFuncPtr FindFunction(const char* aName)
2525 : {
2526 0 : PRLibrary *lib = nsnull;
2527 0 : PRFuncPtr result = PR_FindFunctionSymbolAndLibrary(aName, &lib);
2528 : // Since the library was already loaded, we can safely unload it here.
2529 0 : if (lib) {
2530 0 : PR_UnloadLibrary(lib);
2531 : }
2532 0 : return result;
2533 : }
2534 :
2535 0 : static void MOZ_gdk_display_close(GdkDisplay *display)
2536 : {
2537 : // XXX wallpaper for bug 417163: don't close the Display if we're using the
2538 : // Qt theme because we crash (in Qt code) when using jemalloc.
2539 0 : bool theme_is_qt = false;
2540 : GtkSettings* settings =
2541 0 : gtk_settings_get_for_screen(gdk_display_get_default_screen(display));
2542 : gchar *theme_name;
2543 0 : g_object_get(settings, "gtk-theme-name", &theme_name, NULL);
2544 0 : if (theme_name) {
2545 0 : theme_is_qt = strcmp(theme_name, "Qt") == 0;
2546 0 : if (theme_is_qt)
2547 0 : NS_WARNING("wallpaper bug 417163 for Qt theme");
2548 0 : g_free(theme_name);
2549 : }
2550 :
2551 : // gdk_display_close was broken prior to gtk+-2.10.0.
2552 : // (http://bugzilla.gnome.org/show_bug.cgi?id=85715)
2553 : // gdk_display_manager_set_default_display (gdk_display_manager_get(), NULL)
2554 : // was also broken.
2555 0 : if (gtk_check_version(2,10,0) != NULL) {
2556 : #ifdef MOZ_X11
2557 : // Version check failed - broken gdk_display_close.
2558 : //
2559 : // Let the gdk structures leak but at least close the Display,
2560 : // assuming that gdk will not use it again.
2561 0 : Display* dpy = GDK_DISPLAY_XDISPLAY(display);
2562 0 : if (!theme_is_qt)
2563 0 : XCloseDisplay(dpy);
2564 : #else
2565 : gdk_display_close(display);
2566 : #endif /* MOZ_X11 */
2567 : }
2568 : else {
2569 : #if CLEANUP_MEMORY
2570 : // Get a (new) Pango context that holds a reference to the fontmap that
2571 : // GTK has been using. gdk_pango_context_get() must be called while GTK
2572 : // has a default display.
2573 0 : PangoContext *pangoContext = gdk_pango_context_get();
2574 : #endif
2575 :
2576 0 : bool buggyCairoShutdown = cairo_version() < CAIRO_VERSION_ENCODE(1, 4, 0);
2577 :
2578 0 : if (!buggyCairoShutdown) {
2579 : // We should shut down GDK before we shut down libraries it depends on
2580 : // like Pango and cairo. But if cairo shutdown is buggy, we should
2581 : // shut down cairo first otherwise it may crash because of dangling
2582 : // references to Display objects (see bug 469831).
2583 0 : if (!theme_is_qt)
2584 0 : gdk_display_close(display);
2585 : }
2586 :
2587 : #if CLEANUP_MEMORY
2588 : // This doesn't take a reference.
2589 0 : PangoFontMap *fontmap = pango_context_get_font_map(pangoContext);
2590 : // Do some shutdown of the fontmap, which releases the fonts, clearing a
2591 : // bunch of circular references from the fontmap through the fonts back to
2592 : // itself. The shutdown that this does is much less than what's done by
2593 : // the fontmap's finalize, though.
2594 0 : if (PANGO_IS_FC_FONT_MAP(fontmap))
2595 0 : pango_fc_font_map_shutdown(PANGO_FC_FONT_MAP(fontmap));
2596 0 : g_object_unref(pangoContext);
2597 : // PangoCairo still holds a reference to the fontmap.
2598 : // Now that we have finished with GTK and Pango, we could unref fontmap,
2599 : // which would allow us to call FcFini, but removing what is really
2600 : // Pango's ref feels a bit evil. Pango-1.22 will have support for
2601 : // pango_cairo_font_map_set_default(NULL), which would release the
2602 : // reference on the old fontmap.
2603 :
2604 : #if GTK_CHECK_VERSION(2,8,0)
2605 : // cairo_debug_reset_static_data() is prototyped through cairo.h included
2606 : // by gtk.h.
2607 : #ifdef cairo_debug_reset_static_data
2608 : #error "Looks like we're including Mozilla's cairo instead of system cairo"
2609 : #endif
2610 0 : cairo_debug_reset_static_data();
2611 : #endif // 2.8.0
2612 : #endif // CLEANUP_MEMORY
2613 :
2614 0 : if (buggyCairoShutdown) {
2615 0 : if (!theme_is_qt)
2616 0 : gdk_display_close(display);
2617 : }
2618 : }
2619 0 : }
2620 : #endif // MOZ_WIDGET_GTK2
2621 :
2622 : /**
2623 : * NSPR will search for the "nspr_use_zone_allocator" symbol throughout
2624 : * the process and use it to determine whether the application defines its own
2625 : * memory allocator or not.
2626 : *
2627 : * Since most applications (e.g. Firefox and Thunderbird) don't use any special
2628 : * allocators and therefore don't define this symbol, NSPR must search the
2629 : * entire process, which reduces startup performance.
2630 : *
2631 : * By defining the symbol here, we can avoid the wasted lookup and hopefully
2632 : * improve startup performance.
2633 : */
2634 : NS_VISIBILITY_DEFAULT PRBool nspr_use_zone_allocator = PR_FALSE;
2635 :
2636 : #ifdef CAIRO_HAS_DWRITE_FONT
2637 :
2638 : #include <dwrite.h>
2639 :
2640 : typedef HRESULT (WINAPI*DWriteCreateFactoryFunc)(
2641 : DWRITE_FACTORY_TYPE factoryType,
2642 : REFIID iid,
2643 : IUnknown **factory
2644 : );
2645 :
2646 : #ifdef DEBUG_DWRITE_STARTUP
2647 :
2648 : #define LOGREGISTRY(msg) LogRegistryEvent(msg)
2649 :
2650 : // for use when monitoring process
2651 : static void LogRegistryEvent(const wchar_t *msg)
2652 : {
2653 : HKEY dummyKey;
2654 : HRESULT hr;
2655 : wchar_t buf[512];
2656 :
2657 : wsprintf(buf, L" log %s", msg);
2658 : hr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, buf, 0, KEY_READ, &dummyKey);
2659 : if (SUCCEEDED(hr)) {
2660 : RegCloseKey(dummyKey);
2661 : }
2662 : }
2663 : #else
2664 :
2665 : #define LOGREGISTRY(msg)
2666 :
2667 : #endif
2668 :
2669 : static DWORD InitDwriteBG(LPVOID lpdwThreadParam)
2670 : {
2671 : SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN);
2672 : LOGREGISTRY(L"loading dwrite.dll");
2673 : HMODULE dwdll = LoadLibraryW(L"dwrite.dll");
2674 : if (dwdll) {
2675 : DWriteCreateFactoryFunc createDWriteFactory = (DWriteCreateFactoryFunc)
2676 : GetProcAddress(dwdll, "DWriteCreateFactory");
2677 : if (createDWriteFactory) {
2678 : LOGREGISTRY(L"creating dwrite factory");
2679 : IDWriteFactory *factory;
2680 : HRESULT hr = createDWriteFactory(
2681 : DWRITE_FACTORY_TYPE_SHARED,
2682 : __uuidof(IDWriteFactory),
2683 : reinterpret_cast<IUnknown**>(&factory));
2684 : if (SUCCEEDED(hr)) {
2685 : LOGREGISTRY(L"dwrite factory done");
2686 : factory->Release();
2687 : LOGREGISTRY(L"freed factory");
2688 : } else {
2689 : LOGREGISTRY(L"failed to create factory");
2690 : }
2691 : }
2692 : }
2693 : SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_END);
2694 : return 0;
2695 : }
2696 : #endif
2697 :
2698 : #ifdef MOZ_X11
2699 : #ifndef MOZ_PLATFORM_MAEMO
2700 : bool fire_glxtest_process();
2701 : #endif
2702 : #endif
2703 :
2704 : #include "sampler.h"
2705 :
2706 : int
2707 23 : XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
2708 : {
2709 : NS_TIME_FUNCTION;
2710 23 : SAMPLER_INIT();
2711 46 : SAMPLE_LABEL("Startup", "XRE_Main");
2712 :
2713 23 : StartupTimeline::Record(StartupTimeline::MAIN);
2714 :
2715 : nsresult rv;
2716 : ArgResult ar;
2717 :
2718 : #ifdef DEBUG
2719 23 : if (PR_GetEnv("XRE_MAIN_BREAK"))
2720 0 : NS_BREAK();
2721 : #endif
2722 :
2723 : // see bug 639842
2724 : // it's very important to fire this process BEFORE we set up error handling.
2725 : // indeed, this process is expected to be crashy, and we don't want the user to see its crashes.
2726 : // That's the whole reason for doing this in a separate process.
2727 : #ifdef MOZ_X11
2728 : #ifndef MOZ_PLATFORM_MAEMO
2729 23 : if (fire_glxtest_process())
2730 0 : return 0;
2731 : #endif
2732 : #endif
2733 :
2734 : #ifdef XP_WIN
2735 : // Vista API. Mozilla is DPI Aware.
2736 : typedef BOOL (*SetProcessDPIAwareFunc)(VOID);
2737 :
2738 : SetProcessDPIAwareFunc setDPIAware = (SetProcessDPIAwareFunc)
2739 : GetProcAddress(LoadLibraryW(L"user32.dll"), "SetProcessDPIAware");
2740 :
2741 : if (setDPIAware)
2742 : setDPIAware();
2743 : #endif
2744 :
2745 23 : SetupErrorHandling(argv[0]);
2746 :
2747 : #ifdef CAIRO_HAS_DWRITE_FONT
2748 :
2749 : // Bug 602792 - when DWriteCreateFactory is called the dwrite client dll
2750 : // starts the FntCache service if it isn't already running (it's set
2751 : // to manual startup by default in Windows 7 RTM). Subsequent DirectWrite
2752 : // calls cause the IDWriteFactory object to communicate with the FntCache
2753 : // service with a timeout; if there's no response after the timeout, the
2754 : // DirectWrite client library will assume the service isn't around and do
2755 : // manual font file I/O on _all_ system fonts. To avoid this, load the
2756 : // dwrite library and create a factory as early as possible so that the
2757 : // FntCache service is ready by the time it's needed.
2758 :
2759 : OSVERSIONINFO vinfo;
2760 : vinfo.dwOSVersionInfoSize = sizeof(vinfo);
2761 : if (GetVersionEx(&vinfo) && vinfo.dwMajorVersion >= 6) {
2762 : CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&InitDwriteBG, NULL, 0, NULL);
2763 : }
2764 :
2765 : #endif
2766 :
2767 : #ifdef XP_UNIX
2768 23 : const char *home = PR_GetEnv("HOME");
2769 23 : if (!home || !*home) {
2770 0 : struct passwd *pw = getpwuid(geteuid());
2771 0 : if (!pw || !pw->pw_dir) {
2772 0 : Output(true, "Could not determine HOME directory");
2773 0 : return 1;
2774 : }
2775 0 : SaveWordToEnv("HOME", nsDependentCString(pw->pw_dir));
2776 : }
2777 : #endif
2778 :
2779 : #ifdef MOZ_ACCESSIBILITY_ATK
2780 : // Reset GTK_MODULES, strip atk-bridge if exists
2781 : // Mozilla will load libatk-bridge.so later if necessary
2782 23 : const char* gtkModules = PR_GetEnv("GTK_MODULES");
2783 23 : if (gtkModules && *gtkModules) {
2784 0 : nsCString gtkModulesStr(gtkModules);
2785 0 : gtkModulesStr.ReplaceSubstring("atk-bridge", "");
2786 0 : char* expr = PR_smprintf("GTK_MODULES=%s", gtkModulesStr.get());
2787 0 : if (expr)
2788 0 : PR_SetEnv(expr);
2789 : // We intentionally leak |expr| here since it is required by PR_SetEnv.
2790 : }
2791 :
2792 : // Suppress atk-bridge init at startup, it works after GNOME 2.24.2
2793 23 : SaveToEnv("NO_AT_BRIDGE=1");
2794 : #endif
2795 :
2796 23 : gArgc = argc;
2797 23 : gArgv = argv;
2798 :
2799 23 : NS_ENSURE_TRUE(aAppData, 2);
2800 :
2801 : // Check for application.ini overrides
2802 23 : const char* override = nsnull;
2803 23 : ar = CheckArg("override", true, &override);
2804 23 : if (ar == ARG_BAD) {
2805 0 : Output(true, "Incorrect number of arguments passed to -override");
2806 0 : return 1;
2807 : }
2808 23 : else if (ar == ARG_FOUND) {
2809 0 : nsCOMPtr<nsILocalFile> overrideLF;
2810 0 : rv = XRE_GetFileFromPath(override, getter_AddRefs(overrideLF));
2811 0 : if (NS_FAILED(rv)) {
2812 0 : Output(true, "Error: unrecognized override.ini path.\n");
2813 0 : return 1;
2814 : }
2815 :
2816 0 : nsXREAppData* overrideAppData = const_cast<nsXREAppData*>(aAppData);
2817 0 : rv = XRE_ParseAppData(overrideLF, overrideAppData);
2818 0 : if (NS_FAILED(rv)) {
2819 0 : Output(true, "Couldn't read override.ini");
2820 0 : return 1;
2821 : }
2822 : }
2823 :
2824 46 : ScopedAppData appData(aAppData);
2825 23 : gAppData = &appData;
2826 :
2827 : // Check sanity and correctness of app data.
2828 :
2829 23 : if (!appData.name) {
2830 0 : Output(true, "Error: App:Name not specified in application.ini\n");
2831 0 : return 1;
2832 : }
2833 23 : if (!appData.buildID) {
2834 0 : Output(true, "Error: App:BuildID not specified in application.ini\n");
2835 0 : return 1;
2836 : }
2837 :
2838 46 : ScopedLogging log;
2839 :
2840 23 : if (!appData.xreDirectory) {
2841 46 : nsCOMPtr<nsILocalFile> lf;
2842 23 : rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
2843 23 : if (NS_FAILED(rv))
2844 0 : return 2;
2845 :
2846 46 : nsCOMPtr<nsIFile> greDir;
2847 23 : rv = lf->GetParent(getter_AddRefs(greDir));
2848 23 : if (NS_FAILED(rv))
2849 0 : return 2;
2850 :
2851 23 : rv = CallQueryInterface(greDir, &appData.xreDirectory);
2852 23 : if (NS_FAILED(rv))
2853 0 : return 2;
2854 : }
2855 :
2856 23 : if (!appData.directory) {
2857 23 : NS_IF_ADDREF(appData.directory = appData.xreDirectory);
2858 : }
2859 :
2860 23 : if (appData.size > offsetof(nsXREAppData, minVersion)) {
2861 23 : if (!appData.minVersion) {
2862 0 : Output(true, "Error: Gecko:MinVersion not specified in application.ini\n");
2863 0 : return 1;
2864 : }
2865 :
2866 23 : if (!appData.maxVersion) {
2867 : // If no maxVersion is specified, we assume the app is only compatible
2868 : // with the initial preview release. Do not increment this number ever!
2869 0 : SetAllocatedString(appData.maxVersion, "1.*");
2870 : }
2871 :
2872 46 : if (NS_CompareVersions(appData.minVersion, gToolkitVersion) > 0 ||
2873 23 : NS_CompareVersions(appData.maxVersion, gToolkitVersion) < 0) {
2874 : Output(true, "Error: Platform version '%s' is not compatible with\n"
2875 : "minVersion >= %s\nmaxVersion <= %s\n",
2876 : gToolkitVersion,
2877 0 : appData.minVersion, appData.maxVersion);
2878 0 : return 1;
2879 : }
2880 : }
2881 :
2882 46 : nsXREDirProvider dirProvider;
2883 23 : rv = dirProvider.Initialize(gAppData->directory, gAppData->xreDirectory);
2884 23 : if (NS_FAILED(rv))
2885 0 : return 1;
2886 :
2887 : #ifdef MOZ_CRASHREPORTER
2888 23 : if (EnvHasValue("MOZ_CRASHREPORTER")) {
2889 22 : appData.flags |= NS_XRE_ENABLE_CRASH_REPORTER;
2890 : }
2891 :
2892 45 : if ((appData.flags & NS_XRE_ENABLE_CRASH_REPORTER) &&
2893 22 : NS_SUCCEEDED(
2894 : CrashReporter::SetExceptionHandler(appData.xreDirectory))) {
2895 22 : if (appData.crashReporterURL)
2896 22 : CrashReporter::SetServerURL(nsDependentCString(appData.crashReporterURL));
2897 :
2898 : // pass some basic info from the app data
2899 22 : if (appData.vendor)
2900 22 : CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Vendor"),
2901 44 : nsDependentCString(appData.vendor));
2902 22 : if (appData.name)
2903 22 : CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProductName"),
2904 44 : nsDependentCString(appData.name));
2905 22 : if (appData.ID)
2906 22 : CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProductID"),
2907 44 : nsDependentCString(appData.ID));
2908 22 : if (appData.version)
2909 22 : CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Version"),
2910 44 : nsDependentCString(appData.version));
2911 22 : if (appData.buildID)
2912 22 : CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("BuildID"),
2913 44 : nsDependentCString(appData.buildID));
2914 :
2915 44 : nsDependentCString releaseChannel(NS_STRINGIFY(MOZ_UPDATE_CHANNEL));
2916 22 : CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ReleaseChannel"),
2917 22 : releaseChannel);
2918 22 : CrashReporter::SetRestartArgs(argc, argv);
2919 :
2920 : // annotate other data (user id etc)
2921 44 : nsCOMPtr<nsILocalFile> userAppDataDir;
2922 22 : if (NS_SUCCEEDED(dirProvider.GetUserAppDataDirectory(
2923 : getter_AddRefs(userAppDataDir)))) {
2924 : CrashReporter::SetupExtraData(userAppDataDir,
2925 22 : nsDependentCString(appData.buildID));
2926 :
2927 : // see if we have a crashreporter-override.ini in the application directory
2928 44 : nsCOMPtr<nsIFile> overrideini;
2929 : bool exists;
2930 110 : if (NS_SUCCEEDED(dirProvider.GetAppDir()->Clone(getter_AddRefs(overrideini))) &&
2931 66 : NS_SUCCEEDED(overrideini->AppendNative(NS_LITERAL_CSTRING("crashreporter-override.ini"))) &&
2932 22 : NS_SUCCEEDED(overrideini->Exists(&exists)) &&
2933 : exists) {
2934 : #ifdef XP_WIN
2935 : nsAutoString overridePathW;
2936 : overrideini->GetPath(overridePathW);
2937 : NS_ConvertUTF16toUTF8 overridePath(overridePathW);
2938 : #else
2939 44 : nsCAutoString overridePath;
2940 22 : overrideini->GetNativePath(overridePath);
2941 : #endif
2942 :
2943 22 : SaveWordToEnv("MOZ_CRASHREPORTER_STRINGS_OVERRIDE", overridePath);
2944 : }
2945 : }
2946 : }
2947 : #endif
2948 :
2949 : #ifdef XP_MACOSX
2950 : if (EnvHasValue("MOZ_LAUNCHED_CHILD")) {
2951 : // This is needed, on relaunch, to force the OS to use the "Cocoa Dock
2952 : // API". Otherwise the call to ReceiveNextEvent() below will make it
2953 : // use the "Carbon Dock API". For more info see bmo bug 377166.
2954 : EnsureUseCocoaDockAPI();
2955 :
2956 : // When the app relaunches, the original process exits. This causes
2957 : // the dock tile to stop bouncing, lose the "running" triangle, and
2958 : // if the tile does not permanently reside in the Dock, even disappear.
2959 : // This can be confusing to the user, who is expecting the app to launch.
2960 : // Calling ReceiveNextEvent without requesting any event is enough to
2961 : // cause a dock tile for the child process to appear.
2962 : const EventTypeSpec kFakeEventList[] = { { INT_MAX, INT_MAX } };
2963 : EventRef event;
2964 : ::ReceiveNextEvent(GetEventTypeCount(kFakeEventList), kFakeEventList,
2965 : kEventDurationNoWait, false, &event);
2966 : }
2967 :
2968 : if (CheckArg("foreground")) {
2969 : // The original process communicates that it was in the foreground by
2970 : // adding this argument. This new process, which is taking over for
2971 : // the old one, should make itself the active application.
2972 : ProcessSerialNumber psn;
2973 : if (::GetCurrentProcess(&psn) == noErr)
2974 : ::SetFrontProcess(&psn);
2975 : }
2976 : #endif
2977 :
2978 23 : SaveToEnv("MOZ_LAUNCHED_CHILD=");
2979 :
2980 23 : gRestartArgc = gArgc;
2981 23 : gRestartArgv = (char**) malloc(sizeof(char*) * (gArgc + 1 + (override ? 2 : 0)));
2982 23 : if (!gRestartArgv) return 1;
2983 :
2984 : int i;
2985 138 : for (i = 0; i < gArgc; ++i) {
2986 115 : gRestartArgv[i] = gArgv[i];
2987 : }
2988 :
2989 : // Add the -override argument back (it is removed automatically be CheckArg) if there is one
2990 23 : if (override) {
2991 0 : gRestartArgv[gRestartArgc++] = const_cast<char*>("-override");
2992 0 : gRestartArgv[gRestartArgc++] = const_cast<char*>(override);
2993 : }
2994 :
2995 23 : gRestartArgv[gRestartArgc] = nsnull;
2996 :
2997 :
2998 : #if defined(XP_OS2)
2999 : bool StartOS2App(int aArgc, char **aArgv);
3000 : if (!StartOS2App(gArgc, gArgv))
3001 : return 1;
3002 : ScopedFPHandler handler;
3003 : #endif /* XP_OS2 */
3004 :
3005 23 : if (EnvHasValue("MOZ_SAFE_MODE_RESTART")) {
3006 0 : gSafeMode = true;
3007 : // unset the env variable
3008 0 : SaveToEnv("MOZ_SAFE_MODE_RESTART=");
3009 : }
3010 :
3011 23 : ar = CheckArg("safe-mode", true);
3012 23 : if (ar == ARG_BAD) {
3013 0 : PR_fprintf(PR_STDERR, "Error: argument -safe-mode is invalid when argument -osint is specified\n");
3014 0 : return 1;
3015 23 : } else if (ar == ARG_FOUND) {
3016 0 : gSafeMode = true;
3017 : }
3018 :
3019 : #ifdef XP_WIN
3020 : // If the shift key is pressed and the ctrl and / or alt keys are not pressed
3021 : // during startup start in safe mode. GetKeyState returns a short and the high
3022 : // order bit will be 1 if the key is pressed. By masking the returned short
3023 : // with 0x8000 the result will be 0 if the key is not pressed and non-zero
3024 : // otherwise.
3025 : if (GetKeyState(VK_SHIFT) & 0x8000 &&
3026 : !(GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_MENU) & 0x8000)) {
3027 : gSafeMode = true;
3028 : }
3029 : #endif
3030 :
3031 : #ifdef XP_MACOSX
3032 : if (GetCurrentEventKeyModifiers() & optionKey)
3033 : gSafeMode = true;
3034 : #endif
3035 :
3036 : // Handle -no-remote and -new-instance command line arguments. Setup
3037 : // the environment to better accommodate other components and various
3038 : // restart scenarios.
3039 23 : ar = CheckArg("no-remote", true);
3040 23 : if (ar == ARG_BAD) {
3041 0 : PR_fprintf(PR_STDERR, "Error: argument -no-remote is invalid when argument -osint is specified\n");
3042 0 : return 1;
3043 23 : } else if (ar == ARG_FOUND) {
3044 23 : SaveToEnv("MOZ_NO_REMOTE=1");
3045 : }
3046 23 : ar = CheckArg("new-instance", true);
3047 23 : if (ar == ARG_BAD) {
3048 0 : PR_fprintf(PR_STDERR, "Error: argument -new-instance is invalid when argument -osint is specified\n");
3049 0 : return 1;
3050 23 : } else if (ar == ARG_FOUND) {
3051 0 : SaveToEnv("MOZ_NEW_INSTANCE=1");
3052 : }
3053 :
3054 : // Handle -help and -version command line arguments.
3055 : // They should return quickly, so we deal with them here.
3056 23 : if (CheckArg("h") || CheckArg("help") || CheckArg("?")) {
3057 0 : DumpHelp();
3058 0 : return 0;
3059 : }
3060 :
3061 23 : if (CheckArg("v") || CheckArg("version")) {
3062 0 : DumpVersion();
3063 0 : return 0;
3064 : }
3065 :
3066 : #ifdef NS_TRACE_MALLOC
3067 : gArgc = argc = NS_TraceMallocStartupArgs(gArgc, gArgv);
3068 : #endif
3069 :
3070 23 : rv = XRE_InitCommandLine(gArgc, gArgv);
3071 23 : NS_ENSURE_SUCCESS(rv, 1);
3072 :
3073 : {
3074 : // Check for -register, which registers chrome and then exits immediately.
3075 23 : ar = CheckArg("register", true);
3076 23 : if (ar == ARG_BAD) {
3077 0 : PR_fprintf(PR_STDERR, "Error: argument -register is invalid when argument -osint is specified\n");
3078 0 : return 1;
3079 23 : } else if (ar == ARG_FOUND) {
3080 0 : ScopedXPCOMStartup xpcom;
3081 0 : rv = xpcom.Initialize();
3082 0 : NS_ENSURE_SUCCESS(rv, 1);
3083 :
3084 : {
3085 : nsCOMPtr<nsIChromeRegistry> chromeReg =
3086 0 : mozilla::services::GetChromeRegistryService();
3087 0 : NS_ENSURE_TRUE(chromeReg, 1);
3088 :
3089 0 : chromeReg->CheckForNewChrome();
3090 : }
3091 0 : return 0;
3092 : }
3093 :
3094 : #if defined(MOZ_WIDGET_GTK2) || defined(MOZ_ENABLE_XREMOTE)
3095 : // Stash DESKTOP_STARTUP_ID in malloc'ed memory because gtk_init will clear it.
3096 : #define HAVE_DESKTOP_STARTUP_ID
3097 23 : const char* desktopStartupIDEnv = PR_GetEnv("DESKTOP_STARTUP_ID");
3098 46 : nsCAutoString desktopStartupID;
3099 23 : if (desktopStartupIDEnv) {
3100 0 : desktopStartupID.Assign(desktopStartupIDEnv);
3101 : }
3102 : #endif
3103 :
3104 : #if defined(MOZ_WIDGET_QT)
3105 : nsQAppInstance::AddRef(gArgc, gArgv, true);
3106 :
3107 : #if MOZ_PLATFORM_MAEMO > 5
3108 : if (XRE_GetProcessType() == GeckoProcessType_Default) {
3109 : // try to get the MInputContext if possible to support the MeeGo VKB
3110 : QInputContext* inputContext = qApp->inputContext();
3111 : if (inputContext && inputContext->identifierName() != "MInputContext") {
3112 : QInputContext* context = QInputContextFactory::create("MInputContext",
3113 : qApp);
3114 : if (context)
3115 : qApp->setInputContext(context);
3116 : }
3117 : }
3118 : #endif
3119 : QStringList nonQtArguments = qApp->arguments();
3120 : gQtOnlyArgc = 1;
3121 : gQtOnlyArgv = (char**) malloc(sizeof(char*)
3122 : * (gRestartArgc - nonQtArguments.size() + 2));
3123 :
3124 : // copy binary path
3125 : gQtOnlyArgv[0] = gRestartArgv[0];
3126 :
3127 : for (int i = 1; i < gRestartArgc; ++i) {
3128 : if (!nonQtArguments.contains(gRestartArgv[i])) {
3129 : // copy arguments used by Qt for later
3130 : gQtOnlyArgv[gQtOnlyArgc++] = gRestartArgv[i];
3131 : }
3132 : }
3133 : gQtOnlyArgv[gQtOnlyArgc] = nsnull;
3134 : #endif
3135 : #if defined(MOZ_WIDGET_GTK2)
3136 : #ifdef MOZ_MEMORY
3137 : // Disable the slice allocator, since jemalloc already uses similar layout
3138 : // algorithms, and using a sub-allocator tends to increase fragmentation.
3139 : // This must be done before g_thread_init() is called.
3140 23 : g_slice_set_config(G_SLICE_CONFIG_ALWAYS_MALLOC, 1);
3141 : #endif
3142 23 : g_thread_init(NULL);
3143 : // setup for private colormap. Ideally we'd like to do this
3144 : // in nsAppShell::Create, but we need to get in before gtk
3145 : // has been initialized to make sure everything is running
3146 : // consistently.
3147 23 : if (CheckArg("install"))
3148 0 : gdk_rgb_set_install(TRUE);
3149 :
3150 : // Initialize GTK here for splash.
3151 :
3152 : // Open the display ourselves instead of using gtk_init, so that we can
3153 : // close it without fear that one day gtk might clean up the display it
3154 : // opens.
3155 23 : if (!gtk_parse_args(&gArgc, &gArgv))
3156 0 : return 1;
3157 :
3158 : // display_name is owned by gdk.
3159 23 : const char *display_name = gdk_get_display_arg_name();
3160 23 : if (display_name) {
3161 0 : SaveWordToEnv("DISPLAY", nsDependentCString(display_name));
3162 : } else {
3163 23 : display_name = PR_GetEnv("DISPLAY");
3164 23 : if (!display_name) {
3165 23 : PR_fprintf(PR_STDERR, "Error: no display specified\n");
3166 23 : return 1;
3167 : }
3168 : }
3169 : #endif /* MOZ_WIDGET_GTK2 */
3170 :
3171 : #ifdef MOZ_ENABLE_XREMOTE
3172 : // handle -remote now that xpcom is fired up
3173 : bool disableRemote, newInstance;
3174 : {
3175 0 : char *e = PR_GetEnv("MOZ_NO_REMOTE");
3176 0 : disableRemote = (e && *e);
3177 0 : if (disableRemote) {
3178 0 : newInstance = true;
3179 : } else {
3180 0 : e = PR_GetEnv("MOZ_NEW_INSTANCE");
3181 0 : newInstance = (e && *e);
3182 : }
3183 : }
3184 :
3185 : const char* xremotearg;
3186 0 : ar = CheckArg("remote", true, &xremotearg);
3187 0 : if (ar == ARG_BAD) {
3188 0 : PR_fprintf(PR_STDERR, "Error: -remote requires an argument\n");
3189 0 : return 1;
3190 : }
3191 : const char* desktopStartupIDPtr =
3192 0 : desktopStartupID.IsEmpty() ? nsnull : desktopStartupID.get();
3193 0 : if (ar) {
3194 0 : return HandleRemoteArgument(xremotearg, desktopStartupIDPtr);
3195 : }
3196 :
3197 0 : if (!newInstance) {
3198 : // Try to remote the entire command line. If this fails, start up normally.
3199 0 : RemoteResult rr = RemoteCommandLine(desktopStartupIDPtr);
3200 0 : if (rr == REMOTE_FOUND)
3201 0 : return 0;
3202 0 : else if (rr == REMOTE_ARG_BAD)
3203 0 : return 1;
3204 : }
3205 : #endif
3206 :
3207 : #if defined(MOZ_WIDGET_GTK2)
3208 0 : GdkDisplay* display = nsnull;
3209 0 : display = gdk_display_open(display_name);
3210 0 : if (!display) {
3211 0 : PR_fprintf(PR_STDERR, "Error: cannot open display: %s\n", display_name);
3212 0 : return 1;
3213 : }
3214 : gdk_display_manager_set_default_display (gdk_display_manager_get(),
3215 0 : display);
3216 :
3217 : // g_set_application_name () is only defined in glib2.2 and higher.
3218 : _g_set_application_name_fn _g_set_application_name =
3219 0 : (_g_set_application_name_fn)FindFunction("g_set_application_name");
3220 0 : if (_g_set_application_name) {
3221 0 : _g_set_application_name(gAppData->name);
3222 : }
3223 : _gtk_window_set_auto_startup_notification_fn _gtk_window_set_auto_startup_notification =
3224 0 : (_gtk_window_set_auto_startup_notification_fn)FindFunction("gtk_window_set_auto_startup_notification");
3225 0 : if (_gtk_window_set_auto_startup_notification) {
3226 0 : _gtk_window_set_auto_startup_notification(false);
3227 : }
3228 :
3229 0 : gtk_widget_set_default_colormap(gdk_rgb_get_colormap());
3230 : #endif /* MOZ_WIDGET_GTK2 */
3231 : #ifdef MOZ_X11
3232 : // Do this after initializing GDK, or GDK will install its own handler.
3233 0 : InstallX11ErrorHandler();
3234 : #endif
3235 :
3236 : // Call the code to install our handler
3237 : #ifdef MOZ_JPROF
3238 : setupProfilingStuff();
3239 : #endif
3240 :
3241 : // Try to allocate "native app support."
3242 0 : nsCOMPtr<nsINativeAppSupport> nativeApp;
3243 0 : rv = NS_CreateNativeAppSupport(getter_AddRefs(nativeApp));
3244 0 : if (NS_FAILED(rv))
3245 0 : return 1;
3246 :
3247 0 : bool canRun = false;
3248 0 : rv = nativeApp->Start(&canRun);
3249 0 : if (NS_FAILED(rv) || !canRun) {
3250 0 : return 1;
3251 : }
3252 :
3253 : #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK2)
3254 : // DESKTOP_STARTUP_ID is cleared now,
3255 : // we recover it in case we need a restart.
3256 0 : if (!desktopStartupID.IsEmpty()) {
3257 0 : nsCAutoString desktopStartupEnv;
3258 0 : desktopStartupEnv.AssignLiteral("DESKTOP_STARTUP_ID=");
3259 0 : desktopStartupEnv.Append(desktopStartupID);
3260 : // Leak it with extreme prejudice!
3261 0 : PR_SetEnv(ToNewCString(desktopStartupEnv));
3262 : }
3263 : #endif
3264 :
3265 : #if defined(MOZ_UPDATER) && !defined(ANDROID)
3266 : // Check for and process any available updates
3267 0 : nsCOMPtr<nsIFile> updRoot;
3268 : bool persistent;
3269 : rv = dirProvider.GetFile(XRE_UPDATE_ROOT_DIR, &persistent,
3270 0 : getter_AddRefs(updRoot));
3271 : // XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failed
3272 0 : if (NS_FAILED(rv))
3273 0 : updRoot = dirProvider.GetAppDir();
3274 :
3275 : // If the MOZ_PROCESS_UPDATES environment variable already exists, then
3276 : // we are being called from the callback application.
3277 0 : if (EnvHasValue("MOZ_PROCESS_UPDATES")) {
3278 : // If the caller has asked us to log our arguments, do so. This is used
3279 : // to make sure that the maintenance service successfully launches the
3280 : // callback application.
3281 0 : const char *logFile = nsnull;
3282 0 : if (ARG_FOUND == CheckArg("dump-args", false, &logFile)) {
3283 0 : FILE* logFP = fopen(logFile, "wb");
3284 0 : if (logFP) {
3285 0 : for (i = 1; i < gRestartArgc; ++i) {
3286 0 : fprintf(logFP, "%s\n", gRestartArgv[i]);
3287 : }
3288 0 : fclose(logFP);
3289 : }
3290 : }
3291 0 : return 0;
3292 : }
3293 :
3294 : // Support for processing an update and exiting. The MOZ_PROCESS_UPDATES
3295 : // environment variable will be part of the updater's environment and the
3296 : // application that is relaunched by the updater. When the application is
3297 : // relaunched by the updater it will be removed below and the application
3298 : // will exit.
3299 0 : if (CheckArg("process-updates")) {
3300 0 : SaveToEnv("MOZ_PROCESS_UPDATES=1");
3301 : }
3302 : ProcessUpdates(dirProvider.GetGREDir(),
3303 : dirProvider.GetAppDir(),
3304 : updRoot,
3305 : gRestartArgc,
3306 : gRestartArgv,
3307 0 : appData.version);
3308 0 : if (EnvHasValue("MOZ_PROCESS_UPDATES")) {
3309 0 : SaveToEnv("MOZ_PROCESS_UPDATES=");
3310 0 : return 0;
3311 : }
3312 : #endif
3313 :
3314 0 : nsCOMPtr<nsIProfileLock> profileLock;
3315 0 : bool startOffline = false;
3316 0 : nsCAutoString profileName;
3317 :
3318 0 : nsCOMPtr<nsIToolkitProfileService> profileSvc;
3319 0 : rv = NS_NewToolkitProfileService(getter_AddRefs(profileSvc));
3320 0 : if (rv == NS_ERROR_FILE_ACCESS_DENIED) {
3321 : PR_fprintf(PR_STDERR, "Error: Access was denied while trying to open files in " \
3322 0 : "your profile directory.\n");
3323 : }
3324 0 : if (NS_FAILED(rv)) {
3325 : // We failed to choose or create profile - notify user and quit
3326 0 : ProfileMissingDialog(nativeApp);
3327 0 : return 1;
3328 : }
3329 :
3330 0 : rv = SelectProfile(getter_AddRefs(profileLock), profileSvc, nativeApp, &startOffline,
3331 0 : &profileName);
3332 0 : if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ||
3333 0 : rv == NS_ERROR_ABORT) return 0;
3334 :
3335 0 : if (NS_FAILED(rv)) {
3336 : // We failed to choose or create profile - notify user and quit
3337 0 : ProfileMissingDialog(nativeApp);
3338 0 : return 1;
3339 : }
3340 0 : gProfileLock = profileLock;
3341 :
3342 0 : nsCOMPtr<nsILocalFile> profD;
3343 0 : rv = profileLock->GetDirectory(getter_AddRefs(profD));
3344 0 : NS_ENSURE_SUCCESS(rv, 1);
3345 :
3346 0 : nsCOMPtr<nsILocalFile> profLD;
3347 0 : rv = profileLock->GetLocalDirectory(getter_AddRefs(profLD));
3348 0 : NS_ENSURE_SUCCESS(rv, 1);
3349 :
3350 0 : rv = dirProvider.SetProfile(profD, profLD);
3351 0 : NS_ENSURE_SUCCESS(rv, 1);
3352 :
3353 : //////////////////////// NOW WE HAVE A PROFILE ////////////////////////
3354 :
3355 : #ifdef MOZ_CRASHREPORTER
3356 0 : if (appData.flags & NS_XRE_ENABLE_CRASH_REPORTER)
3357 0 : MakeOrSetMinidumpPath(profD);
3358 : #endif
3359 :
3360 0 : nsCAutoString version;
3361 0 : BuildVersion(version);
3362 :
3363 : #ifdef TARGET_OS_ABI
3364 0 : NS_NAMED_LITERAL_CSTRING(osABI, TARGET_OS_ABI);
3365 : #else
3366 : // No TARGET_XPCOM_ABI, but at least the OS is known
3367 : NS_NAMED_LITERAL_CSTRING(osABI, OS_TARGET "_UNKNOWN");
3368 : #endif
3369 :
3370 : // Check for version compatibility with the last version of the app this
3371 : // profile was started with. The format of the version stamp is defined
3372 : // by the BuildVersion function.
3373 : // Also check to see if something has happened to invalidate our
3374 : // fastload caches, like an extension upgrade or installation.
3375 :
3376 : // If we see .purgecaches, that means someone did a make.
3377 : // Re-register components to catch potential changes.
3378 : // We only offer this in debug builds, though.
3379 0 : nsCOMPtr<nsILocalFile> flagFile;
3380 :
3381 0 : rv = NS_ERROR_FILE_NOT_FOUND;
3382 0 : nsCOMPtr<nsIFile> fFlagFile;
3383 0 : if (gAppData->directory) {
3384 0 : rv = gAppData->directory->Clone(getter_AddRefs(fFlagFile));
3385 : }
3386 0 : flagFile = do_QueryInterface(fFlagFile);
3387 0 : if (flagFile) {
3388 0 : flagFile->AppendNative(FILE_INVALIDATE_CACHES);
3389 : }
3390 :
3391 : bool cachesOK;
3392 : bool versionOK = CheckCompatibility(profD, version, osABI,
3393 : dirProvider.GetGREDir(),
3394 : gAppData->directory, flagFile,
3395 0 : &cachesOK);
3396 0 : if (CheckArg("purgecaches")) {
3397 0 : cachesOK = false;
3398 : }
3399 0 : if (PR_GetEnv("MOZ_PURGE_CACHES")) {
3400 0 : cachesOK = false;
3401 : }
3402 :
3403 : // Every time a profile is loaded by a build with a different version,
3404 : // it updates the compatibility.ini file saying what version last wrote
3405 : // the fastload caches. On subsequent launches if the version matches,
3406 : // there is no need for re-registration. If the user loads the same
3407 : // profile in different builds the component registry must be
3408 : // re-generated to prevent mysterious component loading failures.
3409 : //
3410 0 : if (gSafeMode) {
3411 0 : RemoveComponentRegistries(profD, profLD, false);
3412 0 : WriteVersion(profD, NS_LITERAL_CSTRING("Safe Mode"), osABI,
3413 0 : dirProvider.GetGREDir(), gAppData->directory);
3414 : }
3415 0 : else if (versionOK) {
3416 0 : if (!cachesOK) {
3417 : // Remove caches, forcing component re-registration.
3418 : // The new list of additional components directories is derived from
3419 : // information in "extensions.ini".
3420 0 : RemoveComponentRegistries(profD, profLD, false);
3421 :
3422 : // Rewrite compatibility.ini to remove the flag
3423 : WriteVersion(profD, version, osABI,
3424 0 : dirProvider.GetGREDir(), gAppData->directory);
3425 : }
3426 : // Nothing need be done for the normal startup case.
3427 : }
3428 : else {
3429 : // Remove caches, forcing component re-registration
3430 : // with the default set of components (this disables any potentially
3431 : // troublesome incompatible XPCOM components).
3432 0 : RemoveComponentRegistries(profD, profLD, true);
3433 :
3434 : // Write out version
3435 : WriteVersion(profD, version, osABI,
3436 0 : dirProvider.GetGREDir(), gAppData->directory);
3437 : }
3438 :
3439 0 : if (flagFile) {
3440 0 : flagFile->Remove(true);
3441 : }
3442 :
3443 0 : bool appInitiatedRestart = false;
3444 :
3445 : NS_TIME_FUNCTION_MARK("Next: ScopedXPCOMStartup");
3446 :
3447 : NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup");
3448 :
3449 : // Allows the user to forcefully bypass the restart process at their
3450 : // own risk. Useful for debugging or for tinderboxes where child
3451 : // processes can be problematic.
3452 : {
3453 : // Start the real application
3454 0 : ScopedXPCOMStartup xpcom;
3455 0 : rv = xpcom.Initialize();
3456 : NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup: Initialize");
3457 0 : NS_ENSURE_SUCCESS(rv, 1);
3458 :
3459 :
3460 : #ifdef NS_FUNCTION_TIMER
3461 : // initialize some common services, so we don't pay the cost for these at odd times later on;
3462 : // SetWindowCreator -> ChromeRegistry -> IOService -> SocketTransportService -> (nspr wspm init), Prefs
3463 : {
3464 : nsCOMPtr<nsISupports> comp;
3465 :
3466 : comp = do_GetService("@mozilla.org/preferences-service;1");
3467 : NS_TIME_FUNCTION_MARK("Pref Service");
3468 :
3469 : comp = do_GetService("@mozilla.org/network/socket-transport-service;1");
3470 : NS_TIME_FUNCTION_MARK("Socket Transport Service");
3471 :
3472 : comp = do_GetService("@mozilla.org/network/dns-service;1");
3473 : NS_TIME_FUNCTION_MARK("DNS Service");
3474 :
3475 : comp = do_GetService("@mozilla.org/network/io-service;1");
3476 : NS_TIME_FUNCTION_MARK("IO Service");
3477 :
3478 : comp = do_GetService("@mozilla.org/chrome/chrome-registry;1");
3479 : NS_TIME_FUNCTION_MARK("Chrome Registry Service");
3480 :
3481 : comp = do_GetService("@mozilla.org/focus-event-suppressor-service;1");
3482 : NS_TIME_FUNCTION_MARK("Focus Event Suppressor Service");
3483 : }
3484 : #endif
3485 :
3486 0 : rv = xpcom.SetWindowCreator(nativeApp);
3487 : NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup: SetWindowCreator");
3488 0 : NS_ENSURE_SUCCESS(rv, 1);
3489 :
3490 : NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup: Done");
3491 :
3492 : #ifdef MOZ_CRASHREPORTER
3493 : // tell the crash reporter to also send the release channel
3494 0 : nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv);
3495 0 : if (NS_SUCCEEDED(rv)) {
3496 0 : nsCOMPtr<nsIPrefBranch> defaultPrefBranch;
3497 0 : rv = prefs->GetDefaultBranch(nsnull, getter_AddRefs(defaultPrefBranch));
3498 :
3499 0 : if (NS_SUCCEEDED(rv)) {
3500 0 : nsXPIDLCString sval;
3501 0 : rv = defaultPrefBranch->GetCharPref("app.update.channel", getter_Copies(sval));
3502 0 : if (NS_SUCCEEDED(rv)) {
3503 0 : CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ReleaseChannel"),
3504 0 : sval);
3505 : }
3506 : }
3507 : }
3508 : #endif
3509 :
3510 : NS_TIME_FUNCTION_MARK("Next: AppStartup");
3511 :
3512 : {
3513 0 : if (startOffline) {
3514 0 : nsCOMPtr<nsIIOService2> io (do_GetService("@mozilla.org/network/io-service;1"));
3515 0 : NS_ENSURE_TRUE(io, 1);
3516 0 : io->SetManageOfflineStatus(false);
3517 0 : io->SetOffline(true);
3518 : }
3519 :
3520 : {
3521 : nsCOMPtr<nsIObserver> startupNotifier
3522 0 : (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID, &rv));
3523 0 : NS_ENSURE_SUCCESS(rv, 1);
3524 :
3525 0 : startupNotifier->Observe(nsnull, APPSTARTUP_TOPIC, nsnull);
3526 : }
3527 :
3528 : NS_TIME_FUNCTION_MARK("Finished startupNotifier");
3529 :
3530 : nsCOMPtr<nsIAppStartup> appStartup
3531 0 : (do_GetService(NS_APPSTARTUP_CONTRACTID));
3532 0 : NS_ENSURE_TRUE(appStartup, 1);
3533 :
3534 : NS_TIME_FUNCTION_MARK("Created AppStartup");
3535 :
3536 0 : if (gDoMigration) {
3537 0 : nsCOMPtr<nsIFile> file;
3538 0 : dirProvider.GetAppDir()->Clone(getter_AddRefs(file));
3539 0 : file->AppendNative(NS_LITERAL_CSTRING("override.ini"));
3540 0 : nsINIParser parser;
3541 0 : nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
3542 0 : nsresult rv = parser.Init(localFile);
3543 0 : if (NS_SUCCEEDED(rv)) {
3544 0 : nsCAutoString buf;
3545 0 : rv = parser.GetString("XRE", "EnableProfileMigrator", buf);
3546 0 : if (NS_SUCCEEDED(rv)) {
3547 0 : if (buf[0] == '0' || buf[0] == 'f' || buf[0] == 'F') {
3548 0 : gDoMigration = false;
3549 : }
3550 : }
3551 : }
3552 : }
3553 :
3554 : // Profile Migration
3555 0 : if (gAppData->flags & NS_XRE_ENABLE_PROFILE_MIGRATOR && gDoMigration) {
3556 0 : gDoMigration = false;
3557 : nsCOMPtr<nsIProfileMigrator> pm
3558 0 : (do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID));
3559 0 : if (pm) {
3560 0 : nsCAutoString aKey;
3561 0 : if (gDoProfileReset) {
3562 : // Automatically migrate from the current application if we just
3563 : // reset the profile.
3564 0 : aKey = MOZ_APP_NAME;
3565 0 : pm->Migrate(&dirProvider, aKey);
3566 : // Set the new profile as the default after migration.
3567 0 : rv = SetCurrentProfileAsDefault(profileSvc, profD);
3568 0 : if (NS_FAILED(rv)) NS_WARNING("Could not set current profile as the default");
3569 : } else {
3570 0 : pm->Migrate(&dirProvider, aKey);
3571 : }
3572 : }
3573 : }
3574 :
3575 : NS_TIME_FUNCTION_MARK("Profile migration");
3576 :
3577 0 : dirProvider.DoStartup();
3578 :
3579 : NS_TIME_FUNCTION_MARK("dirProvider.DoStartup() (profile-after-change)");
3580 :
3581 0 : bool shuttingDown = false;
3582 0 : appStartup->GetShuttingDown(&shuttingDown);
3583 :
3584 0 : nsCOMPtr<nsICommandLineRunner> cmdLine;
3585 :
3586 0 : nsCOMPtr<nsIFile> workingDir;
3587 0 : rv = NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR, getter_AddRefs(workingDir));
3588 0 : NS_ENSURE_SUCCESS(rv, 1);
3589 :
3590 0 : if (!shuttingDown) {
3591 0 : cmdLine = do_CreateInstance("@mozilla.org/toolkit/command-line;1");
3592 0 : NS_ENSURE_TRUE(cmdLine, 1);
3593 :
3594 0 : rv = cmdLine->Init(gArgc, gArgv,
3595 0 : workingDir, nsICommandLine::STATE_INITIAL_LAUNCH);
3596 0 : NS_ENSURE_SUCCESS(rv, 1);
3597 :
3598 : /* Special-case services that need early access to the command
3599 : line. */
3600 : nsCOMPtr<nsIObserverService> obsService =
3601 0 : mozilla::services::GetObserverService();
3602 0 : if (obsService) {
3603 0 : obsService->NotifyObservers(cmdLine, "command-line-startup", nsnull);
3604 : }
3605 :
3606 : NS_TIME_FUNCTION_MARK("Early command line init");
3607 :
3608 : NS_TIME_FUNCTION_MARK("Next: prepare for Run");
3609 : }
3610 :
3611 0 : SaveStateForAppInitiatedRestart();
3612 :
3613 : // clear out any environment variables which may have been set
3614 : // during the relaunch process now that we know we won't be relaunching.
3615 0 : SaveToEnv("XRE_PROFILE_PATH=");
3616 0 : SaveToEnv("XRE_PROFILE_LOCAL_PATH=");
3617 0 : SaveToEnv("XRE_PROFILE_NAME=");
3618 0 : SaveToEnv("XRE_START_OFFLINE=");
3619 0 : SaveToEnv("NO_EM_RESTART=");
3620 0 : SaveToEnv("XUL_APP_FILE=");
3621 0 : SaveToEnv("XRE_BINARY_PATH=");
3622 :
3623 : NS_TIME_FUNCTION_MARK("env munging");
3624 :
3625 0 : if (!shuttingDown) {
3626 : NS_TIME_FUNCTION_MARK("Next: CreateHiddenWindow");
3627 :
3628 0 : rv = appStartup->CreateHiddenWindow();
3629 0 : NS_ENSURE_SUCCESS(rv, 1);
3630 :
3631 : #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK2)
3632 0 : nsGTKToolkit* toolkit = nsGTKToolkit::GetToolkit();
3633 0 : if (toolkit && !desktopStartupID.IsEmpty()) {
3634 0 : toolkit->SetDesktopStartupID(desktopStartupID);
3635 : }
3636 : // Clear the environment variable so it won't be inherited by
3637 : // child processes and confuse things.
3638 0 : g_unsetenv ("DESKTOP_STARTUP_ID");
3639 : #endif
3640 :
3641 : #ifdef XP_MACOSX
3642 : // Set up ability to respond to system (Apple) events. This must be
3643 : // done before setting up the command line service.
3644 : SetupMacApplicationDelegate();
3645 :
3646 : // we re-initialize the command-line service and do appleevents munging
3647 : // after we are sure that we're not restarting
3648 : cmdLine = do_CreateInstance("@mozilla.org/toolkit/command-line;1");
3649 : NS_ENSURE_TRUE(cmdLine, 1);
3650 :
3651 : CommandLineServiceMac::SetupMacCommandLine(gArgc, gArgv, false);
3652 :
3653 : rv = cmdLine->Init(gArgc, gArgv,
3654 : workingDir, nsICommandLine::STATE_INITIAL_LAUNCH);
3655 : NS_ENSURE_SUCCESS(rv, 1);
3656 : #endif
3657 :
3658 : nsCOMPtr<nsIObserverService> obsService =
3659 0 : mozilla::services::GetObserverService();
3660 0 : if (obsService)
3661 0 : obsService->NotifyObservers(nsnull, "final-ui-startup", nsnull);
3662 :
3663 : NS_TIME_FUNCTION_MARK("final-ui-startup done");
3664 :
3665 0 : appStartup->GetShuttingDown(&shuttingDown);
3666 : }
3667 :
3668 0 : if (!shuttingDown) {
3669 0 : rv = cmdLine->Run();
3670 0 : NS_ENSURE_SUCCESS_LOG(rv, 1);
3671 :
3672 0 : appStartup->GetShuttingDown(&shuttingDown);
3673 : }
3674 :
3675 : #ifdef MOZ_ENABLE_XREMOTE
3676 0 : nsCOMPtr<nsIRemoteService> remoteService;
3677 : #endif /* MOZ_ENABLE_XREMOTE */
3678 0 : if (!shuttingDown) {
3679 : #ifdef MOZ_ENABLE_XREMOTE
3680 : // if we have X remote support, start listening for requests on the
3681 : // proxy window.
3682 0 : if (!disableRemote)
3683 0 : remoteService = do_GetService("@mozilla.org/toolkit/remote-service;1");
3684 0 : if (remoteService)
3685 0 : remoteService->Startup(gAppData->name,
3686 0 : PromiseFlatCString(profileName).get());
3687 : #endif /* MOZ_ENABLE_XREMOTE */
3688 :
3689 0 : nativeApp->Enable();
3690 : }
3691 :
3692 : #ifdef MOZ_INSTRUMENT_EVENT_LOOP
3693 0 : if (PR_GetEnv("MOZ_INSTRUMENT_EVENT_LOOP") || SAMPLER_IS_ACTIVE()) {
3694 0 : mozilla::InitEventTracing();
3695 : }
3696 : #endif /* MOZ_INSTRUMENT_EVENT_LOOP */
3697 :
3698 : NS_TIME_FUNCTION_MARK("Next: Run");
3699 :
3700 : NS_TIME_FUNCTION_MARK("appStartup->Run");
3701 :
3702 : {
3703 0 : rv = appStartup->Run();
3704 0 : if (NS_FAILED(rv)) {
3705 0 : NS_ERROR("failed to run appstartup");
3706 0 : gLogConsoleErrors = true;
3707 : }
3708 : }
3709 :
3710 : NS_TIME_FUNCTION_MARK("Next: Finish");
3711 :
3712 : NS_TIME_FUNCTION_MARK("appStartup->Run done");
3713 :
3714 : #ifdef MOZ_INSTRUMENT_EVENT_LOOP
3715 0 : mozilla::ShutdownEventTracing();
3716 : #endif
3717 :
3718 : // Check for an application initiated restart. This is one that
3719 : // corresponds to nsIAppStartup.quit(eRestart)
3720 0 : if (rv == NS_SUCCESS_RESTART_APP)
3721 0 : appInitiatedRestart = true;
3722 :
3723 0 : if (!shuttingDown) {
3724 : #ifdef MOZ_ENABLE_XREMOTE
3725 : // shut down the x remote proxy window
3726 0 : if (remoteService)
3727 0 : remoteService->Shutdown();
3728 : #endif /* MOZ_ENABLE_XREMOTE */
3729 : }
3730 :
3731 : }
3732 : }
3733 :
3734 : // unlock the profile after ScopedXPCOMStartup object (xpcom)
3735 : // has gone out of scope. see bug #386739 for more details
3736 0 : profileLock->Unlock();
3737 0 : gProfileLock = nsnull;
3738 :
3739 : #if defined(MOZ_WIDGET_QT)
3740 : nsQAppInstance::Release();
3741 : #endif
3742 :
3743 : // Restart the app after XPCOM has been shut down cleanly.
3744 0 : if (appInitiatedRestart) {
3745 0 : RestoreStateForAppInitiatedRestart();
3746 :
3747 : // Ensure that these environment variables are set:
3748 0 : SaveFileToEnvIfUnset("XRE_PROFILE_PATH", profD);
3749 0 : SaveFileToEnvIfUnset("XRE_PROFILE_LOCAL_PATH", profLD);
3750 0 : SaveWordToEnvIfUnset("XRE_PROFILE_NAME", profileName);
3751 :
3752 : #ifdef MOZ_WIDGET_GTK2
3753 0 : MOZ_gdk_display_close(display);
3754 : #endif
3755 :
3756 0 : rv = LaunchChild(nativeApp, true);
3757 :
3758 : #ifdef MOZ_CRASHREPORTER
3759 0 : if (appData.flags & NS_XRE_ENABLE_CRASH_REPORTER)
3760 0 : CrashReporter::UnsetExceptionHandler();
3761 : #endif
3762 :
3763 0 : return rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ? 0 : 1;
3764 : }
3765 :
3766 : #ifdef MOZ_WIDGET_GTK2
3767 : // gdk_display_close also calls gdk_display_manager_set_default_display
3768 : // appropriately when necessary.
3769 0 : MOZ_gdk_display_close(display);
3770 : #endif
3771 : }
3772 :
3773 : #ifdef MOZ_CRASHREPORTER
3774 0 : if (appData.flags & NS_XRE_ENABLE_CRASH_REPORTER)
3775 0 : CrashReporter::UnsetExceptionHandler();
3776 : #endif
3777 :
3778 0 : XRE_DeinitCommandLine();
3779 :
3780 0 : return NS_FAILED(rv) ? 1 : 0;
3781 : }
3782 :
3783 : nsresult
3784 24 : XRE_InitCommandLine(int aArgc, char* aArgv[])
3785 : {
3786 24 : nsresult rv = NS_OK;
3787 :
3788 : #if defined(OS_WIN)
3789 : CommandLine::Init(aArgc, aArgv);
3790 : #else
3791 :
3792 : // these leak on error, but that's OK: we'll just exit()
3793 48 : char** canonArgs = new char*[aArgc];
3794 :
3795 : // get the canonical version of the binary's path
3796 48 : nsCOMPtr<nsILocalFile> binFile;
3797 24 : rv = XRE_GetBinaryPath(aArgv[0], getter_AddRefs(binFile));
3798 24 : if (NS_FAILED(rv))
3799 0 : return NS_ERROR_FAILURE;
3800 :
3801 48 : nsCAutoString canonBinPath;
3802 24 : rv = binFile->GetNativePath(canonBinPath);
3803 24 : if (NS_FAILED(rv))
3804 0 : return NS_ERROR_FAILURE;
3805 :
3806 24 : canonArgs[0] = strdup(canonBinPath.get());
3807 :
3808 93 : for (int i = 1; i < aArgc; ++i) {
3809 69 : if (aArgv[i]) {
3810 69 : canonArgs[i] = strdup(aArgv[i]);
3811 : }
3812 : }
3813 :
3814 24 : NS_ASSERTION(!CommandLine::IsInitialized(), "Bad news!");
3815 24 : CommandLine::Init(aArgc, canonArgs);
3816 :
3817 117 : for (int i = 0; i < aArgc; ++i)
3818 93 : free(canonArgs[i]);
3819 24 : delete[] canonArgs;
3820 : #endif
3821 :
3822 24 : const char *path = nsnull;
3823 24 : ArgResult ar = CheckArg("greomni", false, &path);
3824 24 : if (ar == ARG_BAD) {
3825 0 : PR_fprintf(PR_STDERR, "Error: argument -greomni requires a path argument\n");
3826 0 : return NS_ERROR_FAILURE;
3827 : }
3828 :
3829 24 : if (!path)
3830 24 : return rv;
3831 :
3832 0 : nsCOMPtr<nsILocalFile> greOmni;
3833 0 : rv = XRE_GetFileFromPath(path, getter_AddRefs(greOmni));
3834 0 : if (NS_FAILED(rv)) {
3835 0 : PR_fprintf(PR_STDERR, "Error: argument -greomni requires a valid path\n");
3836 0 : return rv;
3837 : }
3838 :
3839 0 : ar = CheckArg("appomni", false, &path);
3840 0 : if (ar == ARG_BAD) {
3841 0 : PR_fprintf(PR_STDERR, "Error: argument -appomni requires a path argument\n");
3842 0 : return NS_ERROR_FAILURE;
3843 : }
3844 :
3845 0 : nsCOMPtr<nsILocalFile> appOmni;
3846 0 : if (path) {
3847 0 : rv = XRE_GetFileFromPath(path, getter_AddRefs(appOmni));
3848 0 : if (NS_FAILED(rv)) {
3849 0 : PR_fprintf(PR_STDERR, "Error: argument -appomni requires a valid path\n");
3850 0 : return rv;
3851 : }
3852 : }
3853 :
3854 0 : mozilla::Omnijar::Init(greOmni, appOmni);
3855 0 : return rv;
3856 : }
3857 :
3858 : nsresult
3859 0 : XRE_DeinitCommandLine()
3860 : {
3861 0 : nsresult rv = NS_OK;
3862 :
3863 0 : CommandLine::Terminate();
3864 :
3865 0 : return rv;
3866 : }
3867 :
3868 : GeckoProcessType
3869 313843 : XRE_GetProcessType()
3870 : {
3871 313843 : return mozilla::startup::sChildProcessType;
3872 : }
3873 :
3874 : void
3875 24 : SetupErrorHandling(const char* progname)
3876 : {
3877 : #ifdef XP_WIN
3878 : /* On Windows XPSP3 and Windows Vista if DEP is configured off-by-default
3879 : we still want DEP protection: enable it explicitly and programmatically.
3880 :
3881 : This function is not available on WinXPSP2 so we dynamically load it.
3882 : */
3883 :
3884 : HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
3885 : SetProcessDEPPolicyFunc _SetProcessDEPPolicy =
3886 : (SetProcessDEPPolicyFunc) GetProcAddress(kernel32, "SetProcessDEPPolicy");
3887 : if (_SetProcessDEPPolicy)
3888 : _SetProcessDEPPolicy(PROCESS_DEP_ENABLE);
3889 : #endif
3890 :
3891 : #ifdef XP_WIN32
3892 : // Suppress the "DLL Foo could not be found" dialog, such that if dependent
3893 : // libraries (such as GDI+) are not preset, we gracefully fail to load those
3894 : // XPCOM components, instead of being ungraceful.
3895 : UINT realMode = SetErrorMode(0);
3896 : realMode |= SEM_FAILCRITICALERRORS;
3897 : // If XRE_NO_WINDOWS_CRASH_DIALOG is set, suppress displaying the "This
3898 : // application has crashed" dialog box. This is mainly useful for
3899 : // automated testing environments, e.g. tinderbox, where there's no need
3900 : // for a dozen of the dialog boxes to litter the console
3901 : if (getenv("XRE_NO_WINDOWS_CRASH_DIALOG"))
3902 : realMode |= SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX;
3903 :
3904 : SetErrorMode(realMode);
3905 :
3906 : #endif
3907 :
3908 : #ifndef XP_OS2
3909 24 : InstallSignalHandlers(progname);
3910 : #endif
3911 :
3912 : // Unbuffer stdout, needed for tinderbox tests.
3913 24 : setbuf(stdout, 0);
3914 :
3915 : #if defined(FREEBSD)
3916 : // Disable all SIGFPE's on FreeBSD, as it has non-IEEE-conformant fp
3917 : // trap behavior that trips up on floating-point tests performed by
3918 : // the JS engine. See bugzilla bug 9967 details.
3919 : fpsetmask(0);
3920 : #endif
3921 4416 : }
3922 :
|