/toolkit/xre/nsAppRunner.cpp

http://github.com/zpao/v8monkey · C++ · 3783 lines · 2733 code · 617 blank · 433 comment · 477 complexity · 3ceee28c315af9b2508a8db7d645029d MD5 · raw file

Large files are truncated click here to view the full file

  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * The Original Code is Mozilla Communicator client code.
  16. *
  17. * The Initial Developer of the Original Code is
  18. * Netscape Communications Corporation.
  19. * Portions created by the Initial Developer are Copyright (C) 1998
  20. * the Initial Developer. All Rights Reserved.
  21. *
  22. * Contributor(s):
  23. * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
  24. * Benjamin Smedberg <benjamin@smedbergs.us>
  25. * Ben Goodger <ben@mozilla.org>
  26. * Fredrik Holmqvist <thesuckiestemail@yahoo.se>
  27. * Ben Turner <mozilla@songbirdnest.com>
  28. * Sergei Dolgov <sergei_d@fi.tartu.ee>
  29. *
  30. * Alternatively, the contents of this file may be used under the terms of
  31. * either the GNU General Public License Version 2 or later (the "GPL"), or
  32. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  33. * in which case the provisions of the GPL or the LGPL are applicable instead
  34. * of those above. If you wish to allow use of your version of this file only
  35. * under the terms of either the GPL or the LGPL, and not to allow others to
  36. * use your version of this file under the terms of the MPL, indicate your
  37. * decision by deleting the provisions above and replace them with the notice
  38. * and other provisions required by the GPL or the LGPL. If you do not delete
  39. * the provisions above, a recipient may use your version of this file under
  40. * the terms of any one of the MPL, the GPL or the LGPL.
  41. *
  42. * ***** END LICENSE BLOCK ***** */
  43. #if defined(XP_OS2) && defined(MOZ_OS2_HIGH_MEMORY)
  44. // os2safe.h has to be included before os2.h, needed for high mem
  45. #include <os2safe.h>
  46. #endif
  47. #define XPCOM_TRANSLATE_NSGM_ENTRY_POINT 1
  48. #if defined(MOZ_WIDGET_QT)
  49. #include <QtGui/QApplication>
  50. #include "nsQAppInstance.h"
  51. #include <QtGui/QInputContextFactory>
  52. #include <QtGui/QInputContext>
  53. #endif // MOZ_WIDGET_QT
  54. #include "mozilla/dom/ContentParent.h"
  55. #include "mozilla/dom/ContentChild.h"
  56. #include "mozilla/Util.h"
  57. #include "nsAppRunner.h"
  58. #include "nsUpdateDriver.h"
  59. #ifdef MOZ_INSTRUMENT_EVENT_LOOP
  60. #include "EventTracer.h"
  61. #endif
  62. #ifdef XP_MACOSX
  63. #include "nsVersionComparator.h"
  64. #include "MacLaunchHelper.h"
  65. #include "MacApplicationDelegate.h"
  66. #include "MacAutoreleasePool.h"
  67. // these are needed for sysctl
  68. #include <sys/types.h>
  69. #include <sys/sysctl.h>
  70. #endif
  71. #ifdef XP_OS2
  72. #include "private/pprthred.h"
  73. #endif
  74. #include "prmem.h"
  75. #include "prnetdb.h"
  76. #include "prprf.h"
  77. #include "prproces.h"
  78. #include "prenv.h"
  79. #include "nsIAppShellService.h"
  80. #include "nsIAppStartup.h"
  81. #include "nsIAppStartupNotifier.h"
  82. #include "nsIMutableArray.h"
  83. #include "nsICategoryManager.h"
  84. #include "nsIChromeRegistry.h"
  85. #include "nsICommandLineRunner.h"
  86. #include "nsIComponentManager.h"
  87. #include "nsIComponentRegistrar.h"
  88. #include "nsIContentHandler.h"
  89. #include "nsIDialogParamBlock.h"
  90. #include "nsIDOMWindow.h"
  91. #include "mozilla/ModuleUtils.h"
  92. #include "nsIIOService2.h"
  93. #include "nsIObserverService.h"
  94. #include "nsINativeAppSupport.h"
  95. #include "nsIProcess.h"
  96. #include "nsIProfileUnlocker.h"
  97. #include "nsIPromptService.h"
  98. #include "nsIServiceManager.h"
  99. #include "nsIStringBundle.h"
  100. #include "nsISupportsPrimitives.h"
  101. #include "nsIToolkitChromeRegistry.h"
  102. #include "nsIToolkitProfile.h"
  103. #include "nsIToolkitProfileService.h"
  104. #include "nsIURI.h"
  105. #include "nsIWindowCreator.h"
  106. #include "nsIWindowMediator.h"
  107. #include "nsIWindowWatcher.h"
  108. #include "nsIXULAppInfo.h"
  109. #include "nsIXULRuntime.h"
  110. #include "nsPIDOMWindow.h"
  111. #include "nsIBaseWindow.h"
  112. #include "nsIWidget.h"
  113. #include "nsIDocShell.h"
  114. #include "nsAppShellCID.h"
  115. #include "mozilla/FunctionTimer.h"
  116. #include "mozilla/unused.h"
  117. using namespace mozilla;
  118. using mozilla::unused;
  119. #ifdef XP_WIN
  120. #include "nsIWinAppHelper.h"
  121. #include <windows.h>
  122. #include "cairo/cairo-features.h"
  123. #ifndef PROCESS_DEP_ENABLE
  124. #define PROCESS_DEP_ENABLE 0x1
  125. #endif
  126. #endif
  127. #include "nsCRT.h"
  128. #include "nsCOMPtr.h"
  129. #include "nsDirectoryServiceDefs.h"
  130. #include "nsDirectoryServiceUtils.h"
  131. #include "nsEmbedCID.h"
  132. #include "nsNetUtil.h"
  133. #include "nsReadableUtils.h"
  134. #include "nsStaticComponents.h"
  135. #include "nsXPCOM.h"
  136. #include "nsXPCOMCIDInternal.h"
  137. #include "nsXPIDLString.h"
  138. #include "nsVersionComparator.h"
  139. #include "nsAppDirectoryServiceDefs.h"
  140. #include "nsXULAppAPI.h"
  141. #include "nsXREDirProvider.h"
  142. #include "nsToolkitCompsCID.h"
  143. #include "nsINIParser.h"
  144. #include "mozilla/Omnijar.h"
  145. #include "mozilla/StartupTimeline.h"
  146. #include <stdlib.h>
  147. #ifdef XP_UNIX
  148. #include <sys/stat.h>
  149. #include <unistd.h>
  150. #include <pwd.h>
  151. #endif
  152. #ifdef XP_WIN
  153. #include <process.h>
  154. #include <shlobj.h>
  155. #include "nsThreadUtils.h"
  156. #endif
  157. #ifdef XP_MACOSX
  158. #include "nsILocalFileMac.h"
  159. #include "nsCommandLineServiceMac.h"
  160. #endif
  161. // for X remote support
  162. #ifdef MOZ_ENABLE_XREMOTE
  163. #include "XRemoteClient.h"
  164. #include "nsIRemoteService.h"
  165. #endif
  166. #ifdef NS_TRACE_MALLOC
  167. #include "nsTraceMalloc.h"
  168. #endif
  169. #if defined(DEBUG) && defined(XP_WIN32)
  170. #include <malloc.h>
  171. #endif
  172. #if defined (XP_MACOSX)
  173. #include <Carbon/Carbon.h>
  174. #endif
  175. #ifdef DEBUG
  176. #include "prlog.h"
  177. #endif
  178. #ifdef MOZ_JPROF
  179. #include "jprof.h"
  180. #endif
  181. #ifdef MOZ_CRASHREPORTER
  182. #include "nsExceptionHandler.h"
  183. #include "nsICrashReporter.h"
  184. #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
  185. #include "nsIPrefService.h"
  186. #endif
  187. #include "base/command_line.h"
  188. #include "mozilla/FunctionTimer.h"
  189. #ifdef MOZ_WIDGET_ANDROID
  190. #include "AndroidBridge.h"
  191. #endif
  192. extern PRUint32 gRestartMode;
  193. extern void InstallSignalHandlers(const char *ProgramName);
  194. #include "nsX11ErrorHandler.h"
  195. #define FILE_COMPATIBILITY_INFO NS_LITERAL_CSTRING("compatibility.ini")
  196. #define FILE_INVALIDATE_CACHES NS_LITERAL_CSTRING(".purgecaches")
  197. int gArgc;
  198. char **gArgv;
  199. static const char gToolkitVersion[] = NS_STRINGIFY(GRE_MILESTONE);
  200. static const char gToolkitBuildID[] = NS_STRINGIFY(GRE_BUILDID);
  201. static nsIProfileLock* gProfileLock;
  202. static int gRestartArgc;
  203. static char **gRestartArgv;
  204. #ifdef MOZ_WIDGET_QT
  205. static int gQtOnlyArgc;
  206. static char **gQtOnlyArgv;
  207. #endif
  208. #if defined(MOZ_WIDGET_GTK2)
  209. #if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) \
  210. || defined(NS_TRACE_MALLOC)
  211. #define CLEANUP_MEMORY 1
  212. #define PANGO_ENABLE_BACKEND
  213. #include <pango/pangofc-fontmap.h>
  214. #endif
  215. #include <gtk/gtk.h>
  216. #ifdef MOZ_X11
  217. #include <gdk/gdkx.h>
  218. #endif /* MOZ_X11 */
  219. #include "nsGTKToolkit.h"
  220. #endif
  221. #include "BinaryPath.h"
  222. using mozilla::dom::ContentParent;
  223. using mozilla::dom::ContentChild;
  224. // Save literal putenv string to environment variable.
  225. static void
  226. SaveToEnv(const char *putenv)
  227. {
  228. char *expr = strdup(putenv);
  229. if (expr)
  230. PR_SetEnv(expr);
  231. // We intentionally leak |expr| here since it is required by PR_SetEnv.
  232. }
  233. // Tests that an environment variable exists and has a value
  234. static bool
  235. EnvHasValue(const char *name)
  236. {
  237. const char *val = PR_GetEnv(name);
  238. return (val && *val);
  239. }
  240. // Save the given word to the specified environment variable.
  241. static void
  242. SaveWordToEnv(const char *name, const nsACString & word)
  243. {
  244. char *expr = PR_smprintf("%s=%s", name, PromiseFlatCString(word).get());
  245. if (expr)
  246. PR_SetEnv(expr);
  247. // We intentionally leak |expr| here since it is required by PR_SetEnv.
  248. }
  249. // Save the path of the given file to the specified environment variable.
  250. static void
  251. SaveFileToEnv(const char *name, nsIFile *file)
  252. {
  253. #ifdef XP_WIN
  254. nsAutoString path;
  255. file->GetPath(path);
  256. SetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(), path.get());
  257. #else
  258. nsCAutoString path;
  259. file->GetNativePath(path);
  260. SaveWordToEnv(name, path);
  261. #endif
  262. }
  263. // Load the path of a file saved with SaveFileToEnv
  264. static already_AddRefed<nsILocalFile>
  265. GetFileFromEnv(const char *name)
  266. {
  267. nsresult rv;
  268. nsILocalFile *file = nsnull;
  269. #ifdef XP_WIN
  270. WCHAR path[_MAX_PATH];
  271. if (!GetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(),
  272. path, _MAX_PATH))
  273. return nsnull;
  274. rv = NS_NewLocalFile(nsDependentString(path), true, &file);
  275. if (NS_FAILED(rv))
  276. return nsnull;
  277. return file;
  278. #else
  279. const char *arg = PR_GetEnv(name);
  280. if (!arg || !*arg)
  281. return nsnull;
  282. rv = NS_NewNativeLocalFile(nsDependentCString(arg), true, &file);
  283. if (NS_FAILED(rv))
  284. return nsnull;
  285. return file;
  286. #endif
  287. }
  288. // Save the path of the given word to the specified environment variable
  289. // provided the environment variable does not have a value.
  290. static void
  291. SaveWordToEnvIfUnset(const char *name, const nsACString & word)
  292. {
  293. if (!EnvHasValue(name))
  294. SaveWordToEnv(name, word);
  295. }
  296. // Save the path of the given file to the specified environment variable
  297. // provided the environment variable does not have a value.
  298. static void
  299. SaveFileToEnvIfUnset(const char *name, nsIFile *file)
  300. {
  301. if (!EnvHasValue(name))
  302. SaveFileToEnv(name, file);
  303. }
  304. static bool
  305. strimatch(const char* lowerstr, const char* mixedstr)
  306. {
  307. while(*lowerstr) {
  308. if (!*mixedstr) return false; // mixedstr is shorter
  309. if (tolower(*mixedstr) != *lowerstr) return false; // no match
  310. ++lowerstr;
  311. ++mixedstr;
  312. }
  313. if (*mixedstr) return false; // lowerstr is shorter
  314. return true;
  315. }
  316. /**
  317. * Output a string to the user. This method is really only meant to be used to
  318. * output last-ditch error messages designed for developers NOT END USERS.
  319. *
  320. * @param isError
  321. * Pass true to indicate severe errors.
  322. * @param fmt
  323. * printf-style format string followed by arguments.
  324. */
  325. static void Output(bool isError, const char *fmt, ... )
  326. {
  327. va_list ap;
  328. va_start(ap, fmt);
  329. #if defined(XP_WIN) && !MOZ_WINCONSOLE
  330. char *msg = PR_vsmprintf(fmt, ap);
  331. if (msg)
  332. {
  333. UINT flags = MB_OK;
  334. if (isError)
  335. flags |= MB_ICONERROR;
  336. else
  337. flags |= MB_ICONINFORMATION;
  338. wchar_t wide_msg[1024];
  339. MultiByteToWideChar(CP_ACP,
  340. 0,
  341. msg,
  342. -1,
  343. wide_msg,
  344. sizeof(wide_msg) / sizeof(wchar_t));
  345. MessageBoxW(NULL, wide_msg, L"XULRunner", flags);
  346. PR_smprintf_free(msg);
  347. }
  348. #else
  349. vfprintf(stderr, fmt, ap);
  350. #endif
  351. va_end(ap);
  352. }
  353. enum RemoteResult {
  354. REMOTE_NOT_FOUND = 0,
  355. REMOTE_FOUND = 1,
  356. REMOTE_ARG_BAD = 2
  357. };
  358. enum ArgResult {
  359. ARG_NONE = 0,
  360. ARG_FOUND = 1,
  361. ARG_BAD = 2 // you wanted a param, but there isn't one
  362. };
  363. static void RemoveArg(char **argv)
  364. {
  365. do {
  366. *argv = *(argv + 1);
  367. ++argv;
  368. } while (*argv);
  369. --gArgc;
  370. }
  371. /**
  372. * Check for a commandline flag. If the flag takes a parameter, the
  373. * parameter is returned in aParam. Flags may be in the form -arg or
  374. * --arg (or /arg on win32/OS2).
  375. *
  376. * @param aArg the parameter to check. Must be lowercase.
  377. * @param aCheckOSInt if true returns ARG_BAD if the osint argument is present
  378. * when aArg is also present.
  379. * @param if non-null, the -arg <data> will be stored in this pointer. This is *not*
  380. * allocated, but rather a pointer to the argv data.
  381. */
  382. static ArgResult
  383. CheckArg(const char* aArg, bool aCheckOSInt = false, const char **aParam = nsnull, bool aRemArg = true)
  384. {
  385. NS_ABORT_IF_FALSE(gArgv, "gArgv must be initialized before CheckArg()");
  386. char **curarg = gArgv + 1; // skip argv[0]
  387. ArgResult ar = ARG_NONE;
  388. while (*curarg) {
  389. char *arg = curarg[0];
  390. if (arg[0] == '-'
  391. #if defined(XP_WIN) || defined(XP_OS2)
  392. || *arg == '/'
  393. #endif
  394. ) {
  395. ++arg;
  396. if (*arg == '-')
  397. ++arg;
  398. if (strimatch(aArg, arg)) {
  399. if (aRemArg)
  400. RemoveArg(curarg);
  401. if (!aParam) {
  402. ar = ARG_FOUND;
  403. break;
  404. }
  405. if (*curarg) {
  406. if (**curarg == '-'
  407. #if defined(XP_WIN) || defined(XP_OS2)
  408. || **curarg == '/'
  409. #endif
  410. )
  411. return ARG_BAD;
  412. *aParam = *curarg;
  413. if (aRemArg)
  414. RemoveArg(curarg);
  415. ar = ARG_FOUND;
  416. break;
  417. }
  418. return ARG_BAD;
  419. }
  420. }
  421. ++curarg;
  422. }
  423. if (aCheckOSInt && ar == ARG_FOUND) {
  424. ArgResult arOSInt = CheckArg("osint");
  425. if (arOSInt == ARG_FOUND) {
  426. ar = ARG_BAD;
  427. PR_fprintf(PR_STDERR, "Error: argument -osint is invalid\n");
  428. }
  429. }
  430. return ar;
  431. }
  432. #if defined(XP_WIN)
  433. /**
  434. * Check for a commandline flag from the windows shell and remove it from the
  435. * argv used when restarting. Flags MUST be in the form -arg.
  436. *
  437. * @param aArg the parameter to check. Must be lowercase.
  438. */
  439. static ArgResult
  440. CheckArgShell(const char* aArg)
  441. {
  442. char **curarg = gRestartArgv + 1; // skip argv[0]
  443. while (*curarg) {
  444. char *arg = curarg[0];
  445. if (arg[0] == '-') {
  446. ++arg;
  447. if (strimatch(aArg, arg)) {
  448. do {
  449. *curarg = *(curarg + 1);
  450. ++curarg;
  451. } while (*curarg);
  452. --gRestartArgc;
  453. return ARG_FOUND;
  454. }
  455. }
  456. ++curarg;
  457. }
  458. return ARG_NONE;
  459. }
  460. /**
  461. * Enabled Native App Support to process DDE messages when the app needs to
  462. * restart and the app has been launched by the Windows shell to open an url.
  463. * When aWait is false this will process the DDE events manually. This prevents
  464. * Windows from displaying an error message due to the DDE message not being
  465. * acknowledged.
  466. */
  467. static void
  468. ProcessDDE(nsINativeAppSupport* aNative, bool aWait)
  469. {
  470. // When the app is launched by the windows shell the windows shell
  471. // expects the app to be available for DDE messages and if it isn't
  472. // windows displays an error dialog. To prevent the error the DDE server
  473. // is enabled and pending events are processed when the app needs to
  474. // restart after it was launched by the shell with the requestpending
  475. // argument. The requestpending pending argument is removed to
  476. // differentiate it from being launched when an app restart is not
  477. // required.
  478. ArgResult ar;
  479. ar = CheckArgShell("requestpending");
  480. if (ar == ARG_FOUND) {
  481. aNative->Enable(); // enable win32 DDE responses
  482. if (aWait) {
  483. nsIThread *thread = NS_GetCurrentThread();
  484. // This is just a guesstimate based on testing different values.
  485. // If count is 8 or less windows will display an error dialog.
  486. PRInt32 count = 20;
  487. while(--count >= 0) {
  488. NS_ProcessNextEvent(thread);
  489. PR_Sleep(PR_MillisecondsToInterval(1));
  490. }
  491. }
  492. }
  493. }
  494. #endif
  495. bool gSafeMode = false;
  496. /**
  497. * The nsXULAppInfo object implements nsIFactory so that it can be its own
  498. * singleton.
  499. */
  500. class nsXULAppInfo : public nsIXULAppInfo,
  501. #ifdef XP_WIN
  502. public nsIWinAppHelper,
  503. #endif
  504. #ifdef MOZ_CRASHREPORTER
  505. public nsICrashReporter,
  506. #endif
  507. public nsIXULRuntime
  508. {
  509. public:
  510. nsXULAppInfo() {}
  511. NS_DECL_ISUPPORTS_INHERITED
  512. NS_DECL_NSIXULAPPINFO
  513. NS_DECL_NSIXULRUNTIME
  514. #ifdef MOZ_CRASHREPORTER
  515. NS_DECL_NSICRASHREPORTER
  516. #endif
  517. #ifdef XP_WIN
  518. NS_DECL_NSIWINAPPHELPER
  519. #endif
  520. };
  521. NS_INTERFACE_MAP_BEGIN(nsXULAppInfo)
  522. NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULRuntime)
  523. NS_INTERFACE_MAP_ENTRY(nsIXULRuntime)
  524. #ifdef XP_WIN
  525. NS_INTERFACE_MAP_ENTRY(nsIWinAppHelper)
  526. #endif
  527. #ifdef MOZ_CRASHREPORTER
  528. NS_INTERFACE_MAP_ENTRY(nsICrashReporter)
  529. #endif
  530. NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIXULAppInfo, gAppData ||
  531. XRE_GetProcessType() == GeckoProcessType_Content)
  532. NS_INTERFACE_MAP_END
  533. NS_IMETHODIMP_(nsrefcnt)
  534. nsXULAppInfo::AddRef()
  535. {
  536. return 1;
  537. }
  538. NS_IMETHODIMP_(nsrefcnt)
  539. nsXULAppInfo::Release()
  540. {
  541. return 1;
  542. }
  543. NS_IMETHODIMP
  544. nsXULAppInfo::GetVendor(nsACString& aResult)
  545. {
  546. if (XRE_GetProcessType() == GeckoProcessType_Content) {
  547. NS_WARNING("Attempt to get unavailable information in content process.");
  548. return NS_ERROR_NOT_AVAILABLE;
  549. }
  550. aResult.Assign(gAppData->vendor);
  551. return NS_OK;
  552. }
  553. NS_IMETHODIMP
  554. nsXULAppInfo::GetName(nsACString& aResult)
  555. {
  556. if (XRE_GetProcessType() == GeckoProcessType_Content) {
  557. NS_WARNING("Attempt to get unavailable information in content process.");
  558. return NS_ERROR_NOT_AVAILABLE;
  559. }
  560. aResult.Assign(gAppData->name);
  561. return NS_OK;
  562. }
  563. NS_IMETHODIMP
  564. nsXULAppInfo::GetID(nsACString& aResult)
  565. {
  566. if (XRE_GetProcessType() == GeckoProcessType_Content) {
  567. NS_WARNING("Attempt to get unavailable information in content process.");
  568. return NS_ERROR_NOT_AVAILABLE;
  569. }
  570. aResult.Assign(gAppData->ID);
  571. return NS_OK;
  572. }
  573. NS_IMETHODIMP
  574. nsXULAppInfo::GetVersion(nsACString& aResult)
  575. {
  576. if (XRE_GetProcessType() == GeckoProcessType_Content) {
  577. ContentChild* cc = ContentChild::GetSingleton();
  578. aResult = cc->GetAppInfo().version;
  579. return NS_OK;
  580. }
  581. aResult.Assign(gAppData->version);
  582. return NS_OK;
  583. }
  584. NS_IMETHODIMP
  585. nsXULAppInfo::GetPlatformVersion(nsACString& aResult)
  586. {
  587. aResult.Assign(gToolkitVersion);
  588. return NS_OK;
  589. }
  590. NS_IMETHODIMP
  591. nsXULAppInfo::GetAppBuildID(nsACString& aResult)
  592. {
  593. if (XRE_GetProcessType() == GeckoProcessType_Content) {
  594. ContentChild* cc = ContentChild::GetSingleton();
  595. aResult = cc->GetAppInfo().buildID;
  596. return NS_OK;
  597. }
  598. aResult.Assign(gAppData->buildID);
  599. return NS_OK;
  600. }
  601. NS_IMETHODIMP
  602. nsXULAppInfo::GetPlatformBuildID(nsACString& aResult)
  603. {
  604. aResult.Assign(gToolkitBuildID);
  605. return NS_OK;
  606. }
  607. NS_IMETHODIMP
  608. nsXULAppInfo::GetLogConsoleErrors(bool *aResult)
  609. {
  610. *aResult = gLogConsoleErrors;
  611. return NS_OK;
  612. }
  613. NS_IMETHODIMP
  614. nsXULAppInfo::SetLogConsoleErrors(bool aValue)
  615. {
  616. gLogConsoleErrors = aValue;
  617. return NS_OK;
  618. }
  619. NS_IMETHODIMP
  620. nsXULAppInfo::GetInSafeMode(bool *aResult)
  621. {
  622. *aResult = gSafeMode;
  623. return NS_OK;
  624. }
  625. NS_IMETHODIMP
  626. nsXULAppInfo::GetOS(nsACString& aResult)
  627. {
  628. aResult.AssignLiteral(OS_TARGET);
  629. return NS_OK;
  630. }
  631. NS_IMETHODIMP
  632. nsXULAppInfo::GetXPCOMABI(nsACString& aResult)
  633. {
  634. #ifdef TARGET_XPCOM_ABI
  635. aResult.AssignLiteral(TARGET_XPCOM_ABI);
  636. return NS_OK;
  637. #else
  638. return NS_ERROR_NOT_AVAILABLE;
  639. #endif
  640. }
  641. NS_IMETHODIMP
  642. nsXULAppInfo::GetWidgetToolkit(nsACString& aResult)
  643. {
  644. aResult.AssignLiteral(MOZ_WIDGET_TOOLKIT);
  645. return NS_OK;
  646. }
  647. // Ensure that the GeckoProcessType enum, defined in xpcom/build/nsXULAppAPI.h,
  648. // is synchronized with the const unsigned longs defined in
  649. // xpcom/system/nsIXULRuntime.idl.
  650. #define SYNC_ENUMS(a,b) \
  651. PR_STATIC_ASSERT(nsIXULRuntime::PROCESS_TYPE_ ## a == \
  652. static_cast<int>(GeckoProcessType_ ## b));
  653. SYNC_ENUMS(DEFAULT, Default)
  654. SYNC_ENUMS(PLUGIN, Plugin)
  655. SYNC_ENUMS(CONTENT, Content)
  656. SYNC_ENUMS(IPDLUNITTEST, IPDLUnitTest)
  657. // .. and ensure that that is all of them:
  658. PR_STATIC_ASSERT(GeckoProcessType_IPDLUnitTest + 1 == GeckoProcessType_End);
  659. NS_IMETHODIMP
  660. nsXULAppInfo::GetProcessType(PRUint32* aResult)
  661. {
  662. NS_ENSURE_ARG_POINTER(aResult);
  663. *aResult = XRE_GetProcessType();
  664. return NS_OK;
  665. }
  666. NS_IMETHODIMP
  667. nsXULAppInfo::EnsureContentProcess()
  668. {
  669. if (XRE_GetProcessType() != GeckoProcessType_Default)
  670. return NS_ERROR_NOT_AVAILABLE;
  671. unused << ContentParent::GetNewOrUsed();
  672. return NS_OK;
  673. }
  674. NS_IMETHODIMP
  675. nsXULAppInfo::InvalidateCachesOnRestart()
  676. {
  677. nsCOMPtr<nsIFile> file;
  678. nsresult rv = NS_GetSpecialDirectory(NS_APP_PROFILE_DIR_STARTUP,
  679. getter_AddRefs(file));
  680. if (NS_FAILED(rv))
  681. return rv;
  682. if (!file)
  683. return NS_ERROR_NOT_AVAILABLE;
  684. file->AppendNative(FILE_COMPATIBILITY_INFO);
  685. nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
  686. nsINIParser parser;
  687. rv = parser.Init(localFile);
  688. if (NS_FAILED(rv)) {
  689. // This fails if compatibility.ini is not there, so we'll
  690. // flush the caches on the next restart anyways.
  691. return NS_OK;
  692. }
  693. nsCAutoString buf;
  694. rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
  695. if (NS_FAILED(rv)) {
  696. PRFileDesc *fd = nsnull;
  697. localFile->OpenNSPRFileDesc(PR_RDWR | PR_APPEND, 0600, &fd);
  698. if (!fd) {
  699. NS_ERROR("could not create output stream");
  700. return NS_ERROR_NOT_AVAILABLE;
  701. }
  702. static const char kInvalidationHeader[] = NS_LINEBREAK "InvalidateCaches=1" NS_LINEBREAK;
  703. rv = PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1);
  704. PR_Close(fd);
  705. if (NS_FAILED(rv))
  706. return rv;
  707. }
  708. return NS_OK;
  709. }
  710. NS_IMETHODIMP
  711. nsXULAppInfo::GetReplacedLockTime(PRInt64 *aReplacedLockTime)
  712. {
  713. if (!gProfileLock)
  714. return NS_ERROR_NOT_AVAILABLE;
  715. gProfileLock->GetReplacedLockTime(aReplacedLockTime);
  716. return NS_OK;
  717. }
  718. #ifdef XP_WIN
  719. // Matches the enum in WinNT.h for the Vista SDK but renamed so that we can
  720. // safely build with the Vista SDK and without it.
  721. typedef enum
  722. {
  723. VistaTokenElevationTypeDefault = 1,
  724. VistaTokenElevationTypeFull,
  725. VistaTokenElevationTypeLimited
  726. } VISTA_TOKEN_ELEVATION_TYPE;
  727. // avoid collision with TokeElevationType enum in WinNT.h
  728. // of the Vista SDK
  729. #define VistaTokenElevationType static_cast< TOKEN_INFORMATION_CLASS >( 18 )
  730. NS_IMETHODIMP
  731. nsXULAppInfo::GetUserCanElevate(bool *aUserCanElevate)
  732. {
  733. HANDLE hToken;
  734. VISTA_TOKEN_ELEVATION_TYPE elevationType;
  735. DWORD dwSize;
  736. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) ||
  737. !GetTokenInformation(hToken, VistaTokenElevationType, &elevationType,
  738. sizeof(elevationType), &dwSize)) {
  739. *aUserCanElevate = false;
  740. }
  741. else {
  742. // The possible values returned for elevationType and their meanings are:
  743. // TokenElevationTypeDefault: The token does not have a linked token
  744. // (e.g. UAC disabled or a standard user, so they can't be elevated)
  745. // TokenElevationTypeFull: The token is linked to an elevated token
  746. // (e.g. UAC is enabled and the user is already elevated so they can't
  747. // be elevated again)
  748. // TokenElevationTypeLimited: The token is linked to a limited token
  749. // (e.g. UAC is enabled and the user is not elevated, so they can be
  750. // elevated)
  751. *aUserCanElevate = (elevationType == VistaTokenElevationTypeLimited);
  752. }
  753. if (hToken)
  754. CloseHandle(hToken);
  755. return NS_OK;
  756. }
  757. #endif
  758. #ifdef MOZ_CRASHREPORTER
  759. NS_IMETHODIMP
  760. nsXULAppInfo::GetEnabled(bool *aEnabled)
  761. {
  762. *aEnabled = CrashReporter::GetEnabled();
  763. return NS_OK;
  764. }
  765. NS_IMETHODIMP
  766. nsXULAppInfo::SetEnabled(bool aEnabled)
  767. {
  768. if (aEnabled) {
  769. if (CrashReporter::GetEnabled())
  770. // no point in erroring for double-enabling
  771. return NS_OK;
  772. nsCOMPtr<nsILocalFile> xreDirectory;
  773. if (gAppData) {
  774. xreDirectory = gAppData->xreDirectory;
  775. }
  776. else {
  777. // We didn't get started through XRE_Main, probably
  778. nsCOMPtr<nsIFile> greDir;
  779. NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(greDir));
  780. if (!greDir)
  781. return NS_ERROR_FAILURE;
  782. xreDirectory = do_QueryInterface(greDir);
  783. if (!xreDirectory)
  784. return NS_ERROR_FAILURE;
  785. }
  786. return CrashReporter::SetExceptionHandler(xreDirectory, true);
  787. }
  788. else {
  789. if (!CrashReporter::GetEnabled())
  790. // no point in erroring for double-disabling
  791. return NS_OK;
  792. return CrashReporter::UnsetExceptionHandler();
  793. }
  794. }
  795. NS_IMETHODIMP
  796. nsXULAppInfo::GetServerURL(nsIURL** aServerURL)
  797. {
  798. if (!CrashReporter::GetEnabled())
  799. return NS_ERROR_NOT_INITIALIZED;
  800. nsCAutoString data;
  801. if (!CrashReporter::GetServerURL(data)) {
  802. return NS_ERROR_FAILURE;
  803. }
  804. nsCOMPtr<nsIURI> uri;
  805. NS_NewURI(getter_AddRefs(uri), data);
  806. if (!uri)
  807. return NS_ERROR_FAILURE;
  808. nsCOMPtr<nsIURL> url;
  809. url = do_QueryInterface(uri);
  810. NS_ADDREF(*aServerURL = url);
  811. return NS_OK;
  812. }
  813. NS_IMETHODIMP
  814. nsXULAppInfo::SetServerURL(nsIURL* aServerURL)
  815. {
  816. bool schemeOk;
  817. // only allow https or http URLs
  818. nsresult rv = aServerURL->SchemeIs("https", &schemeOk);
  819. NS_ENSURE_SUCCESS(rv, rv);
  820. if (!schemeOk) {
  821. rv = aServerURL->SchemeIs("http", &schemeOk);
  822. NS_ENSURE_SUCCESS(rv, rv);
  823. if (!schemeOk)
  824. return NS_ERROR_INVALID_ARG;
  825. }
  826. nsCAutoString spec;
  827. rv = aServerURL->GetSpec(spec);
  828. NS_ENSURE_SUCCESS(rv, rv);
  829. return CrashReporter::SetServerURL(spec);
  830. }
  831. NS_IMETHODIMP
  832. nsXULAppInfo::GetMinidumpPath(nsILocalFile** aMinidumpPath)
  833. {
  834. if (!CrashReporter::GetEnabled())
  835. return NS_ERROR_NOT_INITIALIZED;
  836. nsAutoString path;
  837. if (!CrashReporter::GetMinidumpPath(path))
  838. return NS_ERROR_FAILURE;
  839. nsresult rv = NS_NewLocalFile(path, false, aMinidumpPath);
  840. NS_ENSURE_SUCCESS(rv, rv);
  841. return NS_OK;
  842. }
  843. NS_IMETHODIMP
  844. nsXULAppInfo::SetMinidumpPath(nsILocalFile* aMinidumpPath)
  845. {
  846. nsAutoString path;
  847. nsresult rv = aMinidumpPath->GetPath(path);
  848. NS_ENSURE_SUCCESS(rv, rv);
  849. return CrashReporter::SetMinidumpPath(path);
  850. }
  851. NS_IMETHODIMP
  852. nsXULAppInfo::AnnotateCrashReport(const nsACString& key,
  853. const nsACString& data)
  854. {
  855. return CrashReporter::AnnotateCrashReport(key, data);
  856. }
  857. NS_IMETHODIMP
  858. nsXULAppInfo::AppendAppNotesToCrashReport(const nsACString& data)
  859. {
  860. return CrashReporter::AppendAppNotesToCrashReport(data);
  861. }
  862. NS_IMETHODIMP
  863. nsXULAppInfo::RegisterAppMemory(PRUint64 pointer,
  864. PRUint64 len)
  865. {
  866. return CrashReporter::RegisterAppMemory((void *)pointer, len);
  867. }
  868. NS_IMETHODIMP
  869. nsXULAppInfo::WriteMinidumpForException(void* aExceptionInfo)
  870. {
  871. #ifdef XP_WIN32
  872. return CrashReporter::WriteMinidumpForException(static_cast<EXCEPTION_POINTERS*>(aExceptionInfo));
  873. #else
  874. return NS_ERROR_NOT_IMPLEMENTED;
  875. #endif
  876. }
  877. NS_IMETHODIMP
  878. nsXULAppInfo::AppendObjCExceptionInfoToAppNotes(void* aException)
  879. {
  880. #ifdef XP_MACOSX
  881. return CrashReporter::AppendObjCExceptionInfoToAppNotes(aException);
  882. #else
  883. return NS_ERROR_NOT_IMPLEMENTED;
  884. #endif
  885. }
  886. NS_IMETHODIMP
  887. nsXULAppInfo::GetSubmitReports(bool* aEnabled)
  888. {
  889. return CrashReporter::GetSubmitReports(aEnabled);
  890. }
  891. NS_IMETHODIMP
  892. nsXULAppInfo::SetSubmitReports(bool aEnabled)
  893. {
  894. return CrashReporter::SetSubmitReports(aEnabled);
  895. }
  896. #endif
  897. static const nsXULAppInfo kAppInfo;
  898. static nsresult AppInfoConstructor(nsISupports* aOuter,
  899. REFNSIID aIID, void **aResult)
  900. {
  901. NS_ENSURE_NO_AGGREGATION(aOuter);
  902. return const_cast<nsXULAppInfo*>(&kAppInfo)->
  903. QueryInterface(aIID, aResult);
  904. }
  905. bool gLogConsoleErrors
  906. #ifdef DEBUG
  907. = true;
  908. #else
  909. = false;
  910. #endif
  911. #define NS_ENSURE_TRUE_LOG(x, ret) \
  912. PR_BEGIN_MACRO \
  913. if (NS_UNLIKELY(!(x))) { \
  914. NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \
  915. gLogConsoleErrors = true; \
  916. return ret; \
  917. } \
  918. PR_END_MACRO
  919. #define NS_ENSURE_SUCCESS_LOG(res, ret) \
  920. NS_ENSURE_TRUE_LOG(NS_SUCCEEDED(res), ret)
  921. /**
  922. * Because we're starting/stopping XPCOM several times in different scenarios,
  923. * this class is a stack-based critter that makes sure that XPCOM is shut down
  924. * during early returns.
  925. */
  926. class ScopedXPCOMStartup
  927. {
  928. public:
  929. ScopedXPCOMStartup() :
  930. mServiceManager(nsnull) { }
  931. ~ScopedXPCOMStartup();
  932. nsresult Initialize();
  933. nsresult SetWindowCreator(nsINativeAppSupport* native);
  934. static nsresult CreateAppSupport(nsISupports* aOuter, REFNSIID aIID, void** aResult);
  935. private:
  936. nsIServiceManager* mServiceManager;
  937. static nsINativeAppSupport* gNativeAppSupport;
  938. };
  939. ScopedXPCOMStartup::~ScopedXPCOMStartup()
  940. {
  941. NS_IF_RELEASE(gNativeAppSupport);
  942. if (mServiceManager) {
  943. #ifdef XP_MACOSX
  944. // On OS X, we need a pool to catch cocoa objects that are autoreleased
  945. // during teardown.
  946. mozilla::MacAutoreleasePool pool;
  947. #endif
  948. nsCOMPtr<nsIAppStartup> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID));
  949. if (appStartup)
  950. appStartup->DestroyHiddenWindow();
  951. gDirServiceProvider->DoShutdown();
  952. WriteConsoleLog();
  953. NS_ShutdownXPCOM(mServiceManager);
  954. mServiceManager = nsnull;
  955. }
  956. }
  957. // {95d89e3e-a169-41a3-8e56-719978e15b12}
  958. #define APPINFO_CID \
  959. { 0x95d89e3e, 0xa169, 0x41a3, { 0x8e, 0x56, 0x71, 0x99, 0x78, 0xe1, 0x5b, 0x12 } }
  960. // {0C4A446C-EE82-41f2-8D04-D366D2C7A7D4}
  961. static const nsCID kNativeAppSupportCID =
  962. { 0xc4a446c, 0xee82, 0x41f2, { 0x8d, 0x4, 0xd3, 0x66, 0xd2, 0xc7, 0xa7, 0xd4 } };
  963. // {5F5E59CE-27BC-47eb-9D1F-B09CA9049836}
  964. static const nsCID kProfileServiceCID =
  965. { 0x5f5e59ce, 0x27bc, 0x47eb, { 0x9d, 0x1f, 0xb0, 0x9c, 0xa9, 0x4, 0x98, 0x36 } };
  966. static already_AddRefed<nsIFactory>
  967. ProfileServiceFactoryConstructor(const mozilla::Module& module, const mozilla::Module::CIDEntry& entry)
  968. {
  969. nsCOMPtr<nsIFactory> factory;
  970. NS_NewToolkitProfileFactory(getter_AddRefs(factory));
  971. return factory.forget();
  972. }
  973. NS_DEFINE_NAMED_CID(APPINFO_CID);
  974. static const mozilla::Module::CIDEntry kXRECIDs[] = {
  975. { &kAPPINFO_CID, false, NULL, AppInfoConstructor },
  976. { &kProfileServiceCID, false, ProfileServiceFactoryConstructor, NULL },
  977. { &kNativeAppSupportCID, false, NULL, ScopedXPCOMStartup::CreateAppSupport },
  978. { NULL }
  979. };
  980. static const mozilla::Module::ContractIDEntry kXREContracts[] = {
  981. { XULAPPINFO_SERVICE_CONTRACTID, &kAPPINFO_CID },
  982. { XULRUNTIME_SERVICE_CONTRACTID, &kAPPINFO_CID },
  983. #ifdef MOZ_CRASHREPORTER
  984. { NS_CRASHREPORTER_CONTRACTID, &kAPPINFO_CID },
  985. #endif
  986. { NS_PROFILESERVICE_CONTRACTID, &kProfileServiceCID },
  987. { NS_NATIVEAPPSUPPORT_CONTRACTID, &kNativeAppSupportCID },
  988. { NULL }
  989. };
  990. static const mozilla::Module kXREModule = {
  991. mozilla::Module::kVersion,
  992. kXRECIDs,
  993. kXREContracts
  994. };
  995. NSMODULE_DEFN(Apprunner) = &kXREModule;
  996. nsresult
  997. ScopedXPCOMStartup::Initialize()
  998. {
  999. NS_ASSERTION(gDirServiceProvider, "Should not get here!");
  1000. nsresult rv;
  1001. rv = NS_InitXPCOM2(&mServiceManager, gDirServiceProvider->GetAppDir(),
  1002. gDirServiceProvider);
  1003. if (NS_FAILED(rv)) {
  1004. NS_ERROR("Couldn't start xpcom!");
  1005. mServiceManager = nsnull;
  1006. }
  1007. else {
  1008. nsCOMPtr<nsIComponentRegistrar> reg =
  1009. do_QueryInterface(mServiceManager);
  1010. NS_ASSERTION(reg, "Service Manager doesn't QI to Registrar.");
  1011. }
  1012. return rv;
  1013. }
  1014. /**
  1015. * This is a little factory class that serves as a singleton-service-factory
  1016. * for the nativeappsupport object.
  1017. */
  1018. class nsSingletonFactory : public nsIFactory
  1019. {
  1020. public:
  1021. NS_DECL_ISUPPORTS
  1022. NS_DECL_NSIFACTORY
  1023. nsSingletonFactory(nsISupports* aSingleton);
  1024. ~nsSingletonFactory() { }
  1025. private:
  1026. nsCOMPtr<nsISupports> mSingleton;
  1027. };
  1028. nsSingletonFactory::nsSingletonFactory(nsISupports* aSingleton)
  1029. : mSingleton(aSingleton)
  1030. {
  1031. NS_ASSERTION(mSingleton, "Singleton was null!");
  1032. }
  1033. NS_IMPL_ISUPPORTS1(nsSingletonFactory, nsIFactory)
  1034. NS_IMETHODIMP
  1035. nsSingletonFactory::CreateInstance(nsISupports* aOuter,
  1036. const nsIID& aIID,
  1037. void* *aResult)
  1038. {
  1039. NS_ENSURE_NO_AGGREGATION(aOuter);
  1040. return mSingleton->QueryInterface(aIID, aResult);
  1041. }
  1042. NS_IMETHODIMP
  1043. nsSingletonFactory::LockFactory(bool)
  1044. {
  1045. return NS_OK;
  1046. }
  1047. /**
  1048. * Set our windowcreator on the WindowWatcher service.
  1049. */
  1050. nsresult
  1051. ScopedXPCOMStartup::SetWindowCreator(nsINativeAppSupport* native)
  1052. {
  1053. NS_TIME_FUNCTION;
  1054. nsresult rv;
  1055. NS_IF_ADDREF(gNativeAppSupport = native);
  1056. // Inform the chrome registry about OS accessibility
  1057. nsCOMPtr<nsIToolkitChromeRegistry> cr =
  1058. mozilla::services::GetToolkitChromeRegistryService();
  1059. NS_TIME_FUNCTION_MARK("Got ToolkitChromeRegistry service");
  1060. if (cr)
  1061. cr->CheckForOSAccessibility();
  1062. NS_TIME_FUNCTION_MARK("OS Accessibility check");
  1063. nsCOMPtr<nsIWindowCreator> creator (do_GetService(NS_APPSTARTUP_CONTRACTID));
  1064. if (!creator) return NS_ERROR_UNEXPECTED;
  1065. NS_TIME_FUNCTION_MARK("Got AppStartup service");
  1066. nsCOMPtr<nsIWindowWatcher> wwatch
  1067. (do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
  1068. NS_ENSURE_SUCCESS(rv, rv);
  1069. NS_TIME_FUNCTION_MARK("Got WindowWatcher service");
  1070. return wwatch->SetWindowCreator(creator);
  1071. }
  1072. /* static */ nsresult
  1073. ScopedXPCOMStartup::CreateAppSupport(nsISupports* aOuter, REFNSIID aIID, void** aResult)
  1074. {
  1075. if (aOuter)
  1076. return NS_ERROR_NO_AGGREGATION;
  1077. if (!gNativeAppSupport)
  1078. return NS_ERROR_NOT_INITIALIZED;
  1079. return gNativeAppSupport->QueryInterface(aIID, aResult);
  1080. }
  1081. nsINativeAppSupport* ScopedXPCOMStartup::gNativeAppSupport;
  1082. /**
  1083. * A helper class which calls NS_LogInit/NS_LogTerm in its scope.
  1084. */
  1085. class ScopedLogging
  1086. {
  1087. public:
  1088. ScopedLogging() { NS_LogInit(); }
  1089. ~ScopedLogging() { NS_LogTerm(); }
  1090. };
  1091. static void DumpArbitraryHelp()
  1092. {
  1093. nsresult rv;
  1094. ScopedLogging log;
  1095. {
  1096. ScopedXPCOMStartup xpcom;
  1097. xpcom.Initialize();
  1098. nsCOMPtr<nsICommandLineRunner> cmdline
  1099. (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
  1100. if (!cmdline)
  1101. return;
  1102. nsCString text;
  1103. rv = cmdline->GetHelpText(text);
  1104. if (NS_SUCCEEDED(rv))
  1105. printf("%s", text.get());
  1106. }
  1107. }
  1108. // English text needs to go into a dtd file.
  1109. // But when this is called we have no components etc. These strings must either be
  1110. // here, or in a native resource file.
  1111. static void
  1112. DumpHelp()
  1113. {
  1114. printf("Usage: %s [ options ... ] [URL]\n"
  1115. " where options include:\n\n", gArgv[0]);
  1116. #ifdef MOZ_X11
  1117. printf("X11 options\n"
  1118. " --display=DISPLAY X display to use\n"
  1119. " --sync Make X calls synchronous\n");
  1120. #endif
  1121. #ifdef XP_UNIX
  1122. printf(" --g-fatal-warnings Make all warnings fatal\n"
  1123. "\n%s options\n", gAppData->name);
  1124. #endif
  1125. printf(" -h or -help Print this message.\n"
  1126. " -v or -version Print %s version.\n"
  1127. " -P <profile> Start with <profile>.\n"
  1128. " -migration Start with migration wizard.\n"
  1129. " -ProfileManager Start with ProfileManager.\n"
  1130. " -no-remote Do not accept or send remote commands; implies -new-instance.\n"
  1131. " -new-instance Open new instance, not a new window in running instance.\n"
  1132. " -UILocale <locale> Start with <locale> resources as UI Locale.\n"
  1133. " -safe-mode Disables extensions and themes for this session.\n", gAppData->name);
  1134. #if defined(XP_WIN) || defined(XP_OS2)
  1135. printf(" -console Start %s with a debugging console.\n", gAppData->name);
  1136. #endif
  1137. // this works, but only after the components have registered. so if you drop in a new command line handler, -help
  1138. // won't not until the second run.
  1139. // out of the bug, because we ship a component.reg file, it works correctly.
  1140. DumpArbitraryHelp();
  1141. }
  1142. #ifdef DEBUG_warren
  1143. #ifdef XP_WIN
  1144. #define _CRTDBG_MAP_ALLOC
  1145. #include <crtdbg.h>
  1146. #endif
  1147. #endif
  1148. #if defined(FREEBSD)
  1149. // pick up fpsetmask prototype.
  1150. #include <ieeefp.h>
  1151. #endif
  1152. static inline void
  1153. DumpVersion()
  1154. {
  1155. printf("%s %s %s",
  1156. gAppData->vendor ? gAppData->vendor : "", gAppData->name, gAppData->version);
  1157. if (gAppData->copyright)
  1158. printf(", %s", gAppData->copyright);
  1159. printf("\n");
  1160. }
  1161. #ifdef MOZ_ENABLE_XREMOTE
  1162. // use int here instead of a PR type since it will be returned
  1163. // from main - just to keep types consistent
  1164. static int
  1165. HandleRemoteArgument(const char* remote, const char* aDesktopStartupID)
  1166. {
  1167. nsresult rv;
  1168. ArgResult ar;
  1169. const char *profile = 0;
  1170. nsCAutoString program(gAppData->name);
  1171. ToLowerCase(program);
  1172. const char *username = getenv("LOGNAME");
  1173. ar = CheckArg("p", false, &profile);
  1174. if (ar == ARG_BAD) {
  1175. PR_fprintf(PR_STDERR, "Error: argument -p requires a profile name\n");
  1176. return 1;
  1177. }
  1178. const char *temp = nsnull;
  1179. ar = CheckArg("a", false, &temp);
  1180. if (ar == ARG_BAD) {
  1181. PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
  1182. return 1;
  1183. } else if (ar == ARG_FOUND) {
  1184. program.Assign(temp);
  1185. }
  1186. ar = CheckArg("u", false, &username);
  1187. if (ar == ARG_BAD) {
  1188. PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
  1189. return 1;
  1190. }
  1191. XRemoteClient client;
  1192. rv = client.Init();
  1193. if (NS_FAILED(rv)) {
  1194. PR_fprintf(PR_STDERR, "Error: Failed to connect to X server.\n");
  1195. return 1;
  1196. }
  1197. nsXPIDLCString response;
  1198. bool success = false;
  1199. rv = client.SendCommand(program.get(), username, profile, remote,
  1200. aDesktopStartupID, getter_Copies(response), &success);
  1201. // did the command fail?
  1202. if (NS_FAILED(rv)) {
  1203. PR_fprintf(PR_STDERR, "Error: Failed to send command: %s\n",
  1204. response ? response.get() : "No response included");
  1205. return 1;
  1206. }
  1207. if (!success) {
  1208. PR_fprintf(PR_STDERR, "Error: No running window found\n");
  1209. return 2;
  1210. }
  1211. return 0;
  1212. }
  1213. static RemoteResult
  1214. RemoteCommandLine(const char* aDesktopStartupID)
  1215. {
  1216. nsresult rv;
  1217. ArgResult ar;
  1218. nsCAutoString program(gAppData->name);
  1219. ToLowerCase(program);
  1220. const char *username = getenv("LOGNAME");
  1221. const char *temp = nsnull;
  1222. ar = CheckArg("a", true, &temp);
  1223. if (ar == ARG_BAD) {
  1224. PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
  1225. return REMOTE_ARG_BAD;
  1226. } else if (ar == ARG_FOUND) {
  1227. program.Assign(temp);
  1228. }
  1229. ar = CheckArg("u", true, &username);
  1230. if (ar == ARG_BAD) {
  1231. PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
  1232. return REMOTE_ARG_BAD;
  1233. }
  1234. XRemoteClient client;
  1235. rv = client.Init();
  1236. if (NS_FAILED(rv))
  1237. return REMOTE_NOT_FOUND;
  1238. nsXPIDLCString response;
  1239. bool success = false;
  1240. rv = client.SendCommandLine(program.get(), username, nsnull,
  1241. gArgc, gArgv, aDesktopStartupID,
  1242. getter_Copies(response), &success);
  1243. // did the command fail?
  1244. if (NS_FAILED(rv) || !success)
  1245. return REMOTE_NOT_FOUND;
  1246. return REMOTE_FOUND;
  1247. }
  1248. #endif // MOZ_ENABLE_XREMOTE
  1249. void
  1250. XRE_InitOmnijar(nsILocalFile* greOmni, nsILocalFile* appOmni)
  1251. {
  1252. mozilla::Omnijar::Init(greOmni, appOmni);
  1253. }
  1254. nsresult
  1255. XRE_GetBinaryPath(const char* argv0, nsILocalFile* *aResult)
  1256. {
  1257. return mozilla::BinaryPath::GetFile(argv0, aResult);
  1258. }
  1259. #define NS_ERROR_LAUNCHED_CHILD_PROCESS NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_PROFILE, 200)
  1260. #ifdef XP_WIN
  1261. #include "nsWindowsRestart.cpp"
  1262. #include <shellapi.h>
  1263. typedef BOOL (WINAPI* SetProcessDEPPolicyFunc)(DWORD dwFlags);
  1264. #endif
  1265. #if defined(XP_OS2) && (__KLIBC__ == 0 && __KLIBC_MINOR__ >= 6) // broken kLibc
  1266. // Copy the environment maintained by the C library into an ASCIIZ array
  1267. // that can be used to pass it on to the OS/2 Dos* APIs (which otherwise
  1268. // don't know anything about the stuff set by PR_SetEnv() or setenv()).
  1269. char *createEnv()
  1270. {
  1271. // just allocate the maximum amount (24 kB = 0x60000 bytes), to be able to
  1272. // copy the existing environment
  1273. char *env = (char *)calloc(0x6000, sizeof(char));
  1274. if (!env) {
  1275. return NULL;
  1276. }
  1277. // walk along the environ string array of the C library and copy
  1278. // everything (that fits) into the output environment array, leaving
  1279. // null bytes between the entries
  1280. char *penv = env; // movable pointer to result environment ASCIIZ array
  1281. int i = 0, space = 0x6000;
  1282. while (environ[i] && environ[i][0]) {
  1283. int len = strlen(environ[i]);
  1284. if (space - len <= 0) {
  1285. break;
  1286. }
  1287. strcpy(penv, environ[i]);
  1288. i++; // next environment variable
  1289. penv += len + 1; // jump to after next null byte
  1290. space -= len - 1; // subtract consumed length from usable space
  1291. }
  1292. return env;
  1293. }
  1294. // OS2LaunchChild() is there to replace _execv() which is broken in the C
  1295. // runtime library that comes with GCC 3.3.5 on OS/2. It uses createEnv()
  1296. // to copy the process environment and add necessary variables
  1297. //
  1298. // returns -1 on failure and 0 on success
  1299. int OS2LaunchChild(const char *aExePath, int aArgc, char **aArgv)
  1300. {
  1301. // find total length of aArgv
  1302. int len = 0;
  1303. for (int i = 0; i < aArgc; i++) {
  1304. len += strlen(aArgv[i]) + 1; // plus space in between
  1305. }
  1306. len++; // leave space for null byte at end
  1307. // allocate enough space for all strings and nulls,
  1308. // calloc helpfully initializes to null
  1309. char *args = (char *)calloc(len, sizeof(char));
  1310. if (!args) {
  1311. return -1;
  1312. }
  1313. char *pargs = args; // extra pointer to after the last argument
  1314. // build argument list in the format the DosStartSession() wants,
  1315. // adding spaces between the arguments
  1316. for (int i = 0; i < aArgc; i++, *pargs++ = ' ') {
  1317. strcpy(pargs, aArgv[i]);
  1318. pargs += strlen(aArgv[i]);
  1319. }
  1320. if (aArgc > 1) {
  1321. *(pargs-1) = '\0'; // replace last space
  1322. }
  1323. *pargs = '\0';
  1324. // make sure that the program is separated by null byte
  1325. pargs = strchr(args, ' ');
  1326. if (pargs) {
  1327. *pargs = '\0';
  1328. }
  1329. char *env = createEnv();
  1330. char error[CCHMAXPATH] = { 0 };
  1331. RESULTCODES crc = { 0 };
  1332. ULONG rc = DosExecPgm(error, sizeof(error), EXEC_ASYNC, args, env,
  1333. &crc, (PSZ)aExePath);
  1334. free(args); // done with the arguments
  1335. if (env) {
  1336. free(env);
  1337. }
  1338. if (rc != NO_ERROR) {
  1339. return -1;
  1340. }
  1341. return 0;
  1342. }
  1343. #endif
  1344. // If aBlankCommandLine is true, then the application will be launched with a
  1345. // blank command line instead of being launched with the same command line that
  1346. // it was initially started with.
  1347. static nsresult LaunchChild(nsINativeAppSupport* aNative,
  1348. bool aBlankCommandLine = false)
  1349. {
  1350. aNative->Quit(); // release DDE mutex, if we're holding it
  1351. // Restart this process by exec'ing it into the current process
  1352. // if supported by the platform. Otherwise, use NSPR.
  1353. #ifdef MOZ_JPROF
  1354. // make sure JPROF doesn't think we're E10s
  1355. unsetenv("JPROF_SLAVE");
  1356. #endif
  1357. if (aBlankCommandLine) {
  1358. #if defined(MOZ_WIDGET_QT)
  1359. // Remove only arguments not given to Qt
  1360. gRestartArgc = gQtOnlyArgc;
  1361. gRestartArgv = gQtOnlyArgv;
  1362. #else
  1363. gRestartArgc = 1;
  1364. gRestartArgv[gRestartArgc] = nsnull;
  1365. #endif
  1366. }
  1367. SaveToEnv("MOZ_LAUNCHED_CHILD=1");
  1368. #if defined(MOZ_WIDGET_ANDROID)
  1369. mozilla::AndroidBridge::Bridge()->ScheduleRestart();
  1370. #else
  1371. #if defined(XP_MACOSX)
  1372. CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
  1373. PRUint32 restartMode = 0;
  1374. restartMode = gRestartMode;
  1375. LaunchChildMac(gRestartArgc, gRestartArgv, restartMode);
  1376. #else
  1377. nsCOMPtr<nsILocalFile> lf;
  1378. nsresult rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
  1379. if (NS_FAILED(rv))
  1380. return rv;
  1381. #if defined(XP_WIN)
  1382. nsAutoString exePath;
  1383. rv = lf->GetPath(exePath);
  1384. if (NS_FAILED(rv))
  1385. return rv;
  1386. if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv))
  1387. return NS_ERROR_FAILURE;
  1388. #else
  1389. nsCAutoString exePath;
  1390. rv = lf->GetNativePath(exePath);
  1391. if (NS_FAILED(rv))
  1392. return rv;
  1393. #if defined(XP_OS2) && (__KLIBC__ == 0 && __KLIBC_MINOR__ >= 6)
  1394. // implementation of _execv() is broken with kLibc 0.6.x and later
  1395. if (OS2LaunchChild(exePath.get(), gRestartArgc, gRestartArgv) == -1)
  1396. return NS_ERROR_FAILURE;
  1397. #elif defined(XP_OS2)
  1398. if (_execv(exePath.get(), gRestartArgv) == -1)
  1399. return NS_ERROR_FAILURE;
  1400. #elif defined(XP_UNIX)
  1401. if (execv(exePath.get(), gRestartArgv) == -1)
  1402. return NS_ERROR_FAILURE;
  1403. #else
  1404. PRProcess* process = PR_CreateProcess(exePath.get(), gRestartArgv,
  1405. nsnull, nsnull);
  1406. if (!process) return NS_ERROR_FAILURE;
  1407. PRInt32 exitCode;
  1408. PRStatus failed = PR_WaitProcess(process, &exitCode);
  1409. if (failed || exitCode)
  1410. return NS_ERROR_FAILURE;
  1411. #endif // XP_OS2 series
  1412. #endif // WP_WIN
  1413. #endif // WP_MACOSX
  1414. #endif // MOZ_WIDGET_ANDROID
  1415. return NS_ERROR_LAUNCHED_CHILD_PROCESS;
  1416. }
  1417. static const char kProfileProperties[] =
  1418. "chrome://mozapps/locale/profile/profileSelection.properties";
  1419. static nsresult
  1420. ProfileLockedDialog(nsILocalFile* aProfileDir, nsILocalFile* aProfileLocalDir,
  1421. nsIProfileUnlocker* aUnlocker,
  1422. nsINativeAppSupport* aNative, nsIProfileLock* *aResult)
  1423. {
  1424. nsresult rv;
  1425. ScopedXPCOMStartup xpcom;
  1426. rv = xpcom.Initialize();
  1427. NS_ENSURE_SUCCESS(rv, rv);
  1428. rv = xpcom.SetWindowCreator(aNative);
  1429. NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  1430. { //extra scoping is needed so we release these components before xpcom shutdown
  1431. nsCOMPtr<nsIStringBundleService> sbs =
  1432. mozilla::services::GetStringBundleService();
  1433. NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE);
  1434. nsCOMPtr<nsIStringBundle> sb;
  1435. sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
  1436. NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE);
  1437. NS_ConvertUTF8toUTF16 appName(gAppData->name);
  1438. const PRUnichar* params[] = {appName.get(), appName.get()};
  1439. nsXPIDLString killMessage;
  1440. #ifndef XP_MACOSX
  1441. static const PRUnichar kRestartNoUnlocker[] = {'r','e','s','t','a','r','t','M','e','s','s','a','g','e','N','o','U','n','l','o','c','k','e','r','\0'}; // "restartMessageNoUnlocker"
  1442. static const PRUnichar kRestartUnlocker[] = {'r','e','s','t','a','r','t','M','e','s','s','a','g','e','U','n','l','o','c','k','e','r','\0'}; // "restartMessageUnlocker"
  1443. #else
  1444. static const PRUnichar kRestartNoUnlocker[] = {'r','e','s','t','a','r','t','M','e','s','s','a','g','e','N','o','U','n','l','o','c','k','e','r','M','a','c','\0'}; // "restartMessageNoUnlockerMac"
  1445. static const PRUnichar kRestartUnlocker[] = {'r','e','s','t','a','r','t','M','e','s','s','a','g','e','U','n','l','o','c','k','e','r','M','a','c','\0'}; // "restartMessageUnlockerMac"
  1446. #endif
  1447. sb->FormatStringFromName(aUnlocker ? kRestartUnlocker : kRestartNoUnlocker,
  1448. params, 2, getter_Copies(killMessage));
  1449. nsXPIDLString killTitle;
  1450. sb->FormatStringFromName(NS_LITERAL_STRING("restartTitle").get(),
  1451. params, 1, getter_Copies(killTitle));
  1452. if (!killMessage || !killTitle)
  1453. return NS_ERROR_FAILURE;
  1454. nsCOMPtr<nsIPromptService> ps
  1455. (do_GetService(NS_PROMPTSERVICE_CONTRACTID));
  1456. NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE);
  1457. if (aUnlocker) {
  1458. const PRUint32 flags =
  1459. (nsIPromptService::BUTTON_TITLE_CANCEL *
  1460. nsIPromptService::BUTTON_POS_0) +
  1461. (nsIPromptService::BUTTON_TITLE_IS_STRING *
  1462. nsIPromptService::BUTTON_POS_1) +
  1463. nsIPromptService::BUTTON_POS_1_DEFAULT;
  1464. PRInt32 button;
  1465. // The actual value is irrelevant but we shouldn't be handing out
  1466. // malformed JSBools to XPConnect.
  1467. bool checkState = false;
  1468. rv = ps->ConfirmEx(nsnull, killTitle, killMessage, flags,
  1469. killTitle, nsnull, nsnull, nsnull,
  1470. &checkState, &button);
  1471. NS_ENSURE_SUCCESS_LOG(rv, rv);
  1472. if (button == 1) {
  1473. rv = aUnlocker->Unlock(nsIProfileUnlocker::FORCE_QUIT);
  1474. if (NS_FAILED(rv))
  1475. return rv;
  1476. return NS_LockProfilePath(aProfileDir, aProfileLocalDir,
  1477. nsnull, aResult);
  1478. }
  1479. } else {
  1480. rv = ps->Alert(nsnull, killTitle, killMessage);
  1481. NS_ENSURE_SUCCESS_LOG(rv, rv);
  1482. }
  1483. return NS_ERROR_ABORT;
  1484. }
  1485. }
  1486. static nsresult
  1487. ProfileMissingDialog(nsINativeAppSupport* aNative)
  1488. {
  1489. nsresult rv;
  1490. ScopedXPCOMStartup xpcom;
  1491. rv = xpcom.Initialize();
  1492. NS_ENSURE_SUCCESS(rv, rv);
  1493. rv = xpcom.SetWindowCreator(aNative);
  1494. NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  1495. { //extra scoping is needed so we release these components before xpcom shutdown
  1496. nsCOMPtr<nsIStringBundleService> sbs =
  1497. mozilla::services::GetStringBundleService();
  1498. NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE);
  1499. nsCOMPtr<nsIStringBundle> sb;
  1500. sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
  1501. NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE);
  1502. NS_ConvertUTF8toUTF16 appName(gAppData->name);
  1503. const PRUnichar* params[] = {appName.get(), appName.get()};
  1504. nsXPIDLString missingMessage;
  1505. // profileMissing
  1506. static const PRUnichar kMissing[] = {'p','r','o','f','i','l','e','M','i','s','s','i','n','g','\0'};
  1507. sb->FormatStringFromName(kMissing, params, 2, getter_Copies(missingMessage));
  1508. nsXPIDLString missingTitle;
  1509. sb->FormatStringFromName(NS_LITERAL_STRING("profileMissingTitle").get(),
  1510. params, 1, getter_Copies(missingTitle));
  1511. if (missingMessage && missingTitle) {
  1512. nsCOMPtr<nsIPromptService> ps
  1513. (do_GetService(NS_PROMPTSERVICE_CONTRACTID));
  1514. NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE);
  1515. ps->Alert(nsnull, missingTitle, missingMessage);
  1516. }
  1517. return NS_ERROR_ABORT;
  1518. }
  1519. }
  1520. static const char kProfileManagerURL[] =
  1521. "chrome://mozapps/content/profile/profileSelection.xul";
  1522. static nsresult
  1523. ShowProfileManager(nsIToolkitProfileService* aProfileSvc,
  1524. nsINativeAppSupport* aNative)
  1525. {
  1526. nsresult rv;
  1527. nsCOMPtr<nsILocalFile> profD, profLD;
  1528. PRUnichar* profileNamePtr;
  1529. nsCAutoString profileName;
  1530. {
  1531. ScopedXPCOMStartup xpcom;
  1532. rv = xpcom.Initialize();
  1533. NS_ENSURE_SUCCESS(rv, rv);
  1534. rv = xpcom.SetWindowCreator(aNative);
  1535. NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  1536. #ifdef XP_MACOSX
  1537. CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
  1538. #endif
  1539. #ifdef XP_WIN
  1540. // we don't have to wait here because profile manager window will pump
  1541. // and DDE message will be handled
  1542. ProcessDDE(aNative, false);
  1543. #endif
  1544. { //extra scoping is needed so we release these components before xpcom shutdown
  1545. nsCOMPtr<nsIWindowWatcher> windowWatcher
  1546. (do_GetService(NS_WINDOWWATCHER_CONTRACTID));
  1547. nsCOMPtr<nsIDialogParamBlock> ioParamBlock
  1548. (do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID));
  1549. nsCOMPtr<nsIMutableArray> dlgArray (do_CreateInstance(NS_ARRAY_CONTRACTID));
  1550. NS_ENSURE_TRUE(windowWatcher && ioParamBlock && dlgArray, NS_ERROR_FAILURE);
  1551. ioParamBlock->SetObjects(dlgArray);
  1552. nsCOMPtr<nsIAppStartup> appStartup
  1553. (do_GetService(NS_APPSTARTUP_CONTRACTID));
  1554. NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE);
  1555. nsCOMPtr<nsIDOMWindow> newWindow;
  1556. rv = windowWatcher->OpenWindow(nsnull,
  1557. kProfileManagerURL,
  1558. "_blank",
  1559. "centerscreen,chrome,modal,titlebar",
  1560. ioParamBlock,
  1561. getter_AddRefs(newWindow));