ServiceWorkerOp.h (6855B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_serviceworkerop_h__ 8 #define mozilla_dom_serviceworkerop_h__ 9 10 #include <functional> 11 12 #include "ServiceWorkerEvents.h" 13 #include "ServiceWorkerOpPromise.h" 14 #include "mozilla/Maybe.h" 15 #include "mozilla/RefPtr.h" 16 #include "mozilla/TimeStamp.h" 17 #include "mozilla/dom/PromiseNativeHandler.h" 18 #include "mozilla/dom/RemoteWorkerChild.h" 19 #include "mozilla/dom/RemoteWorkerOp.h" 20 #include "mozilla/dom/ServiceWorkerOpArgs.h" 21 #include "mozilla/dom/ServiceWorkerOpPromise.h" 22 #include "mozilla/dom/WorkerRunnable.h" 23 #include "nsISupportsImpl.h" 24 25 namespace mozilla::dom { 26 27 using remoteworker::RemoteWorkerState; 28 29 class FetchEventOpProxyChild; 30 31 class ServiceWorkerOp : public RemoteWorkerOp { 32 public: 33 // `aCallback` will be called when the operation completes or is canceled. 34 static already_AddRefed<ServiceWorkerOp> Create( 35 ServiceWorkerOpArgs&& aArgs, 36 std::function<void(const ServiceWorkerOpResult&)>&& aCallback); 37 38 ServiceWorkerOp( 39 ServiceWorkerOpArgs&& aArgs, 40 std::function<void(const ServiceWorkerOpResult&)>&& aCallback); 41 42 ServiceWorkerOp(const ServiceWorkerOp&) = delete; 43 44 ServiceWorkerOp& operator=(const ServiceWorkerOp&) = delete; 45 46 ServiceWorkerOp(ServiceWorkerOp&&) = default; 47 48 ServiceWorkerOp& operator=(ServiceWorkerOp&&) = default; 49 50 // Returns `true` if the operation has started and `false` otherwise. 51 bool MaybeStart(RemoteWorkerChild* aOwner, RemoteWorkerState& aState) final; 52 53 void StartOnMainThread(RefPtr<RemoteWorkerChild>& aOwner) final; 54 55 void Start(RemoteWorkerNonLifeCycleOpControllerChild* aOwner, 56 RemoteWorkerState& aState) final; 57 58 void Cancel() final; 59 60 protected: 61 ~ServiceWorkerOp(); 62 63 bool Started() const; 64 65 bool IsTerminationOp() const; 66 67 // Override to provide a runnable that's not a `ServiceWorkerOpRunnable.` 68 virtual RefPtr<WorkerThreadRunnable> GetRunnable( 69 WorkerPrivate* aWorkerPrivate); 70 71 // Overridden by ServiceWorkerOp subclasses, it should return true when 72 // the ServiceWorkerOp was executed successfully (and false if it did fail). 73 // Content throwing an exception during event dispatch is still considered 74 // success. 75 virtual bool Exec(JSContext* aCx, WorkerPrivate* aWorkerPrivate) = 0; 76 77 // Override to reject any additional MozPromises that subclasses may contain. 78 virtual void RejectAll(nsresult aStatus); 79 80 ServiceWorkerOpArgs mArgs; 81 82 // Subclasses must settle this promise when appropriate. 83 MozPromiseHolder<ServiceWorkerOpPromise> mPromiseHolder; 84 85 private: 86 class ServiceWorkerOpRunnable; 87 88 bool mStarted = false; 89 }; 90 91 class ExtendableEventOp : public ServiceWorkerOp, 92 public ExtendableEventCallback { 93 using ServiceWorkerOp::ServiceWorkerOp; 94 95 protected: 96 ~ExtendableEventOp() = default; 97 98 void FinishedWithResult(ExtendableEventResult aResult) override; 99 }; 100 101 class FetchEventOp final : public ExtendableEventOp, 102 public PromiseNativeHandler { 103 using ExtendableEventOp::ExtendableEventOp; 104 105 public: 106 NS_DECL_THREADSAFE_ISUPPORTS 107 108 /** 109 * This must be called once and only once before the first call to 110 * `MaybeStart()`; `aActor` will be used for `AsyncLog()` and 111 * `ReportCanceled().` 112 */ 113 void SetActor(RefPtr<FetchEventOpProxyChild> aActor); 114 115 void RevokeActor(FetchEventOpProxyChild* aActor); 116 117 // This must be called at most once before the first call to `MaybeStart().` 118 RefPtr<FetchEventRespondWithPromise> GetRespondWithPromise(); 119 120 // This must be called when `FetchEvent::RespondWith()` is called. 121 void RespondWithCalledAt(const nsCString& aRespondWithScriptSpec, 122 uint32_t aRespondWithLineNumber, 123 uint32_t aRespondWithColumnNumber); 124 125 void ReportCanceled(const nsCString& aPreventDefaultScriptSpec, 126 uint32_t aPreventDefaultLineNumber, 127 uint32_t aPreventDefaultColumnNumber); 128 129 private: 130 class AutoCancel; 131 132 ~FetchEventOp(); 133 134 bool Exec(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override; 135 136 void RejectAll(nsresult aStatus) override; 137 138 void FinishedWithResult(ExtendableEventResult aResult) override; 139 140 /** 141 * `{Resolved,Reject}Callback()` are use to handle the 142 * `FetchEvent::RespondWith()` promise. 143 */ 144 void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue, 145 ErrorResult& aRv) override; 146 147 void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue, 148 ErrorResult& aRv) override; 149 150 void MaybeFinished(); 151 152 // Requires mRespondWithClosure to be non-empty. 153 void AsyncLog(const nsCString& aMessageName, nsTArray<nsString> aParams); 154 155 void AsyncLog(const nsCString& aScriptSpec, uint32_t aLineNumber, 156 uint32_t aColumnNumber, const nsCString& aMessageName, 157 nsTArray<nsString> aParams); 158 159 void GetRequestURL(nsAString& aOutRequestURL); 160 161 // A failure code means that the dispatch failed. 162 nsresult DispatchFetchEvent(JSContext* aCx, WorkerPrivate* aWorkerPrivate); 163 164 // Worker Launcher thread only. Used for `AsyncLog().` 165 RefPtr<FetchEventOpProxyChild> mActor; 166 167 /** 168 * Created on the Worker Launcher thread and settled on the worker thread. 169 * If this isn't settled before `mPromiseHolder` (which it should be), 170 * `FetchEventOpChild` will cancel the intercepted network request. 171 */ 172 MozPromiseHolder<FetchEventRespondWithPromise> mRespondWithPromiseHolder; 173 174 // Worker thread only. 175 Maybe<ExtendableEventResult> mResult; 176 bool mPostDispatchChecksDone = false; 177 178 // Worker thread only; set when `FetchEvent::RespondWith()` is called. 179 Maybe<FetchEventRespondWithClosure> mRespondWithClosure; 180 181 // Must be set to `nullptr` on the worker thread because `Promise`'s 182 // destructor must be called on the worker thread. 183 RefPtr<Promise> mHandled; 184 185 // Must be set to `nullptr` on the worker thread because `Promise`'s 186 // destructor must be called on the worker thread. 187 RefPtr<Promise> mPreloadResponse; 188 189 // Holds the callback that resolves mPreloadResponse. 190 MozPromiseRequestHolder<FetchEventPreloadResponseAvailablePromise> 191 mPreloadResponseAvailablePromiseRequestHolder; 192 MozPromiseRequestHolder<FetchEventPreloadResponseTimingPromise> 193 mPreloadResponseTimingPromiseRequestHolder; 194 MozPromiseRequestHolder<FetchEventPreloadResponseEndPromise> 195 mPreloadResponseEndPromiseRequestHolder; 196 197 TimeStamp mFetchHandlerStart; 198 TimeStamp mFetchHandlerFinish; 199 }; 200 201 } // namespace mozilla::dom 202 203 #endif // mozilla_dom_serviceworkerop_h__