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