From a8602cc877cb4fc007655cd0f52b52b1e7165bc8 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 10 Jun 2020 21:08:58 +0000 Subject: Issue #1587 - Part 1: Implement FetchController/FetchSignal interface --- dom/fetch/FetchController.cpp | 110 ++++++++++++++++++++++++++++++++++++++++++ dom/fetch/FetchController.h | 66 +++++++++++++++++++++++++ dom/fetch/FetchSignal.cpp | 72 +++++++++++++++++++++++++++ dom/fetch/FetchSignal.h | 47 ++++++++++++++++++ dom/fetch/Request.h | 1 + dom/fetch/moz.build | 4 ++ 6 files changed, 300 insertions(+) create mode 100644 dom/fetch/FetchController.cpp create mode 100644 dom/fetch/FetchController.h create mode 100644 dom/fetch/FetchSignal.cpp create mode 100644 dom/fetch/FetchSignal.h (limited to 'dom/fetch') diff --git a/dom/fetch/FetchController.cpp b/dom/fetch/FetchController.cpp new file mode 100644 index 000000000..b3d8a4d9c --- /dev/null +++ b/dom/fetch/FetchController.cpp @@ -0,0 +1,110 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "FetchController.h" +#include "FetchSignal.h" +#include "mozilla/dom/FetchControllerBinding.h" +#include "WorkerPrivate.h" + +namespace mozilla { +namespace dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FetchController, mGlobal, mSignal) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(FetchController) +NS_IMPL_CYCLE_COLLECTING_RELEASE(FetchController) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FetchController) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +/* static */ bool +FetchController::IsEnabled(JSContext* aCx, JSObject* aGlobal) +{ + if (NS_IsMainThread()) { + return Preferences::GetBool("dom.fetchController.enabled", false); + } + + using namespace workers; + + // Otherwise, check the pref via the WorkerPrivate + WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx); + if (!workerPrivate) { + return false; + } + + return workerPrivate->FetchControllerEnabled(); +} + +/* static */ already_AddRefed +FetchController::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv) +{ + nsCOMPtr global = do_QueryInterface(aGlobal.GetAsSupports()); + if (!global) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + RefPtr fetchController = new FetchController(global); + return fetchController.forget(); +} + +FetchController::FetchController(nsIGlobalObject* aGlobal) + : mGlobal(aGlobal) + , mAborted(false) +{} + +JSObject* +FetchController::WrapObject(JSContext* aCx, JS::Handle aGivenProto) +{ + return FetchControllerBinding::Wrap(aCx, this, aGivenProto); +} + +nsIGlobalObject* +FetchController::GetParentObject() const +{ + return mGlobal; +} + +FetchSignal* +FetchController::Signal() +{ + if (!mSignal) { + mSignal = new FetchSignal(this, mAborted); + } + + return mSignal; +} + +void +FetchController::Abort() +{ + if (mAborted) { + return; + } + + mAborted = true; + + if (mSignal) { + mSignal->Abort(); + } +} + +void +FetchController::Follow(FetchSignal& aSignal) +{ + // TODO +} + +void +FetchController::Unfollow(FetchSignal& aSignal) +{ + // TODO +} + +} // dom namespace +} // mozilla namespace diff --git a/dom/fetch/FetchController.h b/dom/fetch/FetchController.h new file mode 100644 index 000000000..854c6f974 --- /dev/null +++ b/dom/fetch/FetchController.h @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_FetchController_h +#define mozilla_dom_FetchController_h + +#include "mozilla/dom/BindingDeclarations.h" +#include "nsCycleCollectionParticipant.h" +#include "nsWrapperCache.h" +#include "mozilla/ErrorResult.h" +#include "nsIGlobalObject.h" + +namespace mozilla { +namespace dom { + +class FetchSignal; + +class FetchController final : public nsISupports + , public nsWrapperCache +{ +public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(FetchController) + + static bool + IsEnabled(JSContext* aCx, JSObject* aGlobal); + + static already_AddRefed + Constructor(const GlobalObject& aGlobal, ErrorResult& aRv); + + explicit FetchController(nsIGlobalObject* aGlobal); + + JSObject* + WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; + + nsIGlobalObject* + GetParentObject() const; + + FetchSignal* + Signal(); + + void + Abort(); + + void + Follow(FetchSignal& aSignal); + + void + Unfollow(FetchSignal& aSignal); + +private: + ~FetchController() = default; + + nsCOMPtr mGlobal; + RefPtr mSignal; + + bool mAborted; +}; + +} // dom namespace +} // mozilla namespace + +#endif // mozilla_dom_FetchController_h diff --git a/dom/fetch/FetchSignal.cpp b/dom/fetch/FetchSignal.cpp new file mode 100644 index 000000000..4395dbcf2 --- /dev/null +++ b/dom/fetch/FetchSignal.cpp @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "FetchSignal.h" +#include "FetchController.h" +#include "mozilla/dom/Event.h" +#include "mozilla/dom/FetchSignalBinding.h" + +namespace mozilla { +namespace dom { + +NS_IMPL_CYCLE_COLLECTION_CLASS(FetchSignal) + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(FetchSignal, + DOMEventTargetHelper) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mController) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(FetchSignal, + DOMEventTargetHelper) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mController) +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FetchSignal) +NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) + +NS_IMPL_ADDREF_INHERITED(FetchSignal, DOMEventTargetHelper) +NS_IMPL_RELEASE_INHERITED(FetchSignal, DOMEventTargetHelper) + +FetchSignal::FetchSignal(FetchController* aController, + bool aAborted) + : DOMEventTargetHelper(aController->GetParentObject()) + , mController(aController) + , mAborted(aAborted) +{} + +JSObject* +FetchSignal::WrapObject(JSContext* aCx, JS::Handle aGivenProto) +{ + return FetchSignalBinding::Wrap(aCx, this, aGivenProto); +} + +bool +FetchSignal::Aborted() const +{ + return mAborted; +} + +void +FetchSignal::Abort() +{ + MOZ_ASSERT(!mAborted); + mAborted = true; + + EventInit init; + init.mBubbles = false; + init.mCancelable = false; + + // TODO which kind of event should we dispatch here? + + RefPtr event = + Event::Constructor(this, NS_LITERAL_STRING("abort"), init); + event->SetTrusted(true); + + DispatchDOMEvent(nullptr, event, nullptr, nullptr); +} + +} // dom namespace +} // mozilla namespace diff --git a/dom/fetch/FetchSignal.h b/dom/fetch/FetchSignal.h new file mode 100644 index 000000000..5bb16b834 --- /dev/null +++ b/dom/fetch/FetchSignal.h @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_FetchSignal_h +#define mozilla_dom_FetchSignal_h + +#include "mozilla/DOMEventTargetHelper.h" + +namespace mozilla { +namespace dom { + +class FetchController; + +class FetchSignal final : public DOMEventTargetHelper +{ +public: + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FetchSignal, DOMEventTargetHelper) + + FetchSignal(FetchController* aController, bool aAborted); + + JSObject* + WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; + + bool + Aborted() const; + + void + Abort(); + + IMPL_EVENT_HANDLER(abort); + +private: + ~FetchSignal() = default; + + RefPtr mController; + + bool mAborted; +}; + +} // dom namespace +} // mozilla namespace + +#endif // mozilla_dom_FetchSignal_h diff --git a/dom/fetch/Request.h b/dom/fetch/Request.h index d33c74812..56a75e5af 100644 --- a/dom/fetch/Request.h +++ b/dom/fetch/Request.h @@ -12,6 +12,7 @@ #include "nsWrapperCache.h" #include "mozilla/dom/Fetch.h" +#include "mozilla/dom/FetchSignal.h" #include "mozilla/dom/InternalRequest.h" // Required here due to certain WebIDL enums/classes being declared in both // files. diff --git a/dom/fetch/moz.build b/dom/fetch/moz.build index be820ab57..757f857f2 100644 --- a/dom/fetch/moz.build +++ b/dom/fetch/moz.build @@ -7,8 +7,10 @@ EXPORTS.mozilla.dom += [ 'ChannelInfo.h', 'Fetch.h', + 'FetchController.h', 'FetchDriver.h', 'FetchIPCTypes.h', + 'FetchSignal.h', 'FetchUtil.h', 'Headers.h', 'InternalHeaders.h', @@ -27,7 +29,9 @@ UNIFIED_SOURCES += [ SOURCES += [ 'ChannelInfo.cpp', + 'FetchController.cpp', 'FetchDriver.cpp', + 'FetchSignal.cpp', 'FetchUtil.cpp', 'Headers.cpp', 'InternalHeaders.cpp', -- cgit v1.2.3 From be82b3331878fb2956d22d9bd3906fca3ab39751 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 10 Jun 2020 21:33:28 +0000 Subject: Issue #1587 - Part 2: Implement controller follow/unfollow --- dom/fetch/FetchController.cpp | 23 +++++++++++-- dom/fetch/FetchController.h | 11 +++++-- dom/fetch/FetchSignal.cpp | 77 +++++++++++++++++++++++++++++++++++++++++-- dom/fetch/FetchSignal.h | 31 +++++++++++++++++ 4 files changed, 134 insertions(+), 8 deletions(-) (limited to 'dom/fetch') diff --git a/dom/fetch/FetchController.cpp b/dom/fetch/FetchController.cpp index b3d8a4d9c..2eb40b980 100644 --- a/dom/fetch/FetchController.cpp +++ b/dom/fetch/FetchController.cpp @@ -12,7 +12,8 @@ namespace mozilla { namespace dom { -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FetchController, mGlobal, mSignal) +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FetchController, mGlobal, mSignal, + mFollowingSignal) NS_IMPL_CYCLE_COLLECTING_ADDREF(FetchController) NS_IMPL_CYCLE_COLLECTING_RELEASE(FetchController) @@ -97,13 +98,29 @@ FetchController::Abort() void FetchController::Follow(FetchSignal& aSignal) { - // TODO + FetchSignal::Follower::Follow(&aSignal); } void FetchController::Unfollow(FetchSignal& aSignal) { - // TODO + if (mFollowingSignal != &aSignal) { + return; + } + + FetchSignal::Follower::Unfollow(); +} + +FetchSignal* +FetchController::Following() const +{ + return mFollowingSignal; +} + +void +FetchController::Aborted() +{ + Abort(); } } // dom namespace diff --git a/dom/fetch/FetchController.h b/dom/fetch/FetchController.h index 854c6f974..7a0132dca 100644 --- a/dom/fetch/FetchController.h +++ b/dom/fetch/FetchController.h @@ -8,6 +8,7 @@ #define mozilla_dom_FetchController_h #include "mozilla/dom/BindingDeclarations.h" +#include "mozilla/dom/FetchSignal.h" #include "nsCycleCollectionParticipant.h" #include "nsWrapperCache.h" #include "mozilla/ErrorResult.h" @@ -16,10 +17,9 @@ namespace mozilla { namespace dom { -class FetchSignal; - class FetchController final : public nsISupports , public nsWrapperCache + , public FetchSignal::Follower { public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS @@ -51,6 +51,13 @@ public: void Unfollow(FetchSignal& aSignal); + FetchSignal* + Following() const; + + // FetchSignal::Follower + + void Aborted() override; + private: ~FetchController() = default; diff --git a/dom/fetch/FetchSignal.cpp b/dom/fetch/FetchSignal.cpp index 4395dbcf2..1924263e8 100644 --- a/dom/fetch/FetchSignal.cpp +++ b/dom/fetch/FetchSignal.cpp @@ -16,12 +16,12 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(FetchSignal) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(FetchSignal, DOMEventTargetHelper) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mController) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mController) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(FetchSignal, DOMEventTargetHelper) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mController) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mController) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FetchSignal) @@ -55,6 +55,11 @@ FetchSignal::Abort() MOZ_ASSERT(!mAborted); mAborted = true; + // Let's inform the followers. + for (uint32_t i = 0; i < mFollowers.Length(); ++i) { + mFollowers[i]->Aborted(); + } + EventInit init; init.mBubbles = false; init.mCancelable = false; @@ -65,7 +70,73 @@ FetchSignal::Abort() Event::Constructor(this, NS_LITERAL_STRING("abort"), init); event->SetTrusted(true); - DispatchDOMEvent(nullptr, event, nullptr, nullptr); + bool dummy; + DispatchEvent(event, &dummy); +} + +void +FetchSignal::AddFollower(FetchSignal::Follower* aFollower) +{ + MOZ_DIAGNOSTIC_ASSERT(aFollower); + if (!mFollowers.Contains(aFollower)) { + mFollowers.AppendElement(aFollower); + } +} + +void +FetchSignal::RemoveFollower(FetchSignal::Follower* aFollower) +{ + MOZ_DIAGNOSTIC_ASSERT(aFollower); + mFollowers.RemoveElement(aFollower); +} + +bool +FetchSignal::CanAcceptFollower(FetchSignal::Follower* aFollower) const +{ + MOZ_DIAGNOSTIC_ASSERT(aFollower); + + if (aFollower == mController) { + return false; + } + + FetchSignal* following = mController->Following(); + if (!following) { + return true; + } + + return following->CanAcceptFollower(aFollower); +} + +// FetchSignal::Follower +// ---------------------------------------------------------------------------- + +FetchSignal::Follower::~Follower() +{ + Unfollow(); +} + +void +FetchSignal::Follower::Follow(FetchSignal* aSignal) +{ + MOZ_DIAGNOSTIC_ASSERT(aSignal); + + if (!aSignal->CanAcceptFollower(this)) { + return; + } + + Unfollow(); + + mFollowingSignal = aSignal; + aSignal->AddFollower(this); +} + +void +FetchSignal::Follower::Unfollow() +{ + if (mFollowingSignal) { + mFollowingSignal->RemoveFollower(this); + mFollowingSignal = nullptr; + } } } // dom namespace diff --git a/dom/fetch/FetchSignal.h b/dom/fetch/FetchSignal.h index 5bb16b834..5d2f13c68 100644 --- a/dom/fetch/FetchSignal.h +++ b/dom/fetch/FetchSignal.h @@ -13,10 +13,29 @@ namespace mozilla { namespace dom { class FetchController; +class FetchSignal; class FetchSignal final : public DOMEventTargetHelper { public: + // This class must be implemented by objects who want to follow a FetchSignal. + class Follower + { + public: + virtual void Aborted() = 0; + + protected: + virtual ~Follower(); + + void + Follow(FetchSignal* aSignal); + + void + Unfollow(); + + RefPtr mFollowingSignal; + }; + NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FetchSignal, DOMEventTargetHelper) @@ -33,11 +52,23 @@ public: IMPL_EVENT_HANDLER(abort); + void + AddFollower(Follower* aFollower); + + void + RemoveFollower(Follower* aFollower); + + bool + CanAcceptFollower(Follower* aFollower) const; + private: ~FetchSignal() = default; RefPtr mController; + // Raw pointers. Follower unregisters itself in the DTOR. + nsTArray mFollowers; + bool mAborted; }; -- cgit v1.2.3 From 1ca6039fb86cfab374fa0f4d37d9a084aa810f28 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 10 Jun 2020 21:51:44 +0000 Subject: Issue #1587 - Part 3: Hook FetchSignal up to the Fetch API --- dom/fetch/Fetch.cpp | 158 +++++++++++++++++++++++++++++++++++++++++----- dom/fetch/FetchDriver.cpp | 45 ++++++++++--- dom/fetch/FetchDriver.h | 29 +++++++-- dom/fetch/FetchSignal.cpp | 8 +++ dom/fetch/FetchSignal.h | 1 + 5 files changed, 211 insertions(+), 30 deletions(-) (limited to 'dom/fetch') diff --git a/dom/fetch/Fetch.cpp b/dom/fetch/Fetch.cpp index f944352e3..11e93205c 100644 --- a/dom/fetch/Fetch.cpp +++ b/dom/fetch/Fetch.cpp @@ -52,41 +52,137 @@ namespace dom { using namespace workers; +// This class helps the proxying of FetchSignal changes cross threads. +class FetchSignalProxy final : public FetchSignal::Follower +{ + // This is created and released on the main-thread. + RefPtr mSignalMainThread; + + // This value is used only for the creation of FetchSignal on the + // main-thread. They are not updated. + const bool mAborted; + + // This runnable propagates changes from the FetchSignal on workers to the + // FetchSignal on main-thread. + class FetchSignalProxyRunnable final : public Runnable + { + RefPtr mProxy; + + public: + explicit FetchSignalProxyRunnable(FetchSignalProxy* aProxy) + : mProxy(aProxy) + {} + + NS_IMETHOD + Run() override + { + MOZ_ASSERT(NS_IsMainThread()); + FetchSignal* signal = mProxy->GetOrCreateSignalForMainThread(); + signal->Abort(); + return NS_OK; + } + }; + +public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FetchSignalProxy) + + explicit FetchSignalProxy(FetchSignal* aSignal) + : mAborted(aSignal->Aborted()) + { + Follow(aSignal); + } + + void + Aborted() override + { + RefPtr runnable = + new FetchSignalProxyRunnable(this); + NS_DispatchToMainThread(runnable); + } + + FetchSignal* + GetOrCreateSignalForMainThread() + { + MOZ_ASSERT(NS_IsMainThread()); + if (!mSignalMainThread) { + mSignalMainThread = new FetchSignal(mAborted); + } + return mSignalMainThread; + } + + void + Shutdown() + { + Unfollow(); + } + +private: + ~FetchSignalProxy() + { + NS_ReleaseOnMainThread(mSignalMainThread.forget()); + } +}; + class WorkerFetchResolver final : public FetchDriverObserver { friend class MainThreadFetchRunnable; + friend class WorkerFetchResponseEndBase; friend class WorkerFetchResponseEndRunnable; friend class WorkerFetchResponseRunnable; RefPtr mPromiseProxy; + RefPtr mSignalProxy; + public: // Returns null if worker is shutting down. static already_AddRefed - Create(workers::WorkerPrivate* aWorkerPrivate, Promise* aPromise) + Create(workers::WorkerPrivate* aWorkerPrivate, Promise* aPromise, + FetchSignal* aSignal) { MOZ_ASSERT(aWorkerPrivate); aWorkerPrivate->AssertIsOnWorkerThread(); - RefPtr proxy = PromiseWorkerProxy::Create(aWorkerPrivate, aPromise); + RefPtr proxy = + PromiseWorkerProxy::Create(aWorkerPrivate, aPromise); if (!proxy) { return nullptr; } - RefPtr r = new WorkerFetchResolver(proxy); + RefPtr signalProxy; + if (aSignal) { + signalProxy = new FetchSignalProxy(aSignal); + } + + RefPtr r = new WorkerFetchResolver(proxy, signalProxy); return r.forget(); } + FetchSignal* + GetFetchSignal() + { + MOZ_ASSERT(NS_IsMainThread()); + + if (!mSignalProxy) { + return nullptr; + } + + return mSignalProxy->GetOrCreateSignalForMainThread(); + } + void OnResponseAvailableInternal(InternalResponse* aResponse) override; void - OnResponseEnd() override; + OnResponseEnd(FetchDriverObserver::EndReason eReason) override; private: - explicit WorkerFetchResolver(PromiseWorkerProxy* aProxy) + WorkerFetchResolver(PromiseWorkerProxy* aProxy, + FetchSignalProxy* aSignalProxy) : mPromiseProxy(aProxy) + , mSignalProxy(aSignalProxy) { MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(mPromiseProxy); + } ~WorkerFetchResolver() @@ -115,8 +211,12 @@ public: mDocument = aDocument; } - virtual void OnResponseEnd() override + void OnResponseEnd(FetchDriverObserver::EndReason aReason) override { + if (aReason == eAborted) { + mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR); + } + FlushConsoleReport(); } @@ -170,9 +270,11 @@ public: fetch->SetWorkerScript(spec); } + RefPtr signal = mResolver->GetFetchSignal(); + // ...but release it before calling Fetch, because mResolver's callback can // be called synchronously and they want the mutex, too. - return fetch->Fetch(mResolver); + return fetch->Fetch(signal, mResolver); } }; @@ -210,6 +312,12 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput, RefPtr r = request->GetInternalRequest(); + RefPtr signal; + if (aInit.mSignal.WasPassed()) { + signal = &aInit.mSignal.Value(); + // Let's FetchDriver to deal with an already aborted signal. + } + if (NS_IsMainThread()) { nsCOMPtr window = do_QueryInterface(aGlobal); nsCOMPtr doc; @@ -240,7 +348,7 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput, RefPtr fetch = new FetchDriver(r, principal, loadGroup); fetch->SetDocument(doc); resolver->SetDocument(doc); - aRv = fetch->Fetch(resolver); + aRv = fetch->Fetch(signal, resolver); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } @@ -252,7 +360,7 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput, r->SetSkipServiceWorker(); } - RefPtr resolver = WorkerFetchResolver::Create(worker, p); + RefPtr resolver = WorkerFetchResolver::Create(worker, p, signal); if (!resolver) { NS_WARNING("Could not add WorkerFetchResolver workerHolder to worker"); aRv.Throw(NS_ERROR_DOM_ABORT_ERR); @@ -306,6 +414,7 @@ public: , mResolver(aResolver) , mInternalResponse(aResponse) { + MOZ_ASSERT(mResolver); } bool @@ -332,9 +441,13 @@ public: class WorkerFetchResponseEndBase { RefPtr mPromiseProxy; + RefPtr mSignalProxy; + public: - explicit WorkerFetchResponseEndBase(PromiseWorkerProxy* aPromiseProxy) + WorkerFetchResponseEndBase(PromiseWorkerProxy* aPromiseProxy, + FetchSignalProxy* aSignalProxy) : mPromiseProxy(aPromiseProxy) + , mSignalProxy(aSignalProxy) { MOZ_ASSERT(mPromiseProxy); } @@ -344,7 +457,16 @@ public: { MOZ_ASSERT(aWorkerPrivate); aWorkerPrivate->AssertIsOnWorkerThread(); + + RefPtr promise = mPromiseProxy->WorkerPromise(); + promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR); + mPromiseProxy->CleanUp(); + + if (mSignalProxy) { + mSignalProxy->Shutdown(); + mSignalProxy = nullptr; + } } }; @@ -352,9 +474,10 @@ class WorkerFetchResponseEndRunnable final : public MainThreadWorkerRunnable , public WorkerFetchResponseEndBase { public: - explicit WorkerFetchResponseEndRunnable(PromiseWorkerProxy* aPromiseProxy) + WorkerFetchResponseEndRunnable(PromiseWorkerProxy* aPromiseProxy, + FetchSignalProxy* aSignalProxy) : MainThreadWorkerRunnable(aPromiseProxy->GetWorkerPrivate()) - , WorkerFetchResponseEndBase(aPromiseProxy) + , WorkerFetchResponseEndBase(aPromiseProxy, aSignalProxy) { } @@ -379,9 +502,10 @@ class WorkerFetchResponseEndControlRunnable final : public MainThreadWorkerContr , public WorkerFetchResponseEndBase { public: - explicit WorkerFetchResponseEndControlRunnable(PromiseWorkerProxy* aPromiseProxy) + WorkerFetchResponseEndControlRunnable(PromiseWorkerProxy* aPromiseProxy, + FetchSignalProxy* aSignalProxy) : MainThreadWorkerControlRunnable(aPromiseProxy->GetWorkerPrivate()) - , WorkerFetchResponseEndBase(aPromiseProxy) + , WorkerFetchResponseEndBase(aPromiseProxy, aSignalProxy) { } @@ -415,7 +539,7 @@ WorkerFetchResolver::OnResponseAvailableInternal(InternalResponse* aResponse) } void -WorkerFetchResolver::OnResponseEnd() +WorkerFetchResolver::OnResponseEnd(FetchDriverObserver::EndReason aReason) { AssertIsOnMainThread(); MutexAutoLock lock(mPromiseProxy->Lock()); @@ -426,11 +550,11 @@ WorkerFetchResolver::OnResponseEnd() FlushConsoleReport(); RefPtr r = - new WorkerFetchResponseEndRunnable(mPromiseProxy); + new WorkerFetchResponseEndRunnable(mPromiseProxy, mSignalProxy); if (!r->Dispatch()) { RefPtr cr = - new WorkerFetchResponseEndControlRunnable(mPromiseProxy); + new WorkerFetchResponseEndControlRunnable(mPromiseProxy, mSignalProxy); // This can fail if the worker thread is canceled or killed causing // the PromiseWorkerProxy to give up its WorkerHolder immediately, // allowing the worker thread to become Dead. diff --git a/dom/fetch/FetchDriver.cpp b/dom/fetch/FetchDriver.cpp index 6294b0dc5..448ec64cd 100644 --- a/dom/fetch/FetchDriver.cpp +++ b/dom/fetch/FetchDriver.cpp @@ -67,7 +67,7 @@ FetchDriver::~FetchDriver() } nsresult -FetchDriver::Fetch(FetchDriverObserver* aObserver) +FetchDriver::Fetch(FetchSignal* aSignal, FetchDriverObserver* aObserver) { workers::AssertIsOnMainThread(); #ifdef DEBUG @@ -90,6 +90,18 @@ FetchDriver::Fetch(FetchDriverObserver* aObserver) } mRequest->SetPrincipalInfo(Move(principalInfo)); + + // If the signal is aborted, it's time to inform the observer and terminate + // the operation. + if (aSignal) { + if (aSignal->Aborted()) { + Aborted(); + return NS_OK; + } + + Follow(aSignal); + } + if (NS_FAILED(HttpFetch())) { FailWithNetworkError(); } @@ -114,11 +126,7 @@ FetchDriver::HttpFetch() nsAutoCString url; mRequest->GetURL(url); nsCOMPtr uri; - rv = NS_NewURI(getter_AddRefs(uri), - url, - nullptr, - nullptr, - ios); + rv = NS_NewURI(getter_AddRefs(uri), url, nullptr, nullptr, ios); NS_ENSURE_SUCCESS(rv, rv); // Unsafe requests aren't allowed with when using no-core mode. @@ -380,6 +388,8 @@ FetchDriver::HttpFetch() NS_ENSURE_SUCCESS(rv, rv); // Step 4 onwards of "HTTP Fetch" is handled internally by Necko. + + mChannel = chan; return NS_OK; } already_AddRefed @@ -433,9 +443,11 @@ FetchDriver::FailWithNetworkError() #ifdef DEBUG mResponseAvailableCalled = true; #endif - mObserver->OnResponseEnd(); + mObserver->OnResponseEnd(FetchDriverObserver::eByNetworking); mObserver = nullptr; } + + mChannel = nullptr; } namespace { @@ -777,10 +789,11 @@ FetchDriver::OnStopRequest(nsIRequest* aRequest, #endif } - mObserver->OnResponseEnd(); + mObserver->OnResponseEnd(FetchDriverObserver::eByNetworking); mObserver = nullptr; } + mChannel = nullptr; return NS_OK; } @@ -921,5 +934,21 @@ FetchDriver::SetRequestHeaders(nsIHttpChannel* aChannel) const } } +void FetchDriver::Aborted() +{ + if (mObserver) { +#ifdef DEBUG + mResponseAvailableCalled = true; +#endif + mObserver->OnResponseEnd(FetchDriverObserver::eAborted); + mObserver = nullptr; + } + + if (mChannel) { + mChannel->Cancel(NS_BINDING_ABORTED); + mChannel = nullptr; + } +} + } // namespace dom } // namespace mozilla diff --git a/dom/fetch/FetchDriver.h b/dom/fetch/FetchDriver.h index f74298a48..0ca9a34ee 100644 --- a/dom/fetch/FetchDriver.h +++ b/dom/fetch/FetchDriver.h @@ -12,6 +12,7 @@ #include "nsIStreamListener.h" #include "nsIThreadRetargetableStreamListener.h" #include "mozilla/ConsoleReportCollector.h" +#include "mozilla/dom/FetchSignal.h" #include "mozilla/dom/SRIMetadata.h" #include "mozilla/RefPtr.h" @@ -49,7 +50,14 @@ public: mGotResponseAvailable = true; OnResponseAvailableInternal(aResponse); } - virtual void OnResponseEnd() + + enum EndReason + { + eAborted, + eByNetworking, + }; + + virtual void OnResponseEnd(EndReason aReason) { }; nsIConsoleReportCollector* GetReporter() const @@ -58,6 +66,7 @@ public: } virtual void FlushConsoleReport() = 0; + protected: virtual ~FetchDriverObserver() { }; @@ -72,7 +81,8 @@ private: class FetchDriver final : public nsIStreamListener, public nsIChannelEventSink, public nsIInterfaceRequestor, - public nsIThreadRetargetableStreamListener + public nsIThreadRetargetableStreamListener, + public FetchSignal::Follower { public: NS_DECL_ISUPPORTS @@ -82,9 +92,12 @@ public: NS_DECL_NSIINTERFACEREQUESTOR NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER - explicit FetchDriver(InternalRequest* aRequest, nsIPrincipal* aPrincipal, - nsILoadGroup* aLoadGroup); - NS_IMETHOD Fetch(FetchDriverObserver* aObserver); + FetchDriver(InternalRequest* aRequest, + nsIPrincipal* aPrincipal, + nsILoadGroup* aLoadGroup); + + nsresult Fetch(FetchSignal* aSignal, + FetchDriverObserver* aObserver); void SetDocument(nsIDocument* aDocument); @@ -96,6 +109,11 @@ public: mWorkerScript = aWorkerScirpt; } + // FetchSignal::Follower + + void + Aborted() override; + private: nsCOMPtr mPrincipal; nsCOMPtr mLoadGroup; @@ -104,6 +122,7 @@ private: nsCOMPtr mPipeOutputStream; RefPtr mObserver; nsCOMPtr mDocument; + nsCOMPtr mChannel; nsAutoPtr mSRIDataVerifier; SRIMetadata mSRIMetadata; nsCString mWorkerScript; diff --git a/dom/fetch/FetchSignal.cpp b/dom/fetch/FetchSignal.cpp index 1924263e8..07ad6b53d 100644 --- a/dom/fetch/FetchSignal.cpp +++ b/dom/fetch/FetchSignal.cpp @@ -37,6 +37,10 @@ FetchSignal::FetchSignal(FetchController* aController, , mAborted(aAborted) {} +FetchSignal::FetchSignal(bool aAborted) + : mAborted(aAborted) +{} + JSObject* FetchSignal::WrapObject(JSContext* aCx, JS::Handle aGivenProto) { @@ -95,6 +99,10 @@ FetchSignal::CanAcceptFollower(FetchSignal::Follower* aFollower) const { MOZ_DIAGNOSTIC_ASSERT(aFollower); + if (!mController) { + return true; + } + if (aFollower == mController) { return false; } diff --git a/dom/fetch/FetchSignal.h b/dom/fetch/FetchSignal.h index 5d2f13c68..4970f03de 100644 --- a/dom/fetch/FetchSignal.h +++ b/dom/fetch/FetchSignal.h @@ -40,6 +40,7 @@ public: NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FetchSignal, DOMEventTargetHelper) FetchSignal(FetchController* aController, bool aAborted); + explicit FetchSignal(bool aAborted); JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; -- cgit v1.2.3 From ec792e2ac7614b8e4281f496d288f20441b837bf Mon Sep 17 00:00:00 2001 From: Moonchild Date: Thu, 11 Jun 2020 08:22:04 +0000 Subject: Issue #1587 - Part 4: Implement FetchObserver --- dom/fetch/FetchObserver.cpp | 66 +++++++++++++++++++++++++++++++++++++++++++++ dom/fetch/FetchObserver.h | 46 +++++++++++++++++++++++++++++++ dom/fetch/moz.build | 2 ++ 3 files changed, 114 insertions(+) create mode 100644 dom/fetch/FetchObserver.cpp create mode 100644 dom/fetch/FetchObserver.h (limited to 'dom/fetch') diff --git a/dom/fetch/FetchObserver.cpp b/dom/fetch/FetchObserver.cpp new file mode 100644 index 000000000..bc8c6fc2b --- /dev/null +++ b/dom/fetch/FetchObserver.cpp @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "FetchObserver.h" +#include "WorkerPrivate.h" + +namespace mozilla { +namespace dom { + +NS_IMPL_CYCLE_COLLECTION_CLASS(FetchObserver) + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(FetchObserver, + DOMEventTargetHelper) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(FetchObserver, + DOMEventTargetHelper) +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FetchObserver) +NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) + +NS_IMPL_ADDREF_INHERITED(FetchObserver, DOMEventTargetHelper) +NS_IMPL_RELEASE_INHERITED(FetchObserver, DOMEventTargetHelper) + +/* static */ bool +FetchObserver::IsEnabled(JSContext* aCx, JSObject* aGlobal) +{ + if (NS_IsMainThread()) { + return Preferences::GetBool("dom.fetchObserver.enabled", false); + } + + using namespace workers; + + // Otherwise, check the pref via the WorkerPrivate + WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx); + if (!workerPrivate) { + return false; + } + + return workerPrivate->FetchObserverEnabled(); +} + +FetchObserver::FetchObserver(nsIGlobalObject* aGlobal, + FetchState aState) + : DOMEventTargetHelper(aGlobal) + , mState(aState) +{} + +JSObject* +FetchObserver::WrapObject(JSContext* aCx, JS::Handle aGivenProto) +{ + return FetchObserverBinding::Wrap(aCx, this, aGivenProto); +} + +FetchState +FetchObserver::State() const +{ + return mState; +} + +} // dom namespace +} // mozilla namespace diff --git a/dom/fetch/FetchObserver.h b/dom/fetch/FetchObserver.h new file mode 100644 index 000000000..81f8e7b09 --- /dev/null +++ b/dom/fetch/FetchObserver.h @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_FetchObserver_h +#define mozilla_dom_FetchObserver_h + +#include "mozilla/DOMEventTargetHelper.h" +#include "mozilla/dom/FetchObserverBinding.h" + +namespace mozilla { +namespace dom { + +class FetchObserver final : public DOMEventTargetHelper +{ +public: + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FetchObserver, DOMEventTargetHelper) + + static bool + IsEnabled(JSContext* aCx, JSObject* aGlobal); + + FetchObserver(nsIGlobalObject* aGlobal, FetchState aState); + + JSObject* + WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; + + FetchState + State() const; + + IMPL_EVENT_HANDLER(statechange); + IMPL_EVENT_HANDLER(requestprogress); + IMPL_EVENT_HANDLER(responseprogress); + +private: + ~FetchObserver() = default; + + FetchState mState; +}; + +} // dom namespace +} // mozilla namespace + +#endif // mozilla_dom_FetchObserver_h diff --git a/dom/fetch/moz.build b/dom/fetch/moz.build index 757f857f2..82fd99173 100644 --- a/dom/fetch/moz.build +++ b/dom/fetch/moz.build @@ -10,6 +10,7 @@ EXPORTS.mozilla.dom += [ 'FetchController.h', 'FetchDriver.h', 'FetchIPCTypes.h', + 'FetchObserver.h', 'FetchSignal.h', 'FetchUtil.h', 'Headers.h', @@ -31,6 +32,7 @@ SOURCES += [ 'ChannelInfo.cpp', 'FetchController.cpp', 'FetchDriver.cpp', + 'FetchObserver.cpp', 'FetchSignal.cpp', 'FetchUtil.cpp', 'Headers.cpp', -- cgit v1.2.3 From fdc11c731c0d0176c4522f1eb8b1d390d6505c6d Mon Sep 17 00:00:00 2001 From: Moonchild Date: Thu, 11 Jun 2020 08:51:07 +0000 Subject: Issue #1587 - Part 5: Hook FetchObserver up to the Fetch API --- dom/fetch/Fetch.cpp | 170 +++++++++++++++++++++++++++++++++++--------- dom/fetch/FetchDriver.cpp | 37 ++++++++++ dom/fetch/FetchDriver.h | 2 + dom/fetch/FetchObserver.cpp | 57 ++++++++++++++- dom/fetch/FetchObserver.h | 10 ++- 5 files changed, 237 insertions(+), 39 deletions(-) (limited to 'dom/fetch') diff --git a/dom/fetch/Fetch.cpp b/dom/fetch/Fetch.cpp index 11e93205c..04aa7fd91 100644 --- a/dom/fetch/Fetch.cpp +++ b/dom/fetch/Fetch.cpp @@ -39,6 +39,7 @@ #include "mozilla/dom/URLSearchParams.h" #include "mozilla/dom/workers/ServiceWorkerManager.h" +#include "FetchObserver.h" #include "InternalRequest.h" #include "InternalResponse.h" @@ -126,18 +127,20 @@ private: class WorkerFetchResolver final : public FetchDriverObserver { friend class MainThreadFetchRunnable; + friend class WorkerDataAvailableRunnable; friend class WorkerFetchResponseEndBase; friend class WorkerFetchResponseEndRunnable; friend class WorkerFetchResponseRunnable; RefPtr mPromiseProxy; RefPtr mSignalProxy; + RefPtr mFetchObserver; public: // Returns null if worker is shutting down. static already_AddRefed Create(workers::WorkerPrivate* aWorkerPrivate, Promise* aPromise, - FetchSignal* aSignal) + FetchSignal* aSignal, FetchObserver* aObserver) { MOZ_ASSERT(aWorkerPrivate); aWorkerPrivate->AssertIsOnWorkerThread(); @@ -152,7 +155,8 @@ public: signalProxy = new FetchSignalProxy(aSignal); } - RefPtr r = new WorkerFetchResolver(proxy, signalProxy); + RefPtr r = + new WorkerFetchResolver(proxy, signalProxy, aObserver); return r.forget(); } @@ -174,15 +178,19 @@ public: void OnResponseEnd(FetchDriverObserver::EndReason eReason) override; + void + OnDataAvailable() override; + private: WorkerFetchResolver(PromiseWorkerProxy* aProxy, - FetchSignalProxy* aSignalProxy) + FetchSignalProxy* aSignalProxy, + FetchObserver* aObserver) : mPromiseProxy(aProxy) , mSignalProxy(aSignalProxy) + , mFetchObserver(aObserver) { MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(mPromiseProxy); - } ~WorkerFetchResolver() @@ -196,12 +204,16 @@ class MainThreadFetchResolver final : public FetchDriverObserver { RefPtr mPromise; RefPtr mResponse; + RefPtr mFetchObserver; nsCOMPtr mDocument; NS_DECL_OWNINGTHREAD public: - explicit MainThreadFetchResolver(Promise* aPromise); + MainThreadFetchResolver(Promise* aPromise, FetchObserver* aObserver) + : mPromise(aPromise) + , mFetchObserver(aObserver) + {} void OnResponseAvailableInternal(InternalResponse* aResponse) override; @@ -217,9 +229,14 @@ public: mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR); } + mFetchObserver = nullptr; + FlushConsoleReport(); } + void + OnDataAvailable() override; + private: ~MainThreadFetchResolver(); @@ -318,6 +335,12 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput, // Let's FetchDriver to deal with an already aborted signal. } + RefPtr observer; + if (aInit.mObserve.WasPassed()) { + observer = new FetchObserver(aGlobal, signal); + aInit.mObserve.Value().HandleEvent(*observer); + } + if (NS_IsMainThread()) { nsCOMPtr window = do_QueryInterface(aGlobal); nsCOMPtr doc; @@ -344,7 +367,8 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput, } } - RefPtr resolver = new MainThreadFetchResolver(p); + RefPtr resolver = + new MainThreadFetchResolver(p, observer); RefPtr fetch = new FetchDriver(r, principal, loadGroup); fetch->SetDocument(doc); resolver->SetDocument(doc); @@ -360,7 +384,8 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput, r->SetSkipServiceWorker(); } - RefPtr resolver = WorkerFetchResolver::Create(worker, p, signal); + RefPtr resolver = + WorkerFetchResolver::Create(worker, p, signal, observer); if (!resolver) { NS_WARNING("Could not add WorkerFetchResolver workerHolder to worker"); aRv.Throw(NS_ERROR_DOM_ABORT_ERR); @@ -374,11 +399,6 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput, return p.forget(); } -MainThreadFetchResolver::MainThreadFetchResolver(Promise* aPromise) - : mPromise(aPromise) -{ -} - void MainThreadFetchResolver::OnResponseAvailableInternal(InternalResponse* aResponse) { @@ -386,16 +406,39 @@ MainThreadFetchResolver::OnResponseAvailableInternal(InternalResponse* aResponse AssertIsOnMainThread(); if (aResponse->Type() != ResponseType::Error) { + if (mFetchObserver) { + mFetchObserver->SetState(FetchState::Complete); + } + nsCOMPtr go = mPromise->GetParentObject(); mResponse = new Response(go, aResponse); mPromise->MaybeResolve(mResponse); } else { + if (mFetchObserver) { + mFetchObserver->SetState(FetchState::Errored); + } + ErrorResult result; result.ThrowTypeError(); mPromise->MaybeReject(result); } } +void +MainThreadFetchResolver::OnDataAvailable() +{ + NS_ASSERT_OWNINGTHREAD(MainThreadFetchResolver); + AssertIsOnMainThread(); + + if (!mFetchObserver) { + return; + } + + if (mFetchObserver->State() == FetchState::Requesting) { + mFetchObserver->SetState(FetchState::Responding); + } +} + MainThreadFetchResolver::~MainThreadFetchResolver() { NS_ASSERT_OWNINGTHREAD(MainThreadFetchResolver); @@ -426,10 +469,18 @@ public: RefPtr promise = mResolver->mPromiseProxy->WorkerPromise(); if (mInternalResponse->Type() != ResponseType::Error) { + if (mResolver->mFetchObserver) { + mResolver->mFetchObserver->SetState(FetchState::Complete); + } + RefPtr global = aWorkerPrivate->GlobalScope(); RefPtr response = new Response(global, mInternalResponse); promise->MaybeResolve(response); } else { + if (mResolver->mFetchObserver) { + mResolver->mFetchObserver->SetState(FetchState::Errored); + } + ErrorResult result; result.ThrowTypeError(); promise->MaybeReject(result); @@ -438,18 +489,42 @@ public: } }; +class WorkerDataAvailableRunnable final : public MainThreadWorkerRunnable +{ + RefPtr mResolver; +public: + WorkerDataAvailableRunnable(WorkerPrivate* aWorkerPrivate, + WorkerFetchResolver* aResolver) + : MainThreadWorkerRunnable(aWorkerPrivate) + , mResolver(aResolver) + { + } + + bool + WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override + { + MOZ_ASSERT(aWorkerPrivate); + aWorkerPrivate->AssertIsOnWorkerThread(); + + if (mResolver->mFetchObserver && + mResolver->mFetchObserver->State() == FetchState::Requesting) { + mResolver->mFetchObserver->SetState(FetchState::Responding); + } + + return true; + } +}; + class WorkerFetchResponseEndBase { - RefPtr mPromiseProxy; - RefPtr mSignalProxy; +protected: + RefPtr mResolver; public: - WorkerFetchResponseEndBase(PromiseWorkerProxy* aPromiseProxy, - FetchSignalProxy* aSignalProxy) - : mPromiseProxy(aPromiseProxy) - , mSignalProxy(aSignalProxy) + explicit WorkerFetchResponseEndBase(WorkerFetchResolver* aResolver) + : mResolver(aResolver) { - MOZ_ASSERT(mPromiseProxy); + MOZ_ASSERT(aResolver); } void @@ -458,14 +533,13 @@ public: MOZ_ASSERT(aWorkerPrivate); aWorkerPrivate->AssertIsOnWorkerThread(); - RefPtr promise = mPromiseProxy->WorkerPromise(); - promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR); + mResolver->mPromiseProxy->CleanUp(); - mPromiseProxy->CleanUp(); + mResolver->mFetchObserver = nullptr; - if (mSignalProxy) { - mSignalProxy->Shutdown(); - mSignalProxy = nullptr; + if (mResolver->mSignalProxy) { + mResolver->mSignalProxy->Shutdown(); + mResolver->mSignalProxy = nullptr; } } }; @@ -473,17 +547,26 @@ public: class WorkerFetchResponseEndRunnable final : public MainThreadWorkerRunnable , public WorkerFetchResponseEndBase { + FetchDriverObserver::EndReason mReason; + public: - WorkerFetchResponseEndRunnable(PromiseWorkerProxy* aPromiseProxy, - FetchSignalProxy* aSignalProxy) - : MainThreadWorkerRunnable(aPromiseProxy->GetWorkerPrivate()) - , WorkerFetchResponseEndBase(aPromiseProxy, aSignalProxy) + WorkerFetchResponseEndRunnable(WorkerPrivate* aWorkerPrivate, + WorkerFetchResolver* aResolver, + FetchDriverObserver::EndReason aReason) + : MainThreadWorkerRunnable(aWorkerPrivate) + , WorkerFetchResponseEndBase(aResolver) + , mReason(aReason) { } bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override { + if (mReason == FetchDriverObserver::eAborted) { + RefPtr promise = mResolver->mPromiseProxy->WorkerPromise(); + promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR); + } + WorkerRunInternal(aWorkerPrivate); return true; } @@ -502,10 +585,10 @@ class WorkerFetchResponseEndControlRunnable final : public MainThreadWorkerContr , public WorkerFetchResponseEndBase { public: - WorkerFetchResponseEndControlRunnable(PromiseWorkerProxy* aPromiseProxy, - FetchSignalProxy* aSignalProxy) - : MainThreadWorkerControlRunnable(aPromiseProxy->GetWorkerPrivate()) - , WorkerFetchResponseEndBase(aPromiseProxy, aSignalProxy) + WorkerFetchResponseEndControlRunnable(WorkerPrivate* aWorkerPrivate, + WorkerFetchResolver* aResolver) + : MainThreadWorkerControlRunnable(aWorkerPrivate) + , WorkerFetchResponseEndBase(aResolver) { } @@ -538,6 +621,21 @@ WorkerFetchResolver::OnResponseAvailableInternal(InternalResponse* aResponse) } } +void +WorkerFetchResolver::OnDataAvailable() +{ + AssertIsOnMainThread(); + + MutexAutoLock lock(mPromiseProxy->Lock()); + if (mPromiseProxy->CleanedUp()) { + return; + } + + RefPtr r = + new WorkerDataAvailableRunnable(mPromiseProxy->GetWorkerPrivate(), this); + Unused << r->Dispatch(); +} + void WorkerFetchResolver::OnResponseEnd(FetchDriverObserver::EndReason aReason) { @@ -550,11 +648,13 @@ WorkerFetchResolver::OnResponseEnd(FetchDriverObserver::EndReason aReason) FlushConsoleReport(); RefPtr r = - new WorkerFetchResponseEndRunnable(mPromiseProxy, mSignalProxy); + new WorkerFetchResponseEndRunnable(mPromiseProxy->GetWorkerPrivate(), + this, aReason); if (!r->Dispatch()) { RefPtr cr = - new WorkerFetchResponseEndControlRunnable(mPromiseProxy, mSignalProxy); + new WorkerFetchResponseEndControlRunnable(mPromiseProxy->GetWorkerPrivate(), + this); // This can fail if the worker thread is canceled or killed causing // the PromiseWorkerProxy to give up its WorkerHolder immediately, // allowing the worker thread to become Dead. diff --git a/dom/fetch/FetchDriver.cpp b/dom/fetch/FetchDriver.cpp index 448ec64cd..e8d726ce1 100644 --- a/dom/fetch/FetchDriver.cpp +++ b/dom/fetch/FetchDriver.cpp @@ -667,6 +667,31 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest, return NS_OK; } +namespace { + +// Runnable to call the observer OnDataAvailable on the main-thread. +class DataAvailableRunnable final : public Runnable +{ + RefPtr mObserver; + +public: + explicit DataAvailableRunnable(FetchDriverObserver* aObserver) + : mObserver(aObserver) + { + MOZ_ASSERT(aObserver); + } + + NS_IMETHOD + Run() override + { + mObserver->OnDataAvailable(); + mObserver = nullptr; + return NS_OK; + } +}; + +} // anonymous namespace + NS_IMETHODIMP FetchDriver::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext, @@ -678,6 +703,18 @@ FetchDriver::OnDataAvailable(nsIRequest* aRequest, // called between OnStartRequest and OnStopRequest, so we don't need to worry // about races. + if (mObserver) { + if (NS_IsMainThread()) { + mObserver->OnDataAvailable(); + } else { + RefPtr runnable = new DataAvailableRunnable(mObserver); + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + } + } + uint32_t aRead; MOZ_ASSERT(mResponse); MOZ_ASSERT(mPipeOutputStream); diff --git a/dom/fetch/FetchDriver.h b/dom/fetch/FetchDriver.h index 0ca9a34ee..e942aa242 100644 --- a/dom/fetch/FetchDriver.h +++ b/dom/fetch/FetchDriver.h @@ -67,6 +67,8 @@ public: virtual void FlushConsoleReport() = 0; + virtual void OnDataAvailable() = 0; + protected: virtual ~FetchDriverObserver() { }; diff --git a/dom/fetch/FetchObserver.cpp b/dom/fetch/FetchObserver.cpp index bc8c6fc2b..982f0ad49 100644 --- a/dom/fetch/FetchObserver.cpp +++ b/dom/fetch/FetchObserver.cpp @@ -6,6 +6,7 @@ #include "FetchObserver.h" #include "WorkerPrivate.h" +#include "mozilla/dom/Event.h" namespace mozilla { namespace dom { @@ -45,10 +46,14 @@ FetchObserver::IsEnabled(JSContext* aCx, JSObject* aGlobal) } FetchObserver::FetchObserver(nsIGlobalObject* aGlobal, - FetchState aState) + FetchSignal* aSignal) : DOMEventTargetHelper(aGlobal) - , mState(aState) -{} + , mState(FetchState::Requesting) +{ + if (aSignal) { + Follow(aSignal); + } +} JSObject* FetchObserver::WrapObject(JSContext* aCx, JS::Handle aGivenProto) @@ -62,5 +67,51 @@ FetchObserver::State() const return mState; } +void +FetchObserver::Aborted() +{ + SetState(FetchState::Aborted); +} + +void +FetchObserver::SetState(FetchState aState) +{ + MOZ_ASSERT(mState < aState); + + if (mState == FetchState::Aborted || + mState == FetchState::Errored || + mState == FetchState::Complete) { + // We are already in a final state. + return; + } + + // We cannot pass from Requesting to Complete directly. + if (mState == FetchState::Requesting && + aState == FetchState::Complete) { + SetState(FetchState::Responding); + } + + mState = aState; + + if (mState == FetchState::Aborted || + mState == FetchState::Errored || + mState == FetchState::Complete) { + Unfollow(); + } + + EventInit init; + init.mBubbles = false; + init.mCancelable = false; + + // TODO which kind of event should we dispatch here? + + RefPtr event = + Event::Constructor(this, NS_LITERAL_STRING("statechange"), init); + event->SetTrusted(true); + + bool dummy; + DispatchEvent(event, &dummy); +} + } // dom namespace } // mozilla namespace diff --git a/dom/fetch/FetchObserver.h b/dom/fetch/FetchObserver.h index 81f8e7b09..45adf2ba1 100644 --- a/dom/fetch/FetchObserver.h +++ b/dom/fetch/FetchObserver.h @@ -9,11 +9,13 @@ #include "mozilla/DOMEventTargetHelper.h" #include "mozilla/dom/FetchObserverBinding.h" +#include "mozilla/dom/FetchSignal.h" namespace mozilla { namespace dom { class FetchObserver final : public DOMEventTargetHelper + , public FetchSignal::Follower { public: NS_DECL_ISUPPORTS_INHERITED @@ -22,7 +24,7 @@ public: static bool IsEnabled(JSContext* aCx, JSObject* aGlobal); - FetchObserver(nsIGlobalObject* aGlobal, FetchState aState); + FetchObserver(nsIGlobalObject* aGlobal, FetchSignal* aSignal); JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; @@ -34,6 +36,12 @@ public: IMPL_EVENT_HANDLER(requestprogress); IMPL_EVENT_HANDLER(responseprogress); + void + Aborted() override; + + void + SetState(FetchState aState); + private: ~FetchObserver() = default; -- cgit v1.2.3 From 1620ec19653125db78f380043a52b6da6a34c281 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Thu, 11 Jun 2020 12:43:17 +0000 Subject: Issue #1587 - Part 6: Move FetchController/Signal to its own dir Since it is specced separately from fetch. --- dom/fetch/FetchController.cpp | 127 ----------------------------------- dom/fetch/FetchController.h | 73 -------------------- dom/fetch/FetchSignal.cpp | 151 ------------------------------------------ dom/fetch/FetchSignal.h | 79 ---------------------- dom/fetch/moz.build | 4 -- 5 files changed, 434 deletions(-) delete mode 100644 dom/fetch/FetchController.cpp delete mode 100644 dom/fetch/FetchController.h delete mode 100644 dom/fetch/FetchSignal.cpp delete mode 100644 dom/fetch/FetchSignal.h (limited to 'dom/fetch') diff --git a/dom/fetch/FetchController.cpp b/dom/fetch/FetchController.cpp deleted file mode 100644 index 2eb40b980..000000000 --- a/dom/fetch/FetchController.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "FetchController.h" -#include "FetchSignal.h" -#include "mozilla/dom/FetchControllerBinding.h" -#include "WorkerPrivate.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FetchController, mGlobal, mSignal, - mFollowingSignal) - -NS_IMPL_CYCLE_COLLECTING_ADDREF(FetchController) -NS_IMPL_CYCLE_COLLECTING_RELEASE(FetchController) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FetchController) - NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -/* static */ bool -FetchController::IsEnabled(JSContext* aCx, JSObject* aGlobal) -{ - if (NS_IsMainThread()) { - return Preferences::GetBool("dom.fetchController.enabled", false); - } - - using namespace workers; - - // Otherwise, check the pref via the WorkerPrivate - WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx); - if (!workerPrivate) { - return false; - } - - return workerPrivate->FetchControllerEnabled(); -} - -/* static */ already_AddRefed -FetchController::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv) -{ - nsCOMPtr global = do_QueryInterface(aGlobal.GetAsSupports()); - if (!global) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - RefPtr fetchController = new FetchController(global); - return fetchController.forget(); -} - -FetchController::FetchController(nsIGlobalObject* aGlobal) - : mGlobal(aGlobal) - , mAborted(false) -{} - -JSObject* -FetchController::WrapObject(JSContext* aCx, JS::Handle aGivenProto) -{ - return FetchControllerBinding::Wrap(aCx, this, aGivenProto); -} - -nsIGlobalObject* -FetchController::GetParentObject() const -{ - return mGlobal; -} - -FetchSignal* -FetchController::Signal() -{ - if (!mSignal) { - mSignal = new FetchSignal(this, mAborted); - } - - return mSignal; -} - -void -FetchController::Abort() -{ - if (mAborted) { - return; - } - - mAborted = true; - - if (mSignal) { - mSignal->Abort(); - } -} - -void -FetchController::Follow(FetchSignal& aSignal) -{ - FetchSignal::Follower::Follow(&aSignal); -} - -void -FetchController::Unfollow(FetchSignal& aSignal) -{ - if (mFollowingSignal != &aSignal) { - return; - } - - FetchSignal::Follower::Unfollow(); -} - -FetchSignal* -FetchController::Following() const -{ - return mFollowingSignal; -} - -void -FetchController::Aborted() -{ - Abort(); -} - -} // dom namespace -} // mozilla namespace diff --git a/dom/fetch/FetchController.h b/dom/fetch/FetchController.h deleted file mode 100644 index 7a0132dca..000000000 --- a/dom/fetch/FetchController.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_FetchController_h -#define mozilla_dom_FetchController_h - -#include "mozilla/dom/BindingDeclarations.h" -#include "mozilla/dom/FetchSignal.h" -#include "nsCycleCollectionParticipant.h" -#include "nsWrapperCache.h" -#include "mozilla/ErrorResult.h" -#include "nsIGlobalObject.h" - -namespace mozilla { -namespace dom { - -class FetchController final : public nsISupports - , public nsWrapperCache - , public FetchSignal::Follower -{ -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(FetchController) - - static bool - IsEnabled(JSContext* aCx, JSObject* aGlobal); - - static already_AddRefed - Constructor(const GlobalObject& aGlobal, ErrorResult& aRv); - - explicit FetchController(nsIGlobalObject* aGlobal); - - JSObject* - WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; - - nsIGlobalObject* - GetParentObject() const; - - FetchSignal* - Signal(); - - void - Abort(); - - void - Follow(FetchSignal& aSignal); - - void - Unfollow(FetchSignal& aSignal); - - FetchSignal* - Following() const; - - // FetchSignal::Follower - - void Aborted() override; - -private: - ~FetchController() = default; - - nsCOMPtr mGlobal; - RefPtr mSignal; - - bool mAborted; -}; - -} // dom namespace -} // mozilla namespace - -#endif // mozilla_dom_FetchController_h diff --git a/dom/fetch/FetchSignal.cpp b/dom/fetch/FetchSignal.cpp deleted file mode 100644 index 07ad6b53d..000000000 --- a/dom/fetch/FetchSignal.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "FetchSignal.h" -#include "FetchController.h" -#include "mozilla/dom/Event.h" -#include "mozilla/dom/FetchSignalBinding.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_CLASS(FetchSignal) - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(FetchSignal, - DOMEventTargetHelper) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mController) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(FetchSignal, - DOMEventTargetHelper) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mController) -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FetchSignal) -NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) - -NS_IMPL_ADDREF_INHERITED(FetchSignal, DOMEventTargetHelper) -NS_IMPL_RELEASE_INHERITED(FetchSignal, DOMEventTargetHelper) - -FetchSignal::FetchSignal(FetchController* aController, - bool aAborted) - : DOMEventTargetHelper(aController->GetParentObject()) - , mController(aController) - , mAborted(aAborted) -{} - -FetchSignal::FetchSignal(bool aAborted) - : mAborted(aAborted) -{} - -JSObject* -FetchSignal::WrapObject(JSContext* aCx, JS::Handle aGivenProto) -{ - return FetchSignalBinding::Wrap(aCx, this, aGivenProto); -} - -bool -FetchSignal::Aborted() const -{ - return mAborted; -} - -void -FetchSignal::Abort() -{ - MOZ_ASSERT(!mAborted); - mAborted = true; - - // Let's inform the followers. - for (uint32_t i = 0; i < mFollowers.Length(); ++i) { - mFollowers[i]->Aborted(); - } - - EventInit init; - init.mBubbles = false; - init.mCancelable = false; - - // TODO which kind of event should we dispatch here? - - RefPtr event = - Event::Constructor(this, NS_LITERAL_STRING("abort"), init); - event->SetTrusted(true); - - bool dummy; - DispatchEvent(event, &dummy); -} - -void -FetchSignal::AddFollower(FetchSignal::Follower* aFollower) -{ - MOZ_DIAGNOSTIC_ASSERT(aFollower); - if (!mFollowers.Contains(aFollower)) { - mFollowers.AppendElement(aFollower); - } -} - -void -FetchSignal::RemoveFollower(FetchSignal::Follower* aFollower) -{ - MOZ_DIAGNOSTIC_ASSERT(aFollower); - mFollowers.RemoveElement(aFollower); -} - -bool -FetchSignal::CanAcceptFollower(FetchSignal::Follower* aFollower) const -{ - MOZ_DIAGNOSTIC_ASSERT(aFollower); - - if (!mController) { - return true; - } - - if (aFollower == mController) { - return false; - } - - FetchSignal* following = mController->Following(); - if (!following) { - return true; - } - - return following->CanAcceptFollower(aFollower); -} - -// FetchSignal::Follower -// ---------------------------------------------------------------------------- - -FetchSignal::Follower::~Follower() -{ - Unfollow(); -} - -void -FetchSignal::Follower::Follow(FetchSignal* aSignal) -{ - MOZ_DIAGNOSTIC_ASSERT(aSignal); - - if (!aSignal->CanAcceptFollower(this)) { - return; - } - - Unfollow(); - - mFollowingSignal = aSignal; - aSignal->AddFollower(this); -} - -void -FetchSignal::Follower::Unfollow() -{ - if (mFollowingSignal) { - mFollowingSignal->RemoveFollower(this); - mFollowingSignal = nullptr; - } -} - -} // dom namespace -} // mozilla namespace diff --git a/dom/fetch/FetchSignal.h b/dom/fetch/FetchSignal.h deleted file mode 100644 index 4970f03de..000000000 --- a/dom/fetch/FetchSignal.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_FetchSignal_h -#define mozilla_dom_FetchSignal_h - -#include "mozilla/DOMEventTargetHelper.h" - -namespace mozilla { -namespace dom { - -class FetchController; -class FetchSignal; - -class FetchSignal final : public DOMEventTargetHelper -{ -public: - // This class must be implemented by objects who want to follow a FetchSignal. - class Follower - { - public: - virtual void Aborted() = 0; - - protected: - virtual ~Follower(); - - void - Follow(FetchSignal* aSignal); - - void - Unfollow(); - - RefPtr mFollowingSignal; - }; - - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FetchSignal, DOMEventTargetHelper) - - FetchSignal(FetchController* aController, bool aAborted); - explicit FetchSignal(bool aAborted); - - JSObject* - WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; - - bool - Aborted() const; - - void - Abort(); - - IMPL_EVENT_HANDLER(abort); - - void - AddFollower(Follower* aFollower); - - void - RemoveFollower(Follower* aFollower); - - bool - CanAcceptFollower(Follower* aFollower) const; - -private: - ~FetchSignal() = default; - - RefPtr mController; - - // Raw pointers. Follower unregisters itself in the DTOR. - nsTArray mFollowers; - - bool mAborted; -}; - -} // dom namespace -} // mozilla namespace - -#endif // mozilla_dom_FetchSignal_h diff --git a/dom/fetch/moz.build b/dom/fetch/moz.build index 82fd99173..e2b466428 100644 --- a/dom/fetch/moz.build +++ b/dom/fetch/moz.build @@ -7,11 +7,9 @@ EXPORTS.mozilla.dom += [ 'ChannelInfo.h', 'Fetch.h', - 'FetchController.h', 'FetchDriver.h', 'FetchIPCTypes.h', 'FetchObserver.h', - 'FetchSignal.h', 'FetchUtil.h', 'Headers.h', 'InternalHeaders.h', @@ -30,10 +28,8 @@ UNIFIED_SOURCES += [ SOURCES += [ 'ChannelInfo.cpp', - 'FetchController.cpp', 'FetchDriver.cpp', 'FetchObserver.cpp', - 'FetchSignal.cpp', 'FetchUtil.cpp', 'Headers.cpp', 'InternalHeaders.cpp', -- cgit v1.2.3 From e97a29a6569fac73e81cf46a0e682ac926ea3456 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Thu, 11 Jun 2020 23:20:52 +0000 Subject: Issue #1587 - Part 7: Rename FetchController to AbortController Also renames FetchSignal to AbortSignal. Includes renaming the various controlling prefs to enable. --- dom/fetch/Fetch.cpp | 52 ++++++++++++++++++++++----------------------- dom/fetch/FetchDriver.cpp | 2 +- dom/fetch/FetchDriver.h | 8 +++---- dom/fetch/FetchObserver.cpp | 2 +- dom/fetch/FetchObserver.h | 6 +++--- dom/fetch/Request.h | 2 +- 6 files changed, 36 insertions(+), 36 deletions(-) (limited to 'dom/fetch') diff --git a/dom/fetch/Fetch.cpp b/dom/fetch/Fetch.cpp index 04aa7fd91..4dbe2de0a 100644 --- a/dom/fetch/Fetch.cpp +++ b/dom/fetch/Fetch.cpp @@ -53,24 +53,24 @@ namespace dom { using namespace workers; -// This class helps the proxying of FetchSignal changes cross threads. -class FetchSignalProxy final : public FetchSignal::Follower +// This class helps the proxying of AbortSignal changes cross threads. +class AbortSignalProxy final : public AbortSignal::Follower { // This is created and released on the main-thread. - RefPtr mSignalMainThread; + RefPtr mSignalMainThread; - // This value is used only for the creation of FetchSignal on the + // This value is used only for the creation of AbortSignal on the // main-thread. They are not updated. const bool mAborted; - // This runnable propagates changes from the FetchSignal on workers to the - // FetchSignal on main-thread. - class FetchSignalProxyRunnable final : public Runnable + // This runnable propagates changes from the AbortSignal on workers to the + // AbortSignal on main-thread. + class AbortSignalProxyRunnable final : public Runnable { - RefPtr mProxy; + RefPtr mProxy; public: - explicit FetchSignalProxyRunnable(FetchSignalProxy* aProxy) + explicit AbortSignalProxyRunnable(AbortSignalProxy* aProxy) : mProxy(aProxy) {} @@ -78,16 +78,16 @@ class FetchSignalProxy final : public FetchSignal::Follower Run() override { MOZ_ASSERT(NS_IsMainThread()); - FetchSignal* signal = mProxy->GetOrCreateSignalForMainThread(); + AbortSignal* signal = mProxy->GetOrCreateSignalForMainThread(); signal->Abort(); return NS_OK; } }; public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FetchSignalProxy) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AbortSignalProxy) - explicit FetchSignalProxy(FetchSignal* aSignal) + explicit AbortSignalProxy(AbortSignal* aSignal) : mAborted(aSignal->Aborted()) { Follow(aSignal); @@ -96,17 +96,17 @@ public: void Aborted() override { - RefPtr runnable = - new FetchSignalProxyRunnable(this); + RefPtr runnable = + new AbortSignalProxyRunnable(this); NS_DispatchToMainThread(runnable); } - FetchSignal* + AbortSignal* GetOrCreateSignalForMainThread() { MOZ_ASSERT(NS_IsMainThread()); if (!mSignalMainThread) { - mSignalMainThread = new FetchSignal(mAborted); + mSignalMainThread = new AbortSignal(mAborted); } return mSignalMainThread; } @@ -118,7 +118,7 @@ public: } private: - ~FetchSignalProxy() + ~AbortSignalProxy() { NS_ReleaseOnMainThread(mSignalMainThread.forget()); } @@ -133,14 +133,14 @@ class WorkerFetchResolver final : public FetchDriverObserver friend class WorkerFetchResponseRunnable; RefPtr mPromiseProxy; - RefPtr mSignalProxy; + RefPtr mSignalProxy; RefPtr mFetchObserver; public: // Returns null if worker is shutting down. static already_AddRefed Create(workers::WorkerPrivate* aWorkerPrivate, Promise* aPromise, - FetchSignal* aSignal, FetchObserver* aObserver) + AbortSignal* aSignal, FetchObserver* aObserver) { MOZ_ASSERT(aWorkerPrivate); aWorkerPrivate->AssertIsOnWorkerThread(); @@ -150,9 +150,9 @@ public: return nullptr; } - RefPtr signalProxy; + RefPtr signalProxy; if (aSignal) { - signalProxy = new FetchSignalProxy(aSignal); + signalProxy = new AbortSignalProxy(aSignal); } RefPtr r = @@ -160,8 +160,8 @@ public: return r.forget(); } - FetchSignal* - GetFetchSignal() + AbortSignal* + GetAbortSignal() { MOZ_ASSERT(NS_IsMainThread()); @@ -183,7 +183,7 @@ public: private: WorkerFetchResolver(PromiseWorkerProxy* aProxy, - FetchSignalProxy* aSignalProxy, + AbortSignalProxy* aSignalProxy, FetchObserver* aObserver) : mPromiseProxy(aProxy) , mSignalProxy(aSignalProxy) @@ -287,7 +287,7 @@ public: fetch->SetWorkerScript(spec); } - RefPtr signal = mResolver->GetFetchSignal(); + RefPtr signal = mResolver->GetAbortSignal(); // ...but release it before calling Fetch, because mResolver's callback can // be called synchronously and they want the mutex, too. @@ -329,7 +329,7 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput, RefPtr r = request->GetInternalRequest(); - RefPtr signal; + RefPtr signal; if (aInit.mSignal.WasPassed()) { signal = &aInit.mSignal.Value(); // Let's FetchDriver to deal with an already aborted signal. diff --git a/dom/fetch/FetchDriver.cpp b/dom/fetch/FetchDriver.cpp index e8d726ce1..067e32db4 100644 --- a/dom/fetch/FetchDriver.cpp +++ b/dom/fetch/FetchDriver.cpp @@ -67,7 +67,7 @@ FetchDriver::~FetchDriver() } nsresult -FetchDriver::Fetch(FetchSignal* aSignal, FetchDriverObserver* aObserver) +FetchDriver::Fetch(AbortSignal* aSignal, FetchDriverObserver* aObserver) { workers::AssertIsOnMainThread(); #ifdef DEBUG diff --git a/dom/fetch/FetchDriver.h b/dom/fetch/FetchDriver.h index e942aa242..57dffa5a7 100644 --- a/dom/fetch/FetchDriver.h +++ b/dom/fetch/FetchDriver.h @@ -12,7 +12,7 @@ #include "nsIStreamListener.h" #include "nsIThreadRetargetableStreamListener.h" #include "mozilla/ConsoleReportCollector.h" -#include "mozilla/dom/FetchSignal.h" +#include "mozilla/dom/AbortSignal.h" #include "mozilla/dom/SRIMetadata.h" #include "mozilla/RefPtr.h" @@ -84,7 +84,7 @@ class FetchDriver final : public nsIStreamListener, public nsIChannelEventSink, public nsIInterfaceRequestor, public nsIThreadRetargetableStreamListener, - public FetchSignal::Follower + public AbortSignal::Follower { public: NS_DECL_ISUPPORTS @@ -98,7 +98,7 @@ public: nsIPrincipal* aPrincipal, nsILoadGroup* aLoadGroup); - nsresult Fetch(FetchSignal* aSignal, + nsresult Fetch(AbortSignal* aSignal, FetchDriverObserver* aObserver); void @@ -111,7 +111,7 @@ public: mWorkerScript = aWorkerScirpt; } - // FetchSignal::Follower + // AbortSignal::Follower void Aborted() override; diff --git a/dom/fetch/FetchObserver.cpp b/dom/fetch/FetchObserver.cpp index 982f0ad49..93d93773f 100644 --- a/dom/fetch/FetchObserver.cpp +++ b/dom/fetch/FetchObserver.cpp @@ -46,7 +46,7 @@ FetchObserver::IsEnabled(JSContext* aCx, JSObject* aGlobal) } FetchObserver::FetchObserver(nsIGlobalObject* aGlobal, - FetchSignal* aSignal) + AbortSignal* aSignal) : DOMEventTargetHelper(aGlobal) , mState(FetchState::Requesting) { diff --git a/dom/fetch/FetchObserver.h b/dom/fetch/FetchObserver.h index 45adf2ba1..5cd835b3d 100644 --- a/dom/fetch/FetchObserver.h +++ b/dom/fetch/FetchObserver.h @@ -9,13 +9,13 @@ #include "mozilla/DOMEventTargetHelper.h" #include "mozilla/dom/FetchObserverBinding.h" -#include "mozilla/dom/FetchSignal.h" +#include "mozilla/dom/AbortSignal.h" namespace mozilla { namespace dom { class FetchObserver final : public DOMEventTargetHelper - , public FetchSignal::Follower + , public AbortSignal::Follower { public: NS_DECL_ISUPPORTS_INHERITED @@ -24,7 +24,7 @@ public: static bool IsEnabled(JSContext* aCx, JSObject* aGlobal); - FetchObserver(nsIGlobalObject* aGlobal, FetchSignal* aSignal); + FetchObserver(nsIGlobalObject* aGlobal, AbortSignal* aSignal); JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; diff --git a/dom/fetch/Request.h b/dom/fetch/Request.h index 56a75e5af..f6fe9be7b 100644 --- a/dom/fetch/Request.h +++ b/dom/fetch/Request.h @@ -12,7 +12,7 @@ #include "nsWrapperCache.h" #include "mozilla/dom/Fetch.h" -#include "mozilla/dom/FetchSignal.h" +#include "mozilla/dom/AbortSignal.h" #include "mozilla/dom/InternalRequest.h" // Required here due to certain WebIDL enums/classes being declared in both // files. -- cgit v1.2.3 From 1c97314804cff846def08b122efb32d514bd1a09 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Fri, 12 Jun 2020 01:46:48 +0000 Subject: Issue #1587 - Part 9: Immediately reject an already-aborted signal --- dom/fetch/Fetch.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'dom/fetch') diff --git a/dom/fetch/Fetch.cpp b/dom/fetch/Fetch.cpp index 4dbe2de0a..191f4cfc3 100644 --- a/dom/fetch/Fetch.cpp +++ b/dom/fetch/Fetch.cpp @@ -332,7 +332,12 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput, RefPtr signal; if (aInit.mSignal.WasPassed()) { signal = &aInit.mSignal.Value(); - // Let's FetchDriver to deal with an already aborted signal. + } + + if (signal && signal->Aborted()) { + // An already aborted signal should reject immediately. + aRv.Throw(NS_ERROR_DOM_ABORT_ERR); + return nullptr; } RefPtr observer; -- cgit v1.2.3