Beispiel #1
0
static nsresult
GetGREVersion(const char *argv0,
              nsACString *aMilestone,
              nsACString *aVersion)
{
  if (aMilestone)
    aMilestone->Assign("<Error>");
  if (aVersion)
    aVersion->Assign("<Error>");

  nsCOMPtr<nsILocalFile> iniFile;
  nsresult rv = XRE_GetBinaryPath(argv0, getter_AddRefs(iniFile));
  if (NS_FAILED(rv))
    return rv;

  iniFile->SetNativeLeafName(NS_LITERAL_CSTRING("platform.ini"));

  nsINIParser parser;
  rv = parser.Init(iniFile);
  if (NS_FAILED(rv))
    return rv;

  if (aMilestone) {
    rv = parser.GetString("Build", "Milestone", *aMilestone);
    if (NS_FAILED(rv))
      return rv;
  }
  if (aVersion) {
    rv = parser.GetString("Build", "BuildID", *aVersion);
    if (NS_FAILED(rv))
      return rv;
  }
  return NS_OK;
}
int main(int argc, char* argv[])
{
  ScopedLogging log;

  nsCOMPtr<nsILocalFile> appini;
  nsresult rv = XRE_GetBinaryPath(argv[0], getter_AddRefs(appini));
  if (NS_FAILED(rv)) {
    Output("Couldn't calculate the application directory.");
    return 255;
  }
  appini->SetNativeLeafName(NS_LITERAL_CSTRING("application.ini"));

  // Allow firefox.exe to launch XULRunner apps via -app <application.ini>
  // Note that -app must be the *first* argument.
  char *appEnv = nsnull;
  const char *appDataFile = PR_GetEnv("XUL_APP_FILE");
  if (appDataFile && *appDataFile) {
    rv = XRE_GetFileFromPath(appDataFile, getter_AddRefs(appini));
    if (NS_FAILED(rv)) {
      Output("Invalid path found: '%s'", appDataFile);
      return 255;
    }
  }
  else if (argc > 1 && IsArg(argv[1], "app")) {
    if (argc == 2) {
      Output("Incorrect number of arguments passed to -app");
      return 255;
    }

    rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(appini));
    if (NS_FAILED(rv)) {
      Output("application.ini path not recognized: '%s'", argv[2]);
      return 255;
    }

    appEnv = PR_smprintf("XUL_APP_FILE=%s", argv[2]);
    PR_SetEnv(appEnv);
    argv[2] = argv[0];
    argv += 2;
    argc -= 2;
  }

  nsXREAppData *appData;
  rv = XRE_CreateAppData(appini, &appData);
  if (NS_FAILED(rv)) {
    Output("Couldn't read application.ini");
    return 255;
  }

  int result = XRE_main(argc, argv, appData);
  XRE_FreeAppData(appData);
  if (appEnv)
    PR_smprintf_free(appEnv);
  return result;
}
Beispiel #3
0
static nsresult
GetXULRunnerDir(const char *argv0, nsIFile* *aResult)
{
  nsresult rv;

  nsCOMPtr<nsILocalFile> appFile;
  rv = XRE_GetBinaryPath(argv0, getter_AddRefs(appFile));
  if (NS_FAILED(rv)) {
    Output(PR_TRUE, "Could not find XULRunner application path.\n");
    return rv;
  }

  rv = appFile->GetParent(aResult);
  if (NS_FAILED(rv)) {
    Output(PR_TRUE, "Could not find XULRunner installation dir.\n");
  }
  return rv;
}
Beispiel #4
0
int main(int argc, char* argv[])
{
  nsCOMPtr<nsIFile> appini;
  nsresult rv = XRE_GetBinaryPath(argv[0], getter_AddRefs(appini));
  if (NS_FAILED(rv)) {
    Output("Couldn't calculate the application directory.");
    return 255;
  }
  appini->SetNativeLeafName(NS_LITERAL_CSTRING("application.ini"));

  nsXREAppData *appData;
  rv = XRE_CreateAppData(appini, &appData);
  if (NS_FAILED(rv)) {
    Output("Couldn't read application.ini");
    return 255;
  }

  int result = XRE_main(argc, argv, appData, 0);
  XRE_FreeAppData(appData);
  return result;
}
nsresult
nsXREDirProvider::GetFilesInternal(const char* aProperty,
                                   nsISimpleEnumerator** aResult)
{
  nsresult rv = NS_OK;
  *aResult = nullptr;

  if (!strcmp(aProperty, XRE_EXTENSIONS_DIR_LIST)) {
    nsCOMArray<nsIFile> directories;

    static const char *const kAppendNothing[] = { nullptr };

    LoadDirsIntoArray(mAppBundleDirectories,
                      kAppendNothing, directories);
    LoadDirsIntoArray(mExtensionDirectories,
                      kAppendNothing, directories);

    rv = NS_NewArrayEnumerator(aResult, directories);
  }
  else if (!strcmp(aProperty, NS_APP_PREFS_DEFAULTS_DIR_LIST)) {
    nsCOMArray<nsIFile> directories;

    LoadDirIntoArray(mXULAppDir, kAppendPrefDir, directories);
    LoadDirsIntoArray(mAppBundleDirectories,
                      kAppendPrefDir, directories);

    rv = NS_NewArrayEnumerator(aResult, directories);
  }
  else if (!strcmp(aProperty, NS_EXT_PREFS_DEFAULTS_DIR_LIST)) {
    nsCOMArray<nsIFile> directories;

    LoadDirsIntoArray(mExtensionDirectories,
                      kAppendPrefDir, directories);

    if (mProfileDir) {
      nsCOMPtr<nsIFile> overrideFile;
      mProfileDir->Clone(getter_AddRefs(overrideFile));
      overrideFile->AppendNative(NS_LITERAL_CSTRING(PREF_OVERRIDE_DIRNAME));

      bool exists;
      if (NS_SUCCEEDED(overrideFile->Exists(&exists)) && exists)
        directories.AppendObject(overrideFile);
    }

    rv = NS_NewArrayEnumerator(aResult, directories);
  }
  else if (!strcmp(aProperty, NS_APP_CHROME_DIR_LIST)) {
    // NS_APP_CHROME_DIR_LIST is only used to get default (native) icons
    // for OS window decoration.

    static const char *const kAppendChromeDir[] = { "chrome", nullptr };
    nsCOMArray<nsIFile> directories;
    LoadDirIntoArray(mXULAppDir,
                     kAppendChromeDir,
                     directories);
    LoadDirsIntoArray(mAppBundleDirectories,
                      kAppendChromeDir,
                      directories);
    LoadDirsIntoArray(mExtensionDirectories,
                      kAppendChromeDir,
                      directories);

    rv = NS_NewArrayEnumerator(aResult, directories);
  }
  else if (!strcmp(aProperty, NS_APP_PLUGINS_DIR_LIST)) {
    nsCOMArray<nsIFile> directories;

    if (mozilla::Preferences::GetBool("plugins.load_appdir_plugins", false)) {
      nsCOMPtr<nsIFile> appdir;
      rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(appdir));
      if (NS_SUCCEEDED(rv)) {
        appdir->SetNativeLeafName(NS_LITERAL_CSTRING("plugins"));
        directories.AppendObject(appdir);
      }
    }

    static const char *const kAppendPlugins[] = { "plugins", nullptr };

    // The root dirserviceprovider does quite a bit for us: we're mainly
    // interested in xulapp and extension-provided plugins.
    LoadDirsIntoArray(mAppBundleDirectories,
                      kAppendPlugins,
                      directories);
    LoadDirsIntoArray(mExtensionDirectories,
                      kAppendPlugins,
                      directories);

    if (mProfileDir) {
      nsCOMArray<nsIFile> profileDir;
      profileDir.AppendObject(mProfileDir);
      LoadDirsIntoArray(profileDir,
                        kAppendPlugins,
                        directories);
    }

    rv = NS_NewArrayEnumerator(aResult, directories);
    NS_ENSURE_SUCCESS(rv, rv);

    rv = NS_SUCCESS_AGGREGATE_RESULT;
  }
  else
    rv = NS_ERROR_FAILURE;

  return rv;
}
NS_IMETHODIMP
nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent,
                          nsIFile** aFile)
{
  nsresult rv;

  bool gettingProfile = false;

  if (!strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR)) {
    // If XRE_NotifyProfile hasn't been called, don't fall through to
    // mAppProvider on the profile keys.
    if (!mProfileNotified)
      return NS_ERROR_FAILURE;

    if (mProfileLocalDir)
      return mProfileLocalDir->Clone(aFile);

    if (mAppProvider)
      return mAppProvider->GetFile(aProperty, aPersistent, aFile);

    // This falls through to the case below
    gettingProfile = true;
  }
  if (!strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) || gettingProfile) {
    if (!mProfileNotified)
      return NS_ERROR_FAILURE;

    if (mProfileDir)
      return mProfileDir->Clone(aFile);

    if (mAppProvider)
      return mAppProvider->GetFile(aProperty, aPersistent, aFile);

    // If we don't succeed here, bail early so that we aren't reentrant
    // through the "GetProfileDir" call below.
    return NS_ERROR_FAILURE;
  }

  if (mAppProvider) {
    rv = mAppProvider->GetFile(aProperty, aPersistent, aFile);
    if (NS_SUCCEEDED(rv) && *aFile)
      return rv;
  }

  *aPersistent = true;

  if (!strcmp(aProperty, NS_GRE_DIR)) {
    return mGREDir->Clone(aFile);
  }
  else if (!strcmp(aProperty, NS_GRE_BIN_DIR)) {
    return mGREBinDir->Clone(aFile);
  }
  else if (!strcmp(aProperty, NS_OS_CURRENT_PROCESS_DIR) ||
           !strcmp(aProperty, NS_APP_INSTALL_CLEANUP_DIR)) {
    return GetAppDir()->Clone(aFile);
  }

  rv = NS_ERROR_FAILURE;
  nsCOMPtr<nsIFile> file;

  if (!strcmp(aProperty, NS_APP_PROFILE_DEFAULTS_50_DIR) ||
           !strcmp(aProperty, NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR)) {
    return GetProfileDefaultsDir(aFile);
  }
  else if (!strcmp(aProperty, NS_APP_PREF_DEFAULTS_50_DIR))
  {
    // return the GRE default prefs directory here, and the app default prefs
    // directory (if applicable) in NS_APP_PREFS_DEFAULTS_DIR_LIST.
    rv = mGREDir->Clone(getter_AddRefs(file));
    if (NS_SUCCEEDED(rv)) {
      rv = file->AppendNative(NS_LITERAL_CSTRING("defaults"));
      if (NS_SUCCEEDED(rv))
        rv = file->AppendNative(NS_LITERAL_CSTRING("pref"));
    }
  }
  else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_DIR) ||
           !strcmp(aProperty, XRE_USER_APP_DATA_DIR)) {
    rv = GetUserAppDataDirectory(getter_AddRefs(file));
  }
  else if (!strcmp(aProperty, XRE_UPDATE_ROOT_DIR)) {
    rv = GetUpdateRootDir(getter_AddRefs(file));
  }
  else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_FILE)) {
    rv = GetUserAppDataDirectory(getter_AddRefs(file));
    if (NS_SUCCEEDED(rv))
      rv = file->AppendNative(NS_LITERAL_CSTRING(APP_REGISTRY_NAME));
  }
  else if (!strcmp(aProperty, NS_APP_USER_PROFILES_ROOT_DIR)) {
    rv = GetUserProfilesRootDir(getter_AddRefs(file), nullptr, nullptr, nullptr);
  }
  else if (!strcmp(aProperty, NS_APP_USER_PROFILES_LOCAL_ROOT_DIR)) {
    rv = GetUserProfilesLocalDir(getter_AddRefs(file), nullptr, nullptr, nullptr);
  }
  else if (!strcmp(aProperty, XRE_EXECUTABLE_FILE) && gArgv[0]) {
    nsCOMPtr<nsIFile> lf;
    rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
    if (NS_SUCCEEDED(rv))
      file = lf;
  }

  else if (!strcmp(aProperty, NS_APP_PROFILE_DIR_STARTUP) && mProfileDir) {
    return mProfileDir->Clone(aFile);
  }
  else if (!strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) {
    if (mProfileLocalDir)
      return mProfileLocalDir->Clone(aFile);

    if (mProfileDir)
      return mProfileDir->Clone(aFile);

    if (mAppProvider)
      return mAppProvider->GetFile(NS_APP_PROFILE_DIR_STARTUP, aPersistent,
                                   aFile);
  }
#if defined(XP_UNIX) || defined(XP_MACOSX)
  else if (!strcmp(aProperty, XRE_SYS_LOCAL_EXTENSION_PARENT_DIR)) {
#ifdef ENABLE_SYSTEM_EXTENSION_DIRS
    return GetSystemExtensionsDirectory(aFile);
#else
    return NS_ERROR_FAILURE;
#endif
  }
#endif
#if defined(XP_UNIX) && !defined(XP_MACOSX)
  else if (!strcmp(aProperty, XRE_SYS_SHARE_EXTENSION_PARENT_DIR)) {
#ifdef ENABLE_SYSTEM_EXTENSION_DIRS
#if defined(__OpenBSD__) || defined(__FreeBSD__)
    static const char *const sysLExtDir = "/usr/local/share/mozilla/extensions";
#else
    static const char *const sysLExtDir = "/usr/share/mozilla/extensions";
#endif
    return NS_NewNativeLocalFile(nsDependentCString(sysLExtDir),
                                 false, aFile);
#else
    return NS_ERROR_FAILURE;
#endif
  }
#endif
  else if (!strcmp(aProperty, XRE_USER_SYS_EXTENSION_DIR)) {
#ifdef ENABLE_SYSTEM_EXTENSION_DIRS
    return GetSysUserExtensionsDirectory(aFile);
#else
    return NS_ERROR_FAILURE;
#endif
  }
  else if (!strcmp(aProperty, XRE_APP_DISTRIBUTION_DIR)) {
    bool persistent = false;
    rv = GetFile(NS_GRE_DIR, &persistent, getter_AddRefs(file));
    if (NS_SUCCEEDED(rv))
      rv = file->AppendNative(NS_LITERAL_CSTRING("distribution"));
  }
  else if (!strcmp(aProperty, XRE_APP_FEATURES_DIR)) {
    rv = GetAppDir()->Clone(getter_AddRefs(file));
    if (NS_SUCCEEDED(rv))
      rv = file->AppendNative(NS_LITERAL_CSTRING("features"));
  }
  else if (NS_SUCCEEDED(GetProfileStartupDir(getter_AddRefs(file)))) {
    // We need to allow component, xpt, and chrome registration to
    // occur prior to the profile-after-change notification.
    if (!strcmp(aProperty, NS_APP_USER_CHROME_DIR)) {
      rv = file->AppendNative(NS_LITERAL_CSTRING("chrome"));
    }
  }

  if (NS_SUCCEEDED(rv) && file) {
    file.forget(aFile);
    return NS_OK;
  }

  bool ensureFilePermissions = false;

  if (NS_SUCCEEDED(GetProfileDir(getter_AddRefs(file)))) {
    if (!strcmp(aProperty, NS_APP_PREFS_50_DIR)) {
      rv = NS_OK;
    }
    else if (!strcmp(aProperty, NS_APP_PREFS_50_FILE)) {
      rv = file->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
    }
    else if (!strcmp(aProperty, NS_LOCALSTORE_UNSAFE_FILE)) {
      rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
    }
    else if (!strcmp(aProperty, NS_APP_LOCALSTORE_50_FILE)) {
      if (gSafeMode) {
        rv = file->AppendNative(NS_LITERAL_CSTRING("localstore-safe.rdf"));
        file->Remove(false);
      }
      else {
        rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
        EnsureProfileFileExists(file);
        ensureFilePermissions = true;
      }
    }
    else if (!strcmp(aProperty, NS_APP_USER_MIMETYPES_50_FILE)) {
      rv = file->AppendNative(NS_LITERAL_CSTRING("mimeTypes.rdf"));
      EnsureProfileFileExists(file);
      ensureFilePermissions = true;
    }
    else if (!strcmp(aProperty, NS_APP_DOWNLOADS_50_FILE)) {
      rv = file->AppendNative(NS_LITERAL_CSTRING("downloads.rdf"));
    }
    else if (!strcmp(aProperty, NS_APP_PREFS_OVERRIDE_DIR)) {
      rv = mProfileDir->Clone(getter_AddRefs(file));
      nsresult tmp = file->AppendNative(NS_LITERAL_CSTRING(PREF_OVERRIDE_DIRNAME));
      if (NS_FAILED(tmp)) {
        rv = tmp;
      }
      tmp = EnsureDirectoryExists(file);
      if (NS_FAILED(tmp)) {
        rv = tmp;
      }
    }
  }
  if (NS_FAILED(rv) || !file)
    return NS_ERROR_FAILURE;

  if (ensureFilePermissions) {
    bool fileToEnsureExists;
    bool isWritable;
    if (NS_SUCCEEDED(file->Exists(&fileToEnsureExists)) && fileToEnsureExists
        && NS_SUCCEEDED(file->IsWritable(&isWritable)) && !isWritable) {
      uint32_t permissions;
      if (NS_SUCCEEDED(file->GetPermissions(&permissions))) {
        rv = file->SetPermissions(permissions | 0600);
        NS_ASSERTION(NS_SUCCEEDED(rv), "failed to ensure file permissions");
      }
    }
  }

  file.forget(aFile);
  return NS_OK;
}
Beispiel #7
0
static void
ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsILocalFile *statusFile,
            nsIFile *appDir, int appArgc, char **appArgv)
{
    nsresult rv;

    // Steps:
    //  - mark update as 'applying'
    //  - copy updater into update dir
    //  - run updater w/ appDir as the current working dir

    nsCOMPtr<nsIFile> updater;
    if (!CopyUpdaterIntoUpdateDir(greDir, appDir, updateDir, updater)) {
        LOG(("failed copying updater\n"));
        return;
    }

    // We need to use the value returned from XRE_GetBinaryPath when attempting
    // to restart the running application.
    nsCOMPtr<nsILocalFile> appFile;

#if defined(XP_MACOSX)
    // On OS X we need to pass the location of the xulrunner-stub executable
    // rather than xulrunner-bin. See bug 349737.
    GetXULRunnerStubPath(appArgv[0], getter_AddRefs(appFile));
#else
    XRE_GetBinaryPath(appArgv[0], getter_AddRefs(appFile));
#endif

    if (!appFile)
        return;

#ifdef XP_WIN
    nsAutoString appFilePathW;
    rv = appFile->GetPath(appFilePathW);
    if (NS_FAILED(rv))
        return;
    NS_ConvertUTF16toUTF8 appFilePath(appFilePathW);

    nsAutoString updaterPathW;
    rv = updater->GetPath(updaterPathW);
    if (NS_FAILED(rv))
        return;

    NS_ConvertUTF16toUTF8 updaterPath(updaterPathW);

#else
    nsCAutoString appFilePath;
    rv = appFile->GetNativePath(appFilePath);
    if (NS_FAILED(rv))
        return;

    nsCAutoString updaterPath;
    rv = updater->GetNativePath(updaterPath);
    if (NS_FAILED(rv))
        return;

#endif

    // Get the directory to which the update will be applied. On Mac OSX we need
    // to apply the update to the Foo.app directory which is the parent of the
    // parent of the appDir. On other platforms we will just apply to the appDir.
#if defined(XP_MACOSX)
    nsCAutoString applyToDir;
    {
        nsCOMPtr<nsIFile> parentDir1, parentDir2;
        rv = appDir->GetParent(getter_AddRefs(parentDir1));
        if (NS_FAILED(rv))
            return;
        rv = parentDir1->GetParent(getter_AddRefs(parentDir2));
        if (NS_FAILED(rv))
            return;
        rv = parentDir2->GetNativePath(applyToDir);
    }
#elif defined(XP_WIN)
    nsAutoString applyToDir;
    rv = appDir->GetPath(applyToDir);
#else
    nsCAutoString applyToDir;
    rv = appDir->GetNativePath(applyToDir);
#endif
    if (NS_FAILED(rv))
        return;

#if defined(XP_WIN)
    nsAutoString updateDirPathW;
    rv = updateDir->GetPath(updateDirPathW);

    NS_ConvertUTF16toUTF8 updateDirPath(updateDirPathW);
#else
    nsCAutoString updateDirPath;
    rv = updateDir->GetNativePath(updateDirPath);
#endif

    if (NS_FAILED(rv))
        return;

    // Get the current working directory.
    char workingDirPath[MAXPATHLEN];
    rv = GetCurrentWorkingDir(workingDirPath, sizeof(workingDirPath));
    if (NS_FAILED(rv))
        return;

    if (!SetStatus(statusFile, "applying")) {
        LOG(("failed setting status to 'applying'\n"));
        return;
    }

    // Construct the PID argument for this process.  If we are using execv, then
    // we pass "0" which is then ignored by the updater.
#if defined(USE_EXECV)
    NS_NAMED_LITERAL_CSTRING(pid, "0");
#else
    nsCAutoString pid;
    pid.AppendInt((PRInt32) getpid());
#endif

    int argc = appArgc + 4;
    char **argv = new char*[argc + 1];
    if (!argv)
        return;
    argv[0] = (char*) updaterPath.get();
    argv[1] = (char*) updateDirPath.get();
    argv[2] = (char*) pid.get();
    if (appArgc) {
        argv[3] = workingDirPath;
        argv[4] = (char*) appFilePath.get();
        for (int i = 1; i < appArgc; ++i)
            argv[4 + i] = appArgv[i];
        argv[4 + appArgc] = nsnull;
    } else {
        argv[3] = nsnull;
        argc = 3;
    }

    LOG(("spawning updater process [%s]\n", updaterPath.get()));

#if defined(USE_EXECV)
    chdir(applyToDir.get());
    execv(updaterPath.get(), argv);
#elif defined(XP_WIN)
    _wchdir(applyToDir.get());

    if (!WinLaunchChild(updaterPathW.get(), appArgc + 4, argv))
        return;
    _exit(0);
#else
    PRStatus status;
    PRProcessAttr *attr;

    attr = PR_NewProcessAttr();
    if (!attr)
        goto end;

    status = PR_ProcessAttrSetCurrentDirectory(attr, applyToDir.get());
    if (status != PR_SUCCESS)
        goto end;

#ifdef XP_MACOSX
    CommandLineServiceMac::SetupMacCommandLine(argc, argv, PR_TRUE);
#endif

    PR_CreateProcessDetached(updaterPath.get(), argv, nsnull, attr);
    exit(0);

end:
    PR_DestroyProcessAttr(attr);
    delete[] argv;
#endif
}
Beispiel #8
0
NS_IMETHODIMP
nsXREDirProvider::GetFile(const char* aProperty, PRBool* aPersistent,
			  nsIFile** aFile)
{
  nsresult rv;

  PRBool gettingProfile = PR_FALSE;

  if (!strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR)) {
    // If XRE_NotifyProfile hasn't been called, don't fall through to
    // mAppProvider on the profile keys.
    if (!mProfileNotified)
      return NS_ERROR_FAILURE;

    if (mProfileLocalDir)
      return mProfileLocalDir->Clone(aFile);

    if (mAppProvider)
      return mAppProvider->GetFile(aProperty, aPersistent, aFile);

    // This falls through to the case below
    gettingProfile = PR_TRUE;
  }
  if (!strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) || gettingProfile) {
    if (!mProfileNotified)
      return NS_ERROR_FAILURE;

    if (mProfileDir)
      return mProfileDir->Clone(aFile);

    if (mAppProvider)
      return mAppProvider->GetFile(aProperty, aPersistent, aFile);

    // If we don't succeed here, bail early so that we aren't reentrant
    // through the "GetProfileDir" call below.
    return NS_ERROR_FAILURE;
  }

  if (mAppProvider) {
    rv = mAppProvider->GetFile(aProperty, aPersistent, aFile);
    if (NS_SUCCEEDED(rv) && *aFile)
      return rv;
  }

  *aPersistent = PR_TRUE;

  if (!strcmp(aProperty, NS_GRE_DIR)) {
    return mGREDir->Clone(aFile);
  }
  else if (!strcmp(aProperty, NS_OS_CURRENT_PROCESS_DIR) ||
      !strcmp(aProperty, NS_APP_INSTALL_CLEANUP_DIR)) {
    return GetAppDir()->Clone(aFile);
  }

  rv = NS_ERROR_FAILURE;
  nsCOMPtr<nsIFile> file;

  if (!strcmp(aProperty, NS_APP_PROFILE_DEFAULTS_50_DIR) ||
           !strcmp(aProperty, NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR)) {
    return GetProfileDefaultsDir(aFile);
  }
  else if (!strcmp(aProperty, NS_APP_PREF_DEFAULTS_50_DIR))
  {
    // return the GRE default prefs directory here, and the app default prefs
    // directory (if applicable) in NS_APP_PREFS_DEFAULTS_DIR_LIST.
    rv = mGREDir->Clone(getter_AddRefs(file));
    if (NS_SUCCEEDED(rv)) {
      rv = file->AppendNative(NS_LITERAL_CSTRING("defaults"));
      if (NS_SUCCEEDED(rv))
        rv = file->AppendNative(NS_LITERAL_CSTRING("pref"));
    }
  }
  else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_DIR) ||
           !strcmp(aProperty, XRE_USER_APP_DATA_DIR)) {
    rv = GetUserAppDataDirectory((nsILocalFile**)(nsIFile**) getter_AddRefs(file));
  }
  else if (!strcmp(aProperty, XRE_UPDATE_ROOT_DIR)) {
#if defined(XP_WIN)
    rv = GetUpdateRootDir(getter_AddRefs(file));
#else
    // Only supported on Windows, so just immediately fail.
    return NS_ERROR_FAILURE;
#endif
  }
  else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_FILE)) {
    rv = GetUserAppDataDirectory((nsILocalFile**)(nsIFile**) getter_AddRefs(file));
    if (NS_SUCCEEDED(rv))
      rv = file->AppendNative(NS_LITERAL_CSTRING(APP_REGISTRY_NAME));
  }
  else if (!strcmp(aProperty, NS_APP_USER_PROFILES_ROOT_DIR)) {
    rv = GetUserAppDataDirectory((nsILocalFile**)(nsIFile**) getter_AddRefs(file));

    if (NS_SUCCEEDED(rv)) {
#if !defined(XP_UNIX) || defined(XP_MACOSX)
      rv = file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
#endif

      // We must create the profile directory here if it does not exist.
      rv |= EnsureDirectoryExists(file);
    }
  }
  else if (!strcmp(aProperty, NS_APP_USER_PROFILES_LOCAL_ROOT_DIR)) {
    rv = GetUserLocalDataDirectory((nsILocalFile**)(nsIFile**) getter_AddRefs(file));

    if (NS_SUCCEEDED(rv)) {
#if !defined(XP_UNIX) || defined(XP_MACOSX)
      rv = file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
#endif

      // We must create the profile directory here if it does not exist.
      rv |= EnsureDirectoryExists(file);
    }
  }
  else if (!strcmp(aProperty, XRE_EXECUTABLE_FILE) && gArgv[0]) {
    nsCOMPtr<nsILocalFile> lf;
    rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
    if (NS_SUCCEEDED(rv))
      file = lf;
  }

  else if (!strcmp(aProperty, NS_APP_PROFILE_DIR_STARTUP) && mProfileDir) {
    return mProfileDir->Clone(aFile);
  }
  else if (!strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) {
    if (mProfileLocalDir)
      return mProfileLocalDir->Clone(aFile);

    if (mProfileDir)
      return mProfileDir->Clone(aFile);

    if (mAppProvider)
      return mAppProvider->GetFile(NS_APP_PROFILE_DIR_STARTUP, aPersistent,
                                   aFile);
  }
#if defined(XP_UNIX) || defined(XP_MACOSX)
  else if (!strcmp(aProperty, XRE_SYS_LOCAL_EXTENSION_PARENT_DIR)) {
    return GetSystemExtensionsDirectory((nsILocalFile**)(nsIFile**) aFile);
  }
#endif
#if defined(XP_UNIX) && !defined(XP_MACOSX)
  else if (!strcmp(aProperty, XRE_SYS_SHARE_EXTENSION_PARENT_DIR)) {
    static const char *const sysLExtDir = "/usr/share/mozilla/extensions";
    return NS_NewNativeLocalFile(nsDependentCString(sysLExtDir),
                                 PR_FALSE, (nsILocalFile**)(nsIFile**) aFile);
  }
#endif
  else if (!strcmp(aProperty, XRE_USER_SYS_EXTENSION_DIR)) {
    return GetSysUserExtensionsDirectory((nsILocalFile**)(nsIFile**) aFile);
  }
  else if (!strcmp(aProperty, XRE_APP_DISTRIBUTION_DIR)) {
    rv = GetAppDir()->Clone(getter_AddRefs(file));
    if (NS_SUCCEEDED(rv))
      rv = file->AppendNative(NS_LITERAL_CSTRING("distribution"));
  }
  else if (NS_SUCCEEDED(GetProfileStartupDir(getter_AddRefs(file)))) {
    // We need to allow component, xpt, and chrome registration to
    // occur prior to the profile-after-change notification.
    if (!strcmp(aProperty, NS_APP_USER_CHROME_DIR)) {
      rv = file->AppendNative(NS_LITERAL_CSTRING("chrome"));
    }
  }

  if (NS_SUCCEEDED(rv) && file) {
    NS_ADDREF(*aFile = file);
    return NS_OK;
  }

  PRBool ensureFilePermissions = PR_FALSE;

  if (NS_SUCCEEDED(GetProfileDir(getter_AddRefs(file)))) {
    if (!strcmp(aProperty, NS_APP_PREFS_50_DIR)) {
      rv = NS_OK;
    }
    else if (!strcmp(aProperty, NS_APP_PREFS_50_FILE)) {
      rv = file->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
    }
    else if (!strcmp(aProperty, NS_LOCALSTORE_UNSAFE_FILE)) {
      rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
    }
    else if (!strcmp(aProperty, NS_APP_LOCALSTORE_50_FILE)) {
      if (gSafeMode) {
        rv = file->AppendNative(NS_LITERAL_CSTRING("localstore-safe.rdf"));
        file->Remove(PR_FALSE);
      }
      else {
        rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
        EnsureProfileFileExists(file);
        ensureFilePermissions = PR_TRUE;
      }
    }
    else if (!strcmp(aProperty, NS_APP_HISTORY_50_FILE)) {
      rv = file->AppendNative(NS_LITERAL_CSTRING("history.dat"));
    }
    else if (!strcmp(aProperty, NS_APP_USER_MIMETYPES_50_FILE)) {
      rv = file->AppendNative(NS_LITERAL_CSTRING("mimeTypes.rdf"));
      EnsureProfileFileExists(file);
      ensureFilePermissions = PR_TRUE;
    }
    else if (!strcmp(aProperty, NS_APP_STORAGE_50_FILE)) {
      rv = file->AppendNative(NS_LITERAL_CSTRING("storage.sdb"));
    }
    else if (!strcmp(aProperty, NS_APP_DOWNLOADS_50_FILE)) {
      rv = file->AppendNative(NS_LITERAL_CSTRING("downloads.rdf"));
    }
    else if (!strcmp(aProperty, NS_APP_PREFS_OVERRIDE_DIR)) {
      rv = mProfileDir->Clone(getter_AddRefs(file));
      rv |= file->AppendNative(NS_LITERAL_CSTRING(PREF_OVERRIDE_DIRNAME));
      rv |= EnsureDirectoryExists(file);
    }
  }
  if (NS_FAILED(rv) || !file)
    return NS_ERROR_FAILURE;

  if (ensureFilePermissions) {
    PRBool fileToEnsureExists;
    PRBool isWritable;
    if (NS_SUCCEEDED(file->Exists(&fileToEnsureExists)) && fileToEnsureExists
        && NS_SUCCEEDED(file->IsWritable(&isWritable)) && !isWritable) {
      PRUint32 permissions;
      if (NS_SUCCEEDED(file->GetPermissions(&permissions))) {
        rv = file->SetPermissions(permissions | 0600);
        NS_ASSERTION(NS_SUCCEEDED(rv), "failed to ensure file permissions");
      }
    }
  }

  NS_ADDREF(*aFile = file);
  return NS_OK;
}