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/dom/DOMPrefs.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 MessagePort; 31 struct PushEventInit; 32 class Request; 33 class ResponseOrPromise; 34 class ServiceWorker; 35 class ServiceWorkerRegistrationInfo; 36 37 // Defined in ServiceWorker.cpp 38 bool ServiceWorkerVisible(JSContext* aCx, JSObject* aObj); 39 40 class CancelChannelRunnable final : public Runnable { 41 nsMainThreadPtrHandle<nsIInterceptedChannel> mChannel; 42 nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration; 43 const nsresult mStatus; 44 45 public: 46 CancelChannelRunnable( 47 nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel, 48 nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration, 49 nsresult aStatus); 50 51 NS_IMETHOD Run() override; 52 }; 53 54 class ExtendableEvent : public Event { 55 public: 56 class ExtensionsHandler { 57 public: 58 virtual bool WaitOnPromise(Promise& aPromise) = 0; 59 60 NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING 61 }; 62 63 private: 64 RefPtr<ExtensionsHandler> mExtensionsHandler; 65 66 protected: 67 bool WaitOnPromise(Promise& aPromise); 68 69 explicit ExtendableEvent(mozilla::dom::EventTarget* aOwner); ~ExtendableEvent()70 ~ExtendableEvent() {} 71 72 public: 73 NS_DECL_ISUPPORTS_INHERITED 74 75 void SetKeepAliveHandler(ExtensionsHandler* aExtensionsHandler); 76 WrapObjectInternal(JSContext * aCx,JS::Handle<JSObject * > aGivenProto)77 virtual JSObject* WrapObjectInternal( 78 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override { 79 return mozilla::dom::ExtendableEventBinding::Wrap(aCx, this, aGivenProto); 80 } 81 Constructor(mozilla::dom::EventTarget * aOwner,const nsAString & aType,const EventInit & aOptions)82 static already_AddRefed<ExtendableEvent> Constructor( 83 mozilla::dom::EventTarget* aOwner, const nsAString& aType, 84 const EventInit& aOptions) { 85 RefPtr<ExtendableEvent> e = new ExtendableEvent(aOwner); 86 bool trusted = e->Init(aOwner); 87 e->InitEvent(aType, aOptions.mBubbles, aOptions.mCancelable); 88 e->SetTrusted(trusted); 89 e->SetComposed(aOptions.mComposed); 90 return e.forget(); 91 } 92 Constructor(const GlobalObject & aGlobal,const nsAString & aType,const EventInit & aOptions,ErrorResult & aRv)93 static already_AddRefed<ExtendableEvent> Constructor( 94 const GlobalObject& aGlobal, const nsAString& aType, 95 const EventInit& aOptions, ErrorResult& aRv) { 96 nsCOMPtr<EventTarget> target = do_QueryInterface(aGlobal.GetAsSupports()); 97 return Constructor(target, aType, aOptions); 98 } 99 100 void WaitUntil(JSContext* aCx, Promise& aPromise, ErrorResult& aRv); 101 AsExtendableEvent()102 virtual ExtendableEvent* AsExtendableEvent() override { return this; } 103 }; 104 105 class FetchEvent final : public ExtendableEvent { 106 nsMainThreadPtrHandle<nsIInterceptedChannel> mChannel; 107 nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration; 108 RefPtr<Request> mRequest; 109 nsCString mScriptSpec; 110 nsCString mPreventDefaultScriptSpec; 111 nsString mClientId; 112 uint32_t mPreventDefaultLineNumber; 113 uint32_t mPreventDefaultColumnNumber; 114 bool mIsReload; 115 bool mWaitToRespond; 116 117 protected: 118 explicit FetchEvent(EventTarget* aOwner); 119 ~FetchEvent(); 120 121 public: 122 NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FetchEvent,ExtendableEvent)123 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FetchEvent, ExtendableEvent) 124 125 // Note, we cannot use NS_FORWARD_TO_EVENT because we want a different 126 // PreventDefault(JSContext*, CallerType) override. 127 NS_FORWARD_NSIDOMEVENT(Event::) 128 129 virtual JSObject* WrapObjectInternal( 130 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override { 131 return FetchEventBinding::Wrap(aCx, this, aGivenProto); 132 } 133 134 void PostInit( 135 nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel, 136 nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration, 137 const nsACString& aScriptSpec); 138 139 static already_AddRefed<FetchEvent> Constructor( 140 const GlobalObject& aGlobal, const nsAString& aType, 141 const FetchEventInit& aOptions, ErrorResult& aRv); 142 WaitToRespond()143 bool WaitToRespond() const { return mWaitToRespond; } 144 Request_()145 Request* Request_() const { 146 MOZ_ASSERT(mRequest); 147 return mRequest; 148 } 149 GetClientId(nsAString & aClientId)150 void GetClientId(nsAString& aClientId) const { aClientId = mClientId; } 151 IsReload()152 bool IsReload() const { return mIsReload; } 153 154 void RespondWith(JSContext* aCx, Promise& aArg, ErrorResult& aRv); 155 156 already_AddRefed<Promise> ForwardTo(const nsAString& aUrl); 157 158 already_AddRefed<Promise> Default(); 159 160 void PreventDefault(JSContext* aCx, CallerType aCallerType) override; 161 162 void ReportCanceled(); 163 }; 164 165 class PushMessageData final : public nsISupports, public nsWrapperCache { 166 public: 167 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 168 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PushMessageData) 169 170 virtual JSObject* WrapObject(JSContext* aCx, 171 JS::Handle<JSObject*> aGivenProto) override; 172 GetParentObject()173 nsISupports* GetParentObject() const { return mOwner; } 174 175 void Json(JSContext* cx, JS::MutableHandle<JS::Value> aRetval, 176 ErrorResult& aRv); 177 void Text(nsAString& aData); 178 void ArrayBuffer(JSContext* cx, JS::MutableHandle<JSObject*> aRetval, 179 ErrorResult& aRv); 180 already_AddRefed<mozilla::dom::Blob> Blob(ErrorResult& aRv); 181 182 PushMessageData(nsISupports* aOwner, nsTArray<uint8_t>&& aBytes); 183 184 private: 185 nsCOMPtr<nsISupports> mOwner; 186 nsTArray<uint8_t> mBytes; 187 nsString mDecodedText; 188 ~PushMessageData(); 189 190 nsresult EnsureDecodedText(); 191 uint8_t* GetContentsCopy(); 192 }; 193 194 class PushEvent final : public ExtendableEvent { 195 RefPtr<PushMessageData> mData; 196 197 protected: 198 explicit PushEvent(mozilla::dom::EventTarget* aOwner); ~PushEvent()199 ~PushEvent() {} 200 201 public: 202 NS_DECL_ISUPPORTS_INHERITED 203 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PushEvent, ExtendableEvent) 204 NS_FORWARD_TO_EVENT 205 206 virtual JSObject* WrapObjectInternal( 207 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; 208 209 static already_AddRefed<PushEvent> Constructor( 210 mozilla::dom::EventTarget* aOwner, const nsAString& aType, 211 const PushEventInit& aOptions, ErrorResult& aRv); 212 Constructor(const GlobalObject & aGlobal,const nsAString & aType,const PushEventInit & aOptions,ErrorResult & aRv)213 static already_AddRefed<PushEvent> Constructor(const GlobalObject& aGlobal, 214 const nsAString& aType, 215 const PushEventInit& aOptions, 216 ErrorResult& aRv) { 217 nsCOMPtr<EventTarget> owner = do_QueryInterface(aGlobal.GetAsSupports()); 218 return Constructor(owner, aType, aOptions, aRv); 219 } 220 GetData()221 PushMessageData* GetData() const { return mData; } 222 }; 223 224 class ExtendableMessageEvent final : public ExtendableEvent { 225 JS::Heap<JS::Value> mData; 226 nsString mOrigin; 227 nsString mLastEventId; 228 RefPtr<Client> mClient; 229 RefPtr<ServiceWorker> mServiceWorker; 230 RefPtr<MessagePort> mMessagePort; 231 nsTArray<RefPtr<MessagePort>> mPorts; 232 233 protected: 234 explicit ExtendableMessageEvent(EventTarget* aOwner); 235 ~ExtendableMessageEvent(); 236 237 public: 238 NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(ExtendableMessageEvent,ExtendableEvent)239 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(ExtendableMessageEvent, 240 ExtendableEvent) 241 242 virtual JSObject* WrapObjectInternal( 243 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override { 244 return mozilla::dom::ExtendableMessageEventBinding::Wrap(aCx, this, 245 aGivenProto); 246 } 247 248 static already_AddRefed<ExtendableMessageEvent> Constructor( 249 mozilla::dom::EventTarget* aOwner, const nsAString& aType, 250 const ExtendableMessageEventInit& aOptions, ErrorResult& aRv); 251 252 static already_AddRefed<ExtendableMessageEvent> Constructor( 253 const GlobalObject& aGlobal, const nsAString& aType, 254 const ExtendableMessageEventInit& aOptions, ErrorResult& aRv); 255 256 void GetData(JSContext* aCx, JS::MutableHandle<JS::Value> aData, 257 ErrorResult& aRv); 258 259 void GetSource( 260 Nullable<OwningClientOrServiceWorkerOrMessagePort>& aValue) const; 261 GetOrigin(nsAString & aOrigin)262 void GetOrigin(nsAString& aOrigin) const { aOrigin = mOrigin; } 263 GetLastEventId(nsAString & aLastEventId)264 void GetLastEventId(nsAString& aLastEventId) const { 265 aLastEventId = mLastEventId; 266 } 267 268 void GetPorts(nsTArray<RefPtr<MessagePort>>& aPorts); 269 }; 270 271 } // namespace dom 272 } // namespace mozilla 273 274 #endif /* mozilla_dom_serviceworkerevents_h__ */ 275