PageRenderTime 131ms CodeModel.GetById 33ms app.highlight 82ms RepoModel.GetById 1ms app.codeStats 1ms

/toolkit/xre/nsAppRunner.cpp

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

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

Large files files are truncated, but you can click here to view the full file