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