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