Bug 1742437 - move mWebExtGlobal from ScriptLoadRequest to DOMScriptLoadContext; r=jonco,smaug

Differential Revision: https://phabricator.services.mozilla.com/D136744
This commit is contained in:
Yulia Startsev
2022-02-17 15:57:49 +00:00
parent 01bec7241f
commit c72a87da4b
6 changed files with 87 additions and 49 deletions

View File

@@ -1236,7 +1236,7 @@ nsresult EventListenerManager::CompileEventHandlerInternal(
RefPtr<ScriptFetchOptions> fetchOptions = new ScriptFetchOptions(
CORS_NONE, aElement->OwnerDoc()->GetReferrerPolicy(),
aElement->OwnerDoc()->NodePrincipal(), nullptr);
aElement->OwnerDoc()->NodePrincipal());
RefPtr<EventScript> eventScript =
new EventScript(fetchOptions, uri, aElement);

View File

@@ -163,7 +163,8 @@ void ModuleLoadRequest::ModuleLoaded() {
LOG(("ScriptLoadRequest (%p): Module loaded", this));
mModuleScript = mLoader->GetFetchedModule(mURI, GetWebExtGlobal());
mModuleScript =
mLoader->GetFetchedModule(mURI, GetLoadContext()->GetWebExtGlobal());
if (!mModuleScript || mModuleScript->HasParseError()) {
ModuleErrored();
return;

View File

@@ -114,9 +114,9 @@ void ModuleLoader::SetModuleFetchStarted(ModuleLoadRequest* aRequest) {
// Update the module map to indicate that a module is currently being fetched.
MOZ_ASSERT(aRequest->IsLoading());
MOZ_ASSERT(
!ModuleMapContainsURL(aRequest->mURI, aRequest->GetWebExtGlobal()));
ModuleMapKey key(aRequest->mURI, aRequest->GetWebExtGlobal());
MOZ_ASSERT(!ModuleMapContainsURL(aRequest->mURI,
aRequest->mLoadContext->GetWebExtGlobal()));
ModuleMapKey key(aRequest->mURI, aRequest->mLoadContext->GetWebExtGlobal());
mFetchingModules.InsertOrUpdate(
key, RefPtr<GenericNonExclusivePromise::Private>{});
}
@@ -134,7 +134,7 @@ void ModuleLoader::SetModuleFetchFinishedAndResumeWaitingRequests(
"%u)",
aRequest, aRequest->mModuleScript.get(), unsigned(aResult)));
ModuleMapKey key(aRequest->mURI, aRequest->GetWebExtGlobal());
ModuleMapKey key(aRequest->mURI, aRequest->mLoadContext->GetWebExtGlobal());
RefPtr<GenericNonExclusivePromise::Private> promise;
if (!mFetchingModules.Remove(key, getter_AddRefs(promise))) {
LOG(

View File

@@ -32,20 +32,17 @@ namespace dom {
// ScriptFetchOptions
//////////////////////////////////////////////////////////////
NS_IMPL_CYCLE_COLLECTION(ScriptFetchOptions, mTriggeringPrincipal,
mWebExtGlobal)
NS_IMPL_CYCLE_COLLECTION(ScriptFetchOptions, mTriggeringPrincipal)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(ScriptFetchOptions, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(ScriptFetchOptions, Release)
ScriptFetchOptions::ScriptFetchOptions(mozilla::CORSMode aCORSMode,
ReferrerPolicy aReferrerPolicy,
nsIPrincipal* aTriggeringPrincipal,
nsIGlobalObject* aWebExtGlobal)
nsIPrincipal* aTriggeringPrincipal)
: mCORSMode(aCORSMode),
mReferrerPolicy(aReferrerPolicy),
mTriggeringPrincipal(aTriggeringPrincipal),
mWebExtGlobal(aWebExtGlobal) {
mTriggeringPrincipal(aTriggeringPrincipal) {
MOZ_ASSERT(mTriggeringPrincipal);
}
@@ -109,7 +106,7 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMScriptLoadContext)
NS_IMPL_CYCLE_COLLECTION_CLASS(DOMScriptLoadContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMScriptLoadContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mElement)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mElement, mWebExtGlobal)
// XXX missing mLoadBlockedDocument ?
if (Runnable* runnable = tmp->mRunnable.exchange(nullptr)) {
runnable->Release();
@@ -118,14 +115,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMScriptLoadContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMScriptLoadContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoadBlockedDocument, mRequest, mElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoadBlockedDocument, mRequest, mElement,
mWebExtGlobal)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMScriptLoadContext)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
DOMScriptLoadContext::DOMScriptLoadContext(Element* aElement,
ScriptLoadRequest* aRequest)
ScriptLoadRequest* aRequest,
nsIGlobalObject* aWebExtGlobal)
: mScriptMode(ScriptMode::eBlocking),
mScriptFromHead(false),
mIsInline(true),
@@ -140,6 +139,7 @@ DOMScriptLoadContext::DOMScriptLoadContext(Element* aElement,
mRunnable(nullptr),
mIsPreload(false),
mElement(aElement),
mWebExtGlobal(aWebExtGlobal),
mRequest(aRequest),
mUnreportedPreloadError(NS_OK) {}
@@ -280,17 +280,26 @@ void DOMScriptLoadContext::PrioritizeAsPreload() {
bool DOMScriptLoadContext::IsPreload() const {
if (mRequest->IsModuleRequest() && !mRequest->IsTopLevel()) {
ModuleLoadRequest* root = mRequest->AsModuleRequest()->GetRootModule();
return root->mLoadContext->IsPreload();
return root->GetLoadContext()->IsPreload();
}
MOZ_ASSERT_IF(mIsPreload, !GetScriptElement());
return mIsPreload;
}
nsIGlobalObject* DOMScriptLoadContext::GetWebExtGlobal() const {
if (mRequest->IsModuleRequest() && !mRequest->IsTopLevel()) {
ModuleLoadRequest* root = mRequest->AsModuleRequest()->GetRootModule();
return root->GetLoadContext()->GetWebExtGlobal();
}
return mWebExtGlobal;
}
nsIScriptElement* DOMScriptLoadContext::GetScriptElement() const {
if (mRequest->IsModuleRequest() && !mRequest->IsTopLevel()) {
ModuleLoadRequest* root = mRequest->AsModuleRequest()->GetRootModule();
return root->mLoadContext->GetScriptElement();
return root->GetLoadContext()->GetScriptElement();
}
nsCOMPtr<nsIScriptElement> scriptElement = do_QueryInterface(mElement);
return scriptElement;

View File

@@ -44,11 +44,24 @@ class ScriptLoadRequestList;
class DOMScriptLoadContext;
/*
* Some options used when fetching script resources. This only loosely
* corresponds to HTML's "script fetch options".
* ScriptFetchOptions loosely corresponds to HTML's "script fetch options",
* https://html.spec.whatwg.org/multipage/webappapis.html#script-fetch-options
* with the exception of the following properties:
* cryptographic nonce
* The cryptographic nonce metadata used for the initial fetch and for
* fetching any imported modules. This is handled by the principal.
* parser metadata
* The parser metadata used for the initial fetch and for fetching any
* imported modules. This is not implemented.
* integrity metadata
* The integrity metadata used for the initial fetch. This is
* implemented in ScriptLoadRequest, as it changes for every
* ScriptLoadRequest.
*
* These are common to all modules in a module graph, and hence a single
* instance is shared by all ModuleLoadRequest objects in a graph.
* In the case of classic scripts without dynamic import, this object is
* used once. For modules, this object is propogated throughout the module
* tree. If there is a dynamically imported module in any type of script,
* the ScriptFetchOptions object will be propogated from its importer.
*/
class ScriptFetchOptions {
@@ -60,15 +73,25 @@ class ScriptFetchOptions {
ScriptFetchOptions(mozilla::CORSMode aCORSMode,
enum ReferrerPolicy aReferrerPolicy,
nsIPrincipal* aTriggeringPrincipal,
nsIGlobalObject* aWebExtGlobal);
nsIPrincipal* aTriggeringPrincipal);
/*
* The credentials mode used for the initial fetch (for module scripts)
* and for fetching any imported modules (for both module scripts and
* classic scripts)
*/
const mozilla::CORSMode mCORSMode;
/*
* The referrer policy used for the initial fetch and for fetching any
* imported modules
*/
const enum ReferrerPolicy mReferrerPolicy;
/*
* related to cryptographic nonce, used to determine CSP
*/
nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
// Global that initiated this request, when using a WebExtension
// content-script.
nsCOMPtr<nsIGlobalObject> mWebExtGlobal;
};
/*
@@ -227,13 +250,6 @@ class ScriptLoadRequest
return mFetchOptions->mTriggeringPrincipal;
}
// This will return nullptr in most cases,
// unless this is a module being imported by a WebExtension content script.
// In that case it's the Sandbox global executing that code.
nsIGlobalObject* GetWebExtGlobal() const {
return mFetchOptions->mWebExtGlobal;
}
void ClearScriptSource();
void SetScript(JSScript* aScript);
@@ -339,7 +355,8 @@ class DOMScriptLoadContext : public PreloaderBase {
virtual ~DOMScriptLoadContext();
public:
explicit DOMScriptLoadContext(Element* aElement, ScriptLoadRequest* aRequest);
explicit DOMScriptLoadContext(Element* aElement, ScriptLoadRequest* aRequest,
nsIGlobalObject* aWebExtGlobal = nullptr);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMScriptLoadContext)
@@ -363,6 +380,11 @@ class DOMScriptLoadContext : public PreloaderBase {
bool IsPreload() const;
// This will return nullptr in most cases,
// unless this is a module being imported by a WebExtension content script.
// In that case it's the Sandbox global executing that code.
nsIGlobalObject* GetWebExtGlobal() const;
bool CompileStarted() const {
return mRequest->InCompilingStage() ||
(mRequest->IsReadyToRun() && mWasCompiledOMT);
@@ -455,6 +477,9 @@ class DOMScriptLoadContext : public PreloaderBase {
// Set on scripts and top level modules.
bool mIsPreload;
nsCOMPtr<Element> mElement;
// Global that initiated this request, when using a WebExtension
// content-script.
nsCOMPtr<nsIGlobalObject> mWebExtGlobal;
RefPtr<ScriptLoadRequest> mRequest;

View File

@@ -681,8 +681,8 @@ bool HostImportModuleDynamically(JSContext* aCx,
xpc::IsWebExtensionContentScriptSandbox(global->GetGlobalJSObject()));
}
options = new ScriptFetchOptions(
mozilla::CORS_NONE, document->GetReferrerPolicy(), principal, global);
options = new ScriptFetchOptions(mozilla::CORS_NONE,
document->GetReferrerPolicy(), principal);
baseURL = document->GetDocBaseURI();
}
@@ -860,11 +860,12 @@ nsresult ScriptLoader::StartModuleLoad(ScriptLoadRequest* aRequest) {
// Check whether the module has been fetched or is currently being fetched,
// and if so wait for it rather than starting a new fetch.
ModuleLoadRequest* request = aRequest->AsModuleRequest();
if (mModuleLoader->ModuleMapContainsURL(request->mURI,
aRequest->GetWebExtGlobal())) {
if (mModuleLoader->ModuleMapContainsURL(
request->mURI, aRequest->GetLoadContext()->GetWebExtGlobal())) {
LOG(("ScriptLoadRequest (%p): Waiting for module fetch", aRequest));
mModuleLoader
->WaitForModuleFetch(request->mURI, aRequest->GetWebExtGlobal())
->WaitForModuleFetch(request->mURI,
aRequest->GetLoadContext()->GetWebExtGlobal())
->Then(GetMainThreadSerialEventTarget(), __func__, request,
&ModuleLoadRequest::ModuleLoaded,
&ModuleLoadRequest::LoadFailed);
@@ -956,7 +957,7 @@ nsresult ScriptLoader::StartLoadInternal(ScriptLoadRequest* aRequest,
if (cic && StaticPrefs::dom_script_loader_bytecode_cache_enabled() &&
// Bug 1436400: no bytecode cache support for modules yet.
!aRequest->IsModuleRequest()) {
MOZ_ASSERT(!aRequest->GetWebExtGlobal(),
MOZ_ASSERT(!aRequest->GetLoadContext()->GetWebExtGlobal(),
"Can not bytecode cache WebExt code");
if (!aRequest->IsLoadingSource()) {
// Inform the HTTP cache that we prefer to have information coming from
@@ -1143,8 +1144,8 @@ already_AddRefed<ScriptLoadRequest> ScriptLoader::CreateLoadRequest(
const SRIMetadata& aIntegrity, ReferrerPolicy aReferrerPolicy) {
nsIURI* referrer = mDocument->GetDocumentURIAsReferrer();
nsCOMPtr<Element> domElement = do_QueryInterface(aElement);
ScriptFetchOptions* fetchOptions = new ScriptFetchOptions(
aCORSMode, aReferrerPolicy, aTriggeringPrincipal, nullptr);
ScriptFetchOptions* fetchOptions =
new ScriptFetchOptions(aCORSMode, aReferrerPolicy, aTriggeringPrincipal);
if (aKind == ScriptKind::eClassic) {
RefPtr<ScriptLoadRequest> aRequest =
@@ -2137,8 +2138,9 @@ void ScriptLoader::FireScriptEvaluated(nsresult aResult,
already_AddRefed<nsIGlobalObject> ScriptLoader::GetGlobalForRequest(
ScriptLoadRequest* aRequest) {
if (aRequest->GetWebExtGlobal()) {
nsCOMPtr<nsIGlobalObject> global = aRequest->GetWebExtGlobal();
if (aRequest->GetLoadContext()->GetWebExtGlobal()) {
nsCOMPtr<nsIGlobalObject> global =
aRequest->GetLoadContext()->GetWebExtGlobal();
return global.forget();
}
@@ -2362,9 +2364,9 @@ nsresult ScriptLoader::EvaluateScriptElement(ScriptLoadRequest* aRequest) {
nsCOMPtr<nsIGlobalObject> globalObject;
nsCOMPtr<nsIScriptContext> context;
if (aRequest->GetWebExtGlobal()) {
if (aRequest->GetLoadContext()->GetWebExtGlobal()) {
// Executing a module from a WebExtension content-script.
globalObject = aRequest->GetWebExtGlobal();
globalObject = aRequest->GetLoadContext()->GetWebExtGlobal();
} else {
// Otherwise we have to ensure that there is a nsIScriptContext.
nsCOMPtr<nsIScriptGlobalObject> scriptGlobal =
@@ -2530,7 +2532,7 @@ nsresult ScriptLoader::EvaluateScript(nsIGlobalObject* aGlobalObject,
// Create a ClassicScript object and associate it with the JSScript.
RefPtr<ClassicScript> classicScript =
new ClassicScript(aRequest->mFetchOptions, aRequest->mBaseURL,
aRequest->mLoadContext->mElement);
aRequest->GetLoadContext()->mElement);
JS::RootedValue classicScriptValue(cx, JS::PrivateValue(classicScript));
JS::CompileOptions options(cx);
@@ -2689,7 +2691,8 @@ void ScriptLoader::EncodeBytecode() {
while (!mBytecodeEncodingQueue.isEmpty()) {
request = mBytecodeEncodingQueue.StealFirst();
MOZ_ASSERT(!request->IsModuleRequest());
MOZ_ASSERT(!request->GetWebExtGlobal(), "Not handling global above");
MOZ_ASSERT(!request->GetLoadContext()->GetWebExtGlobal(),
"Not handling global above");
EncodeRequestBytecode(aes.cx(), request);
request->mScriptBytecode.clearAndFree();
request->DropBytecodeCacheReferences();
@@ -2791,7 +2794,7 @@ void ScriptLoader::GiveUpBytecodeEncoding() {
TRACE_FOR_TEST_NONE(request->GetLoadContext()->GetScriptElement(),
"scriptloader_bytecode_failed");
MOZ_ASSERT(!request->IsModuleRequest());
MOZ_ASSERT(!request->GetWebExtGlobal());
MOZ_ASSERT(!request->GetLoadContext()->GetWebExtGlobal());
if (aes.isSome()) {
JS::RootedScript script(aes->cx(), request->mScript);