Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Functions
nsXULAppAPI.h File Reference
#include "prtypes.h"
#include "nsID.h"
#include "nscore.h"
#include "nsXPCOM.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  nsXREAppData
 Application-specific data needed to start the apprunner. More...

Defines

#define XULAPI
#define NS_XRE_ENABLE_PROFILE_MIGRATOR   (1 << 1)
 Indicates whether or not the profile migrator service may be invoked at startup when creating a profile.
#define NS_XRE_ENABLE_EXTENSION_MANAGER   (1 << 2)
 Indicates whether or not the extension manager service should be initialized at startup.
#define XULAPPINFO_SERVICE_CONTRACTID   "@mozilla.org/xre/app-info;1"
 The contract id for the nsIXULAppInfo service.
#define XRE_USER_APP_DATA_DIR   "UAppData"
 A directory service key which provides the platform-correct "application data" directory.
#define XRE_EXTENSIONS_DIR_LIST   "XREExtDL"
 A directory service key which provides a list of all enabled extension directories.
#define XRE_EXECUTABLE_FILE   "XREExeF"
 A directory service key which provides the executable file used to launch the current process.

Functions

XULAPI int XRE_main (int argc, char *argv[], const nsXREAppData *aAppData)
 Begin an XUL application.
XULAPI nsresult XRE_GetFileFromPath (const char *aPath, nsILocalFile **aResult)
 Given a path relative to the current working directory (or an absolute path), return an appropriate nsILocalFile object.
XULAPI nsresult XRE_GetBinaryPath (const char *argv0, nsILocalFile **aResult)
 Get the path of the running application binary and store it in aResult.
XULAPI void XRE_GetStaticComponents (nsStaticModuleInfo const **aStaticComponents, PRUint32 *aComponentCount)
 Get the static components built in to libxul.
XULAPI nsresult XRE_InitEmbedding (nsILocalFile *aLibXULDirectory, nsILocalFile *aAppDirectory, nsIDirectoryServiceProvider *aAppDirProvider=nsnull, nsStaticModuleInfo const *aStaticComponents=nsnull, PRUint32 aStaticComponentCount=0)
 Initialize libXUL for embedding purposes.
XULAPI void XRE_TermEmbedding ()

Class Documentation

struct nsXREAppData

Application-specific data needed to start the apprunner.

UNDER_REVIEW - This API is under review to be frozen, but isn't frozen yet. Use with caution.

Definition at line 68 of file nsXULAppAPI.h.

Collaboration diagram for nsXREAppData:
Class Members
const char * buildID The application's build identifier, e.g. "2004051604"
const char * copyright The copyright information to print for the -h commandline flag, e.g. "Copyright (c) 2003 mozilla.org".
nsILocalFile * directory The directory of the application to be run. May be null if the xulrunner and the app are installed into the same directory.
PRUint32 flags Combination of NS_XRE_ prefixed flags (defined below).
const char * ID The application's UUID. Used by the extension manager to determine compatible extensions. Optional, but required for advanced application features such as the extension manager and update service.This has traditionally been in the form "{AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE}" but for new applications a more readable form is encouraged: "appname@vendor.tld". Only the following characters are allowed: a-z A-Z 0-9 - . @ _ { } *
const char * name The name of the application. This must be ASCII, and is normally mixed-case, e.g. "Firefox". Required (must not be null or an empty string).
PRUint32 size This should be set to sizeof(nsXREAppData). This structure may be extended in future releases, and this ensures that binary compatibility is maintained.
const char * vendor The name of the application vendor. This must be ASCII, and is normally mixed-case, e.g. "Mozilla". Optional (may be null), but highly recommended. Must not be the empty string.
const char * version The major version, e.g. "0.8.0+". Optional (may be null), but required for advanced application features such as the extension manager and update service. Must not be the empty string.

Define Documentation

Indicates whether or not the extension manager service should be initialized at startup.

Definition at line 143 of file nsXULAppAPI.h.

Indicates whether or not the profile migrator service may be invoked at startup when creating a profile.

Definition at line 137 of file nsXULAppAPI.h.

#define XRE_EXECUTABLE_FILE   "XREExeF"

A directory service key which provides the executable file used to launch the current process.

This is the same value returned by the XRE_GetBinaryPath function defined below.

Definition at line 175 of file nsXULAppAPI.h.

#define XRE_EXTENSIONS_DIR_LIST   "XREExtDL"

A directory service key which provides a list of all enabled extension directories.

The list includes compatible platform-specific extension subdirectories.

Note:
The directory list will have no members when the application is launched in safe mode.

Definition at line 168 of file nsXULAppAPI.h.

#define XRE_USER_APP_DATA_DIR   "UAppData"

A directory service key which provides the platform-correct "application data" directory.

Windows: Documents and Settings<User> Data<Vendor><Application> Unix: ~/.<vendor>/<application> Mac: ~/Library/Application Supports/<Application>

Definition at line 158 of file nsXULAppAPI.h.

Definition at line 59 of file nsXULAppAPI.h.

#define XULAPPINFO_SERVICE_CONTRACTID   "@mozilla.org/xre/app-info;1"

The contract id for the nsIXULAppInfo service.

Definition at line 148 of file nsXULAppAPI.h.


Function Documentation

XULAPI nsresult XRE_GetBinaryPath ( const char *  argv0,
nsILocalFile **  aResult 
)

Get the path of the running application binary and store it in aResult.

Parameters:
argv0The value passed as argv[0] of main(). This value is only used on *nix, and only when other methods of determining the binary path have failed.

Definition at line 1236 of file nsAppRunner.cpp.

{
  nsresult rv;
  nsCOMPtr<nsILocalFile> lf;

  // We need to use platform-specific hackery to find the
  // path of this executable. This is copied, with some modifications, from
  // nsGREDirServiceProvider.cpp

#ifdef XP_WIN
  char exePath[MAXPATHLEN];

  if (!::GetModuleFileName(0, exePath, MAXPATHLEN))
    return NS_ERROR_FAILURE;

  rv = NS_NewNativeLocalFile(nsDependentCString(exePath), PR_TRUE,
                             getter_AddRefs(lf));
  if (NS_FAILED(rv))
    return rv;

#elif defined(XP_MACOSX)
  if (gBinaryPath)
    return NS_NewNativeLocalFile(nsDependentCString(gBinaryPath), PR_FALSE,
                                 aResult);

  NS_NewNativeLocalFile(EmptyCString(), PR_TRUE, getter_AddRefs(lf));
  nsCOMPtr<nsILocalFileMac> lfm (do_QueryInterface(lf));
  if (!lfm)
    return NS_ERROR_FAILURE;

  // Works even if we're not bundled.
  CFBundleRef appBundle = CFBundleGetMainBundle();
  if (!appBundle)
    return NS_ERROR_FAILURE;

  CFURLRef bundleURL = CFBundleCopyExecutableURL(appBundle);
  if (!bundleURL)
    return NS_ERROR_FAILURE;

  FSRef fileRef;
  if (!CFURLGetFSRef(bundleURL, &fileRef)) {
    CFRelease(bundleURL);
    return NS_ERROR_FAILURE;
  }

  rv = lfm->InitWithFSRef(&fileRef);
  CFRelease(bundleURL);

  if (NS_FAILED(rv))
    return rv;

#elif defined(XP_UNIX)
  struct stat fileStat;
  char exePath[MAXPATHLEN];
  char tmpPath[MAXPATHLEN];

  rv = NS_ERROR_FAILURE;

  // on unix, there is no official way to get the path of the current binary.
  // instead of using the MOZILLA_FIVE_HOME hack, which doesn't scale to
  // multiple applications, we will try a series of techniques:
  //
  // 1) look for /proc/<pid>/exe which is a symlink to the executable on newer
  //    Linux kernels
  // 2) use realpath() on argv[0], which works unless we're loaded from the
  //    PATH
  // 3) manually walk through the PATH and look for ourself
  // 4) give up

// #ifdef __linux__
#if 0
  int r = readlink("/proc/self/exe", exePath, MAXPATHLEN);

  // apparently, /proc/self/exe can sometimes return weird data... check it
  if (r > 0 && r < MAXPATHLEN && stat(exePath, &fileStat) == 0) {
    rv = NS_OK;
  }

#endif
  if (NS_FAILED(rv) &&
      realpath(argv0, exePath) && stat(exePath, &fileStat) == 0) {
    rv = NS_OK;
  }

  if (NS_FAILED(rv)) {
    const char *path = getenv("PATH");
    if (!path)
      return NS_ERROR_FAILURE;

    char *pathdup = strdup(path);
    if (!pathdup)
      return NS_ERROR_OUT_OF_MEMORY;

    PRBool found = PR_FALSE;
    char *newStr = pathdup;
    char *token;
    while ( (token = nsCRT::strtok(newStr, ":", &newStr)) ) {
      sprintf(tmpPath, "%s/%s", token, argv0);
      if (realpath(tmpPath, exePath) && stat(exePath, &fileStat) == 0) {
        found = PR_TRUE;
        break;
      }
    }
    free(pathdup);
    if (!found)
      return NS_ERROR_FAILURE;
  }

  rv = NS_NewNativeLocalFile(nsDependentCString(exePath), PR_TRUE,
                             getter_AddRefs(lf));
  if (NS_FAILED(rv))
    return rv;

#elif defined(XP_OS2)
  PPIB ppib;
  PTIB ptib;
  char exePath[MAXPATHLEN];

  DosGetInfoBlocks( &ptib, &ppib);
  DosQueryModuleName( ppib->pib_hmte, MAXPATHLEN, exePath);
  rv = NS_NewNativeLocalFile(nsDependentCString(exePath), PR_TRUE,
                             getter_AddRefs(lf));
  if (NS_FAILED(rv))
    return rv;

#elif defined(XP_BEOS)
  int32 cookie = 0;
  image_info info;

  if(get_next_image_info(0, &cookie, &info) != B_OK)
    return NS_ERROR_FAILURE;

  rv = NS_NewNativeLocalFile(nsDependentCString(info.name), PR_TRUE,
                             getter_AddRefs(lf));
  if (NS_FAILED(rv))
    return rv;

#elif
#error Oops, you need platform-specific code here
#endif

  NS_ADDREF(*aResult = lf);
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

XULAPI nsresult XRE_GetFileFromPath ( const char *  aPath,
nsILocalFile **  aResult 
)

Given a path relative to the current working directory (or an absolute path), return an appropriate nsILocalFile object.

Definition at line 862 of file nsToolkitProfileService.cpp.

{
#if defined(XP_MACOSX)
    PRInt32 pathLen = strlen(aPath);
    if (pathLen > MAXPATHLEN)
        return NS_ERROR_INVALID_ARG;

    CFURLRef fullPath =
        CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8 *) aPath,
                                                pathLen, true);
    if (!fullPath)
        return NS_ERROR_FAILURE;

    nsCOMPtr<nsILocalFile> lf;
    nsresult rv = NS_NewNativeLocalFile(EmptyCString(), PR_TRUE,
                                        getter_AddRefs(lf));
    if (NS_SUCCEEDED(rv)) {
        nsCOMPtr<nsILocalFileMac> lfMac = do_QueryInterface(lf, &rv);
        if (NS_SUCCEEDED(rv)) {
            rv = lfMac->InitWithCFURL(fullPath);
            if (NS_SUCCEEDED(rv))
                NS_ADDREF(*aResult = lf);
        }
    }
    CFRelease(fullPath);
    return rv;

#elif defined(XP_UNIX)
    char fullPath[MAXPATHLEN];

    if (!realpath(aPath, fullPath))
        return NS_ERROR_FAILURE;

    return NS_NewNativeLocalFile(nsDependentCString(fullPath), PR_TRUE,
                                 aResult);
#elif defined(XP_OS2)
    char fullPath[MAXPATHLEN];

    if (!realpath(aPath, fullPath))
        return NS_ERROR_FAILURE;

    // realpath on OS/2 returns a unix-ized path, so re-native-ize
    for (char* ptr = strchr(fullPath, '/'); ptr; ptr = strchr(ptr, '/'))
        *ptr = '\\';

    return NS_NewNativeLocalFile(nsDependentCString(fullPath), PR_TRUE,
                                 aResult);

#elif defined(XP_WIN)
    char fullPath[MAXPATHLEN];

    if (!_fullpath(fullPath, aPath, MAXPATHLEN))
        return NS_ERROR_FAILURE;

    return NS_NewNativeLocalFile(nsDependentCString(fullPath), PR_TRUE,
                                 aResult);

#elif defined(XP_BEOS)
    BPath fullPath;
    if (fullPath.SetTo(aPath, NULL, true))
        return NS_ERROR_FAILURE;

    return NS_NewNativeLocalFile(nsDependentCString(fullPath.Leaf()), PR_TRUE,
                                 aResult);

#else
#error Platform-specific logic needed here.
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

XULAPI void XRE_GetStaticComponents ( nsStaticModuleInfo const **  aStaticComponents,
PRUint32 aComponentCount 
)

Get the static components built in to libxul.

Definition at line 175 of file nsEmbedFunctions.cpp.

{
  *aStaticComponents = kPStaticModules;
  *aComponentCount = kStaticModuleCount;
}

Here is the caller graph for this function:

XULAPI nsresult XRE_InitEmbedding ( nsILocalFile aLibXULDirectory,
nsILocalFile aAppDirectory,
nsIDirectoryServiceProvider aAppDirProvider = nsnull,
nsStaticModuleInfo const aStaticComponents = nsnull,
PRUint32  aStaticComponentCount = 0 
)

Initialize libXUL for embedding purposes.

Parameters:
aLibXULDirectoryThe directory in which the libXUL shared library was found.
aAppDirectoryThe directory in which the application components and resources can be found. This will map to the "resource:app" directory service key.
aAppDirProviderA directory provider for the application. This provider will be aggregated by a libxul provider which will provide the base required GRE keys.
aStaticComponentsStatic components provided by the embedding application. This should not include the components from XRE_GetStaticComponents. May be null if there are no static components.
aStaticComponentCountthe number of static components in aStaticComponents
Note:
This function must be called from the "main" thread.
At the present time, this function may only be called once in a given process. Use XRE_TermEmbedding to clean up and free resources allocated by XRE_InitEmbedding.

Definition at line 186 of file nsEmbedFunctions.cpp.

{
  if (++sInitCounter > 1)
    return NS_OK;

  NS_ENSURE_ARG(aLibXULDirectory);
  NS_ENSURE_ARG(aAppDirectory);

  nsresult rv;

  nsCOMPtr<nsIDirectoryServiceProvider> dirSvc
    (new nsEmbeddingDirProvider(aLibXULDirectory,
                                aAppDirectory,
                                aAppDirProvider));
  if (!dirSvc)
    return NS_ERROR_OUT_OF_MEMORY;

  // Combine the toolkit static components and the app components.
  PRUint32 combinedCount = kStaticModuleCount + aStaticComponentCount;

  sCombined = new nsStaticModuleInfo[combinedCount];
  if (!sCombined)
    return NS_ERROR_OUT_OF_MEMORY;

  memcpy(sCombined, kPStaticModules,
         sizeof(nsStaticModuleInfo) * kStaticModuleCount);
  memcpy(sCombined + kStaticModuleCount, aStaticComponents,
         sizeof(nsStaticModuleInfo) * aStaticComponentCount);

  rv = NS_InitXPCOM3(nsnull, aAppDirectory, dirSvc,
                     sCombined, combinedCount);
  if (NS_FAILED(rv))
    return rv;

  // We do not need to autoregister components here. The CheckUpdateFile()
  // bits in NS_InitXPCOM3 check for an .autoreg file. If the app wants
  // to autoregister every time (for instance, if it's debug), it can do
  // so after we return from this function.

  nsCOMPtr<nsIEventQueueService> eventQService
    (do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv));
  if (NS_FAILED(rv))
    return rv;

  rv = eventQService->CreateThreadEventQueue();
  if (NS_FAILED(rv))
    return rv;

  nsCOMPtr<nsIObserver> startupNotifier
    (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID));
  if (!startupNotifier)
    return NS_ERROR_FAILURE;

  startupNotifier->Observe(nsnull, APPSTARTUP_TOPIC, nsnull);

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

XULAPI int XRE_main ( int  argc,
char *  argv[],
const nsXREAppData aAppData 
)

Begin an XUL application.

Does not return until the user exits the application.

Parameters:
argc/argvCommand-line parameters to pass to the application. These are in the "native" character set.
aAppDataInformation about the application to be run.
Returns:
A native result code suitable for returning from main().
Note:
If the binary is linked against the standalone XPCOM glue, XPCOMGlueStartup() should be called before this method.
XXXbsmedberg Nobody uses the glue yet, but there is a potential problem: on windows, the standalone glue calls SetCurrentDirectory, and relative paths on the command line won't be correct.

Definition at line 2204 of file nsAppRunner.cpp.

{
  nsresult rv;
  ArgResult ar;
  NS_TIMELINE_MARK("enter main");

#ifdef DEBUG
  if (PR_GetEnv("XRE_MAIN_BREAK"))
    NS_BREAK();
#endif

#ifdef XP_WIN32
  // Suppress the "DLL Foo could not be found" dialog, such that if dependent
  // libraries (such as GDI+) are not preset, we gracefully fail to load those
  // XPCOM components, instead of being ungraceful.
  SetErrorMode(SEM_FAILCRITICALERRORS);

#ifdef DEBUG
  // Disable small heap allocator to get heapwalk() giving us
  // accurate heap numbers. Win2k non-debug does not use small heap allocator.
  // Win2k debug seems to be still using it.
  // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__set_sbh_threshold.asp
  _set_sbh_threshold(0);
#endif
#endif

#if defined(XP_UNIX) || defined(XP_BEOS)
  InstallUnixSignalHandlers(argv[0]);
#endif

#ifdef MOZ_ACCESSIBILITY_ATK
  // Reset GTK_MODULES, strip atk-bridge if exists
  // Mozilla will load libatk-bridge.so later if necessary
  const char* gtkModules = PR_GetEnv("GTK_MODULES");
  if (gtkModules && *gtkModules) {
    nsCString gtkModulesStr(gtkModules);
    gtkModulesStr.ReplaceSubstring("atk-bridge", "");
    char* expr = PR_smprintf("GTK_MODULES=%s", gtkModulesStr.get());
    if (expr)
      PR_SetEnv(expr);
    // We intentionally leak |expr| here since it is required by PR_SetEnv.
  }
#endif

  // Unbuffer stdout, needed for tinderbox tests.
  setbuf(stdout, 0);

#if defined(FREEBSD)
  // Disable all SIGFPE's on FreeBSD, as it has non-IEEE-conformant fp
  // trap behavior that trips up on floating-point tests performed by
  // the JS engine.  See bugzilla bug 9967 details.
  fpsetmask(0);
#endif

  gArgc = argc;
  gArgv = argv;

  NS_ASSERTION(aAppData, "must specify XUL app data");

  // In the future when nsXREAppData is extended, this check will need to
  // have more finesse.
  if (aAppData->size < sizeof(nsXREAppData)) {
    NS_ERROR("aAppdata.size isn't set properly!");
    return 1;
  }

#ifdef XP_MACOSX
  // The xulrunner stub executable tricks CFBundleGetMainBundle on
  // purpose into lying about the main bundle path. It will set
  // XRE_BINARY_PATH to inform us of our real location.
  gBinaryPath = getenv("XRE_BINARY_PATH");

  if (gBinaryPath && !*gBinaryPath)
    gBinaryPath = nsnull;

  if (PR_GetEnv("MOZ_LAUNCHED_CHILD")) {
    // When the app relaunches, the original process exits.  This causes
    // the dock tile to stop bouncing, lose the "running" triangle, and
    // if the tile does not permanently reside in the Dock, even disappear.
    // This can be confusing to the user, who is expecting the app to launch.
    // Calling ReceiveNextEvent without requesting any event is enough to
    // cause a dock tile for the child process to appear.
    const EventTypeSpec kFakeEventList[] = { { INT_MAX, INT_MAX } };
    EventRef event;
    ::ReceiveNextEvent(GetEventTypeCount(kFakeEventList), kFakeEventList,
                       kEventDurationNoWait, PR_FALSE, &event);
  }

  if (CheckArg("foreground")) {
    // The original process communicates that it was in the foreground by
    // adding this argument.  This new process, which is taking over for
    // the old one, should make itself the active application.
    ProcessSerialNumber psn;
    if (::GetCurrentProcess(&psn) == noErr)
      ::SetFrontProcess(&psn);
  }
#endif

  PR_SetEnv("MOZ_LAUNCHED_CHILD=");

  gAppData = aAppData;

  gRestartArgc = gArgc;
  gRestartArgv = (char**) malloc(sizeof(char*) * (gArgc + 1));
  if (!gRestartArgv) return 1;

  int i;
  for (i = 0; i < gArgc; ++i) {
    gRestartArgv[i] = gArgv[i];
  }
  gRestartArgv[gArgc] = nsnull;

#if defined(XP_OS2)
  PRBool StartOS2App(int aArgc, char **aArgv);
  if (!StartOS2App(gArgc, gArgv))
    return 1;
  ScopedFPHandler handler;
#endif /* XP_OS2 */

  ar = CheckArg("safe-mode", PR_TRUE);
  if (ar == ARG_BAD) {
    PR_fprintf(PR_STDERR, "Error: argument -safe-mode is invalid when argument -osint is specified\n");
    return 1;
  } else if (ar == ARG_FOUND) {
    gSafeMode = PR_TRUE;
  }

  // Handle -no-remote command line argument. Setup the environment to
  // better accommodate other components and various restart scenarios.
  ar = CheckArg("no-remote", PR_TRUE);
  if (ar == ARG_BAD) {
    PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
    return 1;
  } else if (ar == ARG_FOUND) {
    PR_SetEnv("MOZ_NO_REMOTE=1");
  }

  // Handle -help and -version command line arguments.
  // They should return quickly, so we deal with them here.
  if (CheckArg("h") || CheckArg("help") || CheckArg("?")) {
    DumpHelp();
    return 0;
  }

  if (CheckArg("v") || CheckArg("version")) {
    DumpVersion();
    return 0;
  }
    
#ifdef NS_TRACE_MALLOC
  gArgc = argc = NS_TraceMallocStartupArgs(argc, argv);
#endif

  nsXREDirProvider dirProvider;
  {
    rv = dirProvider.Initialize(gAppData->directory);
    if (NS_FAILED(rv))
      return 1;
  }

  // Check for -register, which registers chrome and then exits immediately.

  ar = CheckArg("register", PR_TRUE);
  if (ar == ARG_BAD) {
    PR_fprintf(PR_STDERR, "Error: argument -register is invalid when argument -osint is specified\n");
    return 1;
  } else if (ar == ARG_FOUND) {
    ScopedXPCOMStartup xpcom;
    rv = xpcom.Initialize();
    NS_ENSURE_SUCCESS(rv, 1);

    {
      nsCOMPtr<nsIChromeRegistry> chromeReg
        (do_GetService("@mozilla.org/chrome/chrome-registry;1"));
      NS_ENSURE_TRUE(chromeReg, 1);

      chromeReg->CheckForNewChrome();
    }
    return 0;
  }

#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_GTK2)
  // setup for private colormap.  Ideally we'd like to do this
  // in nsAppShell::Create, but we need to get in before gtk
  // has been initialized to make sure everything is running
  // consistently.
#if defined(MOZ_WIDGET_GTK2)
  g_thread_init(NULL);
#endif
  if (CheckArg("install"))
    gdk_rgb_set_install(TRUE);

  // Initialize GTK+1/2 here for splash
#if defined(MOZ_WIDGET_GTK)
  gtk_set_locale();
#endif
  gtk_init(&gArgc, &gArgv);

#if defined(MOZ_WIDGET_GTK2)
  // g_set_application_name () is only defined in glib2.2 and higher.
  PRLibrary *glib2 = nsnull;
  _g_set_application_name_fn _g_set_application_name =
      (_g_set_application_name_fn)PR_FindFunctionSymbolAndLibrary("g_set_application_name", &glib2);
  if (_g_set_application_name) {
    _g_set_application_name(gAppData->name);
  }
  if (glib2) {
    PR_UnloadLibrary(glib2);
  }
#endif

  gtk_widget_set_default_visual(gdk_rgb_get_visual());
  gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
#endif /* MOZ_WIDGET_GTK || MOZ_WIDGET_GTK2 */

#if defined(MOZ_WIDGET_QT)
  QApplication qapp(argc, argv);
#endif

// #if defined(MOZ_WIDGET_XLIB)
// XXXtimeless fix me! How do we get a Display from here to nsAppShell.cpp ?
// #endif
    
  // Call the code to install our handler
#ifdef MOZ_JPROF
  setupProfilingStuff();
#endif

  // Try to allocate "native app support."
  nsCOMPtr<nsINativeAppSupport> nativeApp;
  rv = NS_CreateNativeAppSupport(getter_AddRefs(nativeApp));
  if (NS_FAILED(rv))
    return 1;

  PRBool canRun = PR_FALSE;
  rv = nativeApp->Start(&canRun);
  if (NS_FAILED(rv) || !canRun) {
    return 1;
  }

  //----------------------------------------------------------------
  // We need to check if a previous installation occured and
  // if so, make sure it finished and cleaned up correctly.
  //
  // If there is an xpicleanup.dat file left around, that means the
  // previous installation did not finish correctly. We must cleanup
  // before a valid mozilla can run.
  //
  // Show the user a platform-specific Alert message, then spawn the
  // xpicleanup utility, then exit.
  //----------------------------------------------------------------
  nsCOMPtr<nsIFile> registryFile;
  rv = dirProvider.GetAppDir()->Clone(getter_AddRefs(registryFile));
  if (NS_SUCCEEDED(rv)) {
    registryFile->AppendNative(CLEANUP_REGISTRY);

    PRBool exists;
    rv = registryFile->Exists(&exists);
    if (NS_SUCCEEDED(rv) && exists) {
      return VerifyInstallation(dirProvider.GetAppDir());
    }
  }

#ifdef MOZ_ENABLE_XREMOTE
  // handle -remote now that xpcom is fired up

  const char* xremotearg;
  ar = CheckArg("remote", PR_TRUE, &xremotearg);
  if (ar == ARG_BAD) {
    PR_fprintf(PR_STDERR, "Error: -remote requires an argument\n");
    return 1;
  }
  if (ar) {
    return HandleRemoteArgument(xremotearg);
  }

  if (!PR_GetEnv("MOZ_NO_REMOTE")) {
    // Try to remote the entire command line. If this fails, start up normally.
    RemoteResult rr = RemoteCommandLine();
    if (rr == REMOTE_FOUND)
      return 0;
    else if (rr == REMOTE_ARG_BAD)
      return 1;
  }
#endif

#if defined(MOZ_UPDATER)
  // If this is a XULRunner app then the updater needs to know the base
  // directory that contains the application.ini file. This should be the
  // parent of the xulrunner directory on Windows/Linux and it should be the
  // Contents directory on MacOSX. Just in case someone packaged their app
  // incorrectly we'll pass the directory here.
  nsCOMPtr<nsIFile> greDir = dirProvider.GetAppDir();
  NS_ENSURE_TRUE(greDir, 1);

  nsCOMPtr<nsIFile> appDir;
  PRBool dummy;
  rv = dirProvider.GetFile("resource:app",
                           &dummy,
                           getter_AddRefs(appDir));
  if (NS_FAILED(rv)) {
    // This must not be a XULRunner app
    appDir = greDir;
  }

  // Check for and process any available updates
  nsCOMPtr<nsIFile> updRoot;
  PRBool persistent;
  rv = dirProvider.GetFile(XRE_UPDATE_ROOT_DIR, &persistent,
                           getter_AddRefs(updRoot));
  // XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failed
  if (NS_FAILED(rv))
    updRoot = dirProvider.GetAppDir();

  // Check for and process any available updates
  ProcessUpdates(greDir,
                 appDir,
                 updRoot,
                 gRestartArgc,
                 gRestartArgv);
#endif

  nsCOMPtr<nsIProfileLock> profileLock;
  PRBool startOffline = PR_FALSE;

  rv = SelectProfile(getter_AddRefs(profileLock), nativeApp, &startOffline);
  if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ||
      rv == NS_ERROR_ABORT) return 0;
  if (NS_FAILED(rv)) return 1;

  nsCOMPtr<nsILocalFile> profD;
  rv = profileLock->GetDirectory(getter_AddRefs(profD));
  NS_ENSURE_SUCCESS(rv, 1);

  nsCOMPtr<nsILocalFile> profLD;
  rv = profileLock->GetLocalDirectory(getter_AddRefs(profLD));
  NS_ENSURE_SUCCESS(rv, 1);

  rv = dirProvider.SetProfile(profD, profLD);
  NS_ENSURE_SUCCESS(rv, 1);


  PRBool upgraded = PR_FALSE;

  nsCAutoString version;
  BuildVersion(version);

#ifdef TARGET_OS_ABI
    NS_NAMED_LITERAL_CSTRING(osABI, TARGET_OS_ABI);
#else
    // No TARGET_XPCOM_ABI, but at least the OS is known
    NS_NAMED_LITERAL_CSTRING(osABI, OS_TARGET "_UNKNOWN");
#endif

  // Check for version compatibility with the last version of the app this 
  // profile was started with.  The format of the version stamp is defined
  // by the BuildVersion function.
  PRBool versionOK = CheckCompatibility(profD, version, osABI,
                                        dirProvider.GetAppDir(),
                                        gAppData->directory);

  // Every time a profile is loaded by a build with a different version,
  // it updates the compatibility.ini file saying what version last wrote
  // the compreg.dat.  On subsequent launches if the version matches, 
  // there is no need for re-registration.  If the user loads the same
  // profile in different builds the component registry must be
  // re-generated to prevent mysterious component loading failures.
  //
  if (gSafeMode) {
    RemoveComponentRegistries(profD, profLD, PR_FALSE);
    WriteVersion(profD, NS_LITERAL_CSTRING("Safe Mode"), osABI,
                 dirProvider.GetAppDir(), gAppData->directory);
  }
  else if (versionOK) {
    if (ComponentsListChanged(profD)) {
      // Remove compreg.dat and xpti.dat, forcing component re-registration,
      // with the new list of additional components directories specified
      // in "components.ini" which we have just discovered changed since the
      // last time the application was run. 
      RemoveComponentRegistries(profD, profLD, PR_FALSE);
    }
    // Nothing need be done for the normal startup case.
  }
  else {
    // Remove compreg.dat and xpti.dat, forcing component re-registration
    // with the default set of components (this disables any potentially
    // troublesome incompatible XPCOM components). 
    RemoveComponentRegistries(profD, profLD, PR_TRUE);

    // Tell the Extension Manager it should check for incompatible 
    // Extensions and re-write the Components manifest ("components.ini")
    // with a list of XPCOM components for compatible extensions
    upgraded = PR_TRUE;

    // Write out version
    WriteVersion(profD, version, osABI,
                 dirProvider.GetAppDir(), gAppData->directory);
  }

  PRBool needsRestart = PR_FALSE;
  PRBool appInitiatedRestart = PR_FALSE;

  // Allows the user to forcefully bypass the restart process at their
  // own risk. Useful for debugging or for tinderboxes where child 
  // processes can be problematic.
  {
    // Start the real application
    ScopedXPCOMStartup xpcom;
    rv = xpcom.Initialize();
    NS_ENSURE_SUCCESS(rv, 1); 
    rv = xpcom.DoAutoreg();
    rv |= xpcom.InitEventQueue();
    rv |= xpcom.SetWindowCreator(nativeApp);
    NS_ENSURE_SUCCESS(rv, 1);

    {
      if (startOffline) {
        nsCOMPtr<nsIIOService> io (do_GetService("@mozilla.org/network/io-service;1"));
        NS_ENSURE_TRUE(io, 1);
        io->SetOffline(PR_TRUE);
      }

      {
        NS_TIMELINE_ENTER("startupNotifier");
        nsCOMPtr<nsIObserver> startupNotifier
          (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID, &rv));
        NS_ENSURE_SUCCESS(rv, 1);

        startupNotifier->Observe(nsnull, APPSTARTUP_TOPIC, nsnull);
        NS_TIMELINE_LEAVE("startupNotifier");
      }

      nsCOMPtr<nsIAppStartup> appStartup
        (do_GetService(NS_APPSTARTUP_CONTRACTID));
      NS_ENSURE_TRUE(appStartup, 1);

      // So we can open and close windows during startup
      appStartup->EnterLastWindowClosingSurvivalArea();

      if (gDoMigration) {
        nsCOMPtr<nsIFile> file;
        dirProvider.GetAppDir()->Clone(getter_AddRefs(file));
        file->AppendNative(NS_LITERAL_CSTRING("override.ini"));
        nsINIParser parser;
        nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
        nsresult rv = parser.Init(localFile);
        if (NS_SUCCEEDED(rv)) {
          nsCAutoString buf;
          rv = parser.GetString("XRE", "EnableProfileMigrator", buf);
          if (NS_SUCCEEDED(rv)) {
            if (buf[0] == '0' || buf[0] == 'f' || buf[0] == 'F') {
              gDoMigration = PR_FALSE;
            }
          }
        }
      }

      // Profile Migration
      if (gAppData->flags & NS_XRE_ENABLE_PROFILE_MIGRATOR && gDoMigration) {
        gDoMigration = PR_FALSE;
        nsCOMPtr<nsIProfileMigrator> pm
          (do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID));
        if (pm)
          pm->Migrate(&dirProvider);
      }
      dirProvider.DoStartup();

      nsCOMPtr<nsICommandLineRunner> cmdLine
        (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
      NS_ENSURE_TRUE(cmdLine, 1);

      nsCOMPtr<nsIFile> workingDir;
      rv = NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR, getter_AddRefs(workingDir));
      NS_ENSURE_SUCCESS(rv, 1);

      rv = cmdLine->Init(gArgc, gArgv,
                         workingDir, nsICommandLine::STATE_INITIAL_LAUNCH);
      NS_ENSURE_SUCCESS(rv, 1);

      /* Special-case services that need early access to the command
         line. */
      nsCOMPtr<nsIObserver> chromeObserver
        (do_GetService("@mozilla.org/chrome/chrome-registry;1"));
      if (chromeObserver) {
        chromeObserver->Observe(cmdLine, "command-line-startup", nsnull);
      }

      NS_TIMELINE_ENTER("appStartup->CreateHiddenWindow");
      rv = appStartup->CreateHiddenWindow();
      NS_TIMELINE_LEAVE("appStartup->CreateHiddenWindow");
      NS_ENSURE_SUCCESS(rv, 1);

      // Extension Compatibility Checking and Startup
      if (gAppData->flags & NS_XRE_ENABLE_EXTENSION_MANAGER) {
        nsCOMPtr<nsIExtensionManager> em(do_GetService("@mozilla.org/extensions/manager;1"));
        NS_ENSURE_TRUE(em, 1);

        ar = CheckArg("install-global-extension", PR_TRUE);
        if (ar == ARG_BAD) {
          PR_fprintf(PR_STDERR, "Error: argument -install-global-extension is invalid when argument -osint is specified\n");
          return 1;
        } else if (ar == ARG_FOUND) {
          // Do the required processing and then shut down.
          em->HandleCommandLineArgs(cmdLine);
          return 0;
        }

        ar = CheckArg("install-global-theme", PR_TRUE);
        if (ar == ARG_BAD) {
          PR_fprintf(PR_STDERR, "Error: argument -install-global-theme is invalid when argument -osint is specified\n");
          return 1;
        } else if (ar == ARG_FOUND) {
          // Do the required processing and then shut down.
          em->HandleCommandLineArgs(cmdLine);
          return 0;
        }

        if (upgraded) {
          rv = em->CheckForMismatches(&needsRestart);
          if (NS_FAILED(rv)) {
            needsRestart = PR_FALSE;
            upgraded = PR_FALSE;
          }
        }

        if (!upgraded || !needsRestart)
          em->Start(cmdLine, &needsRestart);
      }

      // We want to restart no more than 2 times. The first restart,
      // NO_EM_RESTART == "0" , and the second time, "1".
      char* noEMRestart = PR_GetEnv("NO_EM_RESTART");
      if (noEMRestart && *noEMRestart && *noEMRestart == '1') {
        if (upgraded || needsRestart) {
          NS_WARNING("EM tried to force us to restart twice! Forcefully preventing that.");
        }
        needsRestart = upgraded = PR_FALSE;
      }

      if (!upgraded && !needsRestart) {
        SaveStateForAppInitiatedRestart();

        // clear out any environment variables which may have been set 
        // during the relaunch process now that we know we won't be relaunching.
        PR_SetEnv("XRE_PROFILE_PATH=");
        PR_SetEnv("XRE_PROFILE_LOCAL_PATH=");
        PR_SetEnv("XRE_START_OFFLINE=");
        PR_SetEnv("XRE_IMPORT_PROFILES=");
        PR_SetEnv("NO_EM_RESTART=");
        PR_SetEnv("XUL_APP_FILE=");
        PR_SetEnv("XRE_BINARY_PATH=");

#ifdef XP_MACOSX
        // we re-initialize the command-line service and do appleevents munging
        // after we are sure that we're not restarting
        cmdLine = do_CreateInstance("@mozilla.org/toolkit/command-line;1");
        NS_ENSURE_TRUE(cmdLine, 1);

        SetupMacCommandLine(gArgc, gArgv);

        rv = cmdLine->Init(gArgc, gArgv,
                           workingDir, nsICommandLine::STATE_INITIAL_LAUNCH);
        NS_ENSURE_SUCCESS(rv, 1);

        // Kick off the prebinding update now that we know we won't be
        // relaunching.

        UpdatePrebinding();
#endif
        nsCOMPtr<nsIObserverService> obsService
          (do_GetService("@mozilla.org/observer-service;1"));
        if (obsService)
          obsService->NotifyObservers(nsnull, "final-ui-startup", nsnull);        

        rv = cmdLine->Run();
        NS_ENSURE_SUCCESS_LOG(rv, 1);

        nsCOMPtr<nsIWindowMediator> windowMediator
          (do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv));
        NS_ENSURE_SUCCESS(rv, 1);

        // Make sure there exists at least 1 window.
        nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
        rv = windowMediator->GetEnumerator(nsnull, getter_AddRefs(windowEnumerator));
        NS_ENSURE_SUCCESS(rv, 1);

        PRBool more;
        windowEnumerator->HasMoreElements(&more);
        if (!more) {
          // We didn't open any windows. This is normally not a good thing,
          // so we force console logging to file.
          gLogConsoleErrors = PR_TRUE;
        }
        else {
#ifndef XP_MACOSX
          appStartup->ExitLastWindowClosingSurvivalArea();
#endif

#ifdef MOZ_ENABLE_XREMOTE
          // if we have X remote support and we have our one window up and
          // running start listening for requests on the proxy window.
          nsCOMPtr<nsIRemoteService> remoteService;
          remoteService = do_GetService("@mozilla.org/toolkit/remote-service;1");
          if (remoteService)
            remoteService->Startup(gAppData->name, nsnull);
#endif /* MOZ_ENABLE_XREMOTE */

          // enable win32 DDE responses and Mac appleevents responses
          nativeApp->Enable();

          // Start main event loop
          NS_TIMELINE_ENTER("appStartup->Run");
          rv = appStartup->Run();
          NS_TIMELINE_LEAVE("appStartup->Run");
          if (NS_FAILED(rv)) {
            NS_ERROR("failed to run appstartup");
            gLogConsoleErrors = PR_TRUE;
          }

          // Check for an application initiated restart.  This is one that
          // corresponds to nsIAppStartup.quit(eRestart)
          if (rv == NS_SUCCESS_RESTART_APP) {
            needsRestart = PR_TRUE;
            appInitiatedRestart = PR_TRUE;
          }

#ifdef MOZ_ENABLE_XREMOTE
          // shut down the x remote proxy window
          if (remoteService)
            remoteService->Shutdown();
#endif /* MOZ_ENABLE_XREMOTE */
        }

#ifdef MOZ_TIMELINE
        // Make sure we print this out even if timeline is runtime disabled
        if (NS_FAILED(NS_TIMELINE_LEAVE("main1")))
          NS_TimelineForceMark("...main1");
#endif
      }
      else {
        // Upgrade condition (build id changes), but the restart hint was 
        // not set by the Extension Manager. This is because the compatibility
        // resolution for Extensions is different than for the component 
        // registry - major milestone vs. build id. 
        needsRestart = PR_TRUE;

#ifdef XP_WIN
        ProcessDDE(nativeApp);
#endif

#ifdef XP_MACOSX
        SetupMacCommandLine(gRestartArgc, gRestartArgv);
#endif
      }
    }

    profileLock->Unlock();
  }

  // Restart the app after XPCOM has been shut down cleanly. 
  if (needsRestart) {
    if (appInitiatedRestart) {
      RestoreStateForAppInitiatedRestart();
    }
    else {
      char* noEMRestart = PR_GetEnv("NO_EM_RESTART");
      if (noEMRestart && *noEMRestart) {
        PR_SetEnv("NO_EM_RESTART=1");
      }
      else {
        PR_SetEnv("NO_EM_RESTART=0");
      }
    }

    // Ensure that these environment variables are set:
    SaveFileToEnvIfUnset("XRE_PROFILE_PATH", profD);
    SaveFileToEnvIfUnset("XRE_PROFILE_LOCAL_PATH", profLD);

#ifdef XP_MACOSX
    if (gBinaryPath) {
      static char kEnvVar[MAXPATHLEN];
      sprintf(kEnvVar, "XRE_BINARY_PATH=%s", gBinaryPath);
      PR_SetEnv(kEnvVar);
    }
#endif

    rv = LaunchChild(nativeApp, appInitiatedRestart, upgraded ? -1 : 0);
    return rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ? 0 : 1;
  }

  return NS_FAILED(rv) ? 1 : 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 249 of file nsEmbedFunctions.cpp.

{
  if (--sInitCounter != 0)
    return;

  NS_ShutdownXPCOM(nsnull);
  delete [] sCombined;
}

Here is the call graph for this function:

Here is the caller graph for this function: