diff --git a/dom/cache/TypeUtils.cpp b/dom/cache/TypeUtils.cpp index 2d4cb30eb..46fef3daa 100644 --- a/dom/cache/TypeUtils.cpp +++ b/dom/cache/TypeUtils.cpp @@ -252,7 +252,7 @@ TypeUtils::ToResponse(const CacheResponse& aIn) { if (aIn.type() == ResponseType::Error) { RefPtr error = InternalResponse::NetworkError(); - RefPtr r = new Response(GetGlobalObject(), error); + RefPtr r = new Response(GetGlobalObject(), error, nullptr); return r.forget(); } @@ -301,7 +301,7 @@ TypeUtils::ToResponse(const CacheResponse& aIn) } MOZ_DIAGNOSTIC_ASSERT(ir); - RefPtr ref = new Response(GetGlobalObject(), ir); + RefPtr ref = new Response(GetGlobalObject(), ir, nullptr); return ref.forget(); } already_AddRefed @@ -344,7 +344,7 @@ already_AddRefed TypeUtils::ToRequest(const CacheRequest& aIn) { RefPtr internalRequest = ToInternalRequest(aIn); - RefPtr request = new Request(GetGlobalObject(), internalRequest); + RefPtr request = new Request(GetGlobalObject(), internalRequest, nullptr); return request.forget(); } diff --git a/dom/fetch/Fetch.cpp b/dom/fetch/Fetch.cpp index 9952bdc8c..1e1fb85dd 100644 --- a/dom/fetch/Fetch.cpp +++ b/dom/fetch/Fetch.cpp @@ -110,6 +110,12 @@ public: return mSignalMainThread; } + AbortSignal* + GetSignalForTargetThread() + { + return mFollowingSignal; + } + void Shutdown() { @@ -160,7 +166,7 @@ public: } AbortSignal* - GetAbortSignal() + GetAbortSignalForMainThread() { MOZ_ASSERT(NS_IsMainThread()); @@ -171,6 +177,18 @@ public: return mSignalProxy->GetOrCreateSignalForMainThread(); } + AbortSignal* + GetAbortSignalForTargetThread() + { + mPromiseProxy->GetWorkerPrivate()->AssertIsOnWorkerThread(); + + if (!mSignalProxy) { + return nullptr; + } + + return mSignalProxy->GetSignalForTargetThread(); + } + void OnResponseAvailableInternal(InternalResponse* aResponse) override; @@ -204,14 +222,16 @@ class MainThreadFetchResolver final : public FetchDriverObserver RefPtr mPromise; RefPtr mResponse; RefPtr mFetchObserver; + RefPtr mSignal; nsCOMPtr mDocument; NS_DECL_OWNINGTHREAD public: - MainThreadFetchResolver(Promise* aPromise, FetchObserver* aObserver) + MainThreadFetchResolver(Promise* aPromise, FetchObserver* aObserver, AbortSignal* aSignal) : mPromise(aPromise) , mFetchObserver(aObserver) + , mSignal(aSignal) {} void @@ -286,7 +306,7 @@ public: fetch->SetWorkerScript(spec); } - RefPtr signal = mResolver->GetAbortSignal(); + RefPtr signal = mResolver->GetAbortSignalForMainThread(); // ...but release it before calling Fetch, because mResolver's callback can // be called synchronously and they want the mutex, too. @@ -328,10 +348,7 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput, RefPtr r = request->GetInternalRequest(); - RefPtr signal; - if (aInit.mSignal.WasPassed()) { - signal = &aInit.mSignal.Value(); - } + RefPtr signal = request->GetSignal(); if (signal && signal->Aborted()) { // An already aborted signal should reject immediately. @@ -374,7 +391,7 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput, Telemetry::Accumulate(Telemetry::FETCH_IS_MAINTHREAD, 1); RefPtr resolver = - new MainThreadFetchResolver(p, observer); + new MainThreadFetchResolver(p, observer, signal); RefPtr fetch = new FetchDriver(r, principal, loadGroup); fetch->SetDocument(doc); resolver->SetDocument(doc); @@ -419,7 +436,7 @@ MainThreadFetchResolver::OnResponseAvailableInternal(InternalResponse* aResponse } nsCOMPtr go = mPromise->GetParentObject(); - mResponse = new Response(go, aResponse); + mResponse = new Response(go, aResponse, mSignal); mPromise->MaybeResolve(mResponse); } else { if (mFetchObserver) { @@ -482,7 +499,7 @@ public: } RefPtr global = aWorkerPrivate->GlobalScope(); - RefPtr response = new Response(global, mInternalResponse); + RefPtr response = new Response(global, mInternalResponse, mResolver->GetAbortSignalForTargetThread()); promise->MaybeResolve(response); } else { if (mResolver->mFetchObserver) { @@ -1638,6 +1655,12 @@ template already_AddRefed FetchBody::ConsumeBody(ConsumeType aType, ErrorResult& aRv) { + RefPtr signal = DerivedClass()->GetSignal(); + if (signal && signal->Aborted()) { + aRv.Throw(NS_ERROR_DOM_ABORT_ERR); + return nullptr; + } + mConsumeType = aType; if (BodyUsed()) { aRv.ThrowTypeError(); diff --git a/dom/fetch/Fetch.h b/dom/fetch/Fetch.h index 68ec09c8e..43bb0245b 100644 --- a/dom/fetch/Fetch.h +++ b/dom/fetch/Fetch.h @@ -163,6 +163,9 @@ public: // Always set whenever the FetchBody is created on the worker thread. workers::WorkerPrivate* mWorkerPrivate; + virtual AbortSignal* + GetSignal() const = 0; + protected: FetchBody(); diff --git a/dom/fetch/Request.cpp b/dom/fetch/Request.cpp index 7ca5b43c4..7a54f2e61 100644 --- a/dom/fetch/Request.cpp +++ b/dom/fetch/Request.cpp @@ -32,15 +32,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Request) NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_END -Request::Request(nsIGlobalObject* aOwner, InternalRequest* aRequest) +Request::Request(nsIGlobalObject* aOwner, InternalRequest* aRequest, AbortSignal* aSignal) : FetchBody() , mOwner(aOwner) , mRequest(aRequest) + , mSignal(aSignal) { MOZ_ASSERT(aRequest->Headers()->Guard() == HeadersGuardEnum::Immutable || aRequest->Headers()->Guard() == HeadersGuardEnum::Request || aRequest->Headers()->Guard() == HeadersGuardEnum::Request_no_cors); SetMimeType(); + + // aSignal can be null. } Request::~Request() @@ -281,6 +284,8 @@ Request::Constructor(const GlobalObject& aGlobal, RefPtr request; nsCOMPtr global = do_QueryInterface(aGlobal.GetAsSupports()); + + RefPtr signal; if (aInput.IsRequest()) { RefPtr inputReq = &aInput.GetAsRequest(); @@ -295,6 +300,7 @@ Request::Constructor(const GlobalObject& aGlobal, } request = inputReq->GetInternalRequest(); + signal = inputReq->GetOrCreateSignal(); } else { // aInput is USVString. // We need to get url before we create a InternalRequest. @@ -413,6 +419,10 @@ Request::Constructor(const GlobalObject& aGlobal, request->SetReferrerPolicy(aInit.mReferrerPolicy.Value()); } + if (aInit.mSignal.WasPassed()) { + signal = &aInit.mSignal.Value(); + } + if (NS_IsMainThread()) { nsCOMPtr window = do_QueryInterface(global); if (window) { @@ -574,7 +584,7 @@ Request::Constructor(const GlobalObject& aGlobal, } } - RefPtr domRequest = new Request(global, request); + RefPtr domRequest = new Request(global, request, signal); domRequest->SetMimeType(); if (aInput.IsRequest()) { @@ -590,7 +600,7 @@ Request::Constructor(const GlobalObject& aGlobal, } already_AddRefed -Request::Clone(ErrorResult& aRv) const +Request::Clone(ErrorResult& aRv) { if (BodyUsed()) { aRv.ThrowTypeError(); @@ -603,7 +613,7 @@ Request::Clone(ErrorResult& aRv) const return nullptr; } - RefPtr request = new Request(mOwner, ir); + RefPtr request = new Request(mOwner, ir, GetOrCreateSignal()); return request.forget(); } @@ -617,5 +627,21 @@ Request::Headers_() return mHeaders; } +AbortSignal* +Request::GetOrCreateSignal() +{ + if (!mSignal) { + mSignal = new AbortSignal(false); + } + + return mSignal; +} + +AbortSignal* +Request::GetSignal() const +{ + return mSignal; +} + } // namespace dom } // namespace mozilla diff --git a/dom/fetch/Request.h b/dom/fetch/Request.h index f6fe9be7b..34cbc52cf 100644 --- a/dom/fetch/Request.h +++ b/dom/fetch/Request.h @@ -33,7 +33,7 @@ class Request final : public nsISupports NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Request) public: - Request(nsIGlobalObject* aOwner, InternalRequest* aRequest); + Request(nsIGlobalObject* aOwner, InternalRequest* aRequest, AbortSignal* aSignal); static bool RequestContextEnabled(JSContext* aCx, JSObject* aObj); @@ -142,7 +142,7 @@ public: } already_AddRefed - Clone(ErrorResult& aRv) const; + Clone(ErrorResult& aRv); already_AddRefed GetInternalRequest(); @@ -153,13 +153,22 @@ public: return mRequest->GetPrincipalInfo(); } + AbortSignal* + GetOrCreateSignal(); + + // This can return a null AbortSignal. + AbortSignal* + GetSignal() const override; + private: ~Request(); nsCOMPtr mOwner; RefPtr mRequest; + // Lazily created. RefPtr mHeaders; + RefPtr mSignal; }; } // namespace dom diff --git a/dom/fetch/Response.cpp b/dom/fetch/Response.cpp index a76071bf8..09016cd41 100644 --- a/dom/fetch/Response.cpp +++ b/dom/fetch/Response.cpp @@ -33,10 +33,11 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Response) NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_END -Response::Response(nsIGlobalObject* aGlobal, InternalResponse* aInternalResponse) +Response::Response(nsIGlobalObject* aGlobal, InternalResponse* aInternalResponse, AbortSignal* aSignal) : FetchBody() , mOwner(aGlobal) , mInternalResponse(aInternalResponse) + , mSignal(aSignal) { MOZ_ASSERT(aInternalResponse->Headers()->Guard() == HeadersGuardEnum::Immutable || aInternalResponse->Headers()->Guard() == HeadersGuardEnum::Response); @@ -52,7 +53,7 @@ Response::Error(const GlobalObject& aGlobal) { nsCOMPtr global = do_QueryInterface(aGlobal.GetAsSupports()); RefPtr error = InternalResponse::NetworkError(); - RefPtr r = new Response(global, error); + RefPtr r = new Response(global, error, nullptr); return r.forget(); } @@ -172,7 +173,7 @@ Response::Constructor(const GlobalObject& aGlobal, internalResponse->InitChannelInfo(worker->GetChannelInfo()); } - RefPtr r = new Response(global, internalResponse); + RefPtr r = new Response(global, internalResponse, nullptr); if (aInit.mHeaders.WasPassed()) { internalResponse->Headers()->Clear(); @@ -235,7 +236,7 @@ Response::Clone(ErrorResult& aRv) const } RefPtr ir = mInternalResponse->Clone(); - RefPtr response = new Response(mOwner, ir); + RefPtr response = new Response(mOwner, ir, mSignal); return response.forget(); } @@ -249,7 +250,7 @@ Response::CloneUnfiltered(ErrorResult& aRv) const RefPtr clone = mInternalResponse->Clone(); RefPtr ir = clone->Unfiltered(); - RefPtr ref = new Response(mOwner, ir); + RefPtr ref = new Response(mOwner, ir, mSignal); return ref.forget(); } diff --git a/dom/fetch/Response.h b/dom/fetch/Response.h index 64b3c5f45..8526732ee 100644 --- a/dom/fetch/Response.h +++ b/dom/fetch/Response.h @@ -33,7 +33,7 @@ class Response final : public nsISupports NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Response) public: - Response(nsIGlobalObject* aGlobal, InternalResponse* aInternalResponse); + Response(nsIGlobalObject* aGlobal, InternalResponse* aInternalResponse, AbortSignal* aSignal); Response(const Response& aOther) = delete; @@ -134,13 +134,21 @@ public: already_AddRefed GetInternalResponse() const; + AbortSignal* + GetSignal() const override + { + return mSignal; + } + private: ~Response(); nsCOMPtr mOwner; RefPtr mInternalResponse; + // Lazily created RefPtr mHeaders; + RefPtr mSignal; }; } // namespace dom diff --git a/dom/flyweb/FlyWebPublishedServer.cpp b/dom/flyweb/FlyWebPublishedServer.cpp index c28c5cc85..80be3ac0f 100644 --- a/dom/flyweb/FlyWebPublishedServer.cpp +++ b/dom/flyweb/FlyWebPublishedServer.cpp @@ -82,7 +82,7 @@ FlyWebPublishedServer::FireFetchEvent(InternalRequest* aRequest) { nsCOMPtr global = do_QueryInterface(GetOwner()); RefPtr e = new FlyWebFetchEvent(this, - new Request(global, aRequest), + new Request(global, aRequest, nullptr), aRequest); e->Init(this); e->InitEvent(NS_LITERAL_STRING("fetch"), false, false); @@ -95,7 +95,7 @@ FlyWebPublishedServer::FireWebsocketEvent(InternalRequest* aConnectRequest) { nsCOMPtr global = do_QueryInterface(GetOwner()); RefPtr e = new FlyWebWebSocketEvent(this, - new Request(global, aConnectRequest), + new Request(global, aConnectRequest, nullptr), aConnectRequest); e->Init(this); e->InitEvent(NS_LITERAL_STRING("websocket"), false, false); diff --git a/dom/webidl/Request.webidl b/dom/webidl/Request.webidl index 7536dfe2e..f489a05a0 100644 --- a/dom/webidl/Request.webidl +++ b/dom/webidl/Request.webidl @@ -27,6 +27,10 @@ interface Request { readonly attribute RequestRedirect redirect; readonly attribute DOMString integrity; + [Func="AbortController::IsEnabled", + BinaryName="getOrCreateSignal"] + readonly attribute AbortSignal signal; + [Throws, NewObject] Request clone(); diff --git a/dom/workers/ScriptLoader.cpp b/dom/workers/ScriptLoader.cpp index eb62cbf42..7442b9576 100644 --- a/dom/workers/ScriptLoader.cpp +++ b/dom/workers/ScriptLoader.cpp @@ -699,7 +699,7 @@ private: ir->SetPrincipalInfo(Move(principalInfo)); RefPtr response = - new mozilla::dom::Response(mCacheCreator->Global(), ir); + new mozilla::dom::Response(mCacheCreator->Global(), ir, nullptr); mozilla::dom::RequestOrUSVString request; diff --git a/dom/workers/ServiceWorkerPrivate.cpp b/dom/workers/ServiceWorkerPrivate.cpp index f826a1bbd..5af89ed38 100644 --- a/dom/workers/ServiceWorkerPrivate.cpp +++ b/dom/workers/ServiceWorkerPrivate.cpp @@ -1607,7 +1607,7 @@ private: if (NS_WARN_IF(!global)) { return false; } - RefPtr request = new Request(global, internalReq); + RefPtr request = new Request(global, internalReq, nullptr); MOZ_ASSERT_IF(internalReq->IsNavigationRequest(), request->Redirect() == RequestRedirect::Manual); diff --git a/dom/workers/ServiceWorkerScriptCache.cpp b/dom/workers/ServiceWorkerScriptCache.cpp index 9d62a89c0..1366af643 100644 --- a/dom/workers/ServiceWorkerScriptCache.cpp +++ b/dom/workers/ServiceWorkerScriptCache.cpp @@ -560,7 +560,7 @@ private: ir->SetPrincipalInfo(Move(mPrincipalInfo)); } - RefPtr response = new Response(aCache->GetGlobalObject(), ir); + RefPtr response = new Response(aCache->GetGlobalObject(), ir, nullptr); RequestOrUSVString request; request.SetAsUSVString().Rebind(URL().Data(), URL().Length());