Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/workers/WorkerScope.cpp
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
#include "WorkerScope.h"
8
9
#include "jsapi.h"
10
#include "jsfriendapi.h"
11
#include "mozilla/EventListenerManager.h"
12
#include "mozilla/dom/BindingDeclarations.h"
13
#include "mozilla/dom/Clients.h"
14
#include "mozilla/dom/ClientState.h"
15
#include "mozilla/dom/Console.h"
16
#include "mozilla/dom/DedicatedWorkerGlobalScopeBinding.h"
17
#include "mozilla/dom/DOMPrefs.h"
18
#include "mozilla/dom/Fetch.h"
19
#include "mozilla/dom/FunctionBinding.h"
20
#include "mozilla/dom/IDBFactory.h"
21
#include "mozilla/dom/ImageBitmap.h"
22
#include "mozilla/dom/ImageBitmapBinding.h"
23
#include "mozilla/dom/Performance.h"
24
#include "mozilla/dom/Promise.h"
25
#include "mozilla/dom/PromiseWorkerProxy.h"
26
#include "mozilla/dom/ServiceWorkerGlobalScopeBinding.h"
27
#include "mozilla/dom/SharedWorkerGlobalScopeBinding.h"
28
#include "mozilla/dom/SimpleGlobalObject.h"
29
#include "mozilla/dom/WorkerDebuggerGlobalScopeBinding.h"
30
#include "mozilla/dom/WorkerGlobalScopeBinding.h"
31
#include "mozilla/dom/WorkerLocation.h"
32
#include "mozilla/dom/WorkerNavigator.h"
33
#include "mozilla/dom/cache/CacheStorage.h"
34
#include "mozilla/Services.h"
35
#include "mozilla/StaticPrefs.h"
36
#include "nsServiceManagerUtils.h"
37
38
#include "nsIDocument.h"
39
#include "nsIServiceWorkerManager.h"
40
#include "nsIScriptError.h"
41
#include "nsIScriptTimeoutHandler.h"
42
43
#ifdef ANDROID
44
#include <android/log.h>
45
#endif
46
47
#include "Crypto.h"
48
#include "Principal.h"
49
#include "RuntimeService.h"
50
#include "ScriptLoader.h"
51
#include "WorkerPrivate.h"
52
#include "WorkerRunnable.h"
53
#include "mozilla/dom/ServiceWorkerManager.h"
54
#include "mozilla/dom/ServiceWorkerRegistration.h"
55
56
#ifdef XP_WIN
57
#undef PostMessage
58
#endif
59
60
extern already_AddRefed<nsIScriptTimeoutHandler>
61
NS_CreateJSTimeoutHandler(JSContext* aCx,
62
                          mozilla::dom::WorkerPrivate* aWorkerPrivate,
63
                          mozilla::dom::Function& aFunction,
64
                          const mozilla::dom::Sequence<JS::Value>& aArguments,
65
                          mozilla::ErrorResult& aError);
66
67
extern already_AddRefed<nsIScriptTimeoutHandler>
68
NS_CreateJSTimeoutHandler(JSContext* aCx,
69
                          mozilla::dom::WorkerPrivate* aWorkerPrivate,
70
                          const nsAString& aExpression,
71
                          mozilla::ErrorResult& aRv);
72
73
namespace mozilla {
74
namespace dom {
75
76
using mozilla::dom::cache::CacheStorage;
77
using mozilla::ipc::PrincipalInfo;
78
79
WorkerGlobalScope::WorkerGlobalScope(WorkerPrivate* aWorkerPrivate)
80
: mSerialEventTarget(aWorkerPrivate->HybridEventTarget())
81
, mWindowInteractionsAllowed(0)
82
, mWorkerPrivate(aWorkerPrivate)
83
0
{
84
0
  mWorkerPrivate->AssertIsOnWorkerThread();
85
0
86
0
  // We should always have an event target when the global is created.
87
0
  MOZ_DIAGNOSTIC_ASSERT(mSerialEventTarget);
88
0
}
89
90
WorkerGlobalScope::~WorkerGlobalScope()
91
0
{
92
0
  mWorkerPrivate->AssertIsOnWorkerThread();
93
0
}
94
95
NS_IMPL_CYCLE_COLLECTION_CLASS(WorkerGlobalScope)
96
97
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WorkerGlobalScope,
98
0
                                                  DOMEventTargetHelper)
99
0
  tmp->mWorkerPrivate->AssertIsOnWorkerThread();
100
0
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsole)
101
0
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCrypto)
102
0
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance)
103
0
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocation)
104
0
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigator)
105
0
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexedDB)
106
0
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCacheStorage)
107
0
  tmp->TraverseHostObjectURIs(cb);
108
0
  tmp->mWorkerPrivate->TraverseTimeouts(cb);
109
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
110
111
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WorkerGlobalScope,
112
0
                                                DOMEventTargetHelper)
113
0
  tmp->mWorkerPrivate->AssertIsOnWorkerThread();
114
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsole)
115
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mCrypto)
116
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)
117
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocation)
118
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator)
119
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexedDB)
120
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mCacheStorage)
121
0
  tmp->UnlinkHostObjectURIs();
122
0
  tmp->mWorkerPrivate->UnlinkTimeouts();
123
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
124
125
0
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(WorkerGlobalScope,
126
0
                                               DOMEventTargetHelper)
127
0
  tmp->mWorkerPrivate->AssertIsOnWorkerThread();
128
0
NS_IMPL_CYCLE_COLLECTION_TRACE_END
129
130
NS_IMPL_ADDREF_INHERITED(WorkerGlobalScope, DOMEventTargetHelper)
131
NS_IMPL_RELEASE_INHERITED(WorkerGlobalScope, DOMEventTargetHelper)
132
133
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WorkerGlobalScope)
134
0
  NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
135
0
  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
136
0
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
137
138
JSObject*
139
WorkerGlobalScope::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
140
0
{
141
0
  MOZ_CRASH("We should never get here!");
142
0
}
143
144
void
145
WorkerGlobalScope::NoteTerminating()
146
0
{
147
0
  DisconnectEventTargetObjects();
148
0
  StartDying();
149
0
}
150
151
already_AddRefed<Console>
152
WorkerGlobalScope::GetConsole(ErrorResult& aRv)
153
0
{
154
0
  mWorkerPrivate->AssertIsOnWorkerThread();
155
0
156
0
  if (!mConsole) {
157
0
    mConsole = Console::Create(mWorkerPrivate->GetJSContext(),
158
0
                               nullptr, aRv);
159
0
    if (NS_WARN_IF(aRv.Failed())) {
160
0
      return nullptr;
161
0
    }
162
0
  }
163
0
164
0
  RefPtr<Console> console = mConsole;
165
0
  return console.forget();
166
0
}
167
168
Crypto*
169
WorkerGlobalScope::GetCrypto(ErrorResult& aError)
170
0
{
171
0
  mWorkerPrivate->AssertIsOnWorkerThread();
172
0
173
0
  if (!mCrypto) {
174
0
    mCrypto = new Crypto(this);
175
0
  }
176
0
177
0
  return mCrypto;
178
0
}
179
180
already_AddRefed<CacheStorage>
181
WorkerGlobalScope::GetCaches(ErrorResult& aRv)
182
0
{
183
0
  if (!mCacheStorage) {
184
0
    MOZ_ASSERT(mWorkerPrivate);
185
0
    mCacheStorage = CacheStorage::CreateOnWorker(cache::DEFAULT_NAMESPACE, this,
186
0
                                                 mWorkerPrivate, aRv);
187
0
  }
188
0
189
0
  RefPtr<CacheStorage> ref = mCacheStorage;
190
0
  return ref.forget();
191
0
}
192
193
bool
194
WorkerGlobalScope::IsSecureContext() const
195
0
{
196
0
  bool globalSecure =
197
0
    JS::GetIsSecureContext(js::GetNonCCWObjectRealm(GetWrapperPreserveColor()));
198
0
  MOZ_ASSERT(globalSecure == mWorkerPrivate->IsSecureContext());
199
0
  return globalSecure;
200
0
}
201
202
already_AddRefed<WorkerLocation>
203
WorkerGlobalScope::Location()
204
0
{
205
0
  mWorkerPrivate->AssertIsOnWorkerThread();
206
0
207
0
  if (!mLocation) {
208
0
    WorkerPrivate::LocationInfo& info = mWorkerPrivate->GetLocationInfo();
209
0
210
0
    mLocation = WorkerLocation::Create(info);
211
0
    MOZ_ASSERT(mLocation);
212
0
  }
213
0
214
0
  RefPtr<WorkerLocation> location = mLocation;
215
0
  return location.forget();
216
0
}
217
218
already_AddRefed<WorkerNavigator>
219
WorkerGlobalScope::Navigator()
220
0
{
221
0
  mWorkerPrivate->AssertIsOnWorkerThread();
222
0
223
0
  if (!mNavigator) {
224
0
    mNavigator = WorkerNavigator::Create(mWorkerPrivate->OnLine());
225
0
    MOZ_ASSERT(mNavigator);
226
0
  }
227
0
228
0
  RefPtr<WorkerNavigator> navigator = mNavigator;
229
0
  return navigator.forget();
230
0
}
231
232
already_AddRefed<WorkerNavigator>
233
WorkerGlobalScope::GetExistingNavigator() const
234
0
{
235
0
  mWorkerPrivate->AssertIsOnWorkerThread();
236
0
237
0
  RefPtr<WorkerNavigator> navigator = mNavigator;
238
0
  return navigator.forget();
239
0
}
240
241
OnErrorEventHandlerNonNull*
242
WorkerGlobalScope::GetOnerror()
243
0
{
244
0
  mWorkerPrivate->AssertIsOnWorkerThread();
245
0
246
0
  EventListenerManager* elm = GetExistingListenerManager();
247
0
  return elm ? elm->GetOnErrorEventHandler() : nullptr;
248
0
}
249
250
void
251
WorkerGlobalScope::SetOnerror(OnErrorEventHandlerNonNull* aHandler)
252
0
{
253
0
  mWorkerPrivate->AssertIsOnWorkerThread();
254
0
255
0
  EventListenerManager* elm = GetOrCreateListenerManager();
256
0
  if (elm) {
257
0
    elm->SetEventHandler(aHandler);
258
0
  }
259
0
}
260
261
void
262
WorkerGlobalScope::ImportScripts(const Sequence<nsString>& aScriptURLs,
263
                                 ErrorResult& aRv)
264
0
{
265
0
  mWorkerPrivate->AssertIsOnWorkerThread();
266
0
  workerinternals::Load(mWorkerPrivate, aScriptURLs, WorkerScript, aRv);
267
0
}
268
269
int32_t
270
WorkerGlobalScope::SetTimeout(JSContext* aCx,
271
                              Function& aHandler,
272
                              const int32_t aTimeout,
273
                              const Sequence<JS::Value>& aArguments,
274
                              ErrorResult& aRv)
275
0
{
276
0
  mWorkerPrivate->AssertIsOnWorkerThread();
277
0
278
0
  nsCOMPtr<nsIScriptTimeoutHandler> handler =
279
0
    NS_CreateJSTimeoutHandler(aCx, mWorkerPrivate, aHandler, aArguments, aRv);
280
0
  if (!handler) {
281
0
    return 0;
282
0
  }
283
0
284
0
  return mWorkerPrivate->SetTimeout(aCx, handler, aTimeout, false, aRv);
285
0
}
286
287
int32_t
288
WorkerGlobalScope::SetTimeout(JSContext* aCx,
289
                              const nsAString& aHandler,
290
                              const int32_t aTimeout,
291
                              const Sequence<JS::Value>& /* unused */,
292
                              ErrorResult& aRv)
293
0
{
294
0
  mWorkerPrivate->AssertIsOnWorkerThread();
295
0
296
0
  nsCOMPtr<nsIScriptTimeoutHandler> handler =
297
0
    NS_CreateJSTimeoutHandler(aCx, mWorkerPrivate, aHandler, aRv);
298
0
  if (!handler) {
299
0
    return 0;
300
0
  }
301
0
302
0
  return mWorkerPrivate->SetTimeout(aCx, handler, aTimeout, false, aRv);
303
0
}
304
305
void
306
WorkerGlobalScope::ClearTimeout(int32_t aHandle)
307
0
{
308
0
  mWorkerPrivate->AssertIsOnWorkerThread();
309
0
  mWorkerPrivate->ClearTimeout(aHandle);
310
0
}
311
312
int32_t
313
WorkerGlobalScope::SetInterval(JSContext* aCx,
314
                               Function& aHandler,
315
                               const int32_t aTimeout,
316
                               const Sequence<JS::Value>& aArguments,
317
                               ErrorResult& aRv)
318
0
{
319
0
  mWorkerPrivate->AssertIsOnWorkerThread();
320
0
321
0
  nsCOMPtr<nsIScriptTimeoutHandler> handler =
322
0
    NS_CreateJSTimeoutHandler(aCx, mWorkerPrivate, aHandler, aArguments, aRv);
323
0
  if (NS_WARN_IF(aRv.Failed())) {
324
0
    return 0;
325
0
  }
326
0
327
0
  return mWorkerPrivate->SetTimeout(aCx, handler,  aTimeout, true, aRv);
328
0
}
329
330
int32_t
331
WorkerGlobalScope::SetInterval(JSContext* aCx,
332
                               const nsAString& aHandler,
333
                               const int32_t aTimeout,
334
                               const Sequence<JS::Value>& /* unused */,
335
                               ErrorResult& aRv)
336
0
{
337
0
  mWorkerPrivate->AssertIsOnWorkerThread();
338
0
339
0
  Sequence<JS::Value> dummy;
340
0
341
0
  nsCOMPtr<nsIScriptTimeoutHandler> handler =
342
0
    NS_CreateJSTimeoutHandler(aCx, mWorkerPrivate, aHandler, aRv);
343
0
  if (NS_WARN_IF(aRv.Failed())) {
344
0
    return 0;
345
0
  }
346
0
347
0
  return mWorkerPrivate->SetTimeout(aCx, handler, aTimeout, true, aRv);
348
0
}
349
350
void
351
WorkerGlobalScope::ClearInterval(int32_t aHandle)
352
0
{
353
0
  mWorkerPrivate->AssertIsOnWorkerThread();
354
0
  mWorkerPrivate->ClearTimeout(aHandle);
355
0
}
356
357
void
358
WorkerGlobalScope::GetOrigin(nsAString& aOrigin) const
359
0
{
360
0
  mWorkerPrivate->AssertIsOnWorkerThread();
361
0
  aOrigin = mWorkerPrivate->Origin();
362
0
}
363
364
void
365
WorkerGlobalScope::Atob(const nsAString& aAtob, nsAString& aOutput, ErrorResult& aRv) const
366
0
{
367
0
  mWorkerPrivate->AssertIsOnWorkerThread();
368
0
  aRv = nsContentUtils::Atob(aAtob, aOutput);
369
0
}
370
371
void
372
WorkerGlobalScope::Btoa(const nsAString& aBtoa, nsAString& aOutput, ErrorResult& aRv) const
373
0
{
374
0
  mWorkerPrivate->AssertIsOnWorkerThread();
375
0
  aRv = nsContentUtils::Btoa(aBtoa, aOutput);
376
0
}
377
378
void
379
WorkerGlobalScope::Dump(const Optional<nsAString>& aString) const
380
0
{
381
0
  mWorkerPrivate->AssertIsOnWorkerThread();
382
0
383
0
  if (!aString.WasPassed()) {
384
0
    return;
385
0
  }
386
0
387
0
#if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
388
0
  if (!DOMPrefs::DumpEnabled()) {
389
0
    return;
390
0
  }
391
0
#endif
392
0
393
0
  NS_ConvertUTF16toUTF8 str(aString.Value());
394
0
395
0
  MOZ_LOG(nsContentUtils::DOMDumpLog(), LogLevel::Debug, ("[Worker.Dump] %s", str.get()));
396
#ifdef ANDROID
397
  __android_log_print(ANDROID_LOG_INFO, "Gecko", "%s", str.get());
398
#endif
399
  fputs(str.get(), stdout);
400
0
  fflush(stdout);
401
0
}
402
403
Performance*
404
WorkerGlobalScope::GetPerformance()
405
0
{
406
0
  mWorkerPrivate->AssertIsOnWorkerThread();
407
0
408
0
  if (!mPerformance) {
409
0
    mPerformance = Performance::CreateForWorker(mWorkerPrivate);
410
0
  }
411
0
412
0
  return mPerformance;
413
0
}
414
415
bool
416
WorkerGlobalScope::IsInAutomation(JSContext* aCx, JSObject* /* unused */)
417
0
{
418
0
  return GetWorkerPrivateFromContext(aCx)->IsInAutomation();
419
0
}
420
421
void
422
WorkerGlobalScope::GetJSTestingFunctions(JSContext* aCx,
423
                                         JS::MutableHandle<JSObject*> aFunctions,
424
                                         ErrorResult& aRv)
425
0
{
426
0
  JSObject* obj = js::GetTestingFunctions(aCx);
427
0
  if (!obj) {
428
0
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
429
0
    return;
430
0
  }
431
0
432
0
  aFunctions.set(obj);
433
0
}
434
435
already_AddRefed<Promise>
436
WorkerGlobalScope::Fetch(const RequestOrUSVString& aInput,
437
                         const RequestInit& aInit,
438
                         CallerType aCallerType, ErrorResult& aRv)
439
0
{
440
0
  return FetchRequest(this, aInput, aInit, aCallerType, aRv);
441
0
}
442
443
already_AddRefed<IDBFactory>
444
WorkerGlobalScope::GetIndexedDB(ErrorResult& aErrorResult)
445
0
{
446
0
  mWorkerPrivate->AssertIsOnWorkerThread();
447
0
448
0
  RefPtr<IDBFactory> indexedDB = mIndexedDB;
449
0
450
0
  if (!indexedDB) {
451
0
    if (!mWorkerPrivate->IsStorageAllowed()) {
452
0
      NS_WARNING("IndexedDB is not allowed in this worker!");
453
0
      aErrorResult = NS_ERROR_DOM_SECURITY_ERR;
454
0
      return nullptr;
455
0
    }
456
0
457
0
    JSContext* cx = mWorkerPrivate->GetJSContext();
458
0
    MOZ_ASSERT(cx);
459
0
460
0
    JS::Rooted<JSObject*> owningObject(cx, GetGlobalJSObject());
461
0
    MOZ_ASSERT(owningObject);
462
0
463
0
    const PrincipalInfo& principalInfo = mWorkerPrivate->GetPrincipalInfo();
464
0
465
0
    nsresult rv =
466
0
      IDBFactory::CreateForWorker(cx,
467
0
                                  owningObject,
468
0
                                  principalInfo,
469
0
                                  mWorkerPrivate->WindowID(),
470
0
                                  getter_AddRefs(indexedDB));
471
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
472
0
      aErrorResult = rv;
473
0
      return nullptr;
474
0
    }
475
0
476
0
    mIndexedDB = indexedDB;
477
0
  }
478
0
479
0
  return indexedDB.forget();
480
0
}
481
482
already_AddRefed<Promise>
483
WorkerGlobalScope::CreateImageBitmap(JSContext* aCx,
484
                                     const ImageBitmapSource& aImage,
485
                                     ErrorResult& aRv)
486
0
{
487
0
  if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
488
0
    aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
489
0
    return nullptr;
490
0
  }
491
0
492
0
  return ImageBitmap::Create(this, aImage, Nothing(), aRv);
493
0
}
494
495
already_AddRefed<Promise>
496
WorkerGlobalScope::CreateImageBitmap(JSContext* aCx,
497
                                     const ImageBitmapSource& aImage,
498
                                     int32_t aSx, int32_t aSy, int32_t aSw, int32_t aSh,
499
                                     ErrorResult& aRv)
500
0
{
501
0
  if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
502
0
    aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
503
0
    return nullptr;
504
0
  }
505
0
506
0
  return ImageBitmap::Create(this, aImage, Some(gfx::IntRect(aSx, aSy, aSw, aSh)), aRv);
507
0
}
508
509
already_AddRefed<mozilla::dom::Promise>
510
WorkerGlobalScope::CreateImageBitmap(JSContext* aCx,
511
                                     const ImageBitmapSource& aImage,
512
                                     int32_t aOffset, int32_t aLength,
513
                                     ImageBitmapFormat aFormat,
514
                                     const Sequence<ChannelPixelLayout>& aLayout,
515
                                     ErrorResult& aRv)
516
0
{
517
0
  if (!StaticPrefs::canvas_imagebitmap_extensions_enabled()) {
518
0
    aRv.Throw(NS_ERROR_TYPE_ERR);
519
0
    return nullptr;
520
0
  }
521
0
522
0
  if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
523
0
    return ImageBitmap::Create(this, aImage, aOffset, aLength, aFormat, aLayout,
524
0
                               aRv);
525
0
  } else {
526
0
    aRv.Throw(NS_ERROR_TYPE_ERR);
527
0
    return nullptr;
528
0
  }
529
0
}
530
531
nsresult
532
WorkerGlobalScope::Dispatch(TaskCategory aCategory,
533
                            already_AddRefed<nsIRunnable>&& aRunnable)
534
0
{
535
0
  return EventTargetFor(aCategory)->Dispatch(std::move(aRunnable),
536
0
                                             NS_DISPATCH_NORMAL);
537
0
}
538
539
nsISerialEventTarget*
540
WorkerGlobalScope::EventTargetFor(TaskCategory aCategory) const
541
0
{
542
0
  return mSerialEventTarget;
543
0
}
544
545
AbstractThread*
546
WorkerGlobalScope::AbstractMainThreadFor(TaskCategory aCategory)
547
0
{
548
0
  MOZ_CRASH("AbstractMainThreadFor not supported for workers.");
549
0
}
550
551
Maybe<ClientInfo>
552
WorkerGlobalScope::GetClientInfo() const
553
0
{
554
0
  return mWorkerPrivate->GetClientInfo();
555
0
}
556
557
Maybe<ClientState>
558
WorkerGlobalScope::GetClientState() const
559
0
{
560
0
  Maybe<ClientState> state;
561
0
  state.emplace(mWorkerPrivate->GetClientState());
562
0
  return state;
563
0
}
564
565
Maybe<ServiceWorkerDescriptor>
566
WorkerGlobalScope::GetController() const
567
0
{
568
0
  return mWorkerPrivate->GetController();
569
0
}
570
571
RefPtr<mozilla::dom::ServiceWorkerRegistration>
572
WorkerGlobalScope::GetServiceWorkerRegistration(const ServiceWorkerRegistrationDescriptor& aDescriptor) const
573
0
{
574
0
  mWorkerPrivate->AssertIsOnWorkerThread();
575
0
  RefPtr<ServiceWorkerRegistration> ref;
576
0
  ForEachEventTargetObject([&] (DOMEventTargetHelper* aTarget, bool* aDoneOut) {
577
0
    RefPtr<ServiceWorkerRegistration> swr = do_QueryObject(aTarget);
578
0
    if (!swr || !swr->MatchesDescriptor(aDescriptor)) {
579
0
      return;
580
0
    }
581
0
582
0
    ref = swr.forget();
583
0
    *aDoneOut = true;
584
0
  });
585
0
  return ref.forget();
586
0
}
587
588
RefPtr<ServiceWorkerRegistration>
589
WorkerGlobalScope::GetOrCreateServiceWorkerRegistration(const ServiceWorkerRegistrationDescriptor& aDescriptor)
590
0
{
591
0
  mWorkerPrivate->AssertIsOnWorkerThread();
592
0
  RefPtr<ServiceWorkerRegistration> ref = GetServiceWorkerRegistration(aDescriptor);
593
0
  if (!ref) {
594
0
    ref = ServiceWorkerRegistration::CreateForWorker(mWorkerPrivate, this,
595
0
                                                     aDescriptor);
596
0
  }
597
0
  return ref.forget();
598
0
}
599
600
DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate,
601
                                                       const nsString& aName)
602
  : WorkerGlobalScope(aWorkerPrivate)
603
  , mName(aName)
604
0
{
605
0
}
606
607
bool
608
DedicatedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx,
609
                                             JS::MutableHandle<JSObject*> aReflector)
610
0
{
611
0
  mWorkerPrivate->AssertIsOnWorkerThread();
612
0
  MOZ_ASSERT(!mWorkerPrivate->IsSharedWorker());
613
0
614
0
  JS::RealmOptions options;
615
0
  mWorkerPrivate->CopyJSRealmOptions(options);
616
0
617
0
  const bool usesSystemPrincipal = mWorkerPrivate->UsesSystemPrincipal();
618
0
619
0
  // Note that xpc::ShouldDiscardSystemSource() and
620
0
  // xpc::ExtraWarningsForSystemJS() read prefs that are cached on the main
621
0
  // thread. This is benignly racey.
622
0
  const bool discardSource = usesSystemPrincipal &&
623
0
                             xpc::ShouldDiscardSystemSource();
624
0
  const bool extraWarnings = usesSystemPrincipal &&
625
0
                             xpc::ExtraWarningsForSystemJS();
626
0
627
0
  JS::RealmBehaviors& behaviors = options.behaviors();
628
0
  behaviors.setDiscardSource(discardSource)
629
0
           .extraWarningsOverride().set(extraWarnings);
630
0
631
0
  const bool sharedMemoryEnabled = xpc::SharedMemoryEnabled();
632
0
633
0
  JS::RealmCreationOptions& creationOptions = options.creationOptions();
634
0
  creationOptions.setSharedMemoryAndAtomicsEnabled(sharedMemoryEnabled);
635
0
636
0
  return DedicatedWorkerGlobalScope_Binding::Wrap(aCx, this, this,
637
0
                                                 options,
638
0
                                                 GetWorkerPrincipal(),
639
0
                                                 true, aReflector);
640
0
}
641
642
void
643
DedicatedWorkerGlobalScope::PostMessage(JSContext* aCx,
644
                                        JS::Handle<JS::Value> aMessage,
645
                                        const Sequence<JSObject*>& aTransferable,
646
                                        ErrorResult& aRv)
647
0
{
648
0
  mWorkerPrivate->AssertIsOnWorkerThread();
649
0
  mWorkerPrivate->PostMessageToParent(aCx, aMessage, aTransferable, aRv);
650
0
}
651
652
void
653
DedicatedWorkerGlobalScope::Close()
654
0
{
655
0
  mWorkerPrivate->AssertIsOnWorkerThread();
656
0
  mWorkerPrivate->CloseInternal();
657
0
}
658
659
SharedWorkerGlobalScope::SharedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate,
660
                                                 const nsString& aName)
661
: WorkerGlobalScope(aWorkerPrivate), mName(aName)
662
0
{
663
0
}
664
665
bool
666
SharedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx,
667
                                          JS::MutableHandle<JSObject*> aReflector)
668
0
{
669
0
  mWorkerPrivate->AssertIsOnWorkerThread();
670
0
  MOZ_ASSERT(mWorkerPrivate->IsSharedWorker());
671
0
672
0
  JS::RealmOptions options;
673
0
  mWorkerPrivate->CopyJSRealmOptions(options);
674
0
675
0
  return SharedWorkerGlobalScope_Binding::Wrap(aCx, this, this, options,
676
0
                                              GetWorkerPrincipal(),
677
0
                                              true, aReflector);
678
0
}
679
680
void
681
SharedWorkerGlobalScope::Close()
682
0
{
683
0
  mWorkerPrivate->AssertIsOnWorkerThread();
684
0
  mWorkerPrivate->CloseInternal();
685
0
}
686
687
NS_IMPL_CYCLE_COLLECTION_INHERITED(ServiceWorkerGlobalScope, WorkerGlobalScope,
688
                                   mClients, mRegistration)
689
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ServiceWorkerGlobalScope)
690
0
NS_INTERFACE_MAP_END_INHERITING(WorkerGlobalScope)
691
692
NS_IMPL_ADDREF_INHERITED(ServiceWorkerGlobalScope, WorkerGlobalScope)
693
NS_IMPL_RELEASE_INHERITED(ServiceWorkerGlobalScope, WorkerGlobalScope)
694
695
ServiceWorkerGlobalScope::ServiceWorkerGlobalScope(WorkerPrivate* aWorkerPrivate,
696
                                                   const ServiceWorkerRegistrationDescriptor& aRegistrationDescriptor)
697
  : WorkerGlobalScope(aWorkerPrivate)
698
  , mScope(NS_ConvertUTF8toUTF16(aRegistrationDescriptor.Scope()))
699
700
  // Eagerly create the registration because we will need to receive updates
701
  // about the state of the registration.  We can't wait until first access
702
  // to start receiving these.
703
  , mRegistration(GetOrCreateServiceWorkerRegistration(aRegistrationDescriptor))
704
0
{
705
0
}
706
707
ServiceWorkerGlobalScope::~ServiceWorkerGlobalScope()
708
0
{
709
0
}
710
711
bool
712
ServiceWorkerGlobalScope::WrapGlobalObject(JSContext* aCx,
713
                                           JS::MutableHandle<JSObject*> aReflector)
714
0
{
715
0
  mWorkerPrivate->AssertIsOnWorkerThread();
716
0
  MOZ_ASSERT(mWorkerPrivate->IsServiceWorker());
717
0
718
0
  JS::RealmOptions options;
719
0
  mWorkerPrivate->CopyJSRealmOptions(options);
720
0
721
0
  return ServiceWorkerGlobalScope_Binding::Wrap(aCx, this, this, options,
722
0
                                               GetWorkerPrincipal(),
723
0
                                               true, aReflector);
724
0
}
725
726
already_AddRefed<Clients>
727
ServiceWorkerGlobalScope::GetClients()
728
0
{
729
0
  if (!mClients) {
730
0
    mClients = new Clients(this);
731
0
  }
732
0
733
0
  RefPtr<Clients> ref = mClients;
734
0
  return ref.forget();
735
0
}
736
737
ServiceWorkerRegistration*
738
ServiceWorkerGlobalScope::Registration()
739
0
{
740
0
  return mRegistration;
741
0
}
742
743
EventHandlerNonNull*
744
ServiceWorkerGlobalScope::GetOnfetch()
745
0
{
746
0
  MOZ_ASSERT(mWorkerPrivate);
747
0
  mWorkerPrivate->AssertIsOnWorkerThread();
748
0
749
0
  return GetEventHandler(nsGkAtoms::onfetch);
750
0
}
751
752
namespace {
753
754
class ReportFetchListenerWarningRunnable final : public Runnable
755
{
756
  const nsCString mScope;
757
  nsCString mSourceSpec;
758
  uint32_t mLine;
759
  uint32_t mColumn;
760
761
public:
762
  explicit ReportFetchListenerWarningRunnable(const nsString& aScope)
763
    : mozilla::Runnable("ReportFetchListenerWarningRunnable")
764
    , mScope(NS_ConvertUTF16toUTF8(aScope))
765
0
  {
766
0
    WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
767
0
    MOZ_ASSERT(workerPrivate);
768
0
    JSContext* cx = workerPrivate->GetJSContext();
769
0
    MOZ_ASSERT(cx);
770
0
771
0
    nsJSUtils::GetCallingLocation(cx, mSourceSpec, &mLine, &mColumn);
772
0
  }
773
774
  NS_IMETHOD
775
  Run() override
776
0
  {
777
0
    AssertIsOnMainThread();
778
0
779
0
    ServiceWorkerManager::LocalizeAndReportToAllClients(mScope, "ServiceWorkerNoFetchHandler",
780
0
        nsTArray<nsString>{}, nsIScriptError::warningFlag, NS_ConvertUTF8toUTF16(mSourceSpec),
781
0
        EmptyString(), mLine, mColumn);
782
0
783
0
    return NS_OK;
784
0
  }
785
};
786
787
} // anonymous namespace
788
789
void
790
ServiceWorkerGlobalScope::SetOnfetch(mozilla::dom::EventHandlerNonNull* aCallback)
791
0
{
792
0
  MOZ_ASSERT(mWorkerPrivate);
793
0
  mWorkerPrivate->AssertIsOnWorkerThread();
794
0
795
0
  if (aCallback) {
796
0
    if (mWorkerPrivate->WorkerScriptExecutedSuccessfully()) {
797
0
      RefPtr<Runnable> r = new ReportFetchListenerWarningRunnable(mScope);
798
0
      mWorkerPrivate->DispatchToMainThread(r.forget());
799
0
    }
800
0
    mWorkerPrivate->SetFetchHandlerWasAdded();
801
0
  }
802
0
  SetEventHandler(nsGkAtoms::onfetch, aCallback);
803
0
}
804
805
void
806
ServiceWorkerGlobalScope::EventListenerAdded(nsAtom* aType)
807
0
{
808
0
  MOZ_ASSERT(mWorkerPrivate);
809
0
  mWorkerPrivate->AssertIsOnWorkerThread();
810
0
811
0
  if (aType != nsGkAtoms::onfetch) {
812
0
    return;
813
0
  }
814
0
815
0
  if (mWorkerPrivate->WorkerScriptExecutedSuccessfully()) {
816
0
    RefPtr<Runnable> r = new ReportFetchListenerWarningRunnable(mScope);
817
0
    mWorkerPrivate->DispatchToMainThread(r.forget());
818
0
  }
819
0
820
0
  mWorkerPrivate->SetFetchHandlerWasAdded();
821
0
}
822
823
namespace {
824
825
class SkipWaitingResultRunnable final : public WorkerRunnable
826
{
827
  RefPtr<PromiseWorkerProxy> mPromiseProxy;
828
829
public:
830
  SkipWaitingResultRunnable(WorkerPrivate* aWorkerPrivate,
831
                            PromiseWorkerProxy* aPromiseProxy)
832
    : WorkerRunnable(aWorkerPrivate)
833
    , mPromiseProxy(aPromiseProxy)
834
0
  {
835
0
    AssertIsOnMainThread();
836
0
  }
837
838
  virtual bool
839
  WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
840
0
  {
841
0
    MOZ_ASSERT(aWorkerPrivate);
842
0
    aWorkerPrivate->AssertIsOnWorkerThread();
843
0
844
0
    RefPtr<Promise> promise = mPromiseProxy->WorkerPromise();
845
0
    promise->MaybeResolveWithUndefined();
846
0
847
0
    // Release the reference on the worker thread.
848
0
    mPromiseProxy->CleanUp();
849
0
850
0
    return true;
851
0
  }
852
};
853
854
class WorkerScopeSkipWaitingRunnable final : public Runnable
855
{
856
  RefPtr<PromiseWorkerProxy> mPromiseProxy;
857
  nsCString mScope;
858
859
public:
860
  WorkerScopeSkipWaitingRunnable(PromiseWorkerProxy* aPromiseProxy,
861
                                 const nsCString& aScope)
862
    : mozilla::Runnable("WorkerScopeSkipWaitingRunnable")
863
    , mPromiseProxy(aPromiseProxy)
864
    , mScope(aScope)
865
0
  {
866
0
    MOZ_ASSERT(aPromiseProxy);
867
0
  }
868
869
  NS_IMETHOD
870
  Run() override
871
0
  {
872
0
    AssertIsOnMainThread();
873
0
874
0
    MutexAutoLock lock(mPromiseProxy->Lock());
875
0
    if (mPromiseProxy->CleanedUp()) {
876
0
      return NS_OK;
877
0
    }
878
0
879
0
    WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
880
0
    MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
881
0
882
0
    RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
883
0
    if (swm) {
884
0
      swm->SetSkipWaitingFlag(workerPrivate->GetPrincipal(), mScope,
885
0
                              workerPrivate->ServiceWorkerID());
886
0
    }
887
0
888
0
    RefPtr<SkipWaitingResultRunnable> runnable =
889
0
      new SkipWaitingResultRunnable(workerPrivate, mPromiseProxy);
890
0
891
0
    if (!runnable->Dispatch()) {
892
0
      NS_WARNING("Failed to dispatch SkipWaitingResultRunnable to the worker.");
893
0
    }
894
0
    return NS_OK;
895
0
  }
896
};
897
898
} // namespace
899
900
already_AddRefed<Promise>
901
ServiceWorkerGlobalScope::SkipWaiting(ErrorResult& aRv)
902
0
{
903
0
  mWorkerPrivate->AssertIsOnWorkerThread();
904
0
  MOZ_ASSERT(mWorkerPrivate->IsServiceWorker());
905
0
906
0
  RefPtr<Promise> promise = Promise::Create(this, aRv);
907
0
  if (NS_WARN_IF(aRv.Failed())) {
908
0
    return nullptr;
909
0
  }
910
0
911
0
  RefPtr<PromiseWorkerProxy> promiseProxy =
912
0
    PromiseWorkerProxy::Create(mWorkerPrivate, promise);
913
0
  if (!promiseProxy) {
914
0
    promise->MaybeResolveWithUndefined();
915
0
    return promise.forget();
916
0
  }
917
0
918
0
  RefPtr<WorkerScopeSkipWaitingRunnable> runnable =
919
0
    new WorkerScopeSkipWaitingRunnable(promiseProxy,
920
0
                                       NS_ConvertUTF16toUTF8(mScope));
921
0
922
0
  MOZ_ALWAYS_SUCCEEDS(mWorkerPrivate->DispatchToMainThread(runnable.forget()));
923
0
  return promise.forget();
924
0
}
925
926
WorkerDebuggerGlobalScope::WorkerDebuggerGlobalScope(
927
                                                  WorkerPrivate* aWorkerPrivate)
928
: mWorkerPrivate(aWorkerPrivate)
929
, mSerialEventTarget(aWorkerPrivate->HybridEventTarget())
930
0
{
931
0
  mWorkerPrivate->AssertIsOnWorkerThread();
932
0
933
0
  // We should always have an event target when the global is created.
934
0
  MOZ_DIAGNOSTIC_ASSERT(mSerialEventTarget);
935
0
}
936
937
WorkerDebuggerGlobalScope::~WorkerDebuggerGlobalScope()
938
0
{
939
0
  mWorkerPrivate->AssertIsOnWorkerThread();
940
0
}
941
942
NS_IMPL_CYCLE_COLLECTION_CLASS(WorkerDebuggerGlobalScope)
943
944
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WorkerDebuggerGlobalScope,
945
0
                                                  DOMEventTargetHelper)
946
0
  tmp->mWorkerPrivate->AssertIsOnWorkerThread();
947
0
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsole)
948
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
949
950
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WorkerDebuggerGlobalScope,
951
0
                                                DOMEventTargetHelper)
952
0
  tmp->mWorkerPrivate->AssertIsOnWorkerThread();
953
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsole)
954
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
955
956
0
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(WorkerDebuggerGlobalScope,
957
0
                                               DOMEventTargetHelper)
958
0
  tmp->mWorkerPrivate->AssertIsOnWorkerThread();
959
0
NS_IMPL_CYCLE_COLLECTION_TRACE_END
960
961
NS_IMPL_ADDREF_INHERITED(WorkerDebuggerGlobalScope, DOMEventTargetHelper)
962
NS_IMPL_RELEASE_INHERITED(WorkerDebuggerGlobalScope, DOMEventTargetHelper)
963
964
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WorkerDebuggerGlobalScope)
965
0
  NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
966
0
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
967
968
bool
969
WorkerDebuggerGlobalScope::WrapGlobalObject(JSContext* aCx,
970
                                            JS::MutableHandle<JSObject*> aReflector)
971
0
{
972
0
  mWorkerPrivate->AssertIsOnWorkerThread();
973
0
974
0
  JS::RealmOptions options;
975
0
  mWorkerPrivate->CopyJSRealmOptions(options);
976
0
977
0
  return WorkerDebuggerGlobalScope_Binding::Wrap(aCx, this, this, options,
978
0
                                                GetWorkerPrincipal(), true,
979
0
                                                aReflector);
980
0
}
981
982
void
983
WorkerDebuggerGlobalScope::GetGlobal(JSContext* aCx,
984
                                     JS::MutableHandle<JSObject*> aGlobal,
985
                                     ErrorResult& aRv)
986
0
{
987
0
  WorkerGlobalScope* scope = mWorkerPrivate->GetOrCreateGlobalScope(aCx);
988
0
  if (!scope) {
989
0
    aRv.Throw(NS_ERROR_FAILURE);
990
0
    return;
991
0
  }
992
0
993
0
  aGlobal.set(scope->GetWrapper());
994
0
}
995
996
void
997
WorkerDebuggerGlobalScope::CreateSandbox(JSContext* aCx, const nsAString& aName,
998
                                         JS::Handle<JSObject*> aPrototype,
999
                                         JS::MutableHandle<JSObject*> aResult,
1000
                                         ErrorResult& aRv)
1001
0
{
1002
0
  mWorkerPrivate->AssertIsOnWorkerThread();
1003
0
1004
0
  aResult.set(nullptr);
1005
0
1006
0
  JS::Rooted<JS::Value> protoVal(aCx);
1007
0
  protoVal.setObjectOrNull(aPrototype);
1008
0
  JS::Rooted<JSObject*> sandbox(aCx,
1009
0
    SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::WorkerDebuggerSandbox,
1010
0
                               protoVal));
1011
0
1012
0
  if (!sandbox) {
1013
0
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
1014
0
    return;
1015
0
  }
1016
0
1017
0
  if (!JS_WrapObject(aCx, &sandbox)) {
1018
0
    aRv.NoteJSContextException(aCx);
1019
0
    return;
1020
0
  }
1021
0
1022
0
  aResult.set(sandbox);
1023
0
}
1024
1025
void
1026
WorkerDebuggerGlobalScope::LoadSubScript(JSContext* aCx,
1027
                                         const nsAString& aURL,
1028
                                         const Optional<JS::Handle<JSObject*>>& aSandbox,
1029
                                         ErrorResult& aRv)
1030
0
{
1031
0
  mWorkerPrivate->AssertIsOnWorkerThread();
1032
0
1033
0
  Maybe<JSAutoRealm> ar;
1034
0
  if (aSandbox.WasPassed()) {
1035
0
    JS::Rooted<JSObject*> sandbox(aCx, js::CheckedUnwrap(aSandbox.Value()));
1036
0
    if (!IsWorkerDebuggerSandbox(sandbox)) {
1037
0
      aRv.Throw(NS_ERROR_INVALID_ARG);
1038
0
      return;
1039
0
    }
1040
0
1041
0
    ar.emplace(aCx, sandbox);
1042
0
  }
1043
0
1044
0
  nsTArray<nsString> urls;
1045
0
  urls.AppendElement(aURL);
1046
0
  workerinternals::Load(mWorkerPrivate, urls, DebuggerScript, aRv);
1047
0
}
1048
1049
void
1050
WorkerDebuggerGlobalScope::EnterEventLoop()
1051
0
{
1052
0
  mWorkerPrivate->EnterDebuggerEventLoop();
1053
0
}
1054
1055
void
1056
WorkerDebuggerGlobalScope::LeaveEventLoop()
1057
0
{
1058
0
  mWorkerPrivate->LeaveDebuggerEventLoop();
1059
0
}
1060
1061
void
1062
WorkerDebuggerGlobalScope::PostMessage(const nsAString& aMessage)
1063
0
{
1064
0
  mWorkerPrivate->PostMessageToDebugger(aMessage);
1065
0
}
1066
1067
void
1068
WorkerDebuggerGlobalScope::SetImmediate(Function& aHandler, ErrorResult& aRv)
1069
0
{
1070
0
  mWorkerPrivate->SetDebuggerImmediate(aHandler, aRv);
1071
0
}
1072
1073
void
1074
WorkerDebuggerGlobalScope::ReportError(JSContext* aCx,
1075
                                       const nsAString& aMessage)
1076
0
{
1077
0
  JS::AutoFilename chars;
1078
0
  uint32_t lineno = 0;
1079
0
  JS::DescribeScriptedCaller(aCx, &chars, &lineno);
1080
0
  nsString filename(NS_ConvertUTF8toUTF16(chars.get()));
1081
0
  mWorkerPrivate->ReportErrorToDebugger(filename, lineno, aMessage);
1082
0
}
1083
1084
void
1085
WorkerDebuggerGlobalScope::RetrieveConsoleEvents(JSContext* aCx,
1086
                                                 nsTArray<JS::Value>& aEvents,
1087
                                                 ErrorResult& aRv)
1088
0
{
1089
0
  WorkerGlobalScope* scope = mWorkerPrivate->GetOrCreateGlobalScope(aCx);
1090
0
  if (!scope) {
1091
0
    aRv.Throw(NS_ERROR_FAILURE);
1092
0
    return;
1093
0
  }
1094
0
1095
0
  RefPtr<Console> console = scope->GetConsole(aRv);
1096
0
  if (NS_WARN_IF(aRv.Failed())) {
1097
0
    return;
1098
0
  }
1099
0
1100
0
  console->RetrieveConsoleEvents(aCx, aEvents, aRv);
1101
0
}
1102
1103
void
1104
WorkerDebuggerGlobalScope::SetConsoleEventHandler(JSContext* aCx,
1105
                                                  AnyCallback* aHandler,
1106
                                                  ErrorResult& aRv)
1107
0
{
1108
0
  WorkerGlobalScope* scope = mWorkerPrivate->GetOrCreateGlobalScope(aCx);
1109
0
  if (!scope) {
1110
0
    aRv.Throw(NS_ERROR_FAILURE);
1111
0
    return;
1112
0
  }
1113
0
1114
0
  RefPtr<Console> console = scope->GetConsole(aRv);
1115
0
  if (NS_WARN_IF(aRv.Failed())) {
1116
0
    return;
1117
0
  }
1118
0
1119
0
  console->SetConsoleEventHandler(aHandler);
1120
0
}
1121
1122
already_AddRefed<Console>
1123
WorkerDebuggerGlobalScope::GetConsole(ErrorResult& aRv)
1124
0
{
1125
0
  mWorkerPrivate->AssertIsOnWorkerThread();
1126
0
1127
0
  // Debugger console has its own console object.
1128
0
  if (!mConsole) {
1129
0
    mConsole = Console::Create(mWorkerPrivate->GetJSContext(),
1130
0
                               nullptr, aRv);
1131
0
    if (NS_WARN_IF(aRv.Failed())) {
1132
0
      return nullptr;
1133
0
    }
1134
0
  }
1135
0
1136
0
  RefPtr<Console> console = mConsole;
1137
0
  return console.forget();
1138
0
}
1139
1140
void
1141
WorkerDebuggerGlobalScope::Dump(JSContext* aCx,
1142
                                const Optional<nsAString>& aString) const
1143
0
{
1144
0
  WorkerGlobalScope* scope = mWorkerPrivate->GetOrCreateGlobalScope(aCx);
1145
0
  if (scope) {
1146
0
    scope->Dump(aString);
1147
0
  }
1148
0
}
1149
1150
nsresult
1151
WorkerDebuggerGlobalScope::Dispatch(TaskCategory aCategory,
1152
                                    already_AddRefed<nsIRunnable>&& aRunnable)
1153
0
{
1154
0
  return EventTargetFor(aCategory)->Dispatch(std::move(aRunnable),
1155
0
                                             NS_DISPATCH_NORMAL);
1156
0
}
1157
1158
nsISerialEventTarget*
1159
WorkerDebuggerGlobalScope::EventTargetFor(TaskCategory aCategory) const
1160
0
{
1161
0
  return mSerialEventTarget;
1162
0
}
1163
1164
AbstractThread*
1165
WorkerDebuggerGlobalScope::AbstractMainThreadFor(TaskCategory aCategory)
1166
0
{
1167
0
  MOZ_CRASH("AbstractMainThreadFor not supported for workers.");
1168
0
}
1169
1170
bool
1171
IsWorkerGlobal(JSObject* object)
1172
0
{
1173
0
  return IS_INSTANCE_OF(WorkerGlobalScope, object);
1174
0
}
1175
1176
bool
1177
IsWorkerDebuggerGlobal(JSObject* object)
1178
0
{
1179
0
  return IS_INSTANCE_OF(WorkerDebuggerGlobalScope, object);
1180
0
}
1181
1182
bool
1183
IsWorkerDebuggerSandbox(JSObject* object)
1184
0
{
1185
0
  return SimpleGlobalObject::SimpleGlobalType(object) ==
1186
0
    SimpleGlobalObject::GlobalType::WorkerDebuggerSandbox;
1187
0
}
1188
1189
} // dom namespace
1190
} // mozilla namespace