LCOV - code coverage report
Current view: top level - dom/workers - WorkerPrivate.h (source / functions) Hit Total Coverage
Test: output.info Lines: 130 322 40.4 %
Date: 2017-07-14 16:53:18 Functions: 51 125 40.8 %
Legend: Lines: hit not hit

          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__ */

Generated by: LCOV version 1.13