PageRenderTime 68ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/toolkit/xre/nsAppRunner.cpp

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