ServiceWorkerEvents.h (9726B)
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_serviceworkerevents_h__ 8 #define mozilla_dom_serviceworkerevents_h__ 9 10 #include "mozilla/Attributes.h" 11 #include "mozilla/dom/Event.h" 12 #include "mozilla/dom/ExtendableEventBinding.h" 13 #include "mozilla/dom/ExtendableMessageEventBinding.h" 14 #include "mozilla/dom/FetchEventBinding.h" 15 #include "mozilla/dom/File.h" 16 #include "mozilla/dom/Promise.h" 17 #include "mozilla/dom/Response.h" 18 #include "mozilla/dom/ServiceWorkerUtils.h" 19 #include "mozilla/dom/WorkerCommon.h" 20 #include "nsContentUtils.h" 21 #include "nsProxyRelease.h" 22 23 class nsIInterceptedChannel; 24 25 namespace mozilla::dom { 26 27 class Blob; 28 class Client; 29 class FetchEventOp; 30 class MessagePort; 31 struct PushEventInit; 32 class Request; 33 class ResponseOrPromise; 34 class ServiceWorker; 35 class ServiceWorkerRegistrationInfo; 36 37 class CancelChannelRunnable final : public Runnable { 38 nsMainThreadPtrHandle<nsIInterceptedChannel> mChannel; 39 nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration; 40 const nsresult mStatus; 41 42 public: 43 CancelChannelRunnable( 44 nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel, 45 nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration, 46 nsresult aStatus); 47 48 NS_IMETHOD Run() override; 49 }; 50 51 enum ExtendableEventResult { Rejected = 0, Resolved }; 52 53 class ExtendableEventCallback { 54 public: 55 virtual void FinishedWithResult(ExtendableEventResult aResult) = 0; 56 57 NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING 58 }; 59 60 class ExtendableEvent : public Event { 61 public: 62 class ExtensionsHandler { 63 friend class ExtendableEvent; 64 65 public: 66 virtual bool WaitOnPromise(Promise& aPromise) = 0; 67 68 NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING 69 70 protected: 71 virtual ~ExtensionsHandler(); 72 73 // Also returns false if the owning ExtendableEvent is destroyed. 74 bool GetDispatchFlag() const; 75 76 private: 77 // Only the owning ExtendableEvent is allowed to set this data. 78 void SetExtendableEvent(const ExtendableEvent* const aExtendableEvent); 79 80 MOZ_NON_OWNING_REF const ExtendableEvent* mExtendableEvent = nullptr; 81 }; 82 83 private: 84 RefPtr<ExtensionsHandler> mExtensionsHandler; 85 86 protected: 87 bool GetDispatchFlag() const { return mEvent->mFlags.mIsBeingDispatched; } 88 89 bool WaitOnPromise(Promise& aPromise); 90 91 explicit ExtendableEvent(mozilla::dom::EventTarget* aOwner); 92 93 ~ExtendableEvent() { 94 if (mExtensionsHandler) { 95 mExtensionsHandler->SetExtendableEvent(nullptr); 96 } 97 }; 98 99 public: 100 NS_DECL_ISUPPORTS_INHERITED 101 102 void SetKeepAliveHandler(ExtensionsHandler* aExtensionsHandler); 103 104 virtual JSObject* WrapObjectInternal( 105 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override { 106 return mozilla::dom::ExtendableEvent_Binding::Wrap(aCx, this, aGivenProto); 107 } 108 109 static already_AddRefed<ExtendableEvent> Constructor( 110 mozilla::dom::EventTarget* aOwner, const nsAString& aType, 111 const EventInit& aOptions) { 112 RefPtr<ExtendableEvent> e = new ExtendableEvent(aOwner); 113 bool trusted = e->Init(aOwner); 114 e->InitEvent(aType, aOptions.mBubbles, aOptions.mCancelable); 115 e->SetTrusted(trusted); 116 e->SetComposed(aOptions.mComposed); 117 return e.forget(); 118 } 119 120 static already_AddRefed<ExtendableEvent> Constructor( 121 const GlobalObject& aGlobal, const nsAString& aType, 122 const EventInit& aOptions) { 123 nsCOMPtr<EventTarget> target = do_QueryInterface(aGlobal.GetAsSupports()); 124 return Constructor(target, aType, aOptions); 125 } 126 127 void WaitUntil(JSContext* aCx, Promise& aPromise, ErrorResult& aRv); 128 129 virtual ExtendableEvent* AsExtendableEvent() override { return this; } 130 }; 131 132 class FetchEvent final : public ExtendableEvent { 133 RefPtr<FetchEventOp> mRespondWithHandler; 134 nsMainThreadPtrHandle<nsIInterceptedChannel> mChannel; 135 nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration; 136 RefPtr<Request> mRequest; 137 RefPtr<Promise> mHandled; 138 RefPtr<Promise> mPreloadResponse; 139 nsCString mScriptSpec; 140 nsString mClientId; 141 nsString mResultingClientId; 142 JSCallingLocation mPreventDefaultLocation; 143 bool mWaitToRespond; 144 145 protected: 146 explicit FetchEvent(EventTarget* aOwner); 147 ~FetchEvent(); 148 149 public: 150 NS_DECL_ISUPPORTS_INHERITED 151 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FetchEvent, ExtendableEvent) 152 153 virtual JSObject* WrapObjectInternal( 154 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override { 155 return FetchEvent_Binding::Wrap(aCx, this, aGivenProto); 156 } 157 158 void PostInit( 159 nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel, 160 nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration, 161 const nsACString& aScriptSpec); 162 163 void PostInit(const nsACString& aScriptSpec, 164 RefPtr<FetchEventOp> aRespondWithHandler); 165 166 static already_AddRefed<FetchEvent> Constructor( 167 const GlobalObject& aGlobal, const nsAString& aType, 168 const FetchEventInit& aOptions); 169 170 bool WaitToRespond() const { return mWaitToRespond; } 171 172 Request* Request_() const { 173 MOZ_ASSERT(mRequest); 174 return mRequest; 175 } 176 177 void GetClientId(nsAString& aClientId) const { aClientId = mClientId; } 178 179 void GetResultingClientId(nsAString& aResultingClientId) const { 180 aResultingClientId = mResultingClientId; 181 } 182 183 Promise* Handled() const { return mHandled; } 184 185 Promise* PreloadResponse() const { return mPreloadResponse; } 186 187 void RespondWith(JSContext* aCx, Promise& aArg, ErrorResult& aRv); 188 189 // Pull in the Event version of PreventDefault so we don't get 190 // shadowing warnings. 191 using Event::PreventDefault; 192 void PreventDefault(JSContext* aCx, CallerType aCallerType) override; 193 194 void ReportCanceled(); 195 }; 196 197 class PushMessageData final : public nsISupports, public nsWrapperCache { 198 public: 199 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 200 NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(PushMessageData) 201 202 virtual JSObject* WrapObject(JSContext* aCx, 203 JS::Handle<JSObject*> aGivenProto) override; 204 205 nsIGlobalObject* GetParentObject() const { return mOwner; } 206 207 void Json(JSContext* cx, JS::MutableHandle<JS::Value> aRetval, 208 ErrorResult& aRv); 209 void Text(nsAString& aData); 210 void ArrayBuffer(JSContext* cx, JS::MutableHandle<JSObject*> aRetval, 211 ErrorResult& aRv); 212 already_AddRefed<mozilla::dom::Blob> Blob(ErrorResult& aRv); 213 void Bytes(JSContext* cx, JS::MutableHandle<JSObject*> aRetval, 214 ErrorResult& aRv); 215 216 PushMessageData(nsIGlobalObject* aOwner, nsTArray<uint8_t>&& aBytes); 217 218 private: 219 nsCOMPtr<nsIGlobalObject> mOwner; 220 nsTArray<uint8_t> mBytes; 221 nsString mDecodedText; 222 ~PushMessageData(); 223 224 nsresult EnsureDecodedText(); 225 uint8_t* GetContentsCopy(); 226 void SetUseCounterIfDeclarative(JSContext* aCx); 227 }; 228 229 class PushEvent final : public ExtendableEvent { 230 RefPtr<PushMessageData> mData; 231 232 protected: 233 explicit PushEvent(mozilla::dom::EventTarget* aOwner); 234 ~PushEvent() = default; 235 236 public: 237 NS_DECL_ISUPPORTS_INHERITED 238 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PushEvent, ExtendableEvent) 239 240 virtual JSObject* WrapObjectInternal( 241 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; 242 243 static already_AddRefed<PushEvent> Constructor( 244 mozilla::dom::EventTarget* aOwner, const nsAString& aType, 245 const PushEventInit& aOptions, ErrorResult& aRv); 246 247 static already_AddRefed<PushEvent> Constructor(const GlobalObject& aGlobal, 248 const nsAString& aType, 249 const PushEventInit& aOptions, 250 ErrorResult& aRv) { 251 nsCOMPtr<EventTarget> owner = do_QueryInterface(aGlobal.GetAsSupports()); 252 return Constructor(owner, aType, aOptions, aRv); 253 } 254 255 PushMessageData* GetData() const { return mData; } 256 }; 257 258 class ExtendableMessageEvent final : public ExtendableEvent { 259 JS::Heap<JS::Value> mData; 260 nsString mOrigin; 261 nsString mLastEventId; 262 RefPtr<Client> mClient; 263 RefPtr<ServiceWorker> mServiceWorker; 264 RefPtr<MessagePort> mMessagePort; 265 nsTArray<RefPtr<MessagePort>> mPorts; 266 267 protected: 268 explicit ExtendableMessageEvent(EventTarget* aOwner); 269 ~ExtendableMessageEvent(); 270 271 public: 272 NS_DECL_ISUPPORTS_INHERITED 273 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(ExtendableMessageEvent, 274 ExtendableEvent) 275 276 virtual JSObject* WrapObjectInternal( 277 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override { 278 return mozilla::dom::ExtendableMessageEvent_Binding::Wrap(aCx, this, 279 aGivenProto); 280 } 281 282 static already_AddRefed<ExtendableMessageEvent> Constructor( 283 mozilla::dom::EventTarget* aOwner, const nsAString& aType, 284 const ExtendableMessageEventInit& aOptions); 285 286 static already_AddRefed<ExtendableMessageEvent> Constructor( 287 const GlobalObject& aGlobal, const nsAString& aType, 288 const ExtendableMessageEventInit& aOptions); 289 290 void GetData(JSContext* aCx, JS::MutableHandle<JS::Value> aData, 291 ErrorResult& aRv); 292 293 void GetSource( 294 Nullable<OwningClientOrServiceWorkerOrMessagePort>& aValue) const; 295 296 void GetOrigin(nsAString& aOrigin) const { aOrigin = mOrigin; } 297 298 void GetLastEventId(nsAString& aLastEventId) const { 299 aLastEventId = mLastEventId; 300 } 301 302 void GetPorts(nsTArray<RefPtr<MessagePort>>& aPorts); 303 }; 304 305 } // namespace mozilla::dom 306 307 #endif /* mozilla_dom_serviceworkerevents_h__ */