Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/serviceworkers/ServiceWorkerPrivate.h
Line
Count
Source (jump to first uncovered line)
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_serviceworkerprivate_h
8
#define mozilla_dom_serviceworkerprivate_h
9
10
#include "nsCOMPtr.h"
11
#include "mozilla/dom/WorkerPrivate.h"
12
13
0
#define NOTIFICATION_CLICK_EVENT_NAME "notificationclick"
14
0
#define NOTIFICATION_CLOSE_EVENT_NAME "notificationclose"
15
16
class nsIInterceptedChannel;
17
class nsIWorkerDebugger;
18
19
namespace mozilla {
20
21
class JSObjectHolder;
22
23
namespace dom {
24
25
class ClientInfoAndState;
26
class KeepAliveToken;
27
class ServiceWorkerCloneData;
28
class ServiceWorkerInfo;
29
class ServiceWorkerRegistrationInfo;
30
31
namespace ipc {
32
class StructuredCloneData;
33
} // namespace ipc
34
35
class LifeCycleEventCallback : public Runnable
36
{
37
public:
38
0
  LifeCycleEventCallback() : Runnable("dom::LifeCycleEventCallback") {}
39
40
  // Called on the worker thread.
41
  virtual void
42
  SetResult(bool aResult) = 0;
43
};
44
45
// ServiceWorkerPrivate is a wrapper for managing the on-demand aspect of
46
// service workers. It handles all event dispatching to the worker and ensures
47
// the worker thread is running when needed.
48
//
49
// Lifetime management: To spin up the worker thread we own a |WorkerPrivate|
50
// object which can be cancelled if no events are received for a certain
51
// amount of time. The worker is kept alive by holding a |KeepAliveToken|
52
// reference.
53
//
54
// Extendable events hold tokens for the duration of their handler execution
55
// and until their waitUntil promise is resolved, while ServiceWorkerPrivate
56
// will hold a token for |dom.serviceWorkers.idle_timeout| seconds after each
57
// new event.
58
//
59
// Note: All timer events must be handled on the main thread because the
60
// worker may block indefinitely the worker thread (e. g. infinite loop in the
61
// script).
62
//
63
// There are 3 cases where we may ignore keep alive tokens:
64
// 1. When ServiceWorkerPrivate's token expired, if there are still waitUntil
65
// handlers holding tokens, we wait another |dom.serviceWorkers.idle_extended_timeout|
66
// seconds before forcibly terminating the worker.
67
// 2. If the worker stopped controlling documents and it is not handling push
68
// events.
69
// 3. The content process is shutting down.
70
//
71
// Adding an API function for a new event requires calling |SpawnWorkerIfNeeded|
72
// with an appropriate reason before any runnable is dispatched to the worker.
73
// If the event is extendable then the runnable should inherit
74
// ExtendableEventWorkerRunnable.
75
class ServiceWorkerPrivate final
76
{
77
  friend class KeepAliveToken;
78
79
public:
80
  NS_IMETHOD_(MozExternalRefCountType) AddRef();
81
  NS_IMETHOD_(MozExternalRefCountType) Release();
82
  NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(ServiceWorkerPrivate)
83
84
  typedef mozilla::FalseType HasThreadSafeRefCnt;
85
86
protected:
87
  nsCycleCollectingAutoRefCnt mRefCnt;
88
  NS_DECL_OWNINGTHREAD
89
90
public:
91
  explicit ServiceWorkerPrivate(ServiceWorkerInfo* aInfo);
92
93
  nsresult
94
  SendMessageEvent(RefPtr<ServiceWorkerCloneData>&& aData,
95
                   const ClientInfoAndState& aClientInfoAndState);
96
97
  // This is used to validate the worker script and continue the installation
98
  // process.
99
  nsresult
100
  CheckScriptEvaluation(LifeCycleEventCallback* aCallback);
101
102
  nsresult
103
  SendLifeCycleEvent(const nsAString& aEventType,
104
                     LifeCycleEventCallback* aCallback);
105
106
  nsresult
107
  SendPushEvent(const nsAString& aMessageId,
108
                const Maybe<nsTArray<uint8_t>>& aData,
109
                ServiceWorkerRegistrationInfo* aRegistration);
110
111
  nsresult
112
  SendPushSubscriptionChangeEvent();
113
114
  nsresult
115
  SendNotificationEvent(const nsAString& aEventName,
116
                        const nsAString& aID,
117
                        const nsAString& aTitle,
118
                        const nsAString& aDir,
119
                        const nsAString& aLang,
120
                        const nsAString& aBody,
121
                        const nsAString& aTag,
122
                        const nsAString& aIcon,
123
                        const nsAString& aData,
124
                        const nsAString& aBehavior,
125
                        const nsAString& aScope);
126
127
  nsresult
128
  SendFetchEvent(nsIInterceptedChannel* aChannel, nsILoadGroup* aLoadGroup,
129
                 const nsAString& aClientId, bool aIsReload);
130
131
  bool
132
  MaybeStoreISupports(nsISupports* aSupports);
133
134
  void
135
  RemoveISupports(nsISupports* aSupports);
136
137
  // This will terminate the current running worker thread and drop the
138
  // workerPrivate reference.
139
  // Called by ServiceWorkerInfo when [[Clear Registration]] is invoked
140
  // or whenever the spec mandates that we terminate the worker.
141
  // This is a no-op if the worker has already been stopped.
142
  void
143
  TerminateWorker();
144
145
  void
146
  NoteDeadServiceWorkerInfo();
147
148
  void
149
  NoteStoppedControllingDocuments();
150
151
  void
152
  UpdateState(ServiceWorkerState aState);
153
154
  nsresult
155
  GetDebugger(nsIWorkerDebugger** aResult);
156
157
  nsresult
158
  AttachDebugger();
159
160
  nsresult
161
  DetachDebugger();
162
163
  bool
164
  IsIdle() const;
165
166
  void
167
  SetHandlesFetch(bool aValue);
168
169
private:
170
  enum WakeUpReason {
171
    FetchEvent = 0,
172
    PushEvent,
173
    PushSubscriptionChangeEvent,
174
    MessageEvent,
175
    NotificationClickEvent,
176
    NotificationCloseEvent,
177
    LifeCycleEvent,
178
    AttachEvent
179
  };
180
181
  // Timer callbacks
182
  void
183
  NoteIdleWorkerCallback(nsITimer* aTimer);
184
185
  void
186
  TerminateWorkerCallback(nsITimer* aTimer);
187
188
  void
189
  RenewKeepAliveToken(WakeUpReason aWhy);
190
191
  void
192
  ResetIdleTimeout();
193
194
  void
195
  AddToken();
196
197
  void
198
  ReleaseToken();
199
200
  nsresult
201
  SpawnWorkerIfNeeded(WakeUpReason aWhy,
202
                      bool* aNewWorkerCreated = nullptr,
203
                      nsILoadGroup* aLoadGroup = nullptr);
204
205
  ~ServiceWorkerPrivate();
206
207
  already_AddRefed<KeepAliveToken>
208
  CreateEventKeepAliveToken();
209
210
  // The info object owns us. It is possible to outlive it for a brief period
211
  // of time if there are pending waitUntil promises, in which case it
212
  // will be null and |SpawnWorkerIfNeeded| will always fail.
213
  ServiceWorkerInfo* MOZ_NON_OWNING_REF mInfo;
214
215
  // The WorkerPrivate object can only be closed by this class or by the
216
  // RuntimeService class if gecko is shutting down. Closing the worker
217
  // multiple times is OK, since the second attempt will be a no-op.
218
  RefPtr<WorkerPrivate> mWorkerPrivate;
219
220
  nsCOMPtr<nsITimer> mIdleWorkerTimer;
221
222
  // We keep a token for |dom.serviceWorkers.idle_timeout| seconds to give the
223
  // worker a grace period after each event.
224
  RefPtr<KeepAliveToken> mIdleKeepAliveToken;
225
226
  uint64_t mDebuggerCount;
227
228
  uint64_t mTokenCount;
229
230
  // Meant for keeping objects alive while handling requests from the worker
231
  // on the main thread. Access to this array is provided through
232
  // |StoreISupports| and |RemoveISupports|. Note that the array is also
233
  // cleared whenever the worker is terminated.
234
  nsTArray<nsCOMPtr<nsISupports>> mSupportsArray;
235
236
  // Array of function event worker runnables that are pending due to
237
  // the worker activating.  Main thread only.
238
  nsTArray<RefPtr<WorkerRunnable>> mPendingFunctionalEvents;
239
};
240
241
} // namespace dom
242
} // namespace mozilla
243
244
#endif // mozilla_dom_serviceworkerprivate_h