Bug 1398895: Part 1 - Initialize user prefs before loading any JS components. r?florian
MozReview-Commit-ID: BAH7m0nLiIT
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -4362,28 +4362,16 @@ XREMain::XRE_mainRun()
if (mStartOffline) {
nsCOMPtr<nsIIOService2> io (do_GetService("@mozilla.org/network/io-service;1"));
NS_ENSURE_TRUE(io, NS_ERROR_FAILURE);
io->SetManageOfflineStatus(false);
io->SetOffline(true);
}
- {
- nsCOMPtr<nsIObserver> startupNotifier
- (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID, &rv));
- NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
-
- startupNotifier->Observe(nullptr, APPSTARTUP_TOPIC, nullptr);
- }
-
- nsCOMPtr<nsIAppStartup> appStartup
- (do_GetService(NS_APPSTARTUP_CONTRACTID));
- NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE);
-
#ifdef XP_WIN
if (!PR_GetEnv("XRE_NO_DLL_READAHEAD"))
{
PR_CreateThread(PR_USER_THREAD, ReadAheadDlls_ThreadStart, 0,
PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
PR_UNJOINABLE_THREAD, 0);
}
@@ -4474,16 +4462,32 @@ XREMain::XRE_mainRun()
}
// Need to write out the fact that the profile has been removed, the new profile
// renamed, and potentially that the selected/default profile changed.
mProfileSvc->Flush();
}
}
+ // Initialize user preferences before notifying startup observers so they're
+ // ready in time for early consumers, such as the component loader.
+ mDirProvider.InitializeUserPrefs();
+
+ {
+ nsCOMPtr<nsIObserver> startupNotifier
+ (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
+
+ startupNotifier->Observe(nullptr, APPSTARTUP_TOPIC, nullptr);
+ }
+
+ nsCOMPtr<nsIAppStartup> appStartup
+ (do_GetService(NS_APPSTARTUP_CONTRACTID));
+ NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE);
+
mDirProvider.DoStartup();
OverrideDefaultLocaleIfNeeded();
#ifdef MOZ_CRASHREPORTER
nsCString userAgentLocale;
LocaleService::GetInstance()->GetAppLocaleAsLangTag(userAgentLocale);
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("useragent_locale"), userAgentLocale);
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -33,16 +33,17 @@
#include "nsArrayEnumerator.h"
#include "nsEnumeratorUtils.h"
#include "nsReadableUtils.h"
#include "SpecialSystemDirectory.h"
#include "mozilla/dom/ScriptSettings.h"
+#include "mozilla/AutoRestore.h"
#include "mozilla/Services.h"
#include "mozilla/Omnijar.h"
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
#include <stdlib.h>
#ifdef XP_WIN
@@ -983,16 +984,32 @@ nsXREDirProvider::GetFilesInternal(const
NS_IMETHODIMP
nsXREDirProvider::GetDirectory(nsIFile* *aResult)
{
NS_ENSURE_TRUE(mProfileDir, NS_ERROR_NOT_INITIALIZED);
return mProfileDir->Clone(aResult);
}
+void
+nsXREDirProvider::InitializeUserPrefs()
+{
+ if (!mPrefsInitialized) {
+ // Temporarily set mProfileNotified to true so that the preference service
+ // can access the profile directory during initialization. Afterwards, clear
+ // it so that no other code can inadvertently access it until we get to
+ // profile-do-change.
+ AutoRestore<bool> ar(mProfileNotified);
+ mProfileNotified = true;
+
+ mozilla::Preferences::InitializeUserPrefs();
+ mPrefsInitialized = true;
+ }
+}
+
NS_IMETHODIMP
nsXREDirProvider::DoStartup()
{
nsresult rv;
if (!mProfileNotified) {
nsCOMPtr<nsIObserverService> obsSvc =
mozilla::services::GetObserverService();
@@ -1000,17 +1017,17 @@ nsXREDirProvider::DoStartup()
mProfileNotified = true;
/*
Setup prefs before profile-do-change to be able to use them to track
crashes and because we want to begin crash tracking before other code run
from this notification since they may cause crashes.
*/
- mozilla::Preferences::InitializeUserPrefs();
+ InitializeUserPrefs();
bool safeModeNecessary = false;
nsCOMPtr<nsIAppStartup> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID));
if (appStartup) {
rv = appStartup->TrackStartupCrashBegin(&safeModeNecessary);
if (NS_FAILED(rv) && rv != NS_ERROR_NOT_AVAILABLE)
NS_WARNING("Error while beginning startup crash tracking");
--- a/toolkit/xre/nsXREDirProvider.h
+++ b/toolkit/xre/nsXREDirProvider.h
@@ -47,16 +47,18 @@ public:
const nsACString* aVendorName);
// We only set the profile dir, we don't ensure that it exists;
// that is the responsibility of the toolkit profile service.
// We also don't fire profile-changed notifications... that is
// the responsibility of the apprunner.
nsresult SetProfile(nsIFile* aProfileDir, nsIFile* aProfileLocalDir);
+ void InitializeUserPrefs();
+
void DoShutdown();
static nsresult GetUserAppDataDirectory(nsIFile* *aFile) {
return GetUserDataDirectory(aFile, false, nullptr, nullptr, nullptr);
}
static nsresult GetUserLocalDataDirectory(nsIFile* *aFile) {
return GetUserDataDirectory(aFile, true, nullptr, nullptr, nullptr);
}
@@ -133,16 +135,17 @@ protected:
nsCOMPtr<nsIFile> mGREDir;
// On OSX, mGREBinDir points to .app/Contents/MacOS
nsCOMPtr<nsIFile> mGREBinDir;
// On OSX, mXULAppDir points to .app/Contents/Resources/browser
nsCOMPtr<nsIFile> mXULAppDir;
nsCOMPtr<nsIFile> mProfileDir;
nsCOMPtr<nsIFile> mProfileLocalDir;
bool mProfileNotified;
+ bool mPrefsInitialized = false;
#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
nsCOMPtr<nsIFile> mContentTempDir;
nsCOMPtr<nsIFile> mContentProcessSandboxTempDir;
#endif
nsCOMArray<nsIFile> mAppBundleDirectories;
};
#endif