PageRenderTime 70ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/toolkit/xre/nsAppRunner.cpp

https://bitbucket.org/mkato/mozilla-1.9.0-win64
C++ | 3340 lines | 2433 code | 525 blank | 382 comment | 441 complexity | 2e344f2954b7fe48acce10c1f61b725f MD5 | raw file
Possible License(s): LGPL-3.0, MIT, BSD-3-Clause, MPL-2.0-no-copyleft-exception, GPL-2.0, LGPL-2.1
  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. #include "nsAppRunner.h"
  49. #include "nsUpdateDriver.h"
  50. #ifdef XP_MACOSX
  51. #include "MacLaunchHelper.h"
  52. #include "MacApplicationDelegate.h"
  53. #endif
  54. #ifdef XP_OS2
  55. #include "private/pprthred.h"
  56. #endif
  57. #include "prmem.h"
  58. #include "prnetdb.h"
  59. #include "prprf.h"
  60. #include "prproces.h"
  61. #include "prenv.h"
  62. #include "nsIAppShellService.h"
  63. #include "nsIAppStartup.h"
  64. #include "nsIAppStartupNotifier.h"
  65. #include "nsIMutableArray.h"
  66. #include "nsICategoryManager.h"
  67. #include "nsIChromeRegistry.h"
  68. #include "nsICommandLineRunner.h"
  69. #include "nsIComponentManager.h"
  70. #include "nsIComponentRegistrar.h"
  71. #include "nsIContentHandler.h"
  72. #include "nsIDialogParamBlock.h"
  73. #include "nsIDOMWindow.h"
  74. #include "nsIExtensionManager.h"
  75. #include "nsIFastLoadService.h" // for PLATFORM_FASL_SUFFIX
  76. #include "nsIGenericFactory.h"
  77. #include "nsIIOService2.h"
  78. #include "nsIObserverService.h"
  79. #include "nsINativeAppSupport.h"
  80. #include "nsIProcess.h"
  81. #include "nsIProfileUnlocker.h"
  82. #include "nsIPromptService.h"
  83. #include "nsIServiceManager.h"
  84. #include "nsIStringBundle.h"
  85. #include "nsISupportsPrimitives.h"
  86. #include "nsITimelineService.h"
  87. #include "nsIToolkitChromeRegistry.h"
  88. #include "nsIToolkitProfile.h"
  89. #include "nsIToolkitProfileService.h"
  90. #include "nsIURI.h"
  91. #include "nsIWindowCreator.h"
  92. #include "nsIWindowMediator.h"
  93. #include "nsIWindowWatcher.h"
  94. #include "nsIXULAppInfo.h"
  95. #include "nsIXULRuntime.h"
  96. #include "nsPIDOMWindow.h"
  97. #include "nsIBaseWindow.h"
  98. #include "nsIWidget.h"
  99. #include "nsIDocShell.h"
  100. #include "nsAppShellCID.h"
  101. #ifdef XP_WIN
  102. #include "nsIWinAppHelper.h"
  103. #include <windows.h>
  104. #ifndef PROCESS_DEP_ENABLE
  105. #define PROCESS_DEP_ENABLE 0x1
  106. #endif
  107. #endif
  108. #include "nsCRT.h"
  109. #include "nsCOMPtr.h"
  110. #include "nsDirectoryServiceDefs.h"
  111. #include "nsDirectoryServiceUtils.h"
  112. #include "nsEmbedCID.h"
  113. #include "nsNetUtil.h"
  114. #include "nsReadableUtils.h"
  115. #include "nsStaticComponents.h"
  116. #include "nsXPCOM.h"
  117. #include "nsXPIDLString.h"
  118. #include "nsXPFEComponentsCID.h"
  119. #include "nsVersionComparator.h"
  120. #include "nsAppDirectoryServiceDefs.h"
  121. #include "nsXULAppAPI.h"
  122. #include "nsXREDirProvider.h"
  123. #include "nsToolkitCompsCID.h"
  124. #include "nsINIParser.h"
  125. #include <stdlib.h>
  126. #ifdef XP_UNIX
  127. #include <sys/stat.h>
  128. #include <unistd.h>
  129. #endif
  130. #ifdef XP_BEOS
  131. // execv() behaves bit differently in R5 and Zeta, looks unreliable in such situation
  132. //#include <unistd.h>
  133. #include <AppKit.h>
  134. #include <AppFileInfo.h>
  135. #endif //XP_BEOS
  136. #ifdef XP_WIN
  137. #include <process.h>
  138. #include <shlobj.h>
  139. #include "nsThreadUtils.h"
  140. #endif
  141. #ifdef XP_MACOSX
  142. #include "nsILocalFileMac.h"
  143. #include "nsCommandLineServiceMac.h"
  144. #endif
  145. // for X remote support
  146. #ifdef MOZ_ENABLE_XREMOTE
  147. #ifdef MOZ_WIDGET_PHOTON
  148. #include "PhRemoteClient.h"
  149. #else
  150. #include "XRemoteClient.h"
  151. #endif
  152. #include "nsIRemoteService.h"
  153. #endif
  154. #ifdef NS_TRACE_MALLOC
  155. #include "nsTraceMalloc.h"
  156. #endif
  157. #if defined(DEBUG) && defined(XP_WIN32)
  158. #include <malloc.h>
  159. #endif
  160. #if defined (XP_MACOSX)
  161. #include <Processes.h>
  162. #include <Events.h>
  163. #endif
  164. extern "C" void ShowOSAlert(const char* aMessage);
  165. #ifdef DEBUG
  166. #include "prlog.h"
  167. #endif
  168. #ifdef MOZ_JPROF
  169. #include "jprof.h"
  170. #endif
  171. #ifdef MOZ_CRASHREPORTER
  172. #include "nsExceptionHandler.h"
  173. #include "nsICrashReporter.h"
  174. #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
  175. #endif
  176. // on x86 linux, the current builds of some popular plugins (notably
  177. // flashplayer and real) expect a few builtin symbols from libgcc
  178. // which were available in some older versions of gcc. However,
  179. // they're _NOT_ available in newer versions of gcc (eg 3.1), so if
  180. // we want those plugin to work with a gcc-3.1 built binary, we need
  181. // to provide these symbols. MOZ_ENABLE_OLD_ABI_COMPAT_WRAPPERS defaults
  182. // to true on x86 linux, and false everywhere else.
  183. //
  184. // The fact that the new and free operators are mismatched
  185. // mirrors the way the original functions in egcs 1.1.2 worked.
  186. #ifdef MOZ_ENABLE_OLD_ABI_COMPAT_WRAPPERS
  187. extern "C" {
  188. # ifndef HAVE___BUILTIN_VEC_NEW
  189. void *__builtin_vec_new(size_t aSize, const std::nothrow_t &aNoThrow) throw()
  190. {
  191. return ::operator new(aSize, aNoThrow);
  192. }
  193. # endif
  194. # ifndef HAVE___BUILTIN_VEC_DELETE
  195. void __builtin_vec_delete(void *aPtr, const std::nothrow_t &) throw ()
  196. {
  197. if (aPtr) {
  198. free(aPtr);
  199. }
  200. }
  201. # endif
  202. # ifndef HAVE___BUILTIN_NEW
  203. void *__builtin_new(int aSize)
  204. {
  205. return malloc(aSize);
  206. }
  207. # endif
  208. # ifndef HAVE___BUILTIN_DELETE
  209. void __builtin_delete(void *aPtr)
  210. {
  211. free(aPtr);
  212. }
  213. # endif
  214. # ifndef HAVE___PURE_VIRTUAL
  215. void __pure_virtual(void) {
  216. #ifdef WRAP_SYSTEM_INCLUDES
  217. #pragma GCC visibility push(default)
  218. #endif
  219. extern void __cxa_pure_virtual(void);
  220. #ifdef WRAP_SYSTEM_INCLUDES
  221. #pragma GCC visibility pop
  222. #endif
  223. __cxa_pure_virtual();
  224. }
  225. # endif
  226. }
  227. #endif
  228. #if defined(XP_UNIX) || defined(XP_BEOS)
  229. extern void InstallUnixSignalHandlers(const char *ProgramName);
  230. #endif
  231. int gArgc;
  232. char **gArgv;
  233. static char gToolkitVersion[20];
  234. static char gToolkitBuildID[40];
  235. static int gRestartArgc;
  236. static char **gRestartArgv;
  237. #if defined(MOZ_WIDGET_GTK2)
  238. #include <gtk/gtk.h>
  239. #include <gdk/gdkx.h>
  240. #include "nsGTKToolkit.h"
  241. #endif
  242. // Save the given word to the specified environment variable.
  243. static void
  244. SaveWordToEnv(const char *name, const nsACString & word)
  245. {
  246. char *expr = PR_smprintf("%s=%s", name, PromiseFlatCString(word).get());
  247. if (expr)
  248. PR_SetEnv(expr);
  249. // We intentionally leak |expr| here since it is required by PR_SetEnv.
  250. }
  251. // Save the path of the given file to the specified environment variable.
  252. static void
  253. SaveFileToEnv(const char *name, nsIFile *file)
  254. {
  255. #ifdef XP_WIN
  256. nsAutoString path;
  257. file->GetPath(path);
  258. SetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(), path.get());
  259. #else
  260. nsCAutoString path;
  261. file->GetNativePath(path);
  262. SaveWordToEnv(name, path);
  263. #endif
  264. }
  265. // Load the path of a file saved with SaveFileToEnv
  266. static already_AddRefed<nsILocalFile>
  267. GetFileFromEnv(const char *name)
  268. {
  269. nsresult rv;
  270. nsILocalFile *file = nsnull;
  271. #ifdef XP_WIN
  272. WCHAR path[_MAX_PATH];
  273. if (!GetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(),
  274. path, _MAX_PATH))
  275. return nsnull;
  276. rv = NS_NewLocalFile(nsDependentString(path), PR_TRUE, &file);
  277. if (NS_FAILED(rv))
  278. return nsnull;
  279. return file;
  280. #else
  281. const char *arg = PR_GetEnv(name);
  282. if (!arg || !*arg)
  283. return nsnull;
  284. rv = NS_NewNativeLocalFile(nsDependentCString(arg), PR_TRUE, &file);
  285. if (NS_FAILED(rv))
  286. return nsnull;
  287. return file;
  288. #endif
  289. }
  290. // Save the path of the given word to the specified environment variable
  291. // provided the environment variable does not have a value.
  292. static void
  293. SaveWordToEnvIfUnset(const char *name, const nsACString & word)
  294. {
  295. const char *val = PR_GetEnv(name);
  296. if (!(val && *val))
  297. SaveWordToEnv(name, word);
  298. }
  299. // Save the path of the given file to the specified environment variable
  300. // provided the environment variable does not have a value.
  301. static void
  302. SaveFileToEnvIfUnset(const char *name, nsIFile *file)
  303. {
  304. const char *val = PR_GetEnv(name);
  305. if (!(val && *val))
  306. SaveFileToEnv(name, file);
  307. }
  308. static PRBool
  309. strimatch(const char* lowerstr, const char* mixedstr)
  310. {
  311. while(*lowerstr) {
  312. if (!*mixedstr) return PR_FALSE; // mixedstr is shorter
  313. if (tolower(*mixedstr) != *lowerstr) return PR_FALSE; // no match
  314. ++lowerstr;
  315. ++mixedstr;
  316. }
  317. if (*mixedstr) return PR_FALSE; // lowerstr is shorter
  318. return PR_TRUE;
  319. }
  320. /**
  321. * Output a string to the user. This method is really only meant to be used to
  322. * output last-ditch error messages designed for developers NOT END USERS.
  323. *
  324. * @param isError
  325. * Pass true to indicate severe errors.
  326. * @param fmt
  327. * printf-style format string followed by arguments.
  328. */
  329. static void Output(PRBool isError, const char *fmt, ... )
  330. {
  331. va_list ap;
  332. va_start(ap, fmt);
  333. #if defined(XP_WIN) && !MOZ_WINCONSOLE
  334. char *msg = PR_vsmprintf(fmt, ap);
  335. if (msg)
  336. {
  337. UINT flags = MB_OK;
  338. if (isError)
  339. flags |= MB_ICONERROR;
  340. else
  341. flags |= MB_ICONINFORMATION;
  342. MessageBoxA(NULL, msg, "XULRunner", flags);
  343. PR_smprintf_free(msg);
  344. }
  345. #else
  346. vfprintf(stderr, fmt, ap);
  347. #endif
  348. va_end(ap);
  349. }
  350. enum RemoteResult {
  351. REMOTE_NOT_FOUND = 0,
  352. REMOTE_FOUND = 1,
  353. REMOTE_ARG_BAD = 2
  354. };
  355. enum ArgResult {
  356. ARG_NONE = 0,
  357. ARG_FOUND = 1,
  358. ARG_BAD = 2 // you wanted a param, but there isn't one
  359. };
  360. static void RemoveArg(char **argv)
  361. {
  362. do {
  363. *argv = *(argv + 1);
  364. ++argv;
  365. } while (*argv);
  366. --gArgc;
  367. }
  368. /**
  369. * Check for a commandline flag. If the flag takes a parameter, the
  370. * parameter is returned in aParam. Flags may be in the form -arg or
  371. * --arg (or /arg on win32/OS2).
  372. *
  373. * @param aArg the parameter to check. Must be lowercase.
  374. * @param aCheckOSInt if true returns ARG_BAD if the osint argument is present
  375. * when aArg is also present.
  376. * @param if non-null, the -arg <data> will be stored in this pointer. This is *not*
  377. * allocated, but rather a pointer to the argv data.
  378. */
  379. static ArgResult
  380. CheckArg(const char* aArg, PRBool aCheckOSInt = PR_FALSE, const char **aParam = nsnull)
  381. {
  382. char **curarg = gArgv + 1; // skip argv[0]
  383. ArgResult ar = ARG_NONE;
  384. while (*curarg) {
  385. char *arg = curarg[0];
  386. if (arg[0] == '-'
  387. #if defined(XP_WIN) || defined(XP_OS2)
  388. || *arg == '/'
  389. #endif
  390. ) {
  391. ++arg;
  392. if (*arg == '-')
  393. ++arg;
  394. if (strimatch(aArg, arg)) {
  395. RemoveArg(curarg);
  396. if (!aParam) {
  397. ar = ARG_FOUND;
  398. break;
  399. }
  400. if (*curarg) {
  401. if (**curarg == '-'
  402. #if defined(XP_WIN) || defined(XP_OS2)
  403. || **curarg == '/'
  404. #endif
  405. )
  406. return ARG_BAD;
  407. *aParam = *curarg;
  408. RemoveArg(curarg);
  409. ar = ARG_FOUND;
  410. break;
  411. }
  412. return ARG_BAD;
  413. }
  414. }
  415. ++curarg;
  416. }
  417. if (aCheckOSInt && ar == ARG_FOUND) {
  418. ArgResult arOSInt = CheckArg("osint");
  419. if (arOSInt == ARG_FOUND) {
  420. ar = ARG_BAD;
  421. PR_fprintf(PR_STDERR, "Error: argument -osint is invalid\n");
  422. }
  423. }
  424. return ar;
  425. }
  426. #if defined(XP_WIN)
  427. /**
  428. * Check for a commandline flag from the windows shell and remove it from the
  429. * argv used when restarting. Flags MUST be in the form -arg.
  430. *
  431. * @param aArg the parameter to check. Must be lowercase.
  432. */
  433. static ArgResult
  434. CheckArgShell(const char* aArg)
  435. {
  436. char **curarg = gRestartArgv + 1; // skip argv[0]
  437. while (*curarg) {
  438. char *arg = curarg[0];
  439. if (arg[0] == '-') {
  440. ++arg;
  441. if (strimatch(aArg, arg)) {
  442. do {
  443. *curarg = *(curarg + 1);
  444. ++curarg;
  445. } while (*curarg);
  446. --gRestartArgc;
  447. return ARG_FOUND;
  448. }
  449. }
  450. ++curarg;
  451. }
  452. return ARG_NONE;
  453. }
  454. /**
  455. * Enable Native App Support to process DDE messages when the app needs to
  456. * restart and the app has been launched by the Windows shell to open an url.
  457. * When aWait is false this will process the DDE events manually. This prevents
  458. * Windows from displaying an error message due to the DDE message not being
  459. * acknowledged.
  460. */
  461. static void
  462. ProcessDDE(nsINativeAppSupport* aNative, PRBool aWait)
  463. {
  464. // When the app is launched by the windows shell the windows shell
  465. // expects the app to be available for DDE messages and if it isn't
  466. // windows displays an error dialog. To prevent the error the DDE server
  467. // is enabled and pending events are processed when the app needs to
  468. // restart after it was launched by the shell with the requestpending
  469. // argument. The requestpending pending argument is removed to
  470. // differentiate it from being launched when an app restart is not
  471. // required.
  472. ArgResult ar;
  473. ar = CheckArgShell("requestpending");
  474. if (ar == ARG_FOUND) {
  475. aNative->Enable(); // enable win32 DDE responses
  476. if (aWait) {
  477. nsIThread *thread = NS_GetCurrentThread();
  478. // This is just a guesstimate based on testing different values.
  479. // If count is 8 or less windows will display an error dialog.
  480. PRInt32 count = 20;
  481. while(--count >= 0) {
  482. NS_ProcessNextEvent(thread);
  483. PR_Sleep(PR_MillisecondsToInterval(1));
  484. }
  485. }
  486. }
  487. }
  488. #endif
  489. PRBool gSafeMode = PR_FALSE;
  490. /**
  491. * The nsXULAppInfo object implements nsIFactory so that it can be its own
  492. * singleton.
  493. */
  494. class nsXULAppInfo : public nsIXULAppInfo,
  495. #ifdef XP_WIN
  496. public nsIWinAppHelper,
  497. #endif
  498. #ifdef MOZ_CRASHREPORTER
  499. public nsICrashReporter,
  500. public nsICrashReporter_MOZILLA_1_9_BRANCH,
  501. #endif
  502. public nsIXULRuntime
  503. {
  504. public:
  505. NS_DECL_ISUPPORTS_INHERITED
  506. NS_DECL_NSIXULAPPINFO
  507. NS_DECL_NSIXULRUNTIME
  508. #ifdef MOZ_CRASHREPORTER
  509. NS_DECL_NSICRASHREPORTER
  510. NS_DECL_NSICRASHREPORTER_MOZILLA_1_9_BRANCH
  511. #endif
  512. #ifdef XP_WIN
  513. NS_DECL_NSIWINAPPHELPER
  514. private:
  515. nsresult LaunchAppHelperWithArgs(int aArgc, char **aArgv);
  516. #endif
  517. };
  518. NS_INTERFACE_MAP_BEGIN(nsXULAppInfo)
  519. NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULRuntime)
  520. NS_INTERFACE_MAP_ENTRY(nsIXULRuntime)
  521. #ifdef XP_WIN
  522. NS_INTERFACE_MAP_ENTRY(nsIWinAppHelper)
  523. #endif
  524. #ifdef MOZ_CRASHREPORTER
  525. NS_INTERFACE_MAP_ENTRY(nsICrashReporter)
  526. NS_INTERFACE_MAP_ENTRY(nsICrashReporter_MOZILLA_1_9_BRANCH)
  527. #endif
  528. NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIXULAppInfo, gAppData)
  529. NS_INTERFACE_MAP_END
  530. NS_IMETHODIMP_(nsrefcnt)
  531. nsXULAppInfo::AddRef()
  532. {
  533. return 1;
  534. }
  535. NS_IMETHODIMP_(nsrefcnt)
  536. nsXULAppInfo::Release()
  537. {
  538. return 1;
  539. }
  540. NS_IMETHODIMP
  541. nsXULAppInfo::GetVendor(nsACString& aResult)
  542. {
  543. aResult.Assign(gAppData->vendor);
  544. return NS_OK;
  545. }
  546. NS_IMETHODIMP
  547. nsXULAppInfo::GetName(nsACString& aResult)
  548. {
  549. aResult.Assign(gAppData->name);
  550. return NS_OK;
  551. }
  552. NS_IMETHODIMP
  553. nsXULAppInfo::GetID(nsACString& aResult)
  554. {
  555. aResult.Assign(gAppData->ID);
  556. return NS_OK;
  557. }
  558. NS_IMETHODIMP
  559. nsXULAppInfo::GetVersion(nsACString& aResult)
  560. {
  561. aResult.Assign(gAppData->version);
  562. return NS_OK;
  563. }
  564. NS_IMETHODIMP
  565. nsXULAppInfo::GetPlatformVersion(nsACString& aResult)
  566. {
  567. aResult.Assign(gToolkitVersion);
  568. return NS_OK;
  569. }
  570. NS_IMETHODIMP
  571. nsXULAppInfo::GetAppBuildID(nsACString& aResult)
  572. {
  573. aResult.Assign(gAppData->buildID);
  574. return NS_OK;
  575. }
  576. NS_IMETHODIMP
  577. nsXULAppInfo::GetPlatformBuildID(nsACString& aResult)
  578. {
  579. aResult.Assign(gToolkitBuildID);
  580. return NS_OK;
  581. }
  582. NS_IMETHODIMP
  583. nsXULAppInfo::GetLogConsoleErrors(PRBool *aResult)
  584. {
  585. *aResult = gLogConsoleErrors;
  586. return NS_OK;
  587. }
  588. NS_IMETHODIMP
  589. nsXULAppInfo::SetLogConsoleErrors(PRBool aValue)
  590. {
  591. gLogConsoleErrors = aValue;
  592. return NS_OK;
  593. }
  594. NS_IMETHODIMP
  595. nsXULAppInfo::GetInSafeMode(PRBool *aResult)
  596. {
  597. *aResult = gSafeMode;
  598. return NS_OK;
  599. }
  600. NS_IMETHODIMP
  601. nsXULAppInfo::GetOS(nsACString& aResult)
  602. {
  603. aResult.AssignLiteral(OS_TARGET);
  604. return NS_OK;
  605. }
  606. NS_IMETHODIMP
  607. nsXULAppInfo::GetXPCOMABI(nsACString& aResult)
  608. {
  609. #ifdef TARGET_XPCOM_ABI
  610. aResult.AssignLiteral(TARGET_XPCOM_ABI);
  611. return NS_OK;
  612. #else
  613. return NS_ERROR_NOT_AVAILABLE;
  614. #endif
  615. }
  616. #ifdef XP_WIN
  617. nsresult
  618. nsXULAppInfo::LaunchAppHelperWithArgs(int aArgc, char **aArgv)
  619. {
  620. nsresult rv;
  621. nsCOMPtr<nsIProperties> directoryService =
  622. do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
  623. NS_ENSURE_SUCCESS(rv, rv);
  624. nsCOMPtr<nsILocalFile> appHelper;
  625. rv = directoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(appHelper));
  626. NS_ENSURE_SUCCESS(rv, rv);
  627. rv = appHelper->AppendNative(NS_LITERAL_CSTRING("uninstall"));
  628. NS_ENSURE_SUCCESS(rv, rv);
  629. rv = appHelper->AppendNative(NS_LITERAL_CSTRING("helper.exe"));
  630. NS_ENSURE_SUCCESS(rv, rv);
  631. nsAutoString appHelperPath;
  632. rv = appHelper->GetPath(appHelperPath);
  633. NS_ENSURE_SUCCESS(rv, rv);
  634. if (!WinLaunchChild(appHelperPath.get(), aArgc, aArgv, 1))
  635. return NS_ERROR_FAILURE;
  636. else
  637. return NS_OK;
  638. }
  639. NS_IMETHODIMP
  640. nsXULAppInfo::PostUpdate(nsILocalFile *aLogFile)
  641. {
  642. nsresult rv;
  643. int upgradeArgc = aLogFile ? 3 : 2;
  644. char **upgradeArgv = (char**) malloc(sizeof(char*) * (upgradeArgc + 1));
  645. if (!upgradeArgv)
  646. return NS_ERROR_OUT_OF_MEMORY;
  647. upgradeArgv[0] = "argv0ignoredbywinlaunchchild";
  648. upgradeArgv[1] = "/postupdate";
  649. char *pathArg = nsnull;
  650. if (aLogFile) {
  651. nsCAutoString logFilePath;
  652. rv = aLogFile->GetNativePath(logFilePath);
  653. NS_ENSURE_SUCCESS(rv, rv);
  654. pathArg = PR_smprintf("/uninstalllog=%s", logFilePath.get());
  655. if (!pathArg)
  656. return NS_ERROR_OUT_OF_MEMORY;
  657. upgradeArgv[2] = pathArg;
  658. upgradeArgv[3] = nsnull;
  659. }
  660. else {
  661. upgradeArgv[2] = nsnull;
  662. }
  663. rv = LaunchAppHelperWithArgs(upgradeArgc, upgradeArgv);
  664. if (pathArg)
  665. PR_smprintf_free(pathArg);
  666. free(upgradeArgv);
  667. return rv;
  668. }
  669. // Matches the enum in WinNT.h for the Vista SDK but renamed so that we can
  670. // safely build with the Vista SDK and without it.
  671. typedef enum
  672. {
  673. VistaTokenElevationTypeDefault = 1,
  674. VistaTokenElevationTypeFull,
  675. VistaTokenElevationTypeLimited
  676. } VISTA_TOKEN_ELEVATION_TYPE;
  677. // avoid collision with TokeElevationType enum in WinNT.h
  678. // of the Vista SDK
  679. #define VistaTokenElevationType static_cast< TOKEN_INFORMATION_CLASS >( 18 )
  680. NS_IMETHODIMP
  681. nsXULAppInfo::GetUserCanElevate(PRBool *aUserCanElevate)
  682. {
  683. #ifdef WINCE
  684. *aUserCanElevate = PR_FALSE;
  685. return NS_OK;
  686. #else
  687. HANDLE hToken;
  688. VISTA_TOKEN_ELEVATION_TYPE elevationType;
  689. DWORD dwSize;
  690. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) ||
  691. !GetTokenInformation(hToken, VistaTokenElevationType, &elevationType,
  692. sizeof(elevationType), &dwSize)) {
  693. *aUserCanElevate = PR_FALSE;
  694. }
  695. else {
  696. // The possible values returned for elevationType and their meanings are:
  697. // TokenElevationTypeDefault: The token does not have a linked token
  698. // (e.g. UAC disabled or a standard user, so they can't be elevated)
  699. // TokenElevationTypeFull: The token is linked to an elevated token
  700. // (e.g. UAC is enabled and the user is already elevated so they can't
  701. // be elevated again)
  702. // TokenElevationTypeLimited: The token is linked to a limited token
  703. // (e.g. UAC is enabled and the user is not elevated, so they can be
  704. // elevated)
  705. *aUserCanElevate = (elevationType == VistaTokenElevationTypeLimited);
  706. }
  707. if (hToken)
  708. CloseHandle(hToken);
  709. return NS_OK;
  710. #endif // WINCE
  711. }
  712. #endif
  713. #ifdef MOZ_CRASHREPORTER
  714. NS_IMETHODIMP
  715. nsXULAppInfo::AnnotateCrashReport(const nsACString& key,
  716. const nsACString& data)
  717. {
  718. return CrashReporter::AnnotateCrashReport(key, data);
  719. }
  720. NS_IMETHODIMP
  721. nsXULAppInfo::AppendAppNotesToCrashReport(const nsACString& data)
  722. {
  723. return CrashReporter::AppendAppNotesToCrashReport(data);
  724. }
  725. NS_IMETHODIMP
  726. nsXULAppInfo::WriteMinidumpForException(void* aExceptionInfo)
  727. {
  728. #ifdef XP_WIN32
  729. return CrashReporter::WriteMinidumpForException(static_cast<EXCEPTION_POINTERS*>(aExceptionInfo));
  730. #else
  731. return NS_ERROR_NOT_IMPLEMENTED;
  732. #endif
  733. }
  734. NS_IMETHODIMP
  735. nsXULAppInfo::AppendObjCExceptionInfoToAppNotes(void* aException)
  736. {
  737. #ifdef XP_MACOSX
  738. return CrashReporter::AppendObjCExceptionInfoToAppNotes(aException);
  739. #else
  740. return NS_ERROR_NOT_IMPLEMENTED;
  741. #endif
  742. }
  743. #endif // MOZ_CRASHREPORTER
  744. static const nsXULAppInfo kAppInfo;
  745. static NS_METHOD AppInfoConstructor(nsISupports* aOuter,
  746. REFNSIID aIID, void **aResult)
  747. {
  748. NS_ENSURE_NO_AGGREGATION(aOuter);
  749. return const_cast<nsXULAppInfo*>(&kAppInfo)->
  750. QueryInterface(aIID, aResult);
  751. }
  752. PRBool gLogConsoleErrors
  753. #ifdef DEBUG
  754. = PR_TRUE;
  755. #else
  756. = PR_FALSE;
  757. #endif
  758. #define NS_ENSURE_TRUE_LOG(x, ret) \
  759. PR_BEGIN_MACRO \
  760. if (NS_UNLIKELY(!(x))) { \
  761. NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \
  762. gLogConsoleErrors = PR_TRUE; \
  763. return ret; \
  764. } \
  765. PR_END_MACRO
  766. #define NS_ENSURE_SUCCESS_LOG(res, ret) \
  767. NS_ENSURE_TRUE_LOG(NS_SUCCEEDED(res), ret)
  768. /**
  769. * Because we're starting/stopping XPCOM several times in different scenarios,
  770. * this class is a stack-based critter that makes sure that XPCOM is shut down
  771. * during early returns.
  772. */
  773. class ScopedXPCOMStartup
  774. {
  775. public:
  776. ScopedXPCOMStartup() :
  777. mServiceManager(nsnull) { }
  778. ~ScopedXPCOMStartup();
  779. nsresult Initialize();
  780. nsresult DoAutoreg();
  781. nsresult RegisterProfileService();
  782. nsresult SetWindowCreator(nsINativeAppSupport* native);
  783. private:
  784. nsIServiceManager* mServiceManager;
  785. };
  786. ScopedXPCOMStartup::~ScopedXPCOMStartup()
  787. {
  788. if (mServiceManager) {
  789. nsCOMPtr<nsIAppStartup> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID));
  790. if (appStartup)
  791. appStartup->DestroyHiddenWindow();
  792. gDirServiceProvider->DoShutdown();
  793. WriteConsoleLog();
  794. NS_ShutdownXPCOM(mServiceManager);
  795. mServiceManager = nsnull;
  796. }
  797. }
  798. // {95d89e3e-a169-41a3-8e56-719978e15b12}
  799. #define APPINFO_CID \
  800. { 0x95d89e3e, 0xa169, 0x41a3, { 0x8e, 0x56, 0x71, 0x99, 0x78, 0xe1, 0x5b, 0x12 } }
  801. static nsModuleComponentInfo kComponents[] =
  802. {
  803. {
  804. "nsXULAppInfo",
  805. APPINFO_CID,
  806. XULAPPINFO_SERVICE_CONTRACTID,
  807. AppInfoConstructor
  808. }
  809. #ifdef MOZ_CRASHREPORTER
  810. ,
  811. {
  812. "nsXULAppInfo",
  813. APPINFO_CID,
  814. NS_CRASHREPORTER_CONTRACTID,
  815. AppInfoConstructor
  816. }
  817. #endif
  818. };
  819. NS_IMPL_NSGETMODULE(Apprunner, kComponents)
  820. #if !defined(_BUILD_STATIC_BIN) && !defined(MOZ_ENABLE_LIBXUL)
  821. static nsStaticModuleInfo const kXREStaticModules[] =
  822. {
  823. {
  824. "Apprunner",
  825. Apprunner_NSGetModule
  826. }
  827. };
  828. nsStaticModuleInfo const *const kPStaticModules = kXREStaticModules;
  829. PRUint32 const kStaticModuleCount = NS_ARRAY_LENGTH(kXREStaticModules);
  830. #endif
  831. nsresult
  832. ScopedXPCOMStartup::Initialize()
  833. {
  834. NS_ASSERTION(gDirServiceProvider, "Should not get here!");
  835. nsresult rv;
  836. rv = NS_InitXPCOM3(&mServiceManager, gDirServiceProvider->GetAppDir(),
  837. gDirServiceProvider,
  838. kPStaticModules, kStaticModuleCount);
  839. if (NS_FAILED(rv)) {
  840. NS_ERROR("Couldn't start xpcom!");
  841. mServiceManager = nsnull;
  842. }
  843. else {
  844. nsCOMPtr<nsIComponentRegistrar> reg =
  845. do_QueryInterface(mServiceManager);
  846. NS_ASSERTION(reg, "Service Manager doesn't QI to Registrar.");
  847. }
  848. return rv;
  849. }
  850. // {0C4A446C-EE82-41f2-8D04-D366D2C7A7D4}
  851. static const nsCID kNativeAppSupportCID =
  852. { 0xc4a446c, 0xee82, 0x41f2, { 0x8d, 0x4, 0xd3, 0x66, 0xd2, 0xc7, 0xa7, 0xd4 } };
  853. // {5F5E59CE-27BC-47eb-9D1F-B09CA9049836}
  854. static const nsCID kProfileServiceCID =
  855. { 0x5f5e59ce, 0x27bc, 0x47eb, { 0x9d, 0x1f, 0xb0, 0x9c, 0xa9, 0x4, 0x98, 0x36 } };
  856. nsresult
  857. ScopedXPCOMStartup::RegisterProfileService()
  858. {
  859. NS_ASSERTION(mServiceManager, "Not initialized!");
  860. nsCOMPtr<nsIFactory> factory;
  861. NS_NewToolkitProfileFactory(getter_AddRefs(factory));
  862. if (!factory) return NS_ERROR_OUT_OF_MEMORY;
  863. nsCOMPtr<nsIComponentRegistrar> reg (do_QueryInterface(mServiceManager));
  864. if (!reg) return NS_ERROR_NO_INTERFACE;
  865. return reg->RegisterFactory(kProfileServiceCID,
  866. "Toolkit Profile Service",
  867. NS_PROFILESERVICE_CONTRACTID,
  868. factory);
  869. }
  870. nsresult
  871. ScopedXPCOMStartup::DoAutoreg()
  872. {
  873. #ifdef DEBUG
  874. // _Always_ autoreg if we're in a debug build, under the assumption
  875. // that people are busily modifying components and will be angry if
  876. // their changes aren't noticed.
  877. nsCOMPtr<nsIComponentRegistrar> registrar
  878. (do_QueryInterface(mServiceManager));
  879. NS_ASSERTION(registrar, "Where's the component registrar?");
  880. registrar->AutoRegister(nsnull);
  881. #endif
  882. return NS_OK;
  883. }
  884. /**
  885. * This is a little factory class that serves as a singleton-service-factory
  886. * for the nativeappsupport object.
  887. */
  888. class nsSingletonFactory : public nsIFactory
  889. {
  890. public:
  891. NS_DECL_ISUPPORTS
  892. NS_DECL_NSIFACTORY
  893. nsSingletonFactory(nsISupports* aSingleton);
  894. ~nsSingletonFactory() { }
  895. private:
  896. nsCOMPtr<nsISupports> mSingleton;
  897. };
  898. nsSingletonFactory::nsSingletonFactory(nsISupports* aSingleton)
  899. : mSingleton(aSingleton)
  900. {
  901. NS_ASSERTION(mSingleton, "Singleton was null!");
  902. }
  903. NS_IMPL_ISUPPORTS1(nsSingletonFactory, nsIFactory)
  904. NS_IMETHODIMP
  905. nsSingletonFactory::CreateInstance(nsISupports* aOuter,
  906. const nsIID& aIID,
  907. void* *aResult)
  908. {
  909. NS_ENSURE_NO_AGGREGATION(aOuter);
  910. return mSingleton->QueryInterface(aIID, aResult);
  911. }
  912. NS_IMETHODIMP
  913. nsSingletonFactory::LockFactory(PRBool)
  914. {
  915. return NS_OK;
  916. }
  917. /**
  918. * Set our windowcreator on the WindowWatcher service.
  919. */
  920. nsresult
  921. ScopedXPCOMStartup::SetWindowCreator(nsINativeAppSupport* native)
  922. {
  923. nsresult rv;
  924. nsCOMPtr<nsIComponentRegistrar> registrar
  925. (do_QueryInterface(mServiceManager));
  926. NS_ASSERTION(registrar, "Where's the component registrar?");
  927. nsCOMPtr<nsIFactory> nativeFactory = new nsSingletonFactory(native);
  928. NS_ENSURE_TRUE(nativeFactory, NS_ERROR_OUT_OF_MEMORY);
  929. rv = registrar->RegisterFactory(kNativeAppSupportCID,
  930. "Native App Support",
  931. NS_NATIVEAPPSUPPORT_CONTRACTID,
  932. nativeFactory);
  933. NS_ENSURE_SUCCESS(rv, rv);
  934. // Inform the chrome registry about OS accessibility
  935. nsCOMPtr<nsIToolkitChromeRegistry> cr (do_GetService(NS_CHROMEREGISTRY_CONTRACTID));
  936. if (cr)
  937. cr->CheckForOSAccessibility();
  938. nsCOMPtr<nsIWindowCreator> creator (do_GetService(NS_APPSTARTUP_CONTRACTID));
  939. if (!creator) return NS_ERROR_UNEXPECTED;
  940. nsCOMPtr<nsIWindowWatcher> wwatch
  941. (do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
  942. NS_ENSURE_SUCCESS(rv, rv);
  943. return wwatch->SetWindowCreator(creator);
  944. }
  945. /**
  946. * A helper class which calls NS_LogInit/NS_LogTerm in its scope.
  947. */
  948. class ScopedLogging
  949. {
  950. public:
  951. ScopedLogging() { NS_LogInit(); }
  952. ~ScopedLogging() { NS_LogTerm(); }
  953. };
  954. static void DumpArbitraryHelp()
  955. {
  956. nsresult rv;
  957. ScopedLogging log;
  958. {
  959. nsXREDirProvider dirProvider;
  960. dirProvider.Initialize(nsnull, gAppData->xreDirectory);
  961. ScopedXPCOMStartup xpcom;
  962. xpcom.Initialize();
  963. xpcom.DoAutoreg();
  964. nsCOMPtr<nsICommandLineRunner> cmdline
  965. (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
  966. if (!cmdline)
  967. return;
  968. nsCString text;
  969. rv = cmdline->GetHelpText(text);
  970. if (NS_SUCCEEDED(rv))
  971. printf("%s", text.get());
  972. }
  973. }
  974. // English text needs to go into a dtd file.
  975. // But when this is called we have no components etc. These strings must either be
  976. // here, or in a native resource file.
  977. static void
  978. DumpHelp()
  979. {
  980. printf("Usage: %s [ options ... ] [URL]\n"
  981. " where options include:\n\n", gArgv[0]);
  982. #ifdef MOZ_X11
  983. printf("X11 options\n"
  984. "\t--display=DISPLAY\t\tX display to use\n"
  985. "\t--sync\t\tMake X calls synchronous\n"
  986. "\t--no-xshm\t\tDon't use X shared memory extension\n"
  987. "\t--xim-preedit=STYLE\n"
  988. "\t--xim-status=STYLE\n");
  989. #endif
  990. #ifdef XP_UNIX
  991. printf("\t--g-fatal-warnings\t\tMake all warnings fatal\n"
  992. "\nMozilla options\n");
  993. #endif
  994. printf("\t-height <value>\t\tSet height of startup window to <value>.\n"
  995. "\t-h or -help\t\tPrint this message.\n"
  996. "\t-width <value>\t\tSet width of startup window to <value>.\n"
  997. "\t-v or -version\t\tPrint %s version.\n"
  998. "\t-P <profile>\t\tStart with <profile>.\n"
  999. "\t-ProfileManager\t\tStart with ProfileManager.\n"
  1000. "\t-no-remote\t\tOpen new instance, not a new window in running instance.\n"
  1001. "\t-UILocale <locale>\t\tStart with <locale> resources as UI Locale.\n"
  1002. "\t-safe-mode\t\tDisables extensions and themes for this session.\n", gAppData->name);
  1003. #if defined(XP_WIN) || defined(XP_OS2)
  1004. printf("\t-console\t\tStart %s with a debugging console.\n", gAppData->name);
  1005. #endif
  1006. // this works, but only after the components have registered. so if you drop in a new command line handler, -help
  1007. // won't not until the second run.
  1008. // out of the bug, because we ship a component.reg file, it works correctly.
  1009. DumpArbitraryHelp();
  1010. }
  1011. #ifdef DEBUG_warren
  1012. #ifdef XP_WIN
  1013. #define _CRTDBG_MAP_ALLOC
  1014. #include <crtdbg.h>
  1015. #endif
  1016. #endif
  1017. #if defined(FREEBSD)
  1018. // pick up fpsetmask prototype.
  1019. #include <ieeefp.h>
  1020. #endif
  1021. static inline void
  1022. DumpVersion()
  1023. {
  1024. printf("%s %s %s",
  1025. gAppData->vendor ? gAppData->vendor : "", gAppData->name, gAppData->version);
  1026. if (gAppData->copyright)
  1027. printf(", %s", gAppData->copyright);
  1028. printf("\n");
  1029. }
  1030. #ifdef MOZ_ENABLE_XREMOTE
  1031. // use int here instead of a PR type since it will be returned
  1032. // from main - just to keep types consistent
  1033. static int
  1034. HandleRemoteArgument(const char* remote, const char* aDesktopStartupID)
  1035. {
  1036. nsresult rv;
  1037. ArgResult ar;
  1038. const char *profile = 0;
  1039. nsCAutoString program(gAppData->name);
  1040. ToLowerCase(program);
  1041. const char *username = getenv("LOGNAME");
  1042. ar = CheckArg("p", PR_FALSE, &profile);
  1043. if (ar == ARG_BAD) {
  1044. PR_fprintf(PR_STDERR, "Error: argument -p requires a profile name\n");
  1045. return 1;
  1046. }
  1047. const char *temp = nsnull;
  1048. ar = CheckArg("a", PR_FALSE, &temp);
  1049. if (ar == ARG_BAD) {
  1050. PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
  1051. return 1;
  1052. } else if (ar == ARG_FOUND) {
  1053. program.Assign(temp);
  1054. }
  1055. ar = CheckArg("u", PR_FALSE, &username);
  1056. if (ar == ARG_BAD) {
  1057. PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
  1058. return 1;
  1059. }
  1060. XRemoteClient client;
  1061. rv = client.Init();
  1062. if (NS_FAILED(rv)) {
  1063. PR_fprintf(PR_STDERR, "Error: Failed to connect to X server.\n");
  1064. return 1;
  1065. }
  1066. nsXPIDLCString response;
  1067. PRBool success = PR_FALSE;
  1068. rv = client.SendCommand(program.get(), username, profile, remote,
  1069. aDesktopStartupID, getter_Copies(response), &success);
  1070. // did the command fail?
  1071. if (NS_FAILED(rv)) {
  1072. PR_fprintf(PR_STDERR, "Error: Failed to send command: %s\n",
  1073. response ? response.get() : "No response included");
  1074. return 1;
  1075. }
  1076. if (!success) {
  1077. PR_fprintf(PR_STDERR, "Error: No running window found\n");
  1078. return 2;
  1079. }
  1080. return 0;
  1081. }
  1082. static RemoteResult
  1083. RemoteCommandLine(const char* aDesktopStartupID)
  1084. {
  1085. nsresult rv;
  1086. ArgResult ar;
  1087. nsCAutoString program(gAppData->name);
  1088. ToLowerCase(program);
  1089. const char *username = getenv("LOGNAME");
  1090. const char *temp = nsnull;
  1091. ar = CheckArg("a", PR_TRUE, &temp);
  1092. if (ar == ARG_BAD) {
  1093. PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
  1094. return REMOTE_ARG_BAD;
  1095. } else if (ar == ARG_FOUND) {
  1096. program.Assign(temp);
  1097. }
  1098. ar = CheckArg("u", PR_TRUE, &username);
  1099. if (ar == ARG_BAD) {
  1100. PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
  1101. return REMOTE_ARG_BAD;
  1102. }
  1103. XRemoteClient client;
  1104. rv = client.Init();
  1105. if (NS_FAILED(rv))
  1106. return REMOTE_NOT_FOUND;
  1107. nsXPIDLCString response;
  1108. PRBool success = PR_FALSE;
  1109. rv = client.SendCommandLine(program.get(), username, nsnull,
  1110. gArgc, gArgv, aDesktopStartupID,
  1111. getter_Copies(response), &success);
  1112. // did the command fail?
  1113. if (NS_FAILED(rv) || !success)
  1114. return REMOTE_NOT_FOUND;
  1115. return REMOTE_FOUND;
  1116. }
  1117. #endif // MOZ_ENABLE_XREMOTE
  1118. #ifdef XP_MACOSX
  1119. static char const *gBinaryPath;
  1120. #endif
  1121. nsresult
  1122. XRE_GetBinaryPath(const char* argv0, nsILocalFile* *aResult)
  1123. {
  1124. nsresult rv;
  1125. nsCOMPtr<nsILocalFile> lf;
  1126. // We need to use platform-specific hackery to find the
  1127. // path of this executable. This is copied, with some modifications, from
  1128. // nsGREDirServiceProvider.cpp
  1129. #ifdef XP_WIN
  1130. PRUnichar exePath[MAXPATHLEN];
  1131. if (!::GetModuleFileNameW(0, exePath, MAXPATHLEN))
  1132. return NS_ERROR_FAILURE;
  1133. rv = NS_NewLocalFile(nsDependentString(exePath), PR_TRUE,
  1134. getter_AddRefs(lf));
  1135. if (NS_FAILED(rv))
  1136. return rv;
  1137. #elif defined(XP_MACOSX)
  1138. if (gBinaryPath)
  1139. return NS_NewNativeLocalFile(nsDependentCString(gBinaryPath), PR_FALSE,
  1140. aResult);
  1141. NS_NewNativeLocalFile(EmptyCString(), PR_TRUE, getter_AddRefs(lf));
  1142. nsCOMPtr<nsILocalFileMac> lfm (do_QueryInterface(lf));
  1143. if (!lfm)
  1144. return NS_ERROR_FAILURE;
  1145. // Works even if we're not bundled.
  1146. CFBundleRef appBundle = CFBundleGetMainBundle();
  1147. if (!appBundle)
  1148. return NS_ERROR_FAILURE;
  1149. CFURLRef bundleURL = CFBundleCopyExecutableURL(appBundle);
  1150. if (!bundleURL)
  1151. return NS_ERROR_FAILURE;
  1152. FSRef fileRef;
  1153. if (!CFURLGetFSRef(bundleURL, &fileRef)) {
  1154. CFRelease(bundleURL);
  1155. return NS_ERROR_FAILURE;
  1156. }
  1157. rv = lfm->InitWithFSRef(&fileRef);
  1158. CFRelease(bundleURL);
  1159. if (NS_FAILED(rv))
  1160. return rv;
  1161. #elif defined(XP_UNIX)
  1162. struct stat fileStat;
  1163. char exePath[MAXPATHLEN];
  1164. char tmpPath[MAXPATHLEN];
  1165. rv = NS_ERROR_FAILURE;
  1166. // on unix, there is no official way to get the path of the current binary.
  1167. // instead of using the MOZILLA_FIVE_HOME hack, which doesn't scale to
  1168. // multiple applications, we will try a series of techniques:
  1169. //
  1170. // 1) look for /proc/<pid>/exe which is a symlink to the executable on newer
  1171. // Linux kernels
  1172. // 2) use realpath() on argv[0], which works unless we're loaded from the
  1173. // PATH
  1174. // 3) manually walk through the PATH and look for ourself
  1175. // 4) give up
  1176. // #ifdef __linux__
  1177. #if 0
  1178. int r = readlink("/proc/self/exe", exePath, MAXPATHLEN);
  1179. // apparently, /proc/self/exe can sometimes return weird data... check it
  1180. if (r > 0 && r < MAXPATHLEN && stat(exePath, &fileStat) == 0) {
  1181. rv = NS_OK;
  1182. }
  1183. #endif
  1184. if (NS_FAILED(rv) &&
  1185. realpath(argv0, exePath) && stat(exePath, &fileStat) == 0) {
  1186. rv = NS_OK;
  1187. }
  1188. if (NS_FAILED(rv)) {
  1189. const char *path = getenv("PATH");
  1190. if (!path)
  1191. return NS_ERROR_FAILURE;
  1192. char *pathdup = strdup(path);
  1193. if (!pathdup)
  1194. return NS_ERROR_OUT_OF_MEMORY;
  1195. PRBool found = PR_FALSE;
  1196. char *newStr = pathdup;
  1197. char *token;
  1198. while ( (token = nsCRT::strtok(newStr, ":", &newStr)) ) {
  1199. sprintf(tmpPath, "%s/%s", token, argv0);
  1200. if (realpath(tmpPath, exePath) && stat(exePath, &fileStat) == 0) {
  1201. found = PR_TRUE;
  1202. break;
  1203. }
  1204. }
  1205. free(pathdup);
  1206. if (!found)
  1207. return NS_ERROR_FAILURE;
  1208. }
  1209. rv = NS_NewNativeLocalFile(nsDependentCString(exePath), PR_TRUE,
  1210. getter_AddRefs(lf));
  1211. if (NS_FAILED(rv))
  1212. return rv;
  1213. #elif defined(XP_OS2)
  1214. PPIB ppib;
  1215. PTIB ptib;
  1216. char exePath[MAXPATHLEN];
  1217. DosGetInfoBlocks( &ptib, &ppib);
  1218. DosQueryModuleName( ppib->pib_hmte, MAXPATHLEN, exePath);
  1219. rv = NS_NewNativeLocalFile(nsDependentCString(exePath), PR_TRUE,
  1220. getter_AddRefs(lf));
  1221. if (NS_FAILED(rv))
  1222. return rv;
  1223. #elif defined(XP_BEOS)
  1224. int32 cookie = 0;
  1225. image_info info;
  1226. if(get_next_image_info(0, &cookie, &info) != B_OK)
  1227. return NS_ERROR_FAILURE;
  1228. rv = NS_NewNativeLocalFile(nsDependentCString(info.name), PR_TRUE,
  1229. getter_AddRefs(lf));
  1230. if (NS_FAILED(rv))
  1231. return rv;
  1232. #else
  1233. #error Oops, you need platform-specific code here
  1234. #endif
  1235. NS_ADDREF(*aResult = lf);
  1236. return NS_OK;
  1237. }
  1238. #define NS_ERROR_LAUNCHED_CHILD_PROCESS NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_PROFILE, 200)
  1239. #ifdef XP_WIN
  1240. #include "nsWindowsRestart.cpp"
  1241. #endif
  1242. #if defined(XP_OS2) && (__GNUC__ == 3 && __GNUC_MINOR__ == 3) // broken OS/2 GCC
  1243. // Copy the environment maintained by the C library into an ASCIIZ array
  1244. // that can be used to pass it on to the OS/2 Dos* APIs (which otherwise
  1245. // don't know anything about the stuff set by PR_SetEnv() or setenv()).
  1246. char *createEnv()
  1247. {
  1248. // just allocate the maximum amount (24 kB = 0x60000 bytes), to be able to
  1249. // copy the existing environment
  1250. char *env = (char *)calloc(0x6000, sizeof(char));
  1251. if (!env) {
  1252. return NULL;
  1253. }
  1254. // walk along the environ string array of the C library and copy
  1255. // everything (that fits) into the output environment array, leaving
  1256. // null bytes between the entries
  1257. char *penv = env; // movable pointer to result environment ASCIIZ array
  1258. int i = 0, space = 0x6000;
  1259. while (environ[i] && environ[i][0]) {
  1260. int len = strlen(environ[i]);
  1261. if (space - len <= 0) {
  1262. break;
  1263. }
  1264. strcpy(penv, environ[i]);
  1265. i++; // next environment variable
  1266. penv += len + 1; // jump to after next null byte
  1267. space -= len - 1; // subtract consumed length from usable space
  1268. }
  1269. return env;
  1270. }
  1271. // OS2LaunchChild() is there to replace _execv() which is broken in the C
  1272. // runtime library that comes with GCC 3.3.5 on OS/2. It uses createEnv()
  1273. // to copy the process environment and add necessary variables
  1274. //
  1275. // returns -1 on failure and 0 on success
  1276. int OS2LaunchChild(const char *aExePath, int aArgc, char **aArgv)
  1277. {
  1278. // find total length of aArgv
  1279. int len = 0;
  1280. for (int i = 0; i < aArgc; i++) {
  1281. len += strlen(aArgv[i]) + 1; // plus space in between
  1282. }
  1283. len++; // leave space for null byte at end
  1284. // allocate enough space for all strings and nulls,
  1285. // calloc helpfully initializes to null
  1286. char *args = (char *)calloc(len, sizeof(char));
  1287. if (!args) {
  1288. return -1;
  1289. }
  1290. char *pargs = args; // extra pointer to after the last argument
  1291. // build argument list in the format the DosStartSession() wants,
  1292. // adding spaces between the arguments
  1293. for (int i = 0; i < aArgc; i++, *pargs++ = ' ') {
  1294. strcpy(pargs, aArgv[i]);
  1295. pargs += strlen(aArgv[i]);
  1296. }
  1297. if (aArgc > 1) {
  1298. *(pargs-1) = '\0'; // replace last space
  1299. }
  1300. *pargs = '\0';
  1301. // make sure that the program is separated by null byte
  1302. pargs = strchr(args, ' ');
  1303. if (pargs) {
  1304. *pargs = '\0';
  1305. }
  1306. char *env = createEnv();
  1307. char error[CCHMAXPATH] = { 0 };
  1308. RESULTCODES crc = { 0 };
  1309. ULONG rc = DosExecPgm(error, sizeof(error), EXEC_ASYNC, args, env,
  1310. &crc, (PSZ)aExePath);
  1311. free(args); // done with the arguments
  1312. if (env) {
  1313. free(env);
  1314. }
  1315. if (rc != NO_ERROR) {
  1316. return -1;
  1317. }
  1318. return 0;
  1319. }
  1320. #endif
  1321. // If aBlankCommandLine is true, then the application will be launched with a
  1322. // blank command line instead of being launched with the same command line that
  1323. // it was initially started with.
  1324. static nsresult LaunchChild(nsINativeAppSupport* aNative,
  1325. PRBool aBlankCommandLine = PR_FALSE)
  1326. {
  1327. aNative->Quit(); // release DDE mutex, if we're holding it
  1328. // Restart this process by exec'ing it into the current process
  1329. // if supported by the platform. Otherwise, use NSPR.
  1330. if (aBlankCommandLine) {
  1331. gRestartArgc = 1;
  1332. gRestartArgv[gRestartArgc] = nsnull;
  1333. }
  1334. PR_SetEnv("MOZ_LAUNCHED_CHILD=1");
  1335. #if defined(XP_MACOSX)
  1336. LaunchChildMac(gRestartArgc, gRestartArgv);
  1337. #else
  1338. nsCOMPtr<nsILocalFile> lf;
  1339. nsresult rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
  1340. if (NS_FAILED(rv))
  1341. return rv;
  1342. #if defined(XP_WIN)
  1343. nsAutoString exePath;
  1344. rv = lf->GetPath(exePath);
  1345. if (NS_FAILED(rv))
  1346. return rv;
  1347. if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv, 0))
  1348. return NS_ERROR_FAILURE;
  1349. #else
  1350. nsCAutoString exePath;
  1351. rv = lf->GetNativePath(exePath);
  1352. if (NS_FAILED(rv))
  1353. return rv;
  1354. #if defined(XP_OS2) && (__GNUC__ == 3 && __GNUC_MINOR__ == 3)
  1355. // implementation of _execv() is broken with GCC 3.3.x on OS/2
  1356. if (OS2LaunchChild(exePath.get(), gRestartArgc, gRestartArgv) == -1)
  1357. return NS_ERROR_FAILURE;
  1358. #elif defined(XP_OS2)
  1359. if (_execv(exePath.get(), gRestartArgv) == -1)
  1360. return NS_ERROR_FAILURE;
  1361. #elif defined(XP_UNIX)
  1362. if (execv(exePath.get(), gRestartArgv) == -1)
  1363. return NS_ERROR_FAILURE;
  1364. #elif defined(XP_BEOS)
  1365. extern char **environ;
  1366. status_t res;
  1367. res = resume_thread(load_image(gRestartArgc,(const char **)gRestartArgv,(const char **)environ));
  1368. if (res != B_OK)
  1369. return NS_ERROR_FAILURE;
  1370. #else
  1371. PRProcess* process = PR_CreateProcess(exePath.get(), gRestartArgv,
  1372. nsnull, nsnull);
  1373. if (!process) return NS_ERROR_FAILURE;
  1374. PRInt32 exitCode;
  1375. PRStatus failed = PR_WaitProcess(process, &exitCode);
  1376. if (failed || exitCode)
  1377. return NS_ERROR_FAILURE;
  1378. #endif // XP_OS2 series
  1379. #endif // WP_WIN
  1380. #endif // WP_MACOSX
  1381. return NS_ERROR_LAUNCHED_CHILD_PROCESS;
  1382. }
  1383. static const char kProfileProperties[] =
  1384. "chrome://mozapps/locale/profile/profileSelection.properties";
  1385. static nsresult
  1386. ProfileLockedDialog(nsILocalFile* aProfileDir, nsILocalFile* aProfileLocalDir,
  1387. nsIProfileUnlocker* aUnlocker,
  1388. nsINativeAppSupport* aNative, nsIProfileLock* *aResult)
  1389. {
  1390. nsresult rv;
  1391. ScopedXPCOMStartup xpcom;
  1392. rv = xpcom.Initialize();
  1393. NS_ENSURE_SUCCESS(rv, rv);
  1394. rv = xpcom.DoAutoreg();
  1395. rv |= xpcom.SetWindowCreator(aNative);
  1396. NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  1397. { //extra scoping is needed so we release these components before xpcom shutdown
  1398. nsCOMPtr<nsIStringBundleService> sbs
  1399. (do_GetService(NS_STRINGBUNDLE_CONTRACTID));
  1400. NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE);
  1401. nsCOMPtr<nsIStringBundle> sb;
  1402. sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
  1403. NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE);
  1404. NS_ConvertUTF8toUTF16 appName(gAppData->name);
  1405. const PRUnichar* params[] = {appName.get(), appName.get()};
  1406. nsXPIDLString killMessage;
  1407. #ifndef XP_MACOSX
  1408. 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"
  1409. 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"
  1410. #else
  1411. 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"
  1412. 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"
  1413. #endif
  1414. sb->FormatStringFromName(aUnlocker ? kRestartUnlocker : kRestartNoUnlocker,
  1415. params, 2, getter_Copies(killMessage));
  1416. nsXPIDLString killTitle;
  1417. sb->FormatStringFromName(NS_LITERAL_STRING("restartTitle").get(),
  1418. params, 1, getter_Copies(killTitle));
  1419. if (!killMessage || !killTitle)
  1420. return NS_ERROR_FAILURE;
  1421. nsCOMPtr<nsIPromptService> ps
  1422. (do_GetService(NS_PROMPTSERVICE_CONTRACTID));
  1423. NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE);
  1424. PRUint32 flags = nsIPromptService::BUTTON_TITLE_OK * nsIPromptService::BUTTON_POS_0;
  1425. if (aUnlocker) {
  1426. flags =
  1427. nsIPromptService::BUTTON_TITLE_CANCEL * nsIPromptService::BUTTON_POS_0 +
  1428. nsIPromptService::BUTTON_TITLE_IS_STRING * nsIPromptService::BUTTON_POS_1 +
  1429. nsIPromptService::BUTTON_POS_1_DEFAULT;
  1430. }
  1431. PRInt32 button;
  1432. rv = ps->ConfirmEx(nsnull, killTitle, killMessage, flags,
  1433. killTitle, nsnull, nsnull, nsnull, nsnull, &button);
  1434. NS_ENSURE_SUCCESS_LOG(rv, rv);
  1435. if (button == 1 && aUnlocker) {
  1436. rv = aUnlocker->Unlock(nsIProfileUnlocker::FORCE_QUIT);
  1437. if (NS_FAILED(rv)) return rv;
  1438. return NS_LockProfilePath(aProfileDir, aProfileLocalDir, nsnull, aResult);
  1439. }
  1440. return NS_ERROR_ABORT;
  1441. }
  1442. }
  1443. static const char kProfileManagerURL[] =
  1444. "chrome://mozapps/content/profile/profileSelection.xul";
  1445. static nsresult
  1446. ShowProfileManager(nsIToolkitProfileService* aProfileSvc,
  1447. nsINativeAppSupport* aNative)
  1448. {
  1449. nsresult rv;
  1450. nsCOMPtr<nsILocalFile> profD, profLD;
  1451. PRUnichar* profileNamePtr;
  1452. nsCAutoString profileName;
  1453. {
  1454. ScopedXPCOMStartup xpcom;
  1455. rv = xpcom.Initialize();
  1456. NS_ENSURE_SUCCESS(rv, rv);
  1457. rv = xpcom.DoAutoreg();
  1458. rv |= xpcom.RegisterProfileService();
  1459. rv |= xpcom.SetWindowCreator(aNative);
  1460. NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  1461. #ifdef XP_MACOSX
  1462. SetupMacCommandLine(gRestartArgc, gRestartArgv);
  1463. #endif
  1464. #ifdef XP_WIN
  1465. // we don't have to wait here because profile manager window will pump
  1466. // and DDE message will be handled
  1467. ProcessDDE(aNative, PR_FALSE);
  1468. #endif
  1469. { //extra scoping is needed so we release these components before xpcom shutdown
  1470. nsCOMPtr<nsIWindowWatcher> windowWatcher
  1471. (do_GetService(NS_WINDOWWATCHER_CONTRACTID));
  1472. nsCOMPtr<nsIDialogParamBlock> ioParamBlock
  1473. (do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID));
  1474. nsCOMPtr<nsIMutableArray> dlgArray (do_CreateInstance(NS_ARRAY_CONTRACTID));
  1475. NS_ENSURE_TRUE(windowWatcher && ioParamBlock && dlgArray, NS_ERROR_FAILURE);
  1476. ioParamBlock->SetObjects(dlgArray);
  1477. nsCOMPtr<nsIAppStartup> appStartup
  1478. (do_GetService(NS_APPSTARTUP_CONTRACTID));
  1479. NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE);
  1480. nsCOMPtr<nsIDOMWindow> newWindow;
  1481. rv = windowWatcher->OpenWindow(nsnull,
  1482. kProfileManagerURL,
  1483. "_blank",
  1484. "centerscreen,chrome,modal,titlebar",
  1485. ioParamBlock,
  1486. getter_AddRefs(newWindow));
  1487. NS_ENSURE_SUCCESS_LOG(rv, rv);
  1488. aProfileSvc->Flush();
  1489. PRInt32 dialogConfirmed;
  1490. rv = ioParamBlock->GetInt(0, &dialogConfirmed);
  1491. if (NS_FAILED(rv) || dialogConfirmed == 0) return NS_ERROR_ABORT;
  1492. nsCOMPtr<nsIProfileLock> lock;
  1493. rv = dlgArray->QueryElementAt(0, NS_GET_IID(nsIProfileLock),
  1494. getter_AddRefs(lock));
  1495. NS_ENSURE_SUCCESS_LOG(rv, rv);
  1496. rv = lock->GetDirectory(getter_AddRefs(profD));
  1497. NS_ENSURE_SUCCESS(rv, rv);
  1498. rv = lock->GetLocalDirectory(getter_AddRefs(profLD));
  1499. NS_ENSURE_SUCCESS(rv, rv);
  1500. rv = ioParamBlock->GetString(0, &profileNamePtr);
  1501. NS_ENSURE_SUCCESS(rv, rv);
  1502. CopyUTF16toUTF8(profileNamePtr, profileName);
  1503. NS_Free(profileNamePtr);
  1504. lock->Unlock();
  1505. }
  1506. }
  1507. SaveFileToEnv("XRE_PROFILE_PATH", profD);
  1508. SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", profLD);
  1509. SaveWordToEnv("XRE_PROFILE_NAME", profileName);
  1510. PRBool offline = PR_FALSE;
  1511. aProfileSvc->GetStartOffline(&offline);
  1512. if (offline) {
  1513. PR_SetEnv("XRE_START_OFFLINE=1");
  1514. }
  1515. return LaunchChild(aNative);
  1516. }
  1517. static nsresult
  1518. ImportProfiles(nsIToolkitProfileService* aPService,
  1519. nsINativeAppSupport* aNative)
  1520. {
  1521. nsresult rv;
  1522. PR_SetEnv("XRE_IMPORT_PROFILES=1");
  1523. // try to import old-style profiles
  1524. { // scope XPCOM
  1525. ScopedXPCOMStartup xpcom;
  1526. rv = xpcom.Initialize();
  1527. if (NS_SUCCEEDED(rv)) {
  1528. xpcom.DoAutoreg();
  1529. xpcom.RegisterProfileService();
  1530. #ifdef XP_MACOSX
  1531. SetupMacCommandLine(gRestartArgc, gRestartArgv);
  1532. #endif
  1533. nsCOMPtr<nsIProfileMigrator> migrator
  1534. (do_GetService(NS_PROFILEMIGRATOR_CONTRACTID));
  1535. if (migrator) {
  1536. migrator->Import();
  1537. }
  1538. }
  1539. }
  1540. aPService->Flush();
  1541. return LaunchChild(aNative);
  1542. }
  1543. // Pick a profile. We need to end up with a profile lock.
  1544. //
  1545. // 1) check for -profile <path>
  1546. // 2) check for -P <name>
  1547. // 3) check for -ProfileManager
  1548. // 4) use the default profile, if there is one
  1549. // 5) if there are *no* profiles, set up profile-migration
  1550. // 6) display the profile-manager UI
  1551. static PRBool gDoMigration = PR_FALSE;
  1552. static nsresult
  1553. SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
  1554. PRBool* aStartOffline, nsACString* aProfileName)
  1555. {
  1556. nsresult rv;
  1557. ArgResult ar;
  1558. const char* arg;
  1559. *aResult = nsnull;
  1560. *aStartOffline = PR_FALSE;
  1561. ar = CheckArg("offline", PR_TRUE);
  1562. if (ar == ARG_BAD) {
  1563. PR_fprintf(PR_STDERR, "Error: argument -offline is invalid when argument -osint is specified\n");
  1564. return NS_ERROR_FAILURE;
  1565. }
  1566. arg = PR_GetEnv("XRE_START_OFFLINE");
  1567. if ((arg && *arg) || ar)
  1568. *aStartOffline = PR_TRUE;
  1569. nsCOMPtr<nsILocalFile> lf = GetFileFromEnv("XRE_PROFILE_PATH");
  1570. if (lf) {
  1571. nsCOMPtr<nsILocalFile> localDir =
  1572. GetFileFromEnv("XRE_PROFILE_LOCAL_PATH");
  1573. if (!localDir) {
  1574. localDir = lf;
  1575. }
  1576. arg = PR_GetEnv("XRE_PROFILE_NAME");
  1577. if (arg && *arg && aProfileName)
  1578. aProfileName->Assign(nsDependentCString(arg));
  1579. // Clear out flags that we handled (or should have handled!) last startup.
  1580. const char *dummy;
  1581. CheckArg("p", PR_FALSE, &dummy);
  1582. CheckArg("profile", PR_FALSE, &dummy);
  1583. CheckArg("profilemanager");
  1584. return NS_LockProfilePath(lf, localDir, nsnull, aResult);
  1585. }
  1586. ar = CheckArg("migration", PR_TRUE);
  1587. if (ar == ARG_BAD) {
  1588. PR_fprintf(PR_STDERR, "Error: argument -migration is invalid when argument -osint is specified\n");
  1589. return NS_ERROR_FAILURE;
  1590. } else if (ar == ARG_FOUND) {
  1591. gDoMigration = PR_TRUE;
  1592. }
  1593. ar = CheckArg("profile", PR_TRUE, &arg);
  1594. if (ar == ARG_BAD) {
  1595. PR_fprintf(PR_STDERR, "Error: argument -profile requires a path\n");
  1596. return NS_ERROR_FAILURE;
  1597. }
  1598. if (ar) {
  1599. nsCOMPtr<nsILocalFile> lf;
  1600. rv = XRE_GetFileFromPath(arg, getter_AddRefs(lf));
  1601. NS_ENSURE_SUCCESS(rv, rv);
  1602. nsCOMPtr<nsIProfileUnlocker> unlocker;
  1603. // If a profile path is specified directory on the command line, then
  1604. // assume that the temp directory is the same as the given directory.
  1605. rv = NS_LockProfilePath(lf, lf, getter_AddRefs(unlocker), aResult);
  1606. if (NS_SUCCEEDED(rv))
  1607. return rv;
  1608. return ProfileLockedDialog(lf, lf, unlocker, aNative, aResult);
  1609. }
  1610. nsCOMPtr<nsIToolkitProfileService> profileSvc;
  1611. rv = NS_NewToolkitProfileService(getter_AddRefs(profileSvc));
  1612. NS_ENSURE_SUCCESS(rv, rv);
  1613. ar = CheckArg("createprofile", PR_TRUE, &arg);
  1614. if (ar == ARG_BAD) {
  1615. PR_fprintf(PR_STDERR, "Error: argument -createprofile requires a profile name\n");
  1616. return NS_ERROR_FAILURE;
  1617. }
  1618. if (ar) {
  1619. nsCOMPtr<nsIToolkitProfile> profile;
  1620. const char* delim = strchr(arg, ' ');
  1621. if (delim) {
  1622. nsCOMPtr<nsILocalFile> lf;
  1623. rv = NS_NewNativeLocalFile(nsDependentCString(delim + 1),
  1624. PR_TRUE, getter_AddRefs(lf));
  1625. if (NS_FAILED(rv)) {
  1626. PR_fprintf(PR_STDERR, "Error: profile path not valid.\n");
  1627. return rv;
  1628. }
  1629. // As with -profile, assume that the given path will be used for both the
  1630. // main profile directory and the temp profile directory.
  1631. rv = profileSvc->CreateProfile(lf, lf, nsDependentCSubstring(arg, delim),
  1632. getter_AddRefs(profile));
  1633. } else {
  1634. rv = profileSvc->CreateProfile(nsnull, nsnull, nsDependentCString(arg),
  1635. getter_AddRefs(profile));
  1636. }
  1637. // Some pathological arguments can make it this far
  1638. if (NS_FAILED(rv)) {
  1639. PR_fprintf(PR_STDERR, "Error creating profile.\n");
  1640. return rv;
  1641. }
  1642. rv = NS_ERROR_ABORT;
  1643. profileSvc->Flush();
  1644. // XXXben need to ensure prefs.js exists here so the tinderboxes will
  1645. // not go orange.
  1646. nsCOMPtr<nsILocalFile> prefsJSFile;
  1647. profile->GetRootDir(getter_AddRefs(prefsJSFile));
  1648. prefsJSFile->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
  1649. nsCAutoString pathStr;
  1650. prefsJSFile->GetNativePath(pathStr);
  1651. PR_fprintf(PR_STDERR, "Success: created profile '%s' at '%s'\n", arg, pathStr.get());
  1652. PRBool exists;
  1653. prefsJSFile->Exists(&exists);
  1654. if (!exists)
  1655. prefsJSFile->Create(nsIFile::NORMAL_FILE_TYPE, 0644);
  1656. // XXXdarin perhaps 0600 would be better?
  1657. return rv;
  1658. }
  1659. PRUint32 count;
  1660. rv = profileSvc->GetProfileCount(&count);
  1661. NS_ENSURE_SUCCESS(rv, rv);
  1662. if (gAppData->flags & NS_XRE_ENABLE_PROFILE_MIGRATOR) {
  1663. arg = PR_GetEnv("XRE_IMPORT_PROFILES");
  1664. if (!count && (!arg || !*arg)) {
  1665. return ImportProfiles(profileSvc, aNative);
  1666. }
  1667. }
  1668. ar = CheckArg("p", PR_FALSE, &arg);
  1669. if (ar == ARG_BAD) {
  1670. ar = CheckArg("osint");
  1671. if (ar == ARG_FOUND) {
  1672. PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument -osint is specified\n");
  1673. return NS_ERROR_FAILURE;
  1674. }
  1675. return ShowProfileManager(profileSvc, aNative);
  1676. }
  1677. if (ar) {
  1678. ar = CheckArg("osint");
  1679. if (ar == ARG_FOUND) {
  1680. PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument -osint is specified\n");
  1681. return NS_ERROR_FAILURE;
  1682. }
  1683. nsCOMPtr<nsIToolkitProfile> profile;
  1684. rv = profileSvc->GetProfileByName(nsDependentCString(arg),
  1685. getter_AddRefs(profile));
  1686. if (NS_SUCCEEDED(rv)) {
  1687. nsCOMPtr<nsIProfileUnlocker> unlocker;
  1688. rv = profile->Lock(nsnull, aResult);
  1689. if (NS_SUCCEEDED(rv)) {
  1690. if (aProfileName)
  1691. aProfileName->Assign(nsDependentCString(arg));
  1692. return NS_OK;
  1693. }
  1694. nsCOMPtr<nsILocalFile> profileDir;
  1695. rv = profile->GetRootDir(getter_AddRefs(profileDir));
  1696. NS_ENSURE_SUCCESS(rv, rv);
  1697. nsCOMPtr<nsILocalFile> profileLocalDir;
  1698. rv = profile->GetLocalDir(getter_AddRefs(profileLocalDir));
  1699. NS_ENSURE_SUCCESS(rv, rv);
  1700. return ProfileLockedDialog(profileDir, profileLocalDir, unlocker,
  1701. aNative, aResult);
  1702. }
  1703. return ShowProfileManager(profileSvc, aNative);
  1704. }
  1705. ar = CheckArg("profilemanager", PR_TRUE);
  1706. if (ar == ARG_BAD) {
  1707. PR_fprintf(PR_STDERR, "Error: argument -profilemanager is invalid when argument -osint is specified\n");
  1708. return NS_ERROR_FAILURE;
  1709. } else if (ar == ARG_FOUND) {
  1710. return ShowProfileManager(profileSvc, aNative);
  1711. }
  1712. if (!count) {
  1713. gDoMigration = PR_TRUE;
  1714. // create a default profile
  1715. nsCOMPtr<nsIToolkitProfile> profile;
  1716. nsresult rv = profileSvc->CreateProfile(nsnull, // choose a default dir for us
  1717. nsnull, // choose a default dir for us
  1718. NS_LITERAL_CSTRING("default"),
  1719. getter_AddRefs(profile));
  1720. if (NS_SUCCEEDED(rv)) {
  1721. profileSvc->Flush();
  1722. rv = profile->Lock(nsnull, aResult);
  1723. if (NS_SUCCEEDED(rv)) {
  1724. if (aProfileName)
  1725. aProfileName->Assign(NS_LITERAL_CSTRING("default"));
  1726. return NS_OK;
  1727. }
  1728. }
  1729. }
  1730. PRBool useDefault = PR_TRUE;
  1731. if (count > 1)
  1732. profileSvc->GetStartWithLastProfile(&useDefault);
  1733. if (useDefault) {
  1734. nsCOMPtr<nsIToolkitProfile> profile;
  1735. // GetSelectedProfile will auto-select the only profile if there's just one
  1736. profileSvc->GetSelectedProfile(getter_AddRefs(profile));
  1737. if (profile) {
  1738. nsCOMPtr<nsIProfileUnlocker> unlocker;
  1739. rv = profile->Lock(getter_AddRefs(unlocker), aResult);
  1740. if (NS_SUCCEEDED(rv)) {
  1741. // Try to grab the profile name.
  1742. if (aProfileName) {
  1743. rv = profile->GetName(*aProfileName);
  1744. if (NS_FAILED(rv))
  1745. aProfileName->Truncate(0);
  1746. }
  1747. return NS_OK;
  1748. }
  1749. nsCOMPtr<nsILocalFile> profileDir;
  1750. rv = profile->GetRootDir(getter_AddRefs(profileDir));
  1751. NS_ENSURE_SUCCESS(rv, rv);
  1752. nsCOMPtr<nsILocalFile> profileLocalDir;
  1753. rv = profile->GetRootDir(getter_AddRefs(profileLocalDir));
  1754. NS_ENSURE_SUCCESS(rv, rv);
  1755. return ProfileLockedDialog(profileDir, profileLocalDir, unlocker,
  1756. aNative, aResult);
  1757. }
  1758. }
  1759. return ShowProfileManager(profileSvc, aNative);
  1760. }
  1761. #define FILE_COMPATIBILITY_INFO NS_LITERAL_CSTRING("compatibility.ini")
  1762. static PRBool
  1763. CheckCompatibility(nsIFile* aProfileDir, const nsCString& aVersion,
  1764. const nsCString& aOSABI, nsIFile* aXULRunnerDir,
  1765. nsIFile* aAppDir)
  1766. {
  1767. nsCOMPtr<nsIFile> file;
  1768. aProfileDir->Clone(getter_AddRefs(file));
  1769. if (!file)
  1770. return PR_FALSE;
  1771. file->AppendNative(FILE_COMPATIBILITY_INFO);
  1772. nsINIParser parser;
  1773. nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
  1774. nsresult rv = parser.Init(localFile);
  1775. if (NS_FAILED(rv))
  1776. return PR_FALSE;
  1777. nsCAutoString buf;
  1778. rv = parser.GetString("Compatibility", "LastVersion", buf);
  1779. if (NS_FAILED(rv) || !aVersion.Equals(buf))
  1780. return PR_FALSE;
  1781. rv = parser.GetString("Compatibility", "LastOSABI", buf);
  1782. if (NS_FAILED(rv) || !aOSABI.Equals(buf))
  1783. return PR_FALSE;
  1784. rv = parser.GetString("Compatibility", "LastPlatformDir", buf);
  1785. if (NS_FAILED(rv))
  1786. return PR_FALSE;
  1787. nsCOMPtr<nsILocalFile> lf;
  1788. rv = NS_NewNativeLocalFile(buf, PR_FALSE,
  1789. getter_AddRefs(lf));
  1790. if (NS_FAILED(rv))
  1791. return PR_FALSE;
  1792. PRBool eq;
  1793. rv = lf->Equals(aXULRunnerDir, &eq);
  1794. if (NS_FAILED(rv) || !eq)
  1795. return PR_FALSE;
  1796. if (aAppDir) {
  1797. rv = parser.GetString("Compatibility", "LastAppDir", buf);
  1798. if (NS_FAILED(rv))
  1799. return PR_FALSE;
  1800. rv = NS_NewNativeLocalFile(buf, PR_FALSE,
  1801. getter_AddRefs(lf));
  1802. if (NS_FAILED(rv))
  1803. return PR_FALSE;
  1804. rv = lf->Equals(aAppDir, &eq);
  1805. if (NS_FAILED(rv) || !eq)
  1806. return PR_FALSE;
  1807. }
  1808. return PR_TRUE;
  1809. }
  1810. static void BuildVersion(nsCString &aBuf)
  1811. {
  1812. aBuf.Assign(gAppData->version);
  1813. aBuf.Append('_');
  1814. aBuf.Append(gAppData->buildID);
  1815. aBuf.Append('/');
  1816. aBuf.Append(gToolkitBuildID);
  1817. }
  1818. static void
  1819. WriteVersion(nsIFile* aProfileDir, const nsCString& aVersion,
  1820. const nsCString& aOSABI, nsIFile* aXULRunnerDir,
  1821. nsIFile* aAppDir)
  1822. {
  1823. nsCOMPtr<nsIFile> file;
  1824. aProfileDir->Clone(getter_AddRefs(file));
  1825. if (!file)
  1826. return;
  1827. file->AppendNative(FILE_COMPATIBILITY_INFO);
  1828. nsCOMPtr<nsILocalFile> lf = do_QueryInterface(file);
  1829. nsCAutoString platformDir;
  1830. aXULRunnerDir->GetNativePath(platformDir);
  1831. nsCAutoString appDir;
  1832. if (aAppDir)
  1833. aAppDir->GetNativePath(appDir);
  1834. PRFileDesc *fd = nsnull;
  1835. lf->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0600, &fd);
  1836. if (!fd) {
  1837. NS_ERROR("could not create output stream");
  1838. return;
  1839. }
  1840. static const char kHeader[] = "[Compatibility]" NS_LINEBREAK
  1841. "LastVersion=";
  1842. PR_Write(fd, kHeader, sizeof(kHeader) - 1);
  1843. PR_Write(fd, aVersion.get(), aVersion.Length());
  1844. static const char kOSABIHeader[] = NS_LINEBREAK "LastOSABI=";
  1845. PR_Write(fd, kOSABIHeader, sizeof(kOSABIHeader) - 1);
  1846. PR_Write(fd, aOSABI.get(), aOSABI.Length());
  1847. static const char kPlatformDirHeader[] = NS_LINEBREAK "LastPlatformDir=";
  1848. PR_Write(fd, kPlatformDirHeader, sizeof(kPlatformDirHeader) - 1);
  1849. PR_Write(fd, platformDir.get(), platformDir.Length());
  1850. static const char kAppDirHeader[] = NS_LINEBREAK "LastAppDir=";
  1851. if (aAppDir) {
  1852. PR_Write(fd, kAppDirHeader, sizeof(kAppDirHeader) - 1);
  1853. PR_Write(fd, appDir.get(), appDir.Length());
  1854. }
  1855. static const char kNL[] = NS_LINEBREAK;
  1856. PR_Write(fd, kNL, sizeof(kNL) - 1);
  1857. PR_Close(fd);
  1858. }
  1859. static PRBool ComponentsListChanged(nsIFile* aProfileDir)
  1860. {
  1861. nsCOMPtr<nsIFile> file;
  1862. aProfileDir->Clone(getter_AddRefs(file));
  1863. if (!file)
  1864. return PR_TRUE;
  1865. file->AppendNative(NS_LITERAL_CSTRING(".autoreg"));
  1866. PRBool exists = PR_FALSE;
  1867. file->Exists(&exists);
  1868. return exists;
  1869. }
  1870. static void RemoveComponentRegistries(nsIFile* aProfileDir, nsIFile* aLocalProfileDir,
  1871. PRBool aRemoveEMFiles)
  1872. {
  1873. nsCOMPtr<nsIFile> file;
  1874. aProfileDir->Clone(getter_AddRefs(file));
  1875. if (!file)
  1876. return;
  1877. file->AppendNative(NS_LITERAL_CSTRING("compreg.dat"));
  1878. file->Remove(PR_FALSE);
  1879. file->SetNativeLeafName(NS_LITERAL_CSTRING("xpti.dat"));
  1880. file->Remove(PR_FALSE);
  1881. file->SetNativeLeafName(NS_LITERAL_CSTRING(".autoreg"));
  1882. file->Remove(PR_FALSE);
  1883. if (aRemoveEMFiles) {
  1884. file->SetNativeLeafName(NS_LITERAL_CSTRING("extensions.ini"));
  1885. file->Remove(PR_FALSE);
  1886. }
  1887. aLocalProfileDir->Clone(getter_AddRefs(file));
  1888. if (!file)
  1889. return;
  1890. file->AppendNative(NS_LITERAL_CSTRING("XUL" PLATFORM_FASL_SUFFIX));
  1891. file->Remove(PR_FALSE);
  1892. }
  1893. // To support application initiated restart via nsIAppStartup.quit, we
  1894. // need to save various environment variables, and then restore them
  1895. // before re-launching the application.
  1896. static struct {
  1897. const char *name;
  1898. char *value;
  1899. } gSavedVars[] = {
  1900. {"XUL_APP_FILE", nsnull}
  1901. };
  1902. static void SaveStateForAppInitiatedRestart()
  1903. {
  1904. for (size_t i = 0; i < NS_ARRAY_LENGTH(gSavedVars); ++i) {
  1905. const char *s = PR_GetEnv(gSavedVars[i].name);
  1906. if (s)
  1907. gSavedVars[i].value = PR_smprintf("%s=%s", gSavedVars[i].name, s);
  1908. }
  1909. }
  1910. static void RestoreStateForAppInitiatedRestart()
  1911. {
  1912. for (size_t i = 0; i < NS_ARRAY_LENGTH(gSavedVars); ++i) {
  1913. if (gSavedVars[i].value)
  1914. PR_SetEnv(gSavedVars[i].value);
  1915. }
  1916. }
  1917. #ifdef MOZ_CRASHREPORTER
  1918. // When we first initialize the crash reporter we don't have a profile,
  1919. // so we set the minidump path to $TEMP. Once we have a profile,
  1920. // we set it to $PROFILE/minidumps, creating the directory
  1921. // if needed.
  1922. static void MakeOrSetMinidumpPath(nsIFile* profD)
  1923. {
  1924. nsCOMPtr<nsIFile> dumpD;
  1925. nsresult rv = profD->Clone(getter_AddRefs(dumpD));
  1926. if(dumpD) {
  1927. PRBool fileExists;
  1928. //XXX: do some more error checking here
  1929. dumpD->Append(NS_LITERAL_STRING("minidumps"));
  1930. rv = dumpD->Exists(&fileExists);
  1931. if(!fileExists) {
  1932. dumpD->Create(nsIFile::DIRECTORY_TYPE, 0700);
  1933. }
  1934. nsAutoString pathStr;
  1935. if(NS_SUCCEEDED(dumpD->GetPath(pathStr)))
  1936. CrashReporter::SetMinidumpPath(pathStr);
  1937. }
  1938. }
  1939. #endif
  1940. const nsXREAppData* gAppData = nsnull;
  1941. #if defined(XP_OS2)
  1942. // because we use early returns, we use a stack-based helper to un-set the OS2 FP handler
  1943. class ScopedFPHandler {
  1944. private:
  1945. EXCEPTIONREGISTRATIONRECORD excpreg;
  1946. public:
  1947. ScopedFPHandler() { PR_OS2_SetFloatExcpHandler(&excpreg); }
  1948. ~ScopedFPHandler() { PR_OS2_UnsetFloatExcpHandler(&excpreg); }
  1949. };
  1950. #endif
  1951. #ifdef MOZ_WIDGET_GTK2
  1952. #include "prlink.h"
  1953. typedef void (*_g_set_application_name_fn)(const gchar *application_name);
  1954. typedef void (*_gtk_window_set_auto_startup_notification_fn)(gboolean setting);
  1955. static PRFuncPtr FindFunction(const char* aName)
  1956. {
  1957. PRLibrary *lib = nsnull;
  1958. PRFuncPtr result = PR_FindFunctionSymbolAndLibrary(aName, &lib);
  1959. // Since the library was already loaded, we can safely unload it here.
  1960. if (lib) {
  1961. PR_UnloadLibrary(lib);
  1962. }
  1963. return result;
  1964. }
  1965. static nsIWidget* GetMainWidget(nsIDOMWindow* aWindow)
  1966. {
  1967. // get the native window for this instance
  1968. nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(aWindow));
  1969. NS_ENSURE_TRUE(window, nsnull);
  1970. nsCOMPtr<nsIBaseWindow> baseWindow
  1971. (do_QueryInterface(window->GetDocShell()));
  1972. NS_ENSURE_TRUE(baseWindow, nsnull);
  1973. nsCOMPtr<nsIWidget> mainWidget;
  1974. baseWindow->GetMainWidget(getter_AddRefs(mainWidget));
  1975. return mainWidget;
  1976. }
  1977. static nsGTKToolkit* GetGTKToolkit()
  1978. {
  1979. nsCOMPtr<nsIAppShellService> svc = do_GetService(NS_APPSHELLSERVICE_CONTRACTID);
  1980. if (!svc)
  1981. return nsnull;
  1982. nsCOMPtr<nsIDOMWindowInternal> window;
  1983. svc->GetHiddenDOMWindow(getter_AddRefs(window));
  1984. if (!window)
  1985. return nsnull;
  1986. nsIWidget* widget = GetMainWidget(window);
  1987. if (!widget)
  1988. return nsnull;
  1989. nsIToolkit* toolkit = widget->GetToolkit();
  1990. if (!toolkit)
  1991. return nsnull;
  1992. return static_cast<nsGTKToolkit*>(toolkit);
  1993. }
  1994. static void MOZ_gdk_display_close(GdkDisplay *display)
  1995. {
  1996. // XXX wallpaper for bug 417163: don't close the Display if we're using the
  1997. // Qt theme because we crash (in Qt code) when using jemalloc.
  1998. PRBool theme_is_qt = PR_FALSE;
  1999. GtkSettings* settings =
  2000. gtk_settings_get_for_screen(gdk_display_get_default_screen(display));
  2001. gchar *theme_name;
  2002. g_object_get(settings, "gtk-theme-name", &theme_name, NULL);
  2003. if (theme_name) {
  2004. theme_is_qt = strcmp(theme_name, "Qt") == 0;
  2005. if (theme_is_qt)
  2006. NS_WARNING("wallpaper bug 417163 for Qt theme");
  2007. g_free(theme_name);
  2008. }
  2009. // gdk_display_close was broken prior to gtk+-2.10.0.
  2010. // (http://bugzilla.gnome.org/show_bug.cgi?id=85715)
  2011. // gdk_display_manager_set_default_display (gdk_display_manager_get(), NULL)
  2012. // was also broken.
  2013. if (gtk_check_version(2,10,0) != NULL) {
  2014. // Version check failed - broken gdk_display_close.
  2015. //
  2016. // Let the gdk structures leak but at least close the Display,
  2017. // assuming that gdk will not use it again.
  2018. Display* dpy = GDK_DISPLAY_XDISPLAY(display);
  2019. if (!theme_is_qt)
  2020. XCloseDisplay(dpy);
  2021. }
  2022. else {
  2023. if (!theme_is_qt)
  2024. gdk_display_close(display);
  2025. #if GTK_CHECK_VERSION(2,8,0) && \
  2026. (defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) || defined(NS_TRACE_MALLOC))
  2027. cairo_debug_reset_static_data();
  2028. #endif
  2029. }
  2030. }
  2031. #endif // MOZ_WIDGET_GTK2
  2032. /**
  2033. * NSPR will search for the "nspr_use_zone_allocator" symbol throughout
  2034. * the process and use it to determine whether the application defines its own
  2035. * memory allocator or not.
  2036. *
  2037. * Since most applications (e.g. Firefox and Thunderbird) don't use any special
  2038. * allocators and therefore don't define this symbol, NSPR must search the
  2039. * entire process, which reduces startup performance.
  2040. *
  2041. * By defining the symbol here, we can avoid the wasted lookup and hopefully
  2042. * improve startup performance.
  2043. */
  2044. PRBool nspr_use_zone_allocator = PR_FALSE;
  2045. #ifdef XP_WIN
  2046. typedef BOOL (WINAPI* SetProcessDEPPolicyFunc)(DWORD dwFlags);
  2047. #endif
  2048. int
  2049. XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
  2050. {
  2051. #ifdef XP_WIN
  2052. /* On Windows XPSP3 and Windows Vista if DEP is configured off-by-default
  2053. we still want DEP protection: enable it explicitly and programmatically.
  2054. This function is not available on WinXPSP2 so we dynamically load it.
  2055. */
  2056. HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
  2057. SetProcessDEPPolicyFunc _SetProcessDEPPolicy =
  2058. (SetProcessDEPPolicyFunc) GetProcAddress(kernel32, "SetProcessDEPPolicy");
  2059. if (_SetProcessDEPPolicy)
  2060. _SetProcessDEPPolicy(PROCESS_DEP_ENABLE);
  2061. #endif
  2062. nsresult rv;
  2063. ArgResult ar;
  2064. NS_TIMELINE_MARK("enter main");
  2065. #ifdef DEBUG
  2066. if (PR_GetEnv("XRE_MAIN_BREAK"))
  2067. NS_BREAK();
  2068. #endif
  2069. #if defined (XP_WIN32) && !defined (WINCE)
  2070. // Suppress the "DLL Foo could not be found" dialog, such that if dependent
  2071. // libraries (such as GDI+) are not preset, we gracefully fail to load those
  2072. // XPCOM components, instead of being ungraceful.
  2073. UINT realMode = SetErrorMode(0);
  2074. realMode |= SEM_FAILCRITICALERRORS;
  2075. // If XRE_NO_WINDOWS_CRASH_DIALOG is set, suppress displaying the "This
  2076. // application has crashed" dialog box. This is mainly useful for
  2077. // automated testing environments, e.g. tinderbox, where there's no need
  2078. // for a dozen of the dialog boxes to litter the console
  2079. if (getenv("XRE_NO_WINDOWS_CRASH_DIALOG"))
  2080. realMode |= SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX;
  2081. SetErrorMode(realMode);
  2082. #ifdef DEBUG
  2083. // Disable small heap allocator to get heapwalk() giving us
  2084. // accurate heap numbers. Win2k non-debug does not use small heap allocator.
  2085. // Win2k debug seems to be still using it.
  2086. // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__set_sbh_threshold.asp
  2087. _set_sbh_threshold(0);
  2088. #endif
  2089. #endif
  2090. #if defined(XP_UNIX) || defined(XP_BEOS)
  2091. InstallUnixSignalHandlers(argv[0]);
  2092. #endif
  2093. #ifdef MOZ_ACCESSIBILITY_ATK
  2094. // Reset GTK_MODULES, strip atk-bridge if exists
  2095. // Mozilla will load libatk-bridge.so later if necessary
  2096. const char* gtkModules = PR_GetEnv("GTK_MODULES");
  2097. if (gtkModules && *gtkModules) {
  2098. nsCString gtkModulesStr(gtkModules);
  2099. gtkModulesStr.ReplaceSubstring("atk-bridge", "");
  2100. char* expr = PR_smprintf("GTK_MODULES=%s", gtkModulesStr.get());
  2101. if (expr)
  2102. PR_SetEnv(expr);
  2103. // We intentionally leak |expr| here since it is required by PR_SetEnv.
  2104. }
  2105. // Suppress atk-bridge init at startup, it works after GNOME 2.24.2
  2106. PR_SetEnv("NO_AT_BRIDGE=1");
  2107. #endif
  2108. // Unbuffer stdout, needed for tinderbox tests.
  2109. setbuf(stdout, 0);
  2110. #if defined(FREEBSD)
  2111. // Disable all SIGFPE's on FreeBSD, as it has non-IEEE-conformant fp
  2112. // trap behavior that trips up on floating-point tests performed by
  2113. // the JS engine. See bugzilla bug 9967 details.
  2114. fpsetmask(0);
  2115. #endif
  2116. gArgc = argc;
  2117. gArgv = argv;
  2118. NS_ENSURE_TRUE(aAppData, 2);
  2119. #ifdef XP_MACOSX
  2120. // The xulrunner stub executable tricks CFBundleGetMainBundle on
  2121. // purpose into lying about the main bundle path. It will set
  2122. // XRE_BINARY_PATH to inform us of our real location.
  2123. gBinaryPath = getenv("XRE_BINARY_PATH");
  2124. if (gBinaryPath && !*gBinaryPath)
  2125. gBinaryPath = nsnull;
  2126. #endif
  2127. // Check for application.ini overrides
  2128. const char* override = nsnull;
  2129. ar = CheckArg("override", PR_TRUE, &override);
  2130. if (ar == ARG_BAD) {
  2131. Output(PR_TRUE, "Incorrect number of arguments passed to -override");
  2132. return 1;
  2133. }
  2134. else if (ar == ARG_FOUND) {
  2135. nsCOMPtr<nsILocalFile> overrideLF;
  2136. rv = XRE_GetFileFromPath(override, getter_AddRefs(overrideLF));
  2137. if (NS_FAILED(rv)) {
  2138. Output(PR_TRUE, "Error: unrecognized override.ini path.\n");
  2139. return 1;
  2140. }
  2141. nsXREAppData* overrideAppData = const_cast<nsXREAppData*>(aAppData);
  2142. rv = XRE_ParseAppData(overrideLF, overrideAppData);
  2143. if (NS_FAILED(rv)) {
  2144. Output(PR_TRUE, "Couldn't read override.ini");
  2145. return 1;
  2146. }
  2147. }
  2148. ScopedAppData appData(aAppData);
  2149. gAppData = &appData;
  2150. // Check sanity and correctness of app data.
  2151. if (!appData.name) {
  2152. Output(PR_TRUE, "Error: App:Name not specified in application.ini\n");
  2153. return 1;
  2154. }
  2155. if (!appData.buildID) {
  2156. Output(PR_TRUE, "Error: App:BuildID not specified in application.ini\n");
  2157. return 1;
  2158. }
  2159. ScopedLogging log;
  2160. if (!appData.xreDirectory) {
  2161. nsCOMPtr<nsILocalFile> lf;
  2162. rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
  2163. if (NS_FAILED(rv))
  2164. return 2;
  2165. nsCOMPtr<nsIFile> greDir;
  2166. rv = lf->GetParent(getter_AddRefs(greDir));
  2167. if (NS_FAILED(rv))
  2168. return 2;
  2169. rv = CallQueryInterface(greDir, &appData.xreDirectory);
  2170. if (NS_FAILED(rv))
  2171. return 2;
  2172. }
  2173. nsCOMPtr<nsIFile> iniFile;
  2174. rv = appData.xreDirectory->Clone(getter_AddRefs(iniFile));
  2175. if (NS_FAILED(rv))
  2176. return 2;
  2177. iniFile->AppendNative(NS_LITERAL_CSTRING("platform.ini"));
  2178. nsCOMPtr<nsILocalFile> localIniFile = do_QueryInterface(iniFile);
  2179. if (!localIniFile)
  2180. return 2;
  2181. nsINIParser parser;
  2182. rv = parser.Init(localIniFile);
  2183. if (NS_SUCCEEDED(rv)) {
  2184. rv = parser.GetString("Build", "Milestone",
  2185. gToolkitVersion, sizeof(gToolkitVersion));
  2186. NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to get toolkit version");
  2187. rv = parser.GetString("Build", "BuildID",
  2188. gToolkitBuildID, sizeof(gToolkitBuildID));
  2189. NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to get toolkit buildid");
  2190. }
  2191. else {
  2192. NS_ERROR("Couldn't parse platform.ini!");
  2193. }
  2194. if (appData.size > offsetof(nsXREAppData, minVersion)) {
  2195. if (!appData.minVersion) {
  2196. Output(PR_TRUE, "Error: Gecko:MinVersion not specified in application.ini\n");
  2197. return 1;
  2198. }
  2199. if (!appData.maxVersion) {
  2200. // If no maxVersion is specified, we assume the app is only compatible
  2201. // with the initial preview release. Do not increment this number ever!
  2202. SetAllocatedString(appData.maxVersion, "1.*");
  2203. }
  2204. if (NS_CompareVersions(appData.minVersion, gToolkitVersion) > 0 ||
  2205. NS_CompareVersions(appData.maxVersion, gToolkitVersion) < 0) {
  2206. Output(PR_TRUE, "Error: Platform version '%s' is not compatible with\n"
  2207. "minVersion >= %s\nmaxVersion <= %s\n",
  2208. gToolkitVersion,
  2209. appData.minVersion, appData.maxVersion);
  2210. return 1;
  2211. }
  2212. }
  2213. #ifdef MOZ_CRASHREPORTER
  2214. const char* crashreporterEnv = PR_GetEnv("MOZ_CRASHREPORTER");
  2215. if (crashreporterEnv && *crashreporterEnv) {
  2216. appData.flags |= NS_XRE_ENABLE_CRASH_REPORTER;
  2217. }
  2218. if ((appData.flags & NS_XRE_ENABLE_CRASH_REPORTER) &&
  2219. NS_SUCCEEDED(
  2220. CrashReporter::SetExceptionHandler(appData.xreDirectory,
  2221. appData.crashReporterURL))) {
  2222. // pass some basic info from the app data
  2223. if (appData.vendor)
  2224. CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Vendor"),
  2225. nsDependentCString(appData.vendor));
  2226. if (appData.name)
  2227. CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProductName"),
  2228. nsDependentCString(appData.name));
  2229. if (appData.version)
  2230. CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Version"),
  2231. nsDependentCString(appData.version));
  2232. if (appData.buildID)
  2233. CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("BuildID"),
  2234. nsDependentCString(appData.buildID));
  2235. CrashReporter::SetRestartArgs(argc, argv);
  2236. // annotate other data (user id etc)
  2237. nsXREDirProvider dirProvider;
  2238. nsCOMPtr<nsILocalFile> userAppDataDir;
  2239. rv = dirProvider.Initialize(gAppData->directory, gAppData->xreDirectory);
  2240. if (NS_SUCCEEDED(rv) &&
  2241. NS_SUCCEEDED(dirProvider.GetUserAppDataDirectory(
  2242. getter_AddRefs(userAppDataDir)))) {
  2243. CrashReporter::SetupExtraData(userAppDataDir,
  2244. nsDependentCString(appData.buildID));
  2245. // see if we have a crashreporter-override.ini in the application directory
  2246. nsCOMPtr<nsIFile> overrideini;
  2247. PRBool exists;
  2248. static char overrideEnv[MAXPATHLEN];
  2249. if (NS_SUCCEEDED(dirProvider.GetAppDir()->Clone(getter_AddRefs(overrideini))) &&
  2250. NS_SUCCEEDED(overrideini->AppendNative(NS_LITERAL_CSTRING("crashreporter-override.ini"))) &&
  2251. NS_SUCCEEDED(overrideini->Exists(&exists)) &&
  2252. exists) {
  2253. #ifdef XP_WIN
  2254. nsAutoString overridePathW;
  2255. overrideini->GetPath(overridePathW);
  2256. NS_ConvertUTF16toUTF8 overridePath(overridePathW);
  2257. #else
  2258. nsCAutoString overridePath;
  2259. overrideini->GetNativePath(overridePath);
  2260. #endif
  2261. sprintf(overrideEnv, "MOZ_CRASHREPORTER_STRINGS_OVERRIDE=%s",
  2262. overridePath.get());
  2263. PR_SetEnv(overrideEnv);
  2264. }
  2265. }
  2266. }
  2267. #endif
  2268. #ifdef XP_MACOSX
  2269. if (PR_GetEnv("MOZ_LAUNCHED_CHILD")) {
  2270. // This is needed, on relaunch, to force the OS to use the "Cocoa Dock
  2271. // API". Otherwise the call to ReceiveNextEvent() below will make it
  2272. // use the "Carbon Dock API". For more info see bmo bug 377166.
  2273. EnsureUseCocoaDockAPI();
  2274. // When the app relaunches, the original process exits. This causes
  2275. // the dock tile to stop bouncing, lose the "running" triangle, and
  2276. // if the tile does not permanently reside in the Dock, even disappear.
  2277. // This can be confusing to the user, who is expecting the app to launch.
  2278. // Calling ReceiveNextEvent without requesting any event is enough to
  2279. // cause a dock tile for the child process to appear.
  2280. const EventTypeSpec kFakeEventList[] = { { INT_MAX, INT_MAX } };
  2281. EventRef event;
  2282. ::ReceiveNextEvent(GetEventTypeCount(kFakeEventList), kFakeEventList,
  2283. kEventDurationNoWait, PR_FALSE, &event);
  2284. }
  2285. if (CheckArg("foreground")) {
  2286. // The original process communicates that it was in the foreground by
  2287. // adding this argument. This new process, which is taking over for
  2288. // the old one, should make itself the active application.
  2289. ProcessSerialNumber psn;
  2290. if (::GetCurrentProcess(&psn) == noErr)
  2291. ::SetFrontProcess(&psn);
  2292. }
  2293. #endif
  2294. PR_SetEnv("MOZ_LAUNCHED_CHILD=");
  2295. gRestartArgc = gArgc;
  2296. gRestartArgv = (char**) malloc(sizeof(char*) * (gArgc + 1));
  2297. if (!gRestartArgv) return 1;
  2298. int i;
  2299. for (i = 0; i < gArgc; ++i) {
  2300. gRestartArgv[i] = gArgv[i];
  2301. }
  2302. gRestartArgv[gArgc] = nsnull;
  2303. #if defined(XP_OS2)
  2304. PRBool StartOS2App(int aArgc, char **aArgv);
  2305. if (!StartOS2App(gArgc, gArgv))
  2306. return 1;
  2307. ScopedFPHandler handler;
  2308. #endif /* XP_OS2 */
  2309. ar = CheckArg("safe-mode", PR_TRUE);
  2310. if (ar == ARG_BAD) {
  2311. PR_fprintf(PR_STDERR, "Error: argument -safe-mode is invalid when argument -osint is specified\n");
  2312. return 1;
  2313. } else if (ar == ARG_FOUND) {
  2314. gSafeMode = PR_TRUE;
  2315. }
  2316. #ifdef XP_MACOSX
  2317. if (GetCurrentEventKeyModifiers() & optionKey)
  2318. gSafeMode = PR_TRUE;
  2319. #endif
  2320. // Handle -no-remote command line argument. Setup the environment to
  2321. // better accommodate other components and various restart scenarios.
  2322. ar = CheckArg("no-remote", PR_TRUE);
  2323. if (ar == ARG_BAD) {
  2324. PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
  2325. return 1;
  2326. } else if (ar == ARG_FOUND) {
  2327. PR_SetEnv("MOZ_NO_REMOTE=1");
  2328. }
  2329. // Handle -help and -version command line arguments.
  2330. // They should return quickly, so we deal with them here.
  2331. if (CheckArg("h") || CheckArg("help") || CheckArg("?")) {
  2332. DumpHelp();
  2333. return 0;
  2334. }
  2335. if (CheckArg("v") || CheckArg("version")) {
  2336. DumpVersion();
  2337. return 0;
  2338. }
  2339. #ifdef NS_TRACE_MALLOC
  2340. gArgc = argc = NS_TraceMallocStartupArgs(gArgc, gArgv);
  2341. #endif
  2342. {
  2343. nsXREDirProvider dirProvider;
  2344. rv = dirProvider.Initialize(gAppData->directory, gAppData->xreDirectory);
  2345. if (NS_FAILED(rv))
  2346. return 1;
  2347. // Check for -register, which registers chrome and then exits immediately.
  2348. ar = CheckArg("register", PR_TRUE);
  2349. if (ar == ARG_BAD) {
  2350. PR_fprintf(PR_STDERR, "Error: argument -register is invalid when argument -osint is specified\n");
  2351. return 1;
  2352. } else if (ar == ARG_FOUND) {
  2353. ScopedXPCOMStartup xpcom;
  2354. rv = xpcom.Initialize();
  2355. NS_ENSURE_SUCCESS(rv, 1);
  2356. {
  2357. nsCOMPtr<nsIChromeRegistry> chromeReg
  2358. (do_GetService("@mozilla.org/chrome/chrome-registry;1"));
  2359. NS_ENSURE_TRUE(chromeReg, 1);
  2360. chromeReg->CheckForNewChrome();
  2361. }
  2362. return 0;
  2363. }
  2364. #if defined(MOZ_WIDGET_GTK2) || defined(MOZ_ENABLE_XREMOTE)
  2365. // Stash DESKTOP_STARTUP_ID in malloc'ed memory because gtk_init will clear it.
  2366. #define HAVE_DESKTOP_STARTUP_ID
  2367. const char* desktopStartupIDEnv = PR_GetEnv("DESKTOP_STARTUP_ID");
  2368. nsCAutoString desktopStartupID;
  2369. if (desktopStartupIDEnv) {
  2370. desktopStartupID.Assign(desktopStartupIDEnv);
  2371. }
  2372. #endif
  2373. #if defined(MOZ_WIDGET_GTK2)
  2374. g_thread_init(NULL);
  2375. // setup for private colormap. Ideally we'd like to do this
  2376. // in nsAppShell::Create, but we need to get in before gtk
  2377. // has been initialized to make sure everything is running
  2378. // consistently.
  2379. if (CheckArg("install"))
  2380. gdk_rgb_set_install(TRUE);
  2381. // Initialize GTK here for splash.
  2382. // Open the display ourselves instead of using gtk_init, so that we can
  2383. // close it without fear that one day gtk might clean up the display it
  2384. // opens.
  2385. if (!gtk_parse_args(&gArgc, &gArgv))
  2386. return 1;
  2387. GdkDisplay* display = nsnull;
  2388. {
  2389. // display_name is owned by gdk.
  2390. const char *display_name = gdk_get_display_arg_name();
  2391. if (!display_name) {
  2392. display_name = PR_GetEnv("DISPLAY");
  2393. if (!display_name) {
  2394. PR_fprintf(PR_STDERR, "Error: no display specified\n");
  2395. return 1;
  2396. }
  2397. }
  2398. display = gdk_display_open(display_name);
  2399. if (!display) {
  2400. PR_fprintf(PR_STDERR, "Error: cannot open display: %s\n", display_name);
  2401. return 1;
  2402. }
  2403. }
  2404. gdk_display_manager_set_default_display (gdk_display_manager_get(),
  2405. display);
  2406. // g_set_application_name () is only defined in glib2.2 and higher.
  2407. _g_set_application_name_fn _g_set_application_name =
  2408. (_g_set_application_name_fn)FindFunction("g_set_application_name");
  2409. if (_g_set_application_name) {
  2410. _g_set_application_name(gAppData->name);
  2411. }
  2412. _gtk_window_set_auto_startup_notification_fn _gtk_window_set_auto_startup_notification =
  2413. (_gtk_window_set_auto_startup_notification_fn)FindFunction("gtk_window_set_auto_startup_notification");
  2414. if (_gtk_window_set_auto_startup_notification) {
  2415. _gtk_window_set_auto_startup_notification(PR_FALSE);
  2416. }
  2417. gtk_widget_set_default_visual(gdk_rgb_get_visual());
  2418. gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
  2419. #endif /* MOZ_WIDGET_GTK2 */
  2420. // Call the code to install our handler
  2421. #ifdef MOZ_JPROF
  2422. setupProfilingStuff();
  2423. #endif
  2424. // Try to allocate "native app support."
  2425. nsCOMPtr<nsINativeAppSupport> nativeApp;
  2426. rv = NS_CreateNativeAppSupport(getter_AddRefs(nativeApp));
  2427. if (NS_FAILED(rv))
  2428. return 1;
  2429. PRBool canRun = PR_FALSE;
  2430. rv = nativeApp->Start(&canRun);
  2431. if (NS_FAILED(rv) || !canRun) {
  2432. return 1;
  2433. }
  2434. #ifdef MOZ_ENABLE_XREMOTE
  2435. // handle -remote now that xpcom is fired up
  2436. const char* xremotearg;
  2437. ar = CheckArg("remote", PR_TRUE, &xremotearg);
  2438. if (ar == ARG_BAD) {
  2439. PR_fprintf(PR_STDERR, "Error: -remote requires an argument\n");
  2440. return 1;
  2441. }
  2442. const char* desktopStartupIDPtr =
  2443. desktopStartupID.IsEmpty() ? nsnull : desktopStartupID.get();
  2444. if (ar) {
  2445. return HandleRemoteArgument(xremotearg, desktopStartupIDPtr);
  2446. }
  2447. if (!PR_GetEnv("MOZ_NO_REMOTE")) {
  2448. // Try to remote the entire command line. If this fails, start up normally.
  2449. RemoteResult rr = RemoteCommandLine(desktopStartupIDPtr);
  2450. if (rr == REMOTE_FOUND)
  2451. return 0;
  2452. else if (rr == REMOTE_ARG_BAD)
  2453. return 1;
  2454. }
  2455. #endif
  2456. #if defined(MOZ_UPDATER)
  2457. // Check for and process any available updates
  2458. nsCOMPtr<nsIFile> updRoot;
  2459. PRBool persistent;
  2460. rv = dirProvider.GetFile(XRE_UPDATE_ROOT_DIR, &persistent,
  2461. getter_AddRefs(updRoot));
  2462. // XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failed
  2463. if (NS_FAILED(rv))
  2464. updRoot = dirProvider.GetAppDir();
  2465. ProcessUpdates(dirProvider.GetGREDir(),
  2466. dirProvider.GetAppDir(),
  2467. updRoot,
  2468. gRestartArgc,
  2469. gRestartArgv,
  2470. appData.version);
  2471. #endif
  2472. nsCOMPtr<nsIProfileLock> profileLock;
  2473. PRBool startOffline = PR_FALSE;
  2474. nsCAutoString profileName;
  2475. rv = SelectProfile(getter_AddRefs(profileLock), nativeApp, &startOffline,
  2476. &profileName);
  2477. if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ||
  2478. rv == NS_ERROR_ABORT) return 0;
  2479. if (NS_FAILED(rv)) return 1;
  2480. nsCOMPtr<nsILocalFile> profD;
  2481. rv = profileLock->GetDirectory(getter_AddRefs(profD));
  2482. NS_ENSURE_SUCCESS(rv, 1);
  2483. nsCOMPtr<nsILocalFile> profLD;
  2484. rv = profileLock->GetLocalDirectory(getter_AddRefs(profLD));
  2485. NS_ENSURE_SUCCESS(rv, 1);
  2486. rv = dirProvider.SetProfile(profD, profLD);
  2487. NS_ENSURE_SUCCESS(rv, 1);
  2488. //////////////////////// NOW WE HAVE A PROFILE ////////////////////////
  2489. #ifdef MOZ_CRASHREPORTER
  2490. if (appData.flags & NS_XRE_ENABLE_CRASH_REPORTER)
  2491. MakeOrSetMinidumpPath(profD);
  2492. #endif
  2493. PRBool upgraded = PR_FALSE;
  2494. nsCAutoString version;
  2495. BuildVersion(version);
  2496. #ifdef TARGET_OS_ABI
  2497. NS_NAMED_LITERAL_CSTRING(osABI, TARGET_OS_ABI);
  2498. #else
  2499. // No TARGET_XPCOM_ABI, but at least the OS is known
  2500. NS_NAMED_LITERAL_CSTRING(osABI, OS_TARGET "_UNKNOWN");
  2501. #endif
  2502. // Check for version compatibility with the last version of the app this
  2503. // profile was started with. The format of the version stamp is defined
  2504. // by the BuildVersion function.
  2505. PRBool versionOK = CheckCompatibility(profD, version, osABI,
  2506. dirProvider.GetGREDir(),
  2507. gAppData->directory);
  2508. // Every time a profile is loaded by a build with a different version,
  2509. // it updates the compatibility.ini file saying what version last wrote
  2510. // the compreg.dat. On subsequent launches if the version matches,
  2511. // there is no need for re-registration. If the user loads the same
  2512. // profile in different builds the component registry must be
  2513. // re-generated to prevent mysterious component loading failures.
  2514. //
  2515. if (gSafeMode) {
  2516. RemoveComponentRegistries(profD, profLD, PR_FALSE);
  2517. WriteVersion(profD, NS_LITERAL_CSTRING("Safe Mode"), osABI,
  2518. dirProvider.GetGREDir(), gAppData->directory);
  2519. }
  2520. else if (versionOK) {
  2521. if (ComponentsListChanged(profD)) {
  2522. // Remove compreg.dat and xpti.dat, forcing component re-registration.
  2523. // The new list of additional components directories is derived from
  2524. // information in "extensions.ini".
  2525. RemoveComponentRegistries(profD, profLD, PR_FALSE);
  2526. }
  2527. // Nothing need be done for the normal startup case.
  2528. }
  2529. else {
  2530. // Remove compreg.dat and xpti.dat, forcing component re-registration
  2531. // with the default set of components (this disables any potentially
  2532. // troublesome incompatible XPCOM components).
  2533. RemoveComponentRegistries(profD, profLD, PR_TRUE);
  2534. // Tell the Extension Manager it should check for incompatible
  2535. // Extensions and re-write the "extensions.ini" file with a list of
  2536. // directories for compatible extensions
  2537. upgraded = PR_TRUE;
  2538. // Write out version
  2539. WriteVersion(profD, version, osABI,
  2540. dirProvider.GetGREDir(), gAppData->directory);
  2541. }
  2542. PRBool needsRestart = PR_FALSE;
  2543. PRBool appInitiatedRestart = PR_FALSE;
  2544. // Allows the user to forcefully bypass the restart process at their
  2545. // own risk. Useful for debugging or for tinderboxes where child
  2546. // processes can be problematic.
  2547. {
  2548. // Start the real application
  2549. ScopedXPCOMStartup xpcom;
  2550. rv = xpcom.Initialize();
  2551. NS_ENSURE_SUCCESS(rv, 1);
  2552. rv = xpcom.DoAutoreg();
  2553. rv |= xpcom.RegisterProfileService();
  2554. rv |= xpcom.SetWindowCreator(nativeApp);
  2555. NS_ENSURE_SUCCESS(rv, 1);
  2556. {
  2557. if (startOffline) {
  2558. nsCOMPtr<nsIIOService2> io (do_GetService("@mozilla.org/network/io-service;1"));
  2559. NS_ENSURE_TRUE(io, 1);
  2560. io->SetManageOfflineStatus(PR_FALSE);
  2561. io->SetOffline(PR_TRUE);
  2562. }
  2563. {
  2564. NS_TIMELINE_ENTER("startupNotifier");
  2565. nsCOMPtr<nsIObserver> startupNotifier
  2566. (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID, &rv));
  2567. NS_ENSURE_SUCCESS(rv, 1);
  2568. startupNotifier->Observe(nsnull, APPSTARTUP_TOPIC, nsnull);
  2569. NS_TIMELINE_LEAVE("startupNotifier");
  2570. }
  2571. nsCOMPtr<nsIAppStartup> appStartup
  2572. (do_GetService(NS_APPSTARTUP_CONTRACTID));
  2573. NS_ENSURE_TRUE(appStartup, 1);
  2574. if (gDoMigration) {
  2575. nsCOMPtr<nsIFile> file;
  2576. dirProvider.GetAppDir()->Clone(getter_AddRefs(file));
  2577. file->AppendNative(NS_LITERAL_CSTRING("override.ini"));
  2578. nsINIParser parser;
  2579. nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
  2580. nsresult rv = parser.Init(localFile);
  2581. if (NS_SUCCEEDED(rv)) {
  2582. nsCAutoString buf;
  2583. rv = parser.GetString("XRE", "EnableProfileMigrator", buf);
  2584. if (NS_SUCCEEDED(rv)) {
  2585. if (buf[0] == '0' || buf[0] == 'f' || buf[0] == 'F') {
  2586. gDoMigration = PR_FALSE;
  2587. }
  2588. }
  2589. }
  2590. }
  2591. // Profile Migration
  2592. if (gAppData->flags & NS_XRE_ENABLE_PROFILE_MIGRATOR && gDoMigration) {
  2593. gDoMigration = PR_FALSE;
  2594. nsCOMPtr<nsIProfileMigrator> pm
  2595. (do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID));
  2596. if (pm)
  2597. pm->Migrate(&dirProvider);
  2598. }
  2599. dirProvider.DoStartup();
  2600. nsCOMPtr<nsICommandLineRunner> cmdLine
  2601. (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
  2602. NS_ENSURE_TRUE(cmdLine, 1);
  2603. nsCOMPtr<nsIFile> workingDir;
  2604. rv = NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR, getter_AddRefs(workingDir));
  2605. NS_ENSURE_SUCCESS(rv, 1);
  2606. rv = cmdLine->Init(gArgc, gArgv,
  2607. workingDir, nsICommandLine::STATE_INITIAL_LAUNCH);
  2608. NS_ENSURE_SUCCESS(rv, 1);
  2609. /* Special-case services that need early access to the command
  2610. line. */
  2611. nsCOMPtr<nsIObserver> chromeObserver
  2612. (do_GetService("@mozilla.org/chrome/chrome-registry;1"));
  2613. if (chromeObserver) {
  2614. chromeObserver->Observe(cmdLine, "command-line-startup", nsnull);
  2615. }
  2616. NS_TIMELINE_ENTER("appStartup->CreateHiddenWindow");
  2617. rv = appStartup->CreateHiddenWindow();
  2618. NS_TIMELINE_LEAVE("appStartup->CreateHiddenWindow");
  2619. NS_ENSURE_SUCCESS(rv, 1);
  2620. #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK2)
  2621. nsRefPtr<nsGTKToolkit> toolkit = GetGTKToolkit();
  2622. if (toolkit && !desktopStartupID.IsEmpty()) {
  2623. toolkit->SetDesktopStartupID(desktopStartupID);
  2624. }
  2625. #endif
  2626. // Extension Compatibility Checking and Startup
  2627. if (gAppData->flags & NS_XRE_ENABLE_EXTENSION_MANAGER) {
  2628. nsCOMPtr<nsIExtensionManager> em(do_GetService("@mozilla.org/extensions/manager;1"));
  2629. NS_ENSURE_TRUE(em, 1);
  2630. ar = CheckArg("install-global-extension", PR_TRUE);
  2631. if (ar == ARG_BAD) {
  2632. PR_fprintf(PR_STDERR, "Error: argument -install-global-extension is invalid when argument -osint is specified\n");
  2633. return 1;
  2634. } else if (ar == ARG_FOUND) {
  2635. // Do the required processing and then shut down.
  2636. em->HandleCommandLineArgs(cmdLine);
  2637. return 0;
  2638. }
  2639. ar = CheckArg("install-global-theme", PR_TRUE);
  2640. if (ar == ARG_BAD) {
  2641. PR_fprintf(PR_STDERR, "Error: argument -install-global-theme is invalid when argument -osint is specified\n");
  2642. return 1;
  2643. } else if (ar == ARG_FOUND) {
  2644. // Do the required processing and then shut down.
  2645. em->HandleCommandLineArgs(cmdLine);
  2646. return 0;
  2647. }
  2648. if (upgraded) {
  2649. rv = em->CheckForMismatches(&needsRestart);
  2650. if (NS_FAILED(rv)) {
  2651. needsRestart = PR_FALSE;
  2652. upgraded = PR_FALSE;
  2653. }
  2654. }
  2655. if (!upgraded || !needsRestart)
  2656. em->Start(cmdLine, &needsRestart);
  2657. }
  2658. // We want to restart no more than 2 times. The first restart,
  2659. // NO_EM_RESTART == "0" , and the second time, "1".
  2660. char* noEMRestart = PR_GetEnv("NO_EM_RESTART");
  2661. if (noEMRestart && *noEMRestart && *noEMRestart == '1') {
  2662. if (upgraded || needsRestart) {
  2663. NS_WARNING("EM tried to force us to restart twice! Forcefully preventing that.");
  2664. }
  2665. needsRestart = upgraded = PR_FALSE;
  2666. }
  2667. if (!upgraded && !needsRestart) {
  2668. SaveStateForAppInitiatedRestart();
  2669. // clear out any environment variables which may have been set
  2670. // during the relaunch process now that we know we won't be relaunching.
  2671. PR_SetEnv("XRE_PROFILE_PATH=");
  2672. PR_SetEnv("XRE_PROFILE_LOCAL_PATH=");
  2673. PR_SetEnv("XRE_PROFILE_NAME=");
  2674. PR_SetEnv("XRE_START_OFFLINE=");
  2675. PR_SetEnv("XRE_IMPORT_PROFILES=");
  2676. PR_SetEnv("NO_EM_RESTART=");
  2677. PR_SetEnv("XUL_APP_FILE=");
  2678. PR_SetEnv("XRE_BINARY_PATH=");
  2679. #ifdef XP_MACOSX
  2680. // we re-initialize the command-line service and do appleevents munging
  2681. // after we are sure that we're not restarting
  2682. cmdLine = do_CreateInstance("@mozilla.org/toolkit/command-line;1");
  2683. NS_ENSURE_TRUE(cmdLine, 1);
  2684. SetupMacCommandLine(gArgc, gArgv);
  2685. rv = cmdLine->Init(gArgc, gArgv,
  2686. workingDir, nsICommandLine::STATE_INITIAL_LAUNCH);
  2687. NS_ENSURE_SUCCESS(rv, 1);
  2688. #endif
  2689. #ifdef MOZ_WIDGET_COCOA
  2690. // Prepare Cocoa's form of Apple Event handling.
  2691. SetupMacApplicationDelegate();
  2692. #endif
  2693. nsCOMPtr<nsIObserverService> obsService
  2694. (do_GetService("@mozilla.org/observer-service;1"));
  2695. if (obsService)
  2696. obsService->NotifyObservers(nsnull, "final-ui-startup", nsnull);
  2697. rv = cmdLine->Run();
  2698. NS_ENSURE_SUCCESS_LOG(rv, 1);
  2699. #ifdef MOZ_ENABLE_XREMOTE
  2700. // if we have X remote support, start listening for requests on the
  2701. // proxy window.
  2702. nsCOMPtr<nsIRemoteService> remoteService;
  2703. remoteService = do_GetService("@mozilla.org/toolkit/remote-service;1");
  2704. if (remoteService)
  2705. remoteService->Startup(gAppData->name,
  2706. PromiseFlatCString(profileName).get());
  2707. #endif /* MOZ_ENABLE_XREMOTE */
  2708. // enable win32 DDE responses and Mac appleevents responses
  2709. nativeApp->Enable();
  2710. NS_TIMELINE_ENTER("appStartup->Run");
  2711. rv = appStartup->Run();
  2712. NS_TIMELINE_LEAVE("appStartup->Run");
  2713. if (NS_FAILED(rv)) {
  2714. NS_ERROR("failed to run appstartup");
  2715. gLogConsoleErrors = PR_TRUE;
  2716. }
  2717. // Check for an application initiated restart. This is one that
  2718. // corresponds to nsIAppStartup.quit(eRestart)
  2719. if (rv == NS_SUCCESS_RESTART_APP) {
  2720. needsRestart = PR_TRUE;
  2721. appInitiatedRestart = PR_TRUE;
  2722. }
  2723. #ifdef MOZ_ENABLE_XREMOTE
  2724. // shut down the x remote proxy window
  2725. if (remoteService)
  2726. remoteService->Shutdown();
  2727. #endif /* MOZ_ENABLE_XREMOTE */
  2728. #ifdef MOZ_TIMELINE
  2729. // Make sure we print this out even if timeline is runtime disabled
  2730. if (NS_FAILED(NS_TIMELINE_LEAVE("main1")))
  2731. NS_TimelineForceMark("...main1");
  2732. #endif
  2733. }
  2734. else {
  2735. // Upgrade condition (build id changes), but the restart hint was
  2736. // not set by the Extension Manager. This is because the compatibility
  2737. // resolution for Extensions is different than for the component
  2738. // registry - major milestone vs. build id.
  2739. needsRestart = PR_TRUE;
  2740. #ifdef XP_WIN
  2741. ProcessDDE(nativeApp, PR_TRUE);
  2742. #endif
  2743. #ifdef XP_MACOSX
  2744. SetupMacCommandLine(gRestartArgc, gRestartArgv);
  2745. #endif
  2746. }
  2747. }
  2748. }
  2749. // unlock the profile after ScopedXPCOMStartup object (xpcom)
  2750. // has gone out of scope. see bug #386739 for more details
  2751. profileLock->Unlock();
  2752. // Restart the app after XPCOM has been shut down cleanly.
  2753. if (needsRestart) {
  2754. if (appInitiatedRestart) {
  2755. RestoreStateForAppInitiatedRestart();
  2756. }
  2757. else {
  2758. char* noEMRestart = PR_GetEnv("NO_EM_RESTART");
  2759. if (noEMRestart && *noEMRestart) {
  2760. PR_SetEnv("NO_EM_RESTART=1");
  2761. }
  2762. else {
  2763. PR_SetEnv("NO_EM_RESTART=0");
  2764. }
  2765. }
  2766. // Ensure that these environment variables are set:
  2767. SaveFileToEnvIfUnset("XRE_PROFILE_PATH", profD);
  2768. SaveFileToEnvIfUnset("XRE_PROFILE_LOCAL_PATH", profLD);
  2769. SaveWordToEnvIfUnset("XRE_PROFILE_NAME", profileName);
  2770. #ifdef XP_MACOSX
  2771. if (gBinaryPath) {
  2772. static char kEnvVar[MAXPATHLEN];
  2773. sprintf(kEnvVar, "XRE_BINARY_PATH=%s", gBinaryPath);
  2774. PR_SetEnv(kEnvVar);
  2775. }
  2776. #endif
  2777. // XXXkt s/MOZ_TOOLKIT_GTK2/MOZ_WIDGET_GTK2/?
  2778. // but the hidden window has been destroyed so toolkit is NULL anyway.
  2779. #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_TOOLKIT_GTK2)
  2780. nsGTKToolkit* toolkit = GetGTKToolkit();
  2781. if (toolkit) {
  2782. nsCAutoString currentDesktopStartupID;
  2783. toolkit->GetDesktopStartupID(&currentDesktopStartupID);
  2784. if (!currentDesktopStartupID.IsEmpty()) {
  2785. nsCAutoString desktopStartupEnv;
  2786. desktopStartupEnv.AssignLiteral("DESKTOP_STARTUP_ID=");
  2787. desktopStartupEnv.Append(currentDesktopStartupID);
  2788. // Leak it with extreme prejudice!
  2789. PR_SetEnv(ToNewCString(desktopStartupEnv));
  2790. }
  2791. }
  2792. #endif
  2793. #ifdef MOZ_WIDGET_GTK2
  2794. MOZ_gdk_display_close(display);
  2795. #endif
  2796. rv = LaunchChild(nativeApp, appInitiatedRestart);
  2797. #ifdef MOZ_CRASHREPORTER
  2798. if (appData.flags & NS_XRE_ENABLE_CRASH_REPORTER)
  2799. CrashReporter::UnsetExceptionHandler();
  2800. #endif
  2801. return rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ? 0 : 1;
  2802. }
  2803. #ifdef MOZ_WIDGET_GTK2
  2804. // gdk_display_close also calls gdk_display_manager_set_default_display
  2805. // appropriately when necessary.
  2806. MOZ_gdk_display_close(display);
  2807. #endif
  2808. }
  2809. #ifdef MOZ_CRASHREPORTER
  2810. if (appData.flags & NS_XRE_ENABLE_CRASH_REPORTER)
  2811. CrashReporter::UnsetExceptionHandler();
  2812. #endif
  2813. return NS_FAILED(rv) ? 1 : 0;
  2814. }