зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
ed982614a2
Коммит
83d309574b
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче