Bug 1579367 - Initialize XPCJSContext explicitly, after loading user prefs. r=kmag

This way we get the correct values for start-up prefs in the parent process.

Differential Revision: https://phabricator.services.mozilla.com/D51061

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jan de Mooij 2019-11-22 12:40:17 +00:00
Родитель ed982614a2
Коммит 83d309574b
15 изменённых файлов: 106 добавлений и 38 удалений

Просмотреть файл

@ -85,7 +85,6 @@ using namespace mozilla;
using namespace mozilla::dom;
nsIIOService* nsScriptSecurityManager::sIOService = nullptr;
JSContext* nsScriptSecurityManager::sContext = nullptr;
bool nsScriptSecurityManager::sStrictFileOriginPolicy = true;
namespace {
@ -1371,22 +1370,28 @@ nsresult nsScriptSecurityManager::Init() {
mSystemPrincipal = system;
return NS_OK;
}
void nsScriptSecurityManager::InitJSCallbacks(JSContext* aCx) {
//-- Register security check callback in the JS engine
// Currently this is used to control access to function.caller
sContext = danger::GetJSContext();
static const JSSecurityCallbacks securityCallbacks = {
ContentSecurityPolicyPermitsJSAction,
JSPrincipalsSubsume,
};
MOZ_ASSERT(!JS_GetSecurityCallbacks(sContext));
JS_SetSecurityCallbacks(sContext, &securityCallbacks);
JS_InitDestroyPrincipalsCallback(sContext, nsJSPrincipals::Destroy);
MOZ_ASSERT(!JS_GetSecurityCallbacks(aCx));
JS_SetSecurityCallbacks(aCx, &securityCallbacks);
JS_InitDestroyPrincipalsCallback(aCx, nsJSPrincipals::Destroy);
JS_SetTrustedPrincipals(sContext, system);
JS_SetTrustedPrincipals(aCx, BasePrincipal::Cast(mSystemPrincipal));
}
return NS_OK;
void nsScriptSecurityManager::ClearJSCallbacks(JSContext* aCx) {
JS_SetSecurityCallbacks(aCx, nullptr);
JS_SetTrustedPrincipals(aCx, nullptr);
}
static StaticRefPtr<nsScriptSecurityManager> gScriptSecMan;
@ -1404,12 +1409,6 @@ nsScriptSecurityManager::~nsScriptSecurityManager(void) {
}
void nsScriptSecurityManager::Shutdown() {
if (sContext) {
JS_SetSecurityCallbacks(sContext, nullptr);
JS_SetTrustedPrincipals(sContext, nullptr);
sContext = nullptr;
}
NS_IF_RELEASE(sIOService);
BundleHelper::Shutdown();
}

Просмотреть файл

@ -51,6 +51,9 @@ class nsScriptSecurityManager final : public nsIScriptSecurityManager {
// Invoked exactly once, by XPConnect.
static void InitStatics();
void InitJSCallbacks(JSContext* aCx);
void ClearJSCallbacks(JSContext* aCx);
static already_AddRefed<mozilla::SystemPrincipal>
SystemPrincipalSingletonConstructor();
@ -121,7 +124,6 @@ class nsScriptSecurityManager final : public nsIScriptSecurityManager {
static nsIIOService* sIOService;
static nsIStringBundle* sStrBundle;
static JSContext* sContext;
};
#endif // nsScriptSecurityManager_h__

Просмотреть файл

@ -1262,6 +1262,10 @@ nsresult XPCJSContext::Initialize() {
Preferences::RegisterCallback(ReloadPrefsCallback, "fuzzing.enabled", this);
#endif
MOZ_RELEASE_ASSERT(JS::InitSelfHostedCode(cx), "InitSelfHostedCode failed");
MOZ_RELEASE_ASSERT(Runtime()->InitializeStrings(cx),
"InitializeStrings failed");
return NS_OK;
}

Просмотреть файл

@ -32,6 +32,7 @@
#include "nsIPlatformInfo.h"
#include "nsPIDOMWindow.h"
#include "nsPrintfCString.h"
#include "nsScriptSecurityManager.h"
#include "nsThreadPool.h"
#include "nsWindowSizes.h"
#include "mozilla/Preferences.h"
@ -1120,6 +1121,8 @@ void XPCJSRuntime::Shutdown(JSContext* cx) {
JS::SetGCSliceCallback(cx, mPrevGCSliceCallback);
nsScriptSecurityManager::GetScriptSecurityManager()->ClearJSCallbacks(cx);
// Shut down the helper threads
gHelperThreads->Shutdown();
gHelperThreads = nullptr;
@ -3050,6 +3053,8 @@ void XPCJSRuntime::Initialize(JSContext* cx) {
// these jsids filled in later when we have a JSContext to work with.
mStrIDs[0] = JSID_VOID;
nsScriptSecurityManager::GetScriptSecurityManager()->InitJSCallbacks(cx);
// Unconstrain the runtime's threshold on nominal heap size, to avoid
// triggering GC too often if operating continuously near an arbitrary
// finite threshold (0xffffffff is infinity for uint32_t parameters).

Просмотреть файл

@ -26,6 +26,7 @@
#include "mozilla/dom/DOMException.h"
#include "mozilla/dom/Exceptions.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/ScriptPreloader.h"
#include "nsDOMMutationObserver.h"
#include "nsICycleCollectorListener.h"
@ -71,17 +72,35 @@ nsXPConnect::nsXPConnect() : mShuttingDown(false) {
JS::SetProfilingThreadCallbacks(profiler_register_thread,
profiler_unregister_thread);
#endif
}
// static
void nsXPConnect::InitJSContext() {
MOZ_ASSERT(!gContext);
XPCJSContext* xpccx = XPCJSContext::NewXPCJSContext();
if (!xpccx) {
MOZ_CRASH("Couldn't create XPCJSContext.");
}
gContext = xpccx;
mRuntime = xpccx->Runtime();
gSelf->mRuntime = xpccx->Runtime();
// Initialize our singleton scopes.
gSelf->mRuntime->InitSingletonScopes();
mozJSComponentLoader::InitStatics();
// Initialize the script preloader cache.
Unused << mozilla::ScriptPreloader::GetSingleton();
nsJSContext::EnsureStatics();
}
void xpc::InitializeJSContext() { nsXPConnect::InitJSContext(); }
nsXPConnect::~nsXPConnect() {
MOZ_ASSERT(XPCJSContext::Get() == gContext);
MOZ_ASSERT(mRuntime);
mRuntime->DeleteSingletonScopes();
@ -136,19 +155,6 @@ void nsXPConnect::InitStatics() {
gScriptSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager();
gScriptSecurityManager->GetSystemPrincipal(&gSystemPrincipal);
MOZ_RELEASE_ASSERT(gSystemPrincipal);
JSContext* cx = XPCJSContext::Get()->Context();
if (!JS::InitSelfHostedCode(cx)) {
MOZ_CRASH("InitSelfHostedCode failed");
}
if (!gSelf->mRuntime->InitializeStrings(cx)) {
MOZ_CRASH("InitializeStrings failed");
}
// Initialize our singleton scopes.
gSelf->mRuntime->InitSingletonScopes();
mozJSComponentLoader::InitStatics();
}
// static

Просмотреть файл

@ -246,6 +246,8 @@ class nsXPConnect final : public nsIXPConnect {
// Called by module code on dll shutdown.
static void ReleaseXPConnectSingleton();
static void InitJSContext();
void RecordTraversal(void* p, nsISupports* s);
protected:
@ -258,7 +260,7 @@ class nsXPConnect final : public nsIXPConnect {
static nsXPConnect* gSelf;
static bool gOnceAliveNowDead;
XPCJSRuntime* mRuntime;
XPCJSRuntime* mRuntime = nullptr;
bool mShuttingDown;
friend class nsIXPConnect;

Просмотреть файл

@ -683,6 +683,8 @@ inline bool IsInAutomation() {
return sAutomationPrefIsSet && AreNonLocalConnectionsDisabled();
}
void InitializeJSContext();
/**
* Extract the native nsID object from a JS ID, IfaceID, ClassID, or ContractID
* value.

Просмотреть файл

@ -161,7 +161,6 @@ nsresult nsLayoutStatics::Initialize() {
#endif
StartupJSEnvironment();
nsJSContext::EnsureStatics();
nsGlobalWindowInner::Init();
nsGlobalWindowOuter::Init();

Просмотреть файл

@ -3668,7 +3668,10 @@ void Preferences::InitializeUserPrefs() {
// Don't set mCurrentFile until we're done so that dirty flags work properly.
sPreferences->mCurrentFile = prefsFile.forget();
}
/* static */
void Preferences::FinishInitializingUserPrefs() {
sPreferences->NotifyServiceObservers(NS_PREFSERVICE_READ_TOPIC_ID);
// At this point all the prefs files have been read and telemetry has been

Просмотреть файл

@ -108,6 +108,7 @@ class Preferences final : public nsIPrefService,
// Initialize user prefs from prefs.js/user.js
static void InitializeUserPrefs();
static void FinishInitializingUserPrefs();
// Returns the singleton instance which is addreffed.
static already_AddRefed<Preferences> GetInstanceForService();

Просмотреть файл

@ -1202,7 +1202,7 @@ class ScopedXPCOMStartup {
ScopedXPCOMStartup() : mServiceManager(nullptr) {}
~ScopedXPCOMStartup();
nsresult Initialize();
nsresult Initialize(bool aInitJSContext = true);
nsresult SetWindowCreator(nsINativeAppSupport* native);
private:
@ -1259,13 +1259,13 @@ static const mozilla::Module::ContractIDEntry kXREContracts[] = {
extern const mozilla::Module kXREModule = {mozilla::Module::kVersion, kXRECIDs,
kXREContracts};
nsresult ScopedXPCOMStartup::Initialize() {
nsresult ScopedXPCOMStartup::Initialize(bool aInitJSContext) {
NS_ASSERTION(gDirServiceProvider, "Should not get here!");
nsresult rv;
rv = NS_InitXPCOM(&mServiceManager, gDirServiceProvider->GetAppDir(),
gDirServiceProvider);
gDirServiceProvider, aInitJSContext);
if (NS_FAILED(rv)) {
NS_ERROR("Couldn't start xpcom!");
mServiceManager = nullptr;
@ -4344,10 +4344,21 @@ nsresult XREMain::XRE_mainRun() {
}
}
// We'd like to initialize the JSContext *after* reading the user prefs.
// Unfortunately that's not possible if we have to do profile migration
// because that requires us to execute JS before reading user prefs.
// Restarting the browser after profile migration would fix this. See
// bug 1592523.
bool initializedJSContext = false;
{
// Profile Migration
if (mAppData->flags & NS_XRE_ENABLE_PROFILE_MIGRATOR && gDoMigration) {
gDoMigration = false;
xpc::InitializeJSContext();
initializedJSContext = true;
nsCOMPtr<nsIProfileMigrator> pm(
do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID));
if (pm) {
@ -4389,6 +4400,18 @@ nsresult XREMain::XRE_mainRun() {
// ready in time for early consumers, such as the component loader.
mDirProvider.InitializeUserPrefs();
// Now that all (user) prefs have been loaded we can initialize the main
// thread's JSContext.
if (!initializedJSContext) {
xpc::InitializeJSContext();
}
// Finally, now that JS has been initialized, we can finish pref loading. This
// needs to happen after JS and XPConnect initialization because AutoConfig
// files require JS execution. Note that this means AutoConfig files can't
// override JS engine start-up prefs.
mDirProvider.FinishInitializingUserPrefs();
nsAppStartupNotifier::NotifyObservers(APPSTARTUP_CATEGORY);
nsCOMPtr<nsIAppStartup> appStartup(components::AppStartup::Service());
@ -4710,11 +4733,13 @@ int XREMain::XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig) {
bool appInitiatedRestart = false;
// Start the real application
// Start the real application. We use |aInitJSContext = false| because
// XRE_mainRun wants to initialize the JSContext after reading user prefs.
mScopedXPCOM = MakeUnique<ScopedXPCOMStartup>();
if (!mScopedXPCOM) return 1;
rv = mScopedXPCOM->Initialize();
rv = mScopedXPCOM->Initialize(/* aInitJSContext = */ false);
NS_ENSURE_SUCCESS(rv, 1);
// run!

Просмотреть файл

@ -884,6 +884,17 @@ void nsXREDirProvider::InitializeUserPrefs() {
mProfileNotified = true;
mozilla::Preferences::InitializeUserPrefs();
}
}
void nsXREDirProvider::FinishInitializingUserPrefs() {
if (!mPrefsInitialized) {
// See InitializeUserPrefs above.
mozilla::AutoRestore<bool> ar(mProfileNotified);
mProfileNotified = true;
mozilla::Preferences::FinishInitializingUserPrefs();
mPrefsInitialized = true;
}
}

Просмотреть файл

@ -59,6 +59,7 @@ class nsXREDirProvider final : public nsIDirectoryServiceProvider2,
nsresult SetProfile(nsIFile* aProfileDir, nsIFile* aProfileLocalDir);
void InitializeUserPrefs();
void FinishInitializingUserPrefs();
void DoShutdown();

Просмотреть файл

@ -248,7 +248,8 @@ static bool sInitializedJS = false;
// Note that on OSX, aBinDirectory will point to .app/Contents/Resources/browser
EXPORT_XPCOM_API(nsresult)
NS_InitXPCOM(nsIServiceManager** aResult, nsIFile* aBinDirectory,
nsIDirectoryServiceProvider* aAppFileLocationProvider) {
nsIDirectoryServiceProvider* aAppFileLocationProvider,
bool aInitJSContext) {
static bool sInitialized = false;
if (sInitialized) {
return NS_ERROR_FAILURE;
@ -461,7 +462,6 @@ NS_InitXPCOM(nsIServiceManager** aResult, nsIFile* aBinDirectory,
// Init mozilla::SharedThreadPool (which needs the service manager).
mozilla::SharedThreadPool::InitStatics();
mozilla::ScriptPreloader::GetSingleton();
mozilla::scache::StartupCache::GetSingleton();
mozilla::AvailableMemoryTracker::Init();
@ -485,6 +485,10 @@ NS_InitXPCOM(nsIServiceManager** aResult, nsIFile* aBinDirectory,
loop->thread_name().c_str(), loop->transient_hang_timeout(),
loop->permanent_hang_timeout());
if (aInitJSContext) {
xpc::InitializeJSContext();
}
return NS_OK;
}

Просмотреть файл

@ -63,6 +63,9 @@ struct Module;
* component registry preferences and so on; or use
* <CODE>nullptr</CODE> for the default behaviour.
*
* @param aInitJSContext Whether the nsXPCJSContext should be initialized at
* this point.
*
* @see NS_NewLocalFile
* @see nsIFile
* @see nsIDirectoryServiceProvider
@ -75,7 +78,8 @@ struct Module;
*/
XPCOM_API(nsresult)
NS_InitXPCOM(nsIServiceManager** aResult, nsIFile* aBinDirectory,
nsIDirectoryServiceProvider* aAppFileLocationProvider);
nsIDirectoryServiceProvider* aAppFileLocationProvider,
bool aInitJSContext = true);
/**
* Initialize only minimal components of XPCOM. This ensures nsThreadManager,