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/WorkerCommon.h" 19 20 #include "nsProxyRelease.h" 21 #include "nsContentUtils.h" 22 23 class nsIInterceptedChannel; 24 25 namespace mozilla { 26 namespace dom { 27 28 class Blob; 29 class Client; 30 class FetchEventOp; 31 class MessagePort; 32 struct PushEventInit; 33 class Request; 34 class ResponseOrPromise; 35 class ServiceWorker; 36 class ServiceWorkerRegistrationInfo; 37 38 // Defined in ServiceWorker.cpp 39 bool ServiceWorkerVisible(JSContext* aCx, JSObject* aObj); 40 41 class CancelChannelRunnable final : public Runnable { 42 nsMainThreadPtrHandle<nsIInterceptedChannel> mChannel; 43 nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration; 44 const nsresult mStatus; 45 46 public: 47 CancelChannelRunnable( 48 nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel, 49 nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration, 50 nsresult aStatus); 51 52 NS_IMETHOD Run() override; 53 }; 54 55 enum ExtendableEventResult { Rejected = 0, Resolved }; 56 57 class ExtendableEventCallback { 58 public: 59 virtual void FinishedWithResult(ExtendableEventResult aResult) = 0; 60 61 NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING 62 }; 63 64 class ExtendableEvent : public Event { 65 public: 66 class ExtensionsHandler { 67 friend class ExtendableEvent; 68 69 public: 70 virtual bool WaitOnPromise(Promise& aPromise) = 0; 71 72 NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING 73 74 protected: 75 virtual ~ExtensionsHandler(); 76 77 // Also returns false if the owning ExtendableEvent is destroyed. 78 bool GetDispatchFlag() const; 79 80 private: 81 // Only the owning ExtendableEvent is allowed to set this data. 82 void SetExtendableEvent(const ExtendableEvent* const aExtendableEvent); 83 84 MOZ_NON_OWNING_REF const ExtendableEvent* mExtendableEvent = nullptr; 85 }; 86 87 private: 88 RefPtr<ExtensionsHandler> mExtensionsHandler; 89 90 protected: GetDispatchFlag()91 bool GetDispatchFlag() const { return mEvent->mFlags.mIsBeingDispatched; } 92 93 bool WaitOnPromise(Promise& aPromise); 94 95 explicit ExtendableEvent(mozilla::dom::EventTarget* aOwner); 96 ~ExtendableEvent()97 ~ExtendableEvent() { 98 if (mExtensionsHandler) { 99 mExtensionsHandler->SetExtendableEvent(nullptr); 100 } 101 }; 102 103 public: 104 NS_DECL_ISUPPORTS_INHERITED 105 106 void SetKeepAliveHandler(ExtensionsHandler* aExtensionsHandler); 107 WrapObjectInternal(JSContext * aCx,JS::Handle<JSObject * > aGivenProto)108 virtual JSObject* WrapObjectInternal( 109 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override { 110 return mozilla::dom::ExtendableEvent_Binding::Wrap(aCx, this, aGivenProto); 111 } 112 Constructor(mozilla::dom::EventTarget * aOwner,const nsAString & aType,const EventInit & aOptions)113 static already_AddRefed<ExtendableEvent> Constructor( 114 mozilla::dom::EventTarget* aOwner, const nsAString& aType, 115 const EventInit& aOptions) { 116 RefPtr<ExtendableEvent> e = new ExtendableEvent(aOwner); 117 bool trusted = e->Init(aOwner); 118 e->InitEvent(aType, aOptions.mBubbles, aOptions.mCancelable); 119 e->SetTrusted(trusted); 120 e->SetComposed(aOptions.mComposed); 121 return e.forget(); 122 } 123 Constructor(const GlobalObject & aGlobal,const nsAString & aType,const EventInit & aOptions)124 static already_AddRefed<ExtendableEvent> Constructor( 125 const GlobalObject& aGlobal, const nsAString& aType, 126 const EventInit& aOptions) { 127 nsCOMPtr<EventTarget> target = do_QueryInterface(aGlobal.GetAsSupports()); 128 return Constructor(target, aType, aOptions); 129 } 130 131 void WaitUntil(JSContext* aCx, Promise& aPromise, ErrorResult& aRv); 132 AsExtendableEvent()133 virtual ExtendableEvent* AsExtendableEvent() override { return this; } 134 }; 135 136 class FetchEvent final : public ExtendableEvent { 137 RefPtr<FetchEventOp> mRespondWithHandler; 138 nsMainThreadPtrHandle<nsIInterceptedChannel> mChannel; 139 nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration; 140 RefPtr<Request> mRequest; 141 RefPtr<Promise> mHandled; 142 nsCString mScriptSpec; 143 nsCString mPreventDefaultScriptSpec; 144 nsString mClientId; 145 nsString mResultingClientId; 146 uint32_t mPreventDefaultLineNumber; 147 uint32_t mPreventDefaultColumnNumber; 148 bool mWaitToRespond; 149 150 protected: 151 explicit FetchEvent(EventTarget* aOwner); 152 ~FetchEvent(); 153 154 public: 155 NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FetchEvent,ExtendableEvent)156 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FetchEvent, ExtendableEvent) 157 158 virtual JSObject* WrapObjectInternal( 159 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override { 160 return FetchEvent_Binding::Wrap(aCx, this, aGivenProto); 161 } 162 163 void PostInit( 164 nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel, 165 nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration, 166 const nsACString& aScriptSpec); 167 168 void PostInit(const nsACString& aScriptSpec, 169 RefPtr<FetchEventOp> aRespondWithHandler); 170 171 static already_AddRefed<FetchEvent> Constructor( 172 const GlobalObject& aGlobal, const nsAString& aType, 173 const FetchEventInit& aOptions); 174 WaitToRespond()175 bool WaitToRespond() const { return mWaitToRespond; } 176 Request_()177 Request* Request_() const { 178 MOZ_ASSERT(mRequest); 179 return mRequest; 180 } 181 GetClientId(nsAString & aClientId)182 void GetClientId(nsAString& aClientId) const { aClientId = mClientId; } 183 GetResultingClientId(nsAString & aResultingClientId)184 void GetResultingClientId(nsAString& aResultingClientId) const { 185 aResultingClientId = mResultingClientId; 186 } 187 Handled()188 Promise* Handled() const { return mHandled; } 189 190 void RespondWith(JSContext* aCx, Promise& aArg, ErrorResult& aRv); 191 192 // Pull in the Event version of PreventDefault so we don't get 193 // shadowing warnings. 194 using Event::PreventDefault; 195 void PreventDefault(JSContext* aCx, CallerType aCallerType) override; 196 197 void ReportCanceled(); 198 }; 199 200 class PushMessageData final : public nsISupports, public nsWrapperCache { 201 public: 202 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 203 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PushMessageData) 204 205 virtual JSObject* WrapObject(JSContext* aCx, 206 JS::Handle<JSObject*> aGivenProto) override; 207 GetParentObject()208 nsIGlobalObject* GetParentObject() const { return mOwner; } 209 210 void Json(JSContext* cx, JS::MutableHandle<JS::Value> aRetval, 211 ErrorResult& aRv); 212 void Text(nsAString& aData); 213 void ArrayBuffer(JSContext* cx, JS::MutableHandle<JSObject*> aRetval, 214 ErrorResult& aRv); 215 already_AddRefed<mozilla::dom::Blob> Blob(ErrorResult& aRv); 216 217 PushMessageData(nsIGlobalObject* aOwner, nsTArray<uint8_t>&& aBytes); 218 219 private: 220 nsCOMPtr<nsIGlobalObject> mOwner; 221 nsTArray<uint8_t> mBytes; 222 nsString mDecodedText; 223 ~PushMessageData(); 224 225 nsresult EnsureDecodedText(); 226 uint8_t* GetContentsCopy(); 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 Constructor(const GlobalObject & aGlobal,const nsAString & aType,const PushEventInit & aOptions,ErrorResult & aRv)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 GetData()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 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(ExtendableMessageEvent,ExtendableEvent)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 GetOrigin(nsAString & aOrigin)296 void GetOrigin(nsAString& aOrigin) const { aOrigin = mOrigin; } 297 GetLastEventId(nsAString & aLastEventId)298 void GetLastEventId(nsAString& aLastEventId) const { 299 aLastEventId = mLastEventId; 300 } 301 302 void GetPorts(nsTArray<RefPtr<MessagePort>>& aPorts); 303 }; 304 305 } // namespace dom 306 } // namespace mozilla 307 308 #endif /* mozilla_dom_serviceworkerevents_h__ */ 309