Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/workers/WorkerPrivate.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_workers_workerprivate_h__
8
#define mozilla_dom_workers_workerprivate_h__
9
10
#include "mozilla/dom/WorkerCommon.h"
11
#include "mozilla/CondVar.h"
12
#include "mozilla/DOMEventTargetHelper.h"
13
#include "mozilla/RelativeTimeline.h"
14
#include "nsIContentSecurityPolicy.h"
15
#include "nsIEventTarget.h"
16
#include "nsTObserverArray.h"
17
18
#include "mozilla/dom/Worker.h"
19
#include "mozilla/dom/WorkerHolder.h"
20
#include "mozilla/dom/WorkerLoadInfo.h"
21
#include "mozilla/dom/workerinternals/JSSettings.h"
22
#include "mozilla/dom/workerinternals/Queue.h"
23
#include "mozilla/PerformanceCounter.h"
24
25
class nsIConsoleReportCollector;
26
class nsIThreadInternal;
27
28
namespace mozilla {
29
namespace dom {
30
31
// If you change this, the corresponding list in nsIWorkerDebugger.idl needs
32
// to be updated too.
33
enum WorkerType
34
{
35
  WorkerTypeDedicated,
36
  WorkerTypeShared,
37
  WorkerTypeService
38
};
39
40
class ClientInfo;
41
class ClientSource;
42
class Function;
43
class MessagePort;
44
class MessagePortIdentifier;
45
class PerformanceStorage;
46
class SharedWorker;
47
class WorkerControlRunnable;
48
class WorkerCSPEventListener;
49
class WorkerDebugger;
50
class WorkerDebuggerGlobalScope;
51
class WorkerErrorReport;
52
class WorkerEventTarget;
53
class WorkerGlobalScope;
54
class WorkerRunnable;
55
class WorkerThread;
56
57
// SharedMutex is a small wrapper around an (internal) reference-counted Mutex
58
// object. It exists to avoid changing a lot of code to use Mutex* instead of
59
// Mutex&.
60
class SharedMutex
61
{
62
  typedef mozilla::Mutex Mutex;
63
64
  class RefCountedMutex final : public Mutex
65
  {
66
  public:
67
    explicit RefCountedMutex(const char* aName)
68
    : Mutex(aName)
69
    { }
70
71
    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefCountedMutex)
72
73
  private:
74
    ~RefCountedMutex()
75
    { }
76
  };
77
78
  RefPtr<RefCountedMutex> mMutex;
79
80
public:
81
  explicit SharedMutex(const char* aName)
82
  : mMutex(new RefCountedMutex(aName))
83
  { }
84
85
  SharedMutex(SharedMutex& aOther)
86
  : mMutex(aOther.mMutex)
87
  { }
88
89
  operator Mutex&()
90
0
  {
91
0
    return *mMutex;
92
0
  }
93
94
  operator const Mutex&() const
95
  {
96
    return *mMutex;
97
  }
98
99
  void
100
  AssertCurrentThreadOwns() const
101
  {
102
    mMutex->AssertCurrentThreadOwns();
103
  }
104
};
105
106
class WorkerPrivate
107
  : public RelativeTimeline
108
{
109
public:
110
  struct LocationInfo
111
  {
112
    nsCString mHref;
113
    nsCString mProtocol;
114
    nsCString mHost;
115
    nsCString mHostname;
116
    nsCString mPort;
117
    nsCString mPathname;
118
    nsCString mSearch;
119
    nsCString mHash;
120
    nsString mOrigin;
121
  };
122
123
  NS_INLINE_DECL_REFCOUNTING(WorkerPrivate)
124
125
  static already_AddRefed<WorkerPrivate>
126
  Constructor(JSContext* aCx, const nsAString& aScriptURL, bool aIsChromeWorker,
127
              WorkerType aWorkerType, const nsAString& aWorkerName,
128
              const nsACString& aServiceWorkerScope,
129
              WorkerLoadInfo* aLoadInfo, ErrorResult& aRv);
130
131
  enum LoadGroupBehavior
132
  {
133
    InheritLoadGroup,
134
    OverrideLoadGroup
135
  };
136
137
  static nsresult
138
  GetLoadInfo(JSContext* aCx, nsPIDOMWindowInner* aWindow,
139
              WorkerPrivate* aParent,
140
              const nsAString& aScriptURL, bool aIsChromeWorker,
141
              LoadGroupBehavior aLoadGroupBehavior, WorkerType aWorkerType,
142
              WorkerLoadInfo* aLoadInfo);
143
144
  void
145
  Traverse(nsCycleCollectionTraversalCallback& aCb);
146
147
  void
148
  ClearSelfAndParentEventTargetRef()
149
  {
150
    AssertIsOnParentThread();
151
    MOZ_ASSERT(mSelfRef);
152
    mParentEventTargetRef = nullptr;
153
    mSelfRef = nullptr;
154
  }
155
156
  // May be called on any thread...
157
  bool
158
  Start();
159
160
  // Called on the parent thread.
161
  bool
162
  Notify(WorkerStatus aStatus);
163
164
  bool
165
  Cancel()
166
0
  {
167
0
    return Notify(Canceling);
168
0
  }
169
170
  bool
171
  Kill()
172
0
  {
173
0
    return Notify(Killing);
174
0
  }
175
176
  bool
177
  Close();
178
179
  // The passed principal must be the Worker principal in case of a
180
  // ServiceWorker and the loading principal for any other type.
181
  static void
182
  OverrideLoadInfoLoadGroup(WorkerLoadInfo& aLoadInfo,
183
                            nsIPrincipal* aPrincipal);
184
185
  bool
186
  IsDebuggerRegistered()
187
0
  {
188
0
    AssertIsOnMainThread();
189
0
190
0
    // No need to lock here since this is only ever modified by the same thread.
191
0
    return mDebuggerRegistered;
192
0
  }
193
194
  void
195
  SetIsDebuggerRegistered(bool aDebuggerRegistered)
196
0
  {
197
0
    AssertIsOnMainThread();
198
0
199
0
    MutexAutoLock lock(mMutex);
200
0
201
0
    MOZ_ASSERT(mDebuggerRegistered != aDebuggerRegistered);
202
0
    mDebuggerRegistered = aDebuggerRegistered;
203
0
204
0
    mCondVar.Notify();
205
0
  }
206
207
  void
208
  WaitForIsDebuggerRegistered(bool aDebuggerRegistered)
209
0
  {
210
0
    AssertIsOnParentThread();
211
0
212
0
    MOZ_ASSERT(!NS_IsMainThread());
213
0
214
0
    MutexAutoLock lock(mMutex);
215
0
216
0
    while (mDebuggerRegistered != aDebuggerRegistered) {
217
0
      mCondVar.Wait();
218
0
    }
219
0
  }
220
221
  WorkerDebugger*
222
  Debugger() const
223
0
  {
224
0
    AssertIsOnMainThread();
225
0
226
0
    MOZ_ASSERT(mDebugger);
227
0
    return mDebugger;
228
0
  }
229
230
  void
231
  SetDebugger(WorkerDebugger* aDebugger)
232
0
  {
233
0
    AssertIsOnMainThread();
234
0
235
0
    MOZ_ASSERT(mDebugger != aDebugger);
236
0
    mDebugger = aDebugger;
237
0
  }
238
239
  JS::UniqueChars
240
  AdoptDefaultLocale()
241
0
  {
242
0
    MOZ_ASSERT(mDefaultLocale,
243
0
               "the default locale must have been successfully set for anyone "
244
0
               "to be trying to adopt it");
245
0
    return std::move(mDefaultLocale);
246
0
  }
247
248
  void
249
  DoRunLoop(JSContext* aCx);
250
251
  bool
252
  InterruptCallback(JSContext* aCx);
253
254
  bool
255
  IsOnCurrentThread();
256
257
  void
258
  CloseInternal();
259
260
  bool
261
  FreezeInternal();
262
263
  bool
264
  ThawInternal();
265
266
  void
267
  PropagateFirstPartyStorageAccessGrantedInternal();
268
269
  void
270
  TraverseTimeouts(nsCycleCollectionTraversalCallback& aCallback);
271
272
  void
273
  UnlinkTimeouts();
274
275
  bool
276
  ModifyBusyCountFromWorker(bool aIncrease);
277
278
  bool
279
  AddChildWorker(WorkerPrivate* aChildWorker);
280
281
  void
282
  RemoveChildWorker(WorkerPrivate* aChildWorker);
283
284
  void
285
  PostMessageToParent(JSContext* aCx,
286
                      JS::Handle<JS::Value> aMessage,
287
                      const Sequence<JSObject*>& aTransferable,
288
                      ErrorResult& aRv);
289
290
  void
291
  PostMessageToParentMessagePort(JSContext* aCx,
292
                                 JS::Handle<JS::Value> aMessage,
293
                                 const Sequence<JSObject*>& aTransferable,
294
                                 ErrorResult& aRv);
295
296
  void
297
  EnterDebuggerEventLoop();
298
299
  void
300
  LeaveDebuggerEventLoop();
301
302
  void
303
  PostMessageToDebugger(const nsAString& aMessage);
304
305
  void
306
  SetDebuggerImmediate(Function& aHandler, ErrorResult& aRv);
307
308
  void
309
  ReportErrorToDebugger(const nsAString& aFilename, uint32_t aLineno,
310
                        const nsAString& aMessage);
311
312
  bool
313
  NotifyInternal(WorkerStatus aStatus);
314
315
  void
316
  ReportError(JSContext* aCx, JS::ConstUTF8CharsZ aToStringResult,
317
              JSErrorReport* aReport);
318
319
  static void
320
  ReportErrorToConsole(const char* aMessage);
321
322
  static void
323
  ReportErrorToConsole(const char* aMessage, const nsTArray<nsString>& aParams);
324
325
  int32_t
326
  SetTimeout(JSContext* aCx, nsIScriptTimeoutHandler* aHandler,
327
             int32_t aTimeout, bool aIsInterval,
328
             ErrorResult& aRv);
329
330
  void
331
  ClearTimeout(int32_t aId);
332
333
  bool
334
  RunExpiredTimeouts(JSContext* aCx);
335
336
  bool
337
  RescheduleTimeoutTimer(JSContext* aCx);
338
339
  void
340
  UpdateContextOptionsInternal(JSContext* aCx, const JS::ContextOptions& aContextOptions);
341
342
  void
343
  UpdateLanguagesInternal(const nsTArray<nsString>& aLanguages);
344
345
  void
346
  UpdateJSWorkerMemoryParameterInternal(JSContext* aCx, JSGCParamKey key, uint32_t aValue);
347
348
  enum WorkerRanOrNot {
349
    WorkerNeverRan = 0,
350
    WorkerRan
351
  };
352
353
  void
354
  ScheduleDeletion(WorkerRanOrNot aRanOrNot);
355
356
  bool
357
  CollectRuntimeStats(JS::RuntimeStats* aRtStats, bool aAnonymize);
358
359
#ifdef JS_GC_ZEAL
360
  void
361
  UpdateGCZealInternal(JSContext* aCx, uint8_t aGCZeal, uint32_t aFrequency);
362
#endif
363
364
  void
365
  GarbageCollectInternal(JSContext* aCx, bool aShrinking,
366
                         bool aCollectChildren);
367
368
  void
369
  CycleCollectInternal(bool aCollectChildren);
370
371
  void
372
  OfflineStatusChangeEventInternal(bool aIsOffline);
373
374
  void
375
  MemoryPressureInternal();
376
377
  void
378
  SetFetchHandlerWasAdded()
379
  {
380
    MOZ_ASSERT(IsServiceWorker());
381
    AssertIsOnWorkerThread();
382
    mFetchHandlerWasAdded = true;
383
  }
384
385
  bool
386
  FetchHandlerWasAdded() const
387
  {
388
    MOZ_ASSERT(IsServiceWorker());
389
    AssertIsOnWorkerThread();
390
    return mFetchHandlerWasAdded;
391
  }
392
393
  JSContext*
394
  GetJSContext() const
395
  {
396
    AssertIsOnWorkerThread();
397
    return mJSContext;
398
  }
399
400
  WorkerGlobalScope*
401
  GlobalScope() const
402
  {
403
    AssertIsOnWorkerThread();
404
    return mScope;
405
  }
406
407
  WorkerDebuggerGlobalScope*
408
  DebuggerGlobalScope() const
409
0
  {
410
0
    AssertIsOnWorkerThread();
411
0
    return mDebuggerScope;
412
0
  }
413
414
  void
415
  SetThread(WorkerThread* aThread);
416
417
  bool
418
  IsOnWorkerThread() const;
419
420
  void
421
  AssertIsOnWorkerThread() const
422
#ifdef DEBUG
423
  ;
424
#else
425
  { }
426
#endif
427
428
  // This may block!
429
  void
430
  BeginCTypesCall();
431
432
  // This may block!
433
  void
434
  EndCTypesCall();
435
436
  void
437
  BeginCTypesCallback()
438
0
  {
439
0
    // If a callback is beginning then we need to do the exact same thing as
440
0
    // when a ctypes call ends.
441
0
    EndCTypesCall();
442
0
  }
443
444
  void
445
  EndCTypesCallback()
446
0
  {
447
0
    // If a callback is ending then we need to do the exact same thing as
448
0
    // when a ctypes call begins.
449
0
    BeginCTypesCall();
450
0
  }
451
452
  bool
453
  ConnectMessagePort(JSContext* aCx, MessagePortIdentifier& aIdentifier);
454
455
  WorkerGlobalScope*
456
  GetOrCreateGlobalScope(JSContext* aCx);
457
458
  WorkerDebuggerGlobalScope*
459
  CreateDebuggerGlobalScope(JSContext* aCx);
460
461
  bool
462
  RegisterBindings(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
463
464
  bool
465
  RegisterDebuggerBindings(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
466
467
  bool
468
  OnLine() const
469
  {
470
    AssertIsOnWorkerThread();
471
    return mOnLine;
472
  }
473
474
  void
475
  StopSyncLoop(nsIEventTarget* aSyncLoopTarget, bool aResult);
476
477
  bool
478
  AllPendingRunnablesShouldBeCanceled() const
479
  {
480
    return mCancelAllPendingRunnables;
481
  }
482
483
  void
484
  ClearMainEventQueue(WorkerRanOrNot aRanOrNot);
485
486
  void
487
  ClearDebuggerEventQueue();
488
489
  void
490
  OnProcessNextEvent();
491
492
  void
493
  AfterProcessNextEvent();
494
495
  void
496
  AssertValidSyncLoop(nsIEventTarget* aSyncLoopTarget)
497
#ifdef DEBUG
498
  ;
499
#else
500
  { }
501
#endif
502
503
  void
504
  SetWorkerScriptExecutedSuccessfully()
505
  {
506
    AssertIsOnWorkerThread();
507
    // Should only be called once!
508
    MOZ_ASSERT(!mWorkerScriptExecutedSuccessfully);
509
    mWorkerScriptExecutedSuccessfully = true;
510
  }
511
512
  // Only valid after CompileScriptRunnable has finished running!
513
  bool
514
  WorkerScriptExecutedSuccessfully() const
515
  {
516
    AssertIsOnWorkerThread();
517
    return mWorkerScriptExecutedSuccessfully;
518
  }
519
520
  // Get the event target to use when dispatching to the main thread
521
  // from this Worker thread.  This may be the main thread itself or
522
  // a ThrottledEventQueue to the main thread.
523
  nsIEventTarget*
524
  MainThreadEventTarget();
525
526
  nsresult
527
  DispatchToMainThread(nsIRunnable* aRunnable,
528
                       uint32_t aFlags = NS_DISPATCH_NORMAL);
529
530
  nsresult
531
  DispatchToMainThread(already_AddRefed<nsIRunnable> aRunnable,
532
                       uint32_t aFlags = NS_DISPATCH_NORMAL);
533
534
  // Get an event target that will dispatch runnables as control runnables on
535
  // the worker thread.  Implement nsICancelableRunnable if you wish to take
536
  // action on cancelation.
537
  nsISerialEventTarget*
538
  ControlEventTarget();
539
540
  // Get an event target that will attempt to dispatch a normal WorkerRunnable,
541
  // but if that fails will then fall back to a control runnable.
542
  nsISerialEventTarget*
543
  HybridEventTarget();
544
545
  void
546
  DumpCrashInformation(nsACString& aString);
547
548
  bool
549
  EnsureClientSource();
550
551
  bool
552
  EnsureCSPEventListener();
553
554
  void
555
  EnsurePerformanceStorage();
556
557
  void
558
  EnsurePerformanceCounter();
559
560
  Maybe<ClientInfo>
561
  GetClientInfo() const;
562
563
  const ClientState
564
  GetClientState() const;
565
566
  const Maybe<ServiceWorkerDescriptor>
567
  GetController();
568
569
  void
570
  Control(const ServiceWorkerDescriptor& aServiceWorker);
571
572
  void
573
  ExecutionReady();
574
575
  PerformanceStorage*
576
  GetPerformanceStorage();
577
578
  PerformanceCounter*
579
  GetPerformanceCounter();
580
581
  bool
582
  IsAcceptingEvents()
583
0
  {
584
0
    AssertIsOnParentThread();
585
0
586
0
    MutexAutoLock lock(mMutex);
587
0
    return mParentStatus < Canceling;
588
0
  }
589
590
  WorkerStatus
591
  ParentStatusProtected()
592
0
  {
593
0
    AssertIsOnParentThread();
594
0
    MutexAutoLock lock(mMutex);
595
0
    return mParentStatus;
596
0
  }
597
598
  WorkerStatus
599
  ParentStatus() const
600
  {
601
    mMutex.AssertCurrentThreadOwns();
602
    return mParentStatus;
603
  }
604
605
  Worker*
606
  ParentEventTargetRef() const
607
0
  {
608
0
    MOZ_DIAGNOSTIC_ASSERT(mParentEventTargetRef);
609
0
    return mParentEventTargetRef;
610
0
  }
611
612
  void
613
  SetParentEventTargetRef(Worker* aParentEventTargetRef)
614
0
  {
615
0
    MOZ_DIAGNOSTIC_ASSERT(aParentEventTargetRef);
616
0
    MOZ_DIAGNOSTIC_ASSERT(!mParentEventTargetRef);
617
0
    mParentEventTargetRef = aParentEventTargetRef;
618
0
  }
619
620
  bool
621
  ModifyBusyCount(bool aIncrease);
622
623
  // This method is used by RuntimeService to know what is going wrong the
624
  // shutting down.
625
  uint32_t
626
  BusyCount()
627
0
  {
628
0
    return mBusyCount;
629
0
  }
630
631
  // Check whether this worker is a secure context.  For use from the parent
632
  // thread only; the canonical "is secure context" boolean is stored on the
633
  // compartment of the worker global.  The only reason we don't
634
  // AssertIsOnParentThread() here is so we can assert that this value matches
635
  // the one on the compartment, which has to be done from the worker thread.
636
  bool IsSecureContext() const
637
0
  {
638
0
    return mIsSecureContext;
639
0
  }
640
641
  // Check whether we're running in automation.
642
  bool IsInAutomation() const
643
  {
644
    return mIsInAutomation;
645
  }
646
647
  TimeStamp CreationTimeStamp() const
648
0
  {
649
0
    return mCreationTimeStamp;
650
0
  }
651
652
  DOMHighResTimeStamp CreationTime() const
653
  {
654
    return mCreationTimeHighRes;
655
  }
656
657
  DOMHighResTimeStamp TimeStampToDOMHighRes(const TimeStamp& aTimeStamp) const
658
  {
659
    MOZ_ASSERT(!aTimeStamp.IsNull());
660
    TimeDuration duration = aTimeStamp - mCreationTimeStamp;
661
    return duration.ToMilliseconds();
662
  }
663
664
  LocationInfo&
665
  GetLocationInfo()
666
  {
667
    return mLocationInfo;
668
  }
669
670
  void
671
  CopyJSSettings(workerinternals::JSSettings& aSettings)
672
0
  {
673
0
    mozilla::MutexAutoLock lock(mMutex);
674
0
    aSettings = mJSSettings;
675
0
  }
676
677
  void
678
  CopyJSRealmOptions(JS::RealmOptions& aOptions)
679
  {
680
    mozilla::MutexAutoLock lock(mMutex);
681
    aOptions = IsChromeWorker() ? mJSSettings.chrome.realmOptions
682
                                : mJSSettings.content.realmOptions;
683
  }
684
685
  // The ability to be a chrome worker is orthogonal to the type of
686
  // worker [Dedicated|Shared|Service].
687
  bool
688
  IsChromeWorker() const
689
0
  {
690
0
    return mIsChromeWorker;
691
0
  }
692
693
  WorkerPrivate*
694
  GetParent() const
695
  {
696
    return mParent;
697
  }
698
699
  bool
700
  IsFrozen() const
701
0
  {
702
0
    AssertIsOnParentThread();
703
0
    return mParentFrozen;
704
0
  }
705
706
  bool
707
  IsParentWindowPaused() const
708
0
  {
709
0
    AssertIsOnParentThread();
710
0
    return mParentWindowPausedDepth > 0;
711
0
  }
712
713
  // When we debug a worker, we want to disconnect the window and the worker
714
  // communication. This happens calling this method.
715
  // Note: this method doesn't suspend the worker! Use Freeze/Thaw instead.
716
  void
717
  ParentWindowPaused();
718
719
  void
720
  ParentWindowResumed();
721
722
  const nsString&
723
  ScriptURL() const
724
  {
725
    return mScriptURL;
726
  }
727
728
  const nsString&
729
  WorkerName() const
730
0
  {
731
0
    return mWorkerName;
732
0
  }
733
734
  WorkerType
735
  Type() const
736
0
  {
737
0
    return mWorkerType;
738
0
  }
739
740
  bool
741
  IsDedicatedWorker() const
742
0
  {
743
0
    return mWorkerType == WorkerTypeDedicated;
744
0
  }
745
746
  bool
747
  IsSharedWorker() const
748
  {
749
    return mWorkerType == WorkerTypeShared;
750
  }
751
752
  bool
753
  IsServiceWorker() const
754
  {
755
    return mWorkerType == WorkerTypeService;
756
  }
757
758
  nsContentPolicyType
759
  ContentPolicyType() const
760
0
  {
761
0
    return ContentPolicyType(mWorkerType);
762
0
  }
763
764
  static nsContentPolicyType
765
  ContentPolicyType(WorkerType aWorkerType)
766
0
  {
767
0
    switch (aWorkerType) {
768
0
    case WorkerTypeDedicated:
769
0
      return nsIContentPolicy::TYPE_INTERNAL_WORKER;
770
0
    case WorkerTypeShared:
771
0
      return nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
772
0
    case WorkerTypeService:
773
0
      return nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER;
774
0
    default:
775
0
      MOZ_ASSERT_UNREACHABLE("Invalid worker type");
776
0
      return nsIContentPolicy::TYPE_INVALID;
777
0
    }
778
0
  }
779
780
  nsIScriptContext*
781
  GetScriptContext() const
782
  {
783
    AssertIsOnMainThread();
784
    return mLoadInfo.mScriptContext;
785
  }
786
787
  const nsCString&
788
  Domain() const
789
0
  {
790
0
    return mLoadInfo.mDomain;
791
0
  }
792
793
  bool
794
  IsFromWindow() const
795
  {
796
    return mLoadInfo.mFromWindow;
797
  }
798
799
  nsLoadFlags
800
  GetLoadFlags() const
801
0
  {
802
0
    return mLoadInfo.mLoadFlags;
803
0
  }
804
805
  uint64_t
806
  WindowID() const
807
  {
808
    return mLoadInfo.mWindowID;
809
  }
810
811
  uint64_t
812
  ServiceWorkerID() const
813
  {
814
    return GetServiceWorkerDescriptor().Id();
815
  }
816
817
  const nsCString&
818
  ServiceWorkerScope() const
819
  {
820
    return GetServiceWorkerDescriptor().Scope();
821
  }
822
823
  nsIURI*
824
  GetBaseURI() const
825
  {
826
    AssertIsOnMainThread();
827
    return mLoadInfo.mBaseURI;
828
  }
829
830
  void
831
  SetBaseURI(nsIURI* aBaseURI);
832
833
  nsIURI*
834
  GetResolvedScriptURI() const
835
0
  {
836
0
    AssertIsOnMainThread();
837
0
    return mLoadInfo.mResolvedScriptURI;
838
0
  }
839
840
  const nsString&
841
  ServiceWorkerCacheName() const
842
0
  {
843
0
    MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
844
0
    AssertIsOnMainThread();
845
0
    return mLoadInfo.mServiceWorkerCacheName;
846
0
  }
847
848
  const ServiceWorkerDescriptor&
849
  GetServiceWorkerDescriptor() const
850
  {
851
    MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
852
    MOZ_DIAGNOSTIC_ASSERT(mLoadInfo.mServiceWorkerDescriptor.isSome());
853
    return mLoadInfo.mServiceWorkerDescriptor.ref();
854
  }
855
856
  const ServiceWorkerRegistrationDescriptor&
857
  GetServiceWorkerRegistrationDescriptor() const
858
  {
859
    MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
860
    MOZ_DIAGNOSTIC_ASSERT(mLoadInfo.mServiceWorkerRegistrationDescriptor.isSome());
861
    return mLoadInfo.mServiceWorkerRegistrationDescriptor.ref();
862
  }
863
864
  void
865
  UpdateServiceWorkerState(ServiceWorkerState aState)
866
  {
867
    MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
868
    MOZ_DIAGNOSTIC_ASSERT(mLoadInfo.mServiceWorkerDescriptor.isSome());
869
    return mLoadInfo.mServiceWorkerDescriptor.ref().SetState(aState);
870
  }
871
872
  const Maybe<ServiceWorkerDescriptor>&
873
  GetParentController() const
874
0
  {
875
0
    return mLoadInfo.mParentController;
876
0
  }
877
878
  const ChannelInfo&
879
  GetChannelInfo() const
880
  {
881
    return mLoadInfo.mChannelInfo;
882
  }
883
884
  void
885
  SetChannelInfo(const ChannelInfo& aChannelInfo)
886
  {
887
    AssertIsOnMainThread();
888
    MOZ_ASSERT(!mLoadInfo.mChannelInfo.IsInitialized());
889
    MOZ_ASSERT(aChannelInfo.IsInitialized());
890
    mLoadInfo.mChannelInfo = aChannelInfo;
891
  }
892
893
  void
894
  InitChannelInfo(nsIChannel* aChannel)
895
0
  {
896
0
    mLoadInfo.mChannelInfo.InitFromChannel(aChannel);
897
0
  }
898
899
  void
900
  InitChannelInfo(const ChannelInfo& aChannelInfo)
901
0
  {
902
0
    mLoadInfo.mChannelInfo = aChannelInfo;
903
0
  }
904
905
  nsIPrincipal*
906
  GetPrincipal() const
907
  {
908
    AssertIsOnMainThread();
909
    return mLoadInfo.mPrincipal;
910
  }
911
912
  nsIPrincipal*
913
  GetLoadingPrincipal() const
914
0
  {
915
0
    AssertIsOnMainThread();
916
0
    return mLoadInfo.mLoadingPrincipal;
917
0
  }
918
919
  const nsAString& Origin() const
920
  {
921
    return mLoadInfo.mOrigin;
922
  }
923
924
  nsILoadGroup*
925
  GetLoadGroup() const
926
  {
927
    AssertIsOnMainThread();
928
    return mLoadInfo.mLoadGroup;
929
  }
930
931
  // This method allows the principal to be retrieved off the main thread.
932
  // Principals are main-thread objects so the caller must ensure that all
933
  // access occurs on the main thread.
934
  nsIPrincipal*
935
  GetPrincipalDontAssertMainThread() const
936
0
  {
937
0
      return mLoadInfo.mPrincipal;
938
0
  }
939
940
  bool
941
  UsesSystemPrincipal() const
942
  {
943
    return mLoadInfo.mPrincipalIsSystem;
944
  }
945
946
  const mozilla::ipc::PrincipalInfo&
947
  GetPrincipalInfo() const
948
  {
949
    return *mLoadInfo.mPrincipalInfo;
950
  }
951
952
  already_AddRefed<nsIChannel>
953
  ForgetWorkerChannel()
954
0
  {
955
0
    AssertIsOnMainThread();
956
0
    return mLoadInfo.mChannel.forget();
957
0
  }
958
959
  nsPIDOMWindowInner*
960
  GetWindow()
961
  {
962
    AssertIsOnMainThread();
963
    return mLoadInfo.mWindow;
964
  }
965
966
  nsIContentSecurityPolicy*
967
  GetCSP() const
968
  {
969
    AssertIsOnMainThread();
970
    return mLoadInfo.mCSP;
971
  }
972
973
  void
974
  SetCSP(nsIContentSecurityPolicy* aCSP);
975
976
  nsresult
977
  SetCSPFromHeaderValues(const nsACString& aCSPHeaderValue,
978
                         const nsACString& aCSPReportOnlyHeaderValue);
979
980
  void
981
  SetReferrerPolicyFromHeaderValue(const nsACString& aReferrerPolicyHeaderValue);
982
983
  net::ReferrerPolicy
984
  GetReferrerPolicy() const
985
  {
986
    return mLoadInfo.mReferrerPolicy;
987
  }
988
989
  void
990
  SetReferrerPolicy(net::ReferrerPolicy aReferrerPolicy)
991
  {
992
    mLoadInfo.mReferrerPolicy = aReferrerPolicy;
993
  }
994
995
  bool
996
  IsEvalAllowed() const
997
0
  {
998
0
    return mLoadInfo.mEvalAllowed;
999
0
  }
1000
1001
  void
1002
  SetEvalAllowed(bool aEvalAllowed)
1003
0
  {
1004
0
    mLoadInfo.mEvalAllowed = aEvalAllowed;
1005
0
  }
1006
1007
  bool
1008
  GetReportCSPViolations() const
1009
0
  {
1010
0
    return mLoadInfo.mReportCSPViolations;
1011
0
  }
1012
1013
  void
1014
  SetReportCSPViolations(bool aReport)
1015
  {
1016
    mLoadInfo.mReportCSPViolations = aReport;
1017
  }
1018
1019
  bool
1020
  XHRParamsAllowed() const
1021
0
  {
1022
0
    return mLoadInfo.mXHRParamsAllowed;
1023
0
  }
1024
1025
  void
1026
  SetXHRParamsAllowed(bool aAllowed)
1027
0
  {
1028
0
    mLoadInfo.mXHRParamsAllowed = aAllowed;
1029
0
  }
1030
1031
  bool
1032
  IsStorageAllowed() const
1033
  {
1034
    AssertIsOnWorkerThread();
1035
    return mLoadInfo.mStorageAllowed || mLoadInfo.mFirstPartyStorageAccessGranted;
1036
  }
1037
1038
  const OriginAttributes&
1039
  GetOriginAttributes() const
1040
  {
1041
    return mLoadInfo.mOriginAttributes;
1042
  }
1043
1044
  // Determine if the SW testing per-window flag is set by devtools
1045
  bool
1046
  ServiceWorkersTestingInWindow() const
1047
  {
1048
    return mLoadInfo.mServiceWorkersTestingInWindow;
1049
  }
1050
1051
  // Determine if the worker is currently loading its top level script.
1052
  bool
1053
  IsLoadingWorkerScript() const
1054
  {
1055
    return mLoadingWorkerScript;
1056
  }
1057
1058
  // Called by ScriptLoader to track when this worker is loading its
1059
  // top level script.
1060
  void
1061
  SetLoadingWorkerScript(bool aLoadingWorkerScript)
1062
0
  {
1063
0
    // any thread
1064
0
    mLoadingWorkerScript = aLoadingWorkerScript;
1065
0
  }
1066
1067
  void
1068
  QueueRunnable(nsIRunnable* aRunnable)
1069
0
  {
1070
0
    AssertIsOnParentThread();
1071
0
    mQueuedRunnables.AppendElement(aRunnable);
1072
0
  }
1073
1074
  bool
1075
  RegisterSharedWorker(SharedWorker* aSharedWorker, MessagePort* aPort);
1076
1077
  void
1078
  BroadcastErrorToSharedWorkers(JSContext* aCx,
1079
                                const WorkerErrorReport* aReport,
1080
                                bool aIsErrorEvent);
1081
1082
  void
1083
  GetAllSharedWorkers(nsTArray<RefPtr<SharedWorker>>& aSharedWorkers);
1084
1085
  void
1086
  CloseSharedWorkersForWindow(nsPIDOMWindowInner* aWindow);
1087
1088
  void
1089
  CloseAllSharedWorkers();
1090
1091
  void
1092
  FlushReportsToSharedWorkers(nsIConsoleReportCollector* aReporter);
1093
1094
  // We can assume that an nsPIDOMWindow will be available for Freeze, Thaw
1095
  // as these are only used for globals going in and out of the bfcache.
1096
  //
1097
  // XXXbz: This is a bald-faced lie given the uses in RegisterSharedWorker and
1098
  // CloseSharedWorkersForWindow, which pass null for aWindow to Thaw and Freeze
1099
  // respectively.  See bug 1251722.
1100
  bool
1101
  Freeze(nsPIDOMWindowInner* aWindow);
1102
1103
  bool
1104
  Thaw(nsPIDOMWindowInner* aWindow);
1105
1106
  void
1107
  PropagateFirstPartyStorageAccessGranted();
1108
1109
  void
1110
  EnableDebugger();
1111
1112
  void
1113
  DisableDebugger();
1114
1115
  already_AddRefed<WorkerRunnable>
1116
  MaybeWrapAsWorkerRunnable(already_AddRefed<nsIRunnable> aRunnable);
1117
1118
  bool
1119
  ProxyReleaseMainThreadObjects();
1120
1121
  void
1122
  GarbageCollect(bool aShrinking);
1123
1124
  void
1125
  CycleCollect(bool aDummy);
1126
1127
  nsresult
1128
  SetPrincipalOnMainThread(nsIPrincipal* aPrincipal, nsILoadGroup* aLoadGroup);
1129
1130
  nsresult
1131
  SetPrincipalFromChannel(nsIChannel* aChannel);
1132
1133
  bool
1134
  FinalChannelPrincipalIsValid(nsIChannel* aChannel);
1135
1136
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1137
  bool
1138
  PrincipalURIMatchesScriptURL();
1139
#endif
1140
1141
  void
1142
  UpdateOverridenLoadGroup(nsILoadGroup* aBaseLoadGroup);
1143
1144
  void
1145
  WorkerScriptLoaded();
1146
1147
  nsIDocument* GetDocument() const;
1148
1149
  void
1150
  MemoryPressure(bool aDummy);
1151
1152
  void
1153
  UpdateContextOptions(const JS::ContextOptions& aContextOptions);
1154
1155
  void
1156
  UpdateLanguages(const nsTArray<nsString>& aLanguages);
1157
1158
  void
1159
  UpdateJSWorkerMemoryParameter(JSGCParamKey key, uint32_t value);
1160
1161
#ifdef JS_GC_ZEAL
1162
  void
1163
  UpdateGCZeal(uint8_t aGCZeal, uint32_t aFrequency);
1164
#endif
1165
1166
  void
1167
  OfflineStatusChangeEvent(bool aIsOffline);
1168
1169
  nsresult
1170
  Dispatch(already_AddRefed<WorkerRunnable> aRunnable,
1171
           nsIEventTarget* aSyncLoopTarget = nullptr);
1172
1173
  nsresult
1174
  DispatchControlRunnable(already_AddRefed<WorkerControlRunnable> aWorkerControlRunnable);
1175
1176
  nsresult
1177
  DispatchDebuggerRunnable(already_AddRefed<WorkerRunnable> aDebuggerRunnable);
1178
1179
#ifdef DEBUG
1180
  void
1181
  AssertIsOnParentThread() const;
1182
1183
  void
1184
  AssertInnerWindowIsCorrect() const;
1185
#else
1186
  void
1187
  AssertIsOnParentThread() const
1188
0
  { }
1189
1190
  void
1191
  AssertInnerWindowIsCorrect() const
1192
0
  { }
1193
#endif
1194
1195
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1196
  bool
1197
  PrincipalIsValid() const;
1198
#endif
1199
1200
  void
1201
  StartCancelingTimer();
1202
1203
private:
1204
  WorkerPrivate(WorkerPrivate* aParent,
1205
                const nsAString& aScriptURL, bool aIsChromeWorker,
1206
                WorkerType aWorkerType, const nsAString& aWorkerName,
1207
                const nsACString& aServiceWorkerScope,
1208
                WorkerLoadInfo& aLoadInfo);
1209
1210
  ~WorkerPrivate();
1211
1212
  bool
1213
  MayContinueRunning()
1214
  {
1215
    AssertIsOnWorkerThread();
1216
1217
    WorkerStatus status;
1218
    {
1219
      MutexAutoLock lock(mMutex);
1220
      status = mStatus;
1221
    }
1222
1223
    if (status < Canceling) {
1224
      return true;
1225
    }
1226
1227
    return false;
1228
  }
1229
1230
  void
1231
  CancelAllTimeouts();
1232
1233
  enum class ProcessAllControlRunnablesResult
1234
  {
1235
    // We did not process anything.
1236
    Nothing,
1237
    // We did process something, states may have changed, but we can keep
1238
    // executing script.
1239
    MayContinue,
1240
    // We did process something, and should not continue executing script.
1241
    Abort
1242
  };
1243
1244
  ProcessAllControlRunnablesResult
1245
  ProcessAllControlRunnables()
1246
  {
1247
    MutexAutoLock lock(mMutex);
1248
    return ProcessAllControlRunnablesLocked();
1249
  }
1250
1251
  ProcessAllControlRunnablesResult
1252
  ProcessAllControlRunnablesLocked();
1253
1254
  void
1255
  EnableMemoryReporter();
1256
1257
  void
1258
  DisableMemoryReporter();
1259
1260
  void
1261
  WaitForWorkerEvents();
1262
1263
  // If the worker shutdown status is equal or greater then aFailStatus, this
1264
  // operation will fail and nullptr will be returned. See WorkerHolder.h for
1265
  // more information about the correct value to use.
1266
  already_AddRefed<nsIEventTarget>
1267
  CreateNewSyncLoop(WorkerStatus aFailStatus);
1268
1269
  bool
1270
  RunCurrentSyncLoop();
1271
1272
  bool
1273
  DestroySyncLoop(uint32_t aLoopIndex);
1274
1275
  void
1276
  InitializeGCTimers();
1277
1278
  enum GCTimerMode
1279
  {
1280
    PeriodicTimer = 0,
1281
    IdleTimer,
1282
    NoTimer
1283
  };
1284
1285
  void
1286
  SetGCTimerMode(GCTimerMode aMode);
1287
1288
  void
1289
  ShutdownGCTimers();
1290
1291
  bool
1292
  AddHolder(WorkerHolder* aHolder, WorkerStatus aFailStatus);
1293
1294
  void
1295
  RemoveHolder(WorkerHolder* aHolder);
1296
1297
  void
1298
  NotifyHolders(WorkerStatus aStatus);
1299
1300
  bool
1301
  HasActiveHolders()
1302
  {
1303
    return !(mChildWorkers.IsEmpty() && mTimeouts.IsEmpty() &&
1304
             mHolders.IsEmpty());
1305
  }
1306
1307
  class EventTarget;
1308
  friend class EventTarget;
1309
  friend class mozilla::dom::WorkerHolder;
1310
  friend class AutoSyncLoopHolder;
1311
1312
  struct TimeoutInfo;
1313
1314
  class MemoryReporter;
1315
  friend class MemoryReporter;
1316
1317
  friend class mozilla::dom::WorkerThread;
1318
1319
  SharedMutex mMutex;
1320
  mozilla::CondVar mCondVar;
1321
1322
  WorkerPrivate* mParent;
1323
1324
  nsString mScriptURL;
1325
1326
  // This is the worker name for shared workers and dedicated workers.
1327
  nsString mWorkerName;
1328
1329
  WorkerType mWorkerType;
1330
1331
  // The worker is owned by its thread, which is represented here.  This is set
1332
  // in Constructor() and emptied by WorkerFinishedRunnable, and conditionally
1333
  // traversed by the cycle collector if the busy count is zero.
1334
  //
1335
  // There are 4 ways a worker can be terminated:
1336
  // 1. GC/CC - When the worker is in idle state (busycount == 0), it allows to
1337
  //    traverse the 'hidden' mParentEventTargetRef pointer. This is the exposed
1338
  //    Worker webidl object. Doing this, CC will be able to detect a cycle and
1339
  //    Unlink is called. In Unlink, Worker calls Cancel().
1340
  // 2. Worker::Cancel() is called - the shutdown procedure starts immediately.
1341
  // 3. WorkerScope::Close() is called - Similar to point 2.
1342
  // 4. xpcom-shutdown notification - We call Kill().
1343
  RefPtr<Worker> mParentEventTargetRef;
1344
  RefPtr<WorkerPrivate> mSelfRef;
1345
1346
  // The lifetime of these objects within LoadInfo is managed explicitly;
1347
  // they do not need to be cycle collected.
1348
  WorkerLoadInfo mLoadInfo;
1349
  LocationInfo mLocationInfo;
1350
1351
  // Protected by mMutex.
1352
  workerinternals::JSSettings mJSSettings;
1353
1354
  WorkerDebugger* mDebugger;
1355
1356
  workerinternals::Queue<WorkerControlRunnable*, 4> mControlQueue;
1357
  workerinternals::Queue<WorkerRunnable*, 4> mDebuggerQueue;
1358
1359
  // Touched on multiple threads, protected with mMutex.
1360
  JSContext* mJSContext;
1361
  RefPtr<WorkerThread> mThread;
1362
  PRThread* mPRThread;
1363
1364
  // Things touched on worker thread only.
1365
  RefPtr<WorkerGlobalScope> mScope;
1366
  RefPtr<WorkerDebuggerGlobalScope> mDebuggerScope;
1367
  nsTArray<WorkerPrivate*> mChildWorkers;
1368
  nsTObserverArray<WorkerHolder*> mHolders;
1369
  nsTArray<nsAutoPtr<TimeoutInfo>> mTimeouts;
1370
  RefPtr<ThrottledEventQueue> mMainThreadThrottledEventQueue;
1371
  nsCOMPtr<nsIEventTarget> mMainThreadEventTarget;
1372
  RefPtr<WorkerEventTarget> mWorkerControlEventTarget;
1373
  RefPtr<WorkerEventTarget> mWorkerHybridEventTarget;
1374
1375
  struct SyncLoopInfo
1376
  {
1377
    explicit SyncLoopInfo(EventTarget* aEventTarget);
1378
1379
    RefPtr<EventTarget> mEventTarget;
1380
    bool mCompleted;
1381
    bool mResult;
1382
#ifdef DEBUG
1383
    bool mHasRun;
1384
#endif
1385
  };
1386
1387
  // This is only modified on the worker thread, but in DEBUG builds
1388
  // AssertValidSyncLoop function iterates it on other threads. Therefore
1389
  // modifications are done with mMutex held *only* in DEBUG builds.
1390
  nsTArray<nsAutoPtr<SyncLoopInfo>> mSyncLoopStack;
1391
1392
  nsCOMPtr<nsITimer> mTimer;
1393
  nsCOMPtr<nsITimerCallback> mTimerRunnable;
1394
1395
  nsCOMPtr<nsITimer> mCancelingTimer;
1396
1397
  nsCOMPtr<nsITimer> mGCTimer;
1398
1399
  RefPtr<MemoryReporter> mMemoryReporter;
1400
1401
  // fired on the main thread if the worker script fails to load
1402
  nsCOMPtr<nsIRunnable> mLoadFailedRunnable;
1403
1404
  RefPtr<PerformanceStorage> mPerformanceStorage;
1405
1406
  RefPtr<WorkerCSPEventListener> mCSPEventListener;
1407
1408
  // Only used for top level workers.
1409
  nsTArray<nsCOMPtr<nsIRunnable>> mQueuedRunnables;
1410
1411
  // Protected by mMutex.
1412
  nsTArray<RefPtr<WorkerRunnable>> mPreStartRunnables;
1413
1414
  // Only touched on the parent thread (currently this is always the main
1415
  // thread as SharedWorkers are always top-level).
1416
  nsTArray<RefPtr<SharedWorker>> mSharedWorkers;
1417
1418
  JS::UniqueChars mDefaultLocale; // nulled during worker JSContext init
1419
  TimeStamp mKillTime;
1420
  WorkerStatus mParentStatus;
1421
  WorkerStatus mStatus;
1422
  UniquePtr<ClientSource> mClientSource;
1423
1424
  // This is touched on parent thread only, but it can be read on a different
1425
  // thread before crashing because hanging.
1426
  Atomic<uint64_t> mBusyCount;
1427
1428
  Atomic<bool> mLoadingWorkerScript;
1429
1430
  TimeStamp mCreationTimeStamp;
1431
  DOMHighResTimeStamp mCreationTimeHighRes;
1432
1433
  // Things touched on worker thread only.
1434
  uint32_t mNumHoldersPreventingShutdownStart;
1435
  uint32_t mDebuggerEventLoopLevel;
1436
1437
  uint32_t mErrorHandlerRecursionCount;
1438
  uint32_t mNextTimeoutId;
1439
1440
  // SharedWorkers may have multiple windows paused, so this must be
1441
  // a count instead of just a boolean.
1442
  uint32_t mParentWindowPausedDepth;
1443
1444
  bool mFrozen;
1445
  bool mTimerRunning;
1446
  bool mRunningExpiredTimeouts;
1447
  bool mPendingEventQueueClearing;
1448
  bool mCancelAllPendingRunnables;
1449
  bool mPeriodicGCTimerRunning;
1450
  bool mIdleGCTimerRunning;
1451
  bool mWorkerScriptExecutedSuccessfully;
1452
  bool mFetchHandlerWasAdded;
1453
  bool mOnLine;
1454
  bool mMainThreadObjectsForgotten;
1455
  bool mIsChromeWorker;
1456
  bool mParentFrozen;
1457
1458
  // mIsSecureContext is set once in our constructor; after that it can be read
1459
  // from various threads.  We could make this const if we were OK with setting
1460
  // it in the initializer list via calling some function that takes all sorts
1461
  // of state (loadinfo, worker type, parent).
1462
  //
1463
  // It's a bit unfortunate that we have to have an out-of-band boolean for
1464
  // this, but we need access to this state from the parent thread, and we can't
1465
  // use our global object's secure state there.
1466
  bool mIsSecureContext;
1467
1468
  bool mDebuggerRegistered;
1469
1470
  // mIsInAutomation is true when we're running in test automation.
1471
  // We expose some extra testing functions in that case.
1472
  bool mIsInAutomation;
1473
1474
  // This pointer will be null if dom.performance.enable_scheduler_timing is
1475
  // false (default value)
1476
  RefPtr<mozilla::PerformanceCounter> mPerformanceCounter;
1477
};
1478
1479
class AutoSyncLoopHolder
1480
{
1481
  WorkerPrivate* mWorkerPrivate;
1482
  nsCOMPtr<nsIEventTarget> mTarget;
1483
  uint32_t mIndex;
1484
1485
public:
1486
  // See CreateNewSyncLoop() for more information about the correct value to use
1487
  // for aFailStatus.
1488
  AutoSyncLoopHolder(WorkerPrivate* aWorkerPrivate, WorkerStatus aFailStatus)
1489
  : mWorkerPrivate(aWorkerPrivate)
1490
  , mTarget(aWorkerPrivate->CreateNewSyncLoop(aFailStatus))
1491
  , mIndex(aWorkerPrivate->mSyncLoopStack.Length() - 1)
1492
  {
1493
    aWorkerPrivate->AssertIsOnWorkerThread();
1494
  }
1495
1496
  ~AutoSyncLoopHolder()
1497
  {
1498
    if (mWorkerPrivate && mTarget) {
1499
      mWorkerPrivate->AssertIsOnWorkerThread();
1500
      mWorkerPrivate->StopSyncLoop(mTarget, false);
1501
      mWorkerPrivate->DestroySyncLoop(mIndex);
1502
    }
1503
  }
1504
1505
  bool
1506
  Run()
1507
  {
1508
    WorkerPrivate* workerPrivate = mWorkerPrivate;
1509
    mWorkerPrivate = nullptr;
1510
1511
    workerPrivate->AssertIsOnWorkerThread();
1512
1513
    return workerPrivate->RunCurrentSyncLoop();
1514
  }
1515
1516
  nsIEventTarget*
1517
  GetEventTarget() const
1518
  {
1519
    // This can be null if CreateNewSyncLoop() fails.
1520
    return mTarget;
1521
  }
1522
};
1523
1524
} // dom namespace
1525
} // mozilla namespace
1526
1527
#endif /* mozilla_dom_workers_workerprivate_h__ */