dom/workers/WorkerPrivate.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef mozilla_dom_workers_workerprivate_h__
     7 #define mozilla_dom_workers_workerprivate_h__
     9 #include "Workers.h"
    11 #include "nsIContentSecurityPolicy.h"
    12 #include "nsPIDOMWindow.h"
    14 #include "mozilla/CondVar.h"
    15 #include "mozilla/DOMEventTargetHelper.h"
    16 #include "mozilla/TimeStamp.h"
    17 #include "mozilla/dom/BindingDeclarations.h"
    18 #include "nsCycleCollectionParticipant.h"
    19 #include "nsDataHashtable.h"
    20 #include "nsHashKeys.h"
    21 #include "nsRefPtrHashtable.h"
    22 #include "nsString.h"
    23 #include "nsTArray.h"
    24 #include "nsThreadUtils.h"
    25 #include "StructuredCloneTags.h"
    27 #include "Queue.h"
    28 #include "WorkerFeature.h"
    30 class JSAutoStructuredCloneBuffer;
    31 class nsIChannel;
    32 class nsIDocument;
    33 class nsIEventTarget;
    34 class nsIPrincipal;
    35 class nsIScriptContext;
    36 class nsIThread;
    37 class nsIThreadInternal;
    38 class nsITimer;
    39 class nsIURI;
    41 namespace JS {
    42 class RuntimeStats;
    43 }
    45 namespace mozilla {
    46 namespace dom {
    47 class Function;
    48 }
    49 }
    51 #ifdef DEBUG
    52 struct PRThread;
    53 #endif
    55 BEGIN_WORKERS_NAMESPACE
    57 class AutoSyncLoopHolder;
    58 class MessagePort;
    59 class SharedWorker;
    60 class WorkerControlRunnable;
    61 class WorkerGlobalScope;
    62 class WorkerPrivate;
    63 class WorkerRunnable;
    65 // SharedMutex is a small wrapper around an (internal) reference-counted Mutex
    66 // object. It exists to avoid changing a lot of code to use Mutex* instead of
    67 // Mutex&.
    68 class SharedMutex
    69 {
    70   typedef mozilla::Mutex Mutex;
    72   class RefCountedMutex MOZ_FINAL : public Mutex
    73   {
    74   public:
    75     RefCountedMutex(const char* aName)
    76     : Mutex(aName)
    77     { }
    79     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefCountedMutex)
    81   private:
    82     ~RefCountedMutex()
    83     { }
    84   };
    86   nsRefPtr<RefCountedMutex> mMutex;
    88 public:
    89   SharedMutex(const char* aName)
    90   : mMutex(new RefCountedMutex(aName))
    91   { }
    93   SharedMutex(SharedMutex& aOther)
    94   : mMutex(aOther.mMutex)
    95   { }
    97   operator Mutex&()
    98   {
    99     return *mMutex;
   100   }
   102   operator const Mutex&() const
   103   {
   104     return *mMutex;
   105   }
   107   void
   108   AssertCurrentThreadOwns() const
   109   {
   110     mMutex->AssertCurrentThreadOwns();
   111   }
   112 };
   114 template <class Derived>
   115 class WorkerPrivateParent : public DOMEventTargetHelper
   116 {
   117   class SynchronizeAndResumeRunnable;
   119 protected:
   120   class EventTarget;
   121   friend class EventTarget;
   123 public:
   124   struct LocationInfo
   125   {
   126     nsCString mHref;
   127     nsCString mProtocol;
   128     nsCString mHost;
   129     nsCString mHostname;
   130     nsCString mPort;
   131     nsCString mPathname;
   132     nsCString mSearch;
   133     nsCString mHash;
   134     nsString mOrigin;
   135   };
   137   struct LoadInfo
   138   {
   139     // All of these should be released in ForgetMainThreadObjects.
   140     nsCOMPtr<nsIURI> mBaseURI;
   141     nsCOMPtr<nsIURI> mResolvedScriptURI;
   142     nsCOMPtr<nsIPrincipal> mPrincipal;
   143     nsCOMPtr<nsIScriptContext> mScriptContext;
   144     nsCOMPtr<nsPIDOMWindow> mWindow;
   145     nsCOMPtr<nsIContentSecurityPolicy> mCSP;
   146     nsCOMPtr<nsIChannel> mChannel;
   148     nsCString mDomain;
   150     bool mEvalAllowed;
   151     bool mReportCSPViolations;
   152     bool mXHRParamsAllowed;
   153     bool mPrincipalIsSystem;
   154     bool mIsInPrivilegedApp;
   155     bool mIsInCertifiedApp;
   157     LoadInfo()
   158     : mEvalAllowed(false), mReportCSPViolations(false),
   159       mXHRParamsAllowed(false), mPrincipalIsSystem(false),
   160       mIsInPrivilegedApp(false), mIsInCertifiedApp(false)
   161     { }
   163     void
   164     StealFrom(LoadInfo& aOther)
   165     {
   166       MOZ_ASSERT(!mBaseURI);
   167       aOther.mBaseURI.swap(mBaseURI);
   169       MOZ_ASSERT(!mResolvedScriptURI);
   170       aOther.mResolvedScriptURI.swap(mResolvedScriptURI);
   172       MOZ_ASSERT(!mPrincipal);
   173       aOther.mPrincipal.swap(mPrincipal);
   175       MOZ_ASSERT(!mScriptContext);
   176       aOther.mScriptContext.swap(mScriptContext);
   178       MOZ_ASSERT(!mWindow);
   179       aOther.mWindow.swap(mWindow);
   181       MOZ_ASSERT(!mCSP);
   182       aOther.mCSP.swap(mCSP);
   184       MOZ_ASSERT(!mChannel);
   185       aOther.mChannel.swap(mChannel);
   187       mDomain = aOther.mDomain;
   188       mEvalAllowed = aOther.mEvalAllowed;
   189       mReportCSPViolations = aOther.mReportCSPViolations;
   190       mXHRParamsAllowed = aOther.mXHRParamsAllowed;
   191       mPrincipalIsSystem = aOther.mPrincipalIsSystem;
   192       mIsInPrivilegedApp = aOther.mIsInPrivilegedApp;
   193       mIsInCertifiedApp = aOther.mIsInCertifiedApp;
   194     }
   195   };
   197   enum WorkerType
   198   {
   199     WorkerTypeDedicated,
   200     WorkerTypeShared
   201   };
   203 protected:
   204   typedef mozilla::ErrorResult ErrorResult;
   206   SharedMutex mMutex;
   207   mozilla::CondVar mCondVar;
   208   mozilla::CondVar mMemoryReportCondVar;
   210   // Protected by mMutex.
   211   nsRefPtr<EventTarget> mEventTarget;
   212   nsTArray<nsRefPtr<WorkerRunnable>> mPreStartRunnables;
   214 private:
   215   WorkerPrivate* mParent;
   216   nsString mScriptURL;
   217   nsCString mSharedWorkerName;
   218   LocationInfo mLocationInfo;
   219   // The lifetime of these objects within LoadInfo is managed explicitly;
   220   // they do not need to be cycle collected.
   221   LoadInfo mLoadInfo;
   223   // Only used for top level workers.
   224   nsTArray<nsCOMPtr<nsIRunnable>> mQueuedRunnables;
   225   nsRevocableEventPtr<SynchronizeAndResumeRunnable> mSynchronizeRunnable;
   227   // Only for ChromeWorkers without window and only touched on the main thread.
   228   nsTArray<nsCString> mHostObjectURIs;
   230   // Protected by mMutex.
   231   JSSettings mJSSettings;
   233   // Only touched on the parent thread (currently this is always the main
   234   // thread as SharedWorkers are always top-level).
   235   nsDataHashtable<nsUint64HashKey, SharedWorker*> mSharedWorkers;
   237   uint64_t mBusyCount;
   238   uint64_t mMessagePortSerial;
   239   Status mParentStatus;
   240   bool mParentSuspended;
   241   bool mIsChromeWorker;
   242   bool mMainThreadObjectsForgotten;
   243   WorkerType mWorkerType;
   244   TimeStamp mCreationTimeStamp;
   246 protected:
   247   // The worker is owned by its thread, which is represented here.  This is set
   248   // in Construct() and emptied by WorkerFinishedRunnable, and conditionally
   249   // traversed by the cycle collector if the busy count is zero.
   250   nsRefPtr<WorkerPrivate> mSelfRef;
   252   WorkerPrivateParent(JSContext* aCx, WorkerPrivate* aParent,
   253                       const nsAString& aScriptURL, bool aIsChromeWorker,
   254                       WorkerType aWorkerType,
   255                       const nsACString& aSharedWorkerName,
   256                       LoadInfo& aLoadInfo);
   258   ~WorkerPrivateParent();
   260 private:
   261   Derived*
   262   ParentAsWorkerPrivate() const
   263   {
   264     return static_cast<Derived*>(const_cast<WorkerPrivateParent*>(this));
   265   }
   267   // aCx is null when called from the finalizer
   268   bool
   269   NotifyPrivate(JSContext* aCx, Status aStatus);
   271   // aCx is null when called from the finalizer
   272   bool
   273   TerminatePrivate(JSContext* aCx)
   274   {
   275     return NotifyPrivate(aCx, Terminating);
   276   }
   278   void
   279   PostMessageInternal(JSContext* aCx, JS::Handle<JS::Value> aMessage,
   280                       const Optional<Sequence<JS::Value> >& aTransferable,
   281                       bool aToMessagePort, uint64_t aMessagePortSerial,
   282                       ErrorResult& aRv);
   284   nsresult
   285   DispatchPrivate(WorkerRunnable* aRunnable, nsIEventTarget* aSyncLoopTarget);
   287 public:
   288   virtual JSObject*
   289   WrapObject(JSContext* aCx) MOZ_OVERRIDE;
   291   NS_DECL_ISUPPORTS_INHERITED
   292   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WorkerPrivateParent,
   293                                                          DOMEventTargetHelper)
   295   void
   296   ClearSelfRef()
   297   {
   298     AssertIsOnParentThread();
   299     MOZ_ASSERT(mSelfRef);
   300     mSelfRef = nullptr;
   301   }
   303   nsresult
   304   Dispatch(WorkerRunnable* aRunnable)
   305   {
   306     return DispatchPrivate(aRunnable, nullptr);
   307   }
   309   nsresult
   310   DispatchControlRunnable(WorkerControlRunnable* aWorkerControlRunnable);
   312   already_AddRefed<WorkerRunnable>
   313   MaybeWrapAsWorkerRunnable(nsIRunnable* aRunnable);
   315   already_AddRefed<nsIEventTarget>
   316   GetEventTarget();
   318   // May be called on any thread...
   319   bool
   320   Start();
   322   // Called on the parent thread.
   323   bool
   324   Notify(JSContext* aCx, Status aStatus)
   325   {
   326     return NotifyPrivate(aCx, aStatus);
   327   }
   329   bool
   330   Cancel(JSContext* aCx)
   331   {
   332     return Notify(aCx, Canceling);
   333   }
   335   bool
   336   Kill(JSContext* aCx)
   337   {
   338     return Notify(aCx, Killing);
   339   }
   341   bool
   342   Suspend(JSContext* aCx, nsPIDOMWindow* aWindow);
   344   bool
   345   Resume(JSContext* aCx, nsPIDOMWindow* aWindow);
   347   bool
   348   SynchronizeAndResume(JSContext* aCx, nsPIDOMWindow* aWindow,
   349                        nsIScriptContext* aScriptContext);
   351   bool
   352   Terminate(JSContext* aCx)
   353   {
   354     AssertIsOnParentThread();
   355     return TerminatePrivate(aCx);
   356   }
   358   bool
   359   Close(JSContext* aCx);
   361   bool
   362   ModifyBusyCount(JSContext* aCx, bool aIncrease);
   364   void
   365   ForgetMainThreadObjects(nsTArray<nsCOMPtr<nsISupports> >& aDoomed);
   367   void
   368   PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
   369               const Optional<Sequence<JS::Value> >& aTransferable,
   370               ErrorResult& aRv)
   371   {
   372     PostMessageInternal(aCx, aMessage, aTransferable, false, 0, aRv);
   373   }
   375   void
   376   PostMessageToMessagePort(JSContext* aCx,
   377                            uint64_t aMessagePortSerial,
   378                            JS::Handle<JS::Value> aMessage,
   379                            const Optional<Sequence<JS::Value> >& aTransferable,
   380                            ErrorResult& aRv);
   382   bool
   383   DispatchMessageEventToMessagePort(
   384                                JSContext* aCx,
   385                                uint64_t aMessagePortSerial,
   386                                JSAutoStructuredCloneBuffer&& aBuffer,
   387                                nsTArray<nsCOMPtr<nsISupports>>& aClonedObjects);
   389   uint64_t
   390   GetInnerWindowId();
   392   void
   393   UpdateRuntimeAndContextOptions(JSContext* aCx,
   394                                  const JS::RuntimeOptions& aRuntimeOptions,
   395                                  const JS::ContextOptions& aContentCxOptions,
   396                                  const JS::ContextOptions& aChromeCxOptions);
   398   void
   399   UpdatePreference(JSContext* aCx, WorkerPreference aPref, bool aValue);
   401   void
   402   UpdateJSWorkerMemoryParameter(JSContext* aCx, JSGCParamKey key,
   403                                 uint32_t value);
   405 #ifdef JS_GC_ZEAL
   406   void
   407   UpdateGCZeal(JSContext* aCx, uint8_t aGCZeal, uint32_t aFrequency);
   408 #endif
   410   void
   411   GarbageCollect(JSContext* aCx, bool aShrinking);
   413   void
   414   CycleCollect(JSContext* aCx, bool aDummy);
   416   void
   417   OfflineStatusChangeEvent(JSContext* aCx, bool aIsOffline);
   419   bool
   420   RegisterSharedWorker(JSContext* aCx, SharedWorker* aSharedWorker);
   422   void
   423   UnregisterSharedWorker(JSContext* aCx, SharedWorker* aSharedWorker);
   425   void
   426   BroadcastErrorToSharedWorkers(JSContext* aCx,
   427                                 const nsAString& aMessage,
   428                                 const nsAString& aFilename,
   429                                 const nsAString& aLine,
   430                                 uint32_t aLineNumber,
   431                                 uint32_t aColumnNumber,
   432                                 uint32_t aFlags);
   434   void
   435   WorkerScriptLoaded();
   437   void
   438   QueueRunnable(nsIRunnable* aRunnable)
   439   {
   440     AssertIsOnMainThread();
   441     mQueuedRunnables.AppendElement(aRunnable);
   442   }
   444   WorkerPrivate*
   445   GetParent() const
   446   {
   447     return mParent;
   448   }
   450   bool
   451   IsSuspended() const
   452   {
   453     AssertIsOnParentThread();
   454     return mParentSuspended;
   455   }
   457   bool
   458   IsAcceptingEvents()
   459   {
   460     AssertIsOnParentThread();
   462     MutexAutoLock lock(mMutex);
   463     return mParentStatus < Terminating;
   464     }
   466   Status
   467   ParentStatus() const
   468   {
   469     mMutex.AssertCurrentThreadOwns();
   470     return mParentStatus;
   471   }
   473   JSContext*
   474   ParentJSContext() const;
   476   nsIScriptContext*
   477   GetScriptContext() const
   478   {
   479     AssertIsOnMainThread();
   480     return mLoadInfo.mScriptContext;
   481   }
   483   const nsString&
   484   ScriptURL() const
   485   {
   486     return mScriptURL;
   487   }
   489   const nsCString&
   490   Domain() const
   491   {
   492     return mLoadInfo.mDomain;
   493   }
   495   nsIURI*
   496   GetBaseURI() const
   497   {
   498     AssertIsOnMainThread();
   499     return mLoadInfo.mBaseURI;
   500   }
   502   void
   503   SetBaseURI(nsIURI* aBaseURI);
   505   nsIURI*
   506   GetResolvedScriptURI() const
   507   {
   508     AssertIsOnMainThread();
   509     return mLoadInfo.mResolvedScriptURI;
   510   }
   512   TimeStamp CreationTimeStamp() const
   513   {
   514     return mCreationTimeStamp;
   515   }
   517   nsIPrincipal*
   518   GetPrincipal() const
   519   {
   520     AssertIsOnMainThread();
   521     return mLoadInfo.mPrincipal;
   522   }
   524   // This method allows the principal to be retrieved off the main thread.
   525   // Principals are main-thread objects so the caller must ensure that all
   526   // access occurs on the main thread.
   527   nsIPrincipal*
   528   GetPrincipalDontAssertMainThread() const
   529   {
   530       return mLoadInfo.mPrincipal;
   531   }
   533   void
   534   SetPrincipal(nsIPrincipal* aPrincipal);
   536   bool
   537   UsesSystemPrincipal() const
   538   {
   539     return mLoadInfo.mPrincipalIsSystem;
   540   }
   542   bool
   543   IsInPrivilegedApp() const
   544   {
   545     return mLoadInfo.mIsInPrivilegedApp;
   546   }
   548   bool
   549   IsInCertifiedApp() const
   550   {
   551     return mLoadInfo.mIsInCertifiedApp;
   552   }
   554   already_AddRefed<nsIChannel>
   555   ForgetWorkerChannel()
   556   {
   557     AssertIsOnMainThread();
   558     return mLoadInfo.mChannel.forget();
   559   }
   561   nsIDocument*
   562   GetDocument() const
   563   {
   564     AssertIsOnMainThread();
   565     return mLoadInfo.mWindow ? mLoadInfo.mWindow->GetExtantDoc() : nullptr;
   566   }
   568   nsPIDOMWindow*
   569   GetWindow()
   570   {
   571     AssertIsOnMainThread();
   572     return mLoadInfo.mWindow;
   573   }
   575   nsIContentSecurityPolicy*
   576   GetCSP() const
   577   {
   578     AssertIsOnMainThread();
   579     return mLoadInfo.mCSP;
   580   }
   582   void
   583   SetCSP(nsIContentSecurityPolicy* aCSP)
   584   {
   585     AssertIsOnMainThread();
   586     mLoadInfo.mCSP = aCSP;
   587   }
   589   bool
   590   IsEvalAllowed() const
   591   {
   592     return mLoadInfo.mEvalAllowed;
   593   }
   595   void
   596   SetEvalAllowed(bool aEvalAllowed)
   597   {
   598     mLoadInfo.mEvalAllowed = aEvalAllowed;
   599   }
   601   bool
   602   GetReportCSPViolations() const
   603   {
   604     return mLoadInfo.mReportCSPViolations;
   605   }
   607   bool
   608   XHRParamsAllowed() const
   609   {
   610     return mLoadInfo.mXHRParamsAllowed;
   611   }
   613   void
   614   SetXHRParamsAllowed(bool aAllowed)
   615   {
   616     mLoadInfo.mXHRParamsAllowed = aAllowed;
   617   }
   619   LocationInfo&
   620   GetLocationInfo()
   621   {
   622     return mLocationInfo;
   623   }
   625   void
   626   CopyJSSettings(JSSettings& aSettings)
   627   {
   628     mozilla::MutexAutoLock lock(mMutex);
   629     aSettings = mJSSettings;
   630   }
   632   void
   633   CopyJSCompartmentOptions(JS::CompartmentOptions& aOptions)
   634   {
   635     mozilla::MutexAutoLock lock(mMutex);
   636     aOptions = IsChromeWorker() ? mJSSettings.chrome.compartmentOptions
   637                                 : mJSSettings.content.compartmentOptions;
   638   }
   640   // The ability to be a chrome worker is orthogonal to the type of
   641   // worker [Dedicated|Shared].
   642   bool
   643   IsChromeWorker() const
   644   {
   645     return mIsChromeWorker;
   646   }
   648   bool
   649   IsDedicatedWorker() const
   650   {
   651     return mWorkerType == WorkerTypeDedicated;
   652   }
   654   bool
   655   IsSharedWorker() const
   656   {
   657     return mWorkerType == WorkerTypeShared;
   658   }
   660   const nsCString&
   661   SharedWorkerName() const
   662   {
   663     return mSharedWorkerName;
   664   }
   666   uint64_t
   667   NextMessagePortSerial()
   668   {
   669     AssertIsOnMainThread();
   670     return mMessagePortSerial++;
   671   }
   673   void
   674   GetAllSharedWorkers(nsTArray<nsRefPtr<SharedWorker>>& aSharedWorkers);
   676   void
   677   CloseSharedWorkersForWindow(nsPIDOMWindow* aWindow);
   679   void
   680   RegisterHostObjectURI(const nsACString& aURI);
   682   void
   683   UnregisterHostObjectURI(const nsACString& aURI);
   685   void
   686   StealHostObjectURIs(nsTArray<nsCString>& aArray);
   688   IMPL_EVENT_HANDLER(message)
   689   IMPL_EVENT_HANDLER(error)
   691 #ifdef DEBUG
   692   void
   693   AssertIsOnParentThread() const;
   695   void
   696   AssertInnerWindowIsCorrect() const;
   697 #else
   698   void
   699   AssertIsOnParentThread() const
   700   { }
   702   void
   703   AssertInnerWindowIsCorrect() const
   704   { }
   705 #endif
   706 };
   708 class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate>
   709 {
   710   friend class WorkerPrivateParent<WorkerPrivate>;
   711   typedef WorkerPrivateParent<WorkerPrivate> ParentType;
   712   friend class AutoSyncLoopHolder;
   714   struct TimeoutInfo;
   716   class MemoryReporter;
   717   friend class MemoryReporter;
   719   enum GCTimerMode
   720   {
   721     PeriodicTimer = 0,
   722     IdleTimer,
   723     NoTimer
   724   };
   726   Queue<WorkerControlRunnable*, 4> mControlQueue;
   728   // Touched on multiple threads, protected with mMutex.
   729   JSContext* mJSContext;
   730   nsRefPtr<WorkerCrossThreadDispatcher> mCrossThreadDispatcher;
   731   nsTArray<nsCOMPtr<nsIRunnable>> mUndispatchedRunnablesForSyncLoop;
   732   nsCOMPtr<nsIThread> mThread;
   734   // Things touched on worker thread only.
   735   nsRefPtr<WorkerGlobalScope> mScope;
   736   nsTArray<ParentType*> mChildWorkers;
   737   nsTArray<WorkerFeature*> mFeatures;
   738   nsTArray<nsAutoPtr<TimeoutInfo>> mTimeouts;
   740   struct SyncLoopInfo
   741   {
   742     SyncLoopInfo(EventTarget* aEventTarget);
   744     nsRefPtr<EventTarget> mEventTarget;
   745     bool mCompleted;
   746     bool mResult;
   747 #ifdef DEBUG
   748     bool mHasRun;
   749 #endif
   750   };
   752   // This is only modified on the worker thread, but in DEBUG builds
   753   // AssertValidSyncLoop function iterates it on other threads. Therefore
   754   // modifications are done with mMutex held *only* in DEBUG builds.
   755   nsTArray<nsAutoPtr<SyncLoopInfo>> mSyncLoopStack;
   757   nsCOMPtr<nsITimer> mTimer;
   759   nsCOMPtr<nsITimer> mGCTimer;
   760   nsCOMPtr<nsIEventTarget> mPeriodicGCTimerTarget;
   761   nsCOMPtr<nsIEventTarget> mIdleGCTimerTarget;
   763   nsRefPtr<MemoryReporter> mMemoryReporter;
   765   nsRefPtrHashtable<nsUint64HashKey, MessagePort> mWorkerPorts;
   767   TimeStamp mKillTime;
   768   uint32_t mErrorHandlerRecursionCount;
   769   uint32_t mNextTimeoutId;
   770   Status mStatus;
   771   bool mSuspended;
   772   bool mTimerRunning;
   773   bool mRunningExpiredTimeouts;
   774   bool mCloseHandlerStarted;
   775   bool mCloseHandlerFinished;
   776   bool mMemoryReporterRunning;
   777   bool mBlockedForMemoryReporter;
   778   bool mCancelAllPendingRunnables;
   779   bool mPeriodicGCTimerRunning;
   780   bool mIdleGCTimerRunning;
   782 #ifdef DEBUG
   783   PRThread* mPRThread;
   784 #endif
   786   bool mPreferences[WORKERPREF_COUNT];
   787   bool mOnLine;
   789 protected:
   790   ~WorkerPrivate();
   792 public:
   793   static already_AddRefed<WorkerPrivate>
   794   Constructor(const GlobalObject& aGlobal, const nsAString& aScriptURL,
   795               ErrorResult& aRv);
   797   static already_AddRefed<WorkerPrivate>
   798   Constructor(const GlobalObject& aGlobal, const nsAString& aScriptURL,
   799               bool aIsChromeWorker, WorkerType aWorkerType,
   800               const nsACString& aSharedWorkerName,
   801               LoadInfo* aLoadInfo, ErrorResult& aRv);
   803   static bool
   804   WorkerAvailable(JSContext* /* unused */, JSObject* /* unused */);
   806   static nsresult
   807   GetLoadInfo(JSContext* aCx, nsPIDOMWindow* aWindow, WorkerPrivate* aParent,
   808               const nsAString& aScriptURL, bool aIsChromeWorker,
   809               LoadInfo* aLoadInfo);
   811   void
   812   DoRunLoop(JSContext* aCx);
   814   bool
   815   InterruptCallback(JSContext* aCx);
   817   nsresult
   818   IsOnCurrentThread(bool* aIsOnCurrentThread);
   820   bool
   821   CloseInternal(JSContext* aCx)
   822   {
   823     AssertIsOnWorkerThread();
   824     return NotifyInternal(aCx, Closing);
   825   }
   827   bool
   828   SuspendInternal(JSContext* aCx);
   830   bool
   831   ResumeInternal(JSContext* aCx);
   833   void
   834   TraceTimeouts(const TraceCallbacks& aCallbacks, void* aClosure) const;
   836   bool
   837   ModifyBusyCountFromWorker(JSContext* aCx, bool aIncrease);
   839   bool
   840   AddChildWorker(JSContext* aCx, ParentType* aChildWorker);
   842   void
   843   RemoveChildWorker(JSContext* aCx, ParentType* aChildWorker);
   845   bool
   846   AddFeature(JSContext* aCx, WorkerFeature* aFeature);
   848   void
   849   RemoveFeature(JSContext* aCx, WorkerFeature* aFeature);
   851   void
   852   NotifyFeatures(JSContext* aCx, Status aStatus);
   854   bool
   855   HasActiveFeatures()
   856   {
   857     return !(mChildWorkers.IsEmpty() && mTimeouts.IsEmpty() &&
   858              mFeatures.IsEmpty());
   859   }
   861   void
   862   PostMessageToParent(JSContext* aCx,
   863                       JS::Handle<JS::Value> aMessage,
   864                       const Optional<Sequence<JS::Value>>& aTransferable,
   865                       ErrorResult& aRv)
   866   {
   867     PostMessageToParentInternal(aCx, aMessage, aTransferable, false, 0, aRv);
   868   }
   870   void
   871   PostMessageToParentMessagePort(
   872                              JSContext* aCx,
   873                              uint64_t aMessagePortSerial,
   874                              JS::Handle<JS::Value> aMessage,
   875                              const Optional<Sequence<JS::Value>>& aTransferable,
   876                              ErrorResult& aRv);
   878   bool
   879   NotifyInternal(JSContext* aCx, Status aStatus);
   881   void
   882   ReportError(JSContext* aCx, const char* aMessage, JSErrorReport* aReport);
   884   int32_t
   885   SetTimeout(JSContext* aCx,
   886              Function* aHandler,
   887              const nsAString& aStringHandler,
   888              int32_t aTimeout,
   889              const Sequence<JS::Value>& aArguments,
   890              bool aIsInterval,
   891              ErrorResult& aRv);
   893   void
   894   ClearTimeout(int32_t aId);
   896   bool
   897   RunExpiredTimeouts(JSContext* aCx);
   899   bool
   900   RescheduleTimeoutTimer(JSContext* aCx);
   902   void
   903   CloseHandlerStarted()
   904   {
   905     AssertIsOnWorkerThread();
   906     mCloseHandlerStarted = true;
   907   }
   909   void
   910   CloseHandlerFinished()
   911   {
   912     AssertIsOnWorkerThread();
   913     mCloseHandlerFinished = true;
   914   }
   916   void
   917   UpdateRuntimeAndContextOptionsInternal(
   918                                     JSContext* aCx,
   919                                     const JS::RuntimeOptions& aRuntimeOptions,
   920                                     const JS::ContextOptions& aContentCxOptions,
   921                                     const JS::ContextOptions& aChromeCxOptions);
   923   void
   924   UpdatePreferenceInternal(JSContext* aCx, WorkerPreference aPref, bool aValue);
   926   void
   927   UpdateJSWorkerMemoryParameterInternal(JSContext* aCx, JSGCParamKey key, uint32_t aValue);
   929   enum WorkerRanOrNot {
   930     WorkerNeverRan = 0,
   931     WorkerRan
   932   };
   934   void
   935   ScheduleDeletion(WorkerRanOrNot aRanOrNot);
   937   bool
   938   BlockAndCollectRuntimeStats(JS::RuntimeStats* aRtStats);
   940 #ifdef JS_GC_ZEAL
   941   void
   942   UpdateGCZealInternal(JSContext* aCx, uint8_t aGCZeal, uint32_t aFrequency);
   943 #endif
   945   void
   946   GarbageCollectInternal(JSContext* aCx, bool aShrinking,
   947                          bool aCollectChildren);
   949   void
   950   CycleCollectInternal(JSContext* aCx, bool aCollectChildren);
   952   void
   953   OfflineStatusChangeEventInternal(JSContext* aCx, bool aIsOffline);
   955   JSContext*
   956   GetJSContext() const
   957   {
   958     AssertIsOnWorkerThread();
   959     return mJSContext;
   960   }
   962   WorkerGlobalScope*
   963   GlobalScope() const
   964   {
   965     AssertIsOnWorkerThread();
   966     return mScope;
   967   }
   969   void
   970   SetThread(nsIThread* aThread);
   972   void
   973   AssertIsOnWorkerThread() const
   974 #ifdef DEBUG
   975   ;
   976 #else
   977   { }
   978 #endif
   980   WorkerCrossThreadDispatcher*
   981   GetCrossThreadDispatcher();
   983   // This may block!
   984   void
   985   BeginCTypesCall();
   987   // This may block!
   988   void
   989   EndCTypesCall();
   991   void
   992   BeginCTypesCallback()
   993   {
   994     // If a callback is beginning then we need to do the exact same thing as
   995     // when a ctypes call ends.
   996     EndCTypesCall();
   997   }
   999   void
  1000   EndCTypesCallback()
  1002     // If a callback is ending then we need to do the exact same thing as
  1003     // when a ctypes call begins.
  1004     BeginCTypesCall();
  1007   bool
  1008   ConnectMessagePort(JSContext* aCx, uint64_t aMessagePortSerial);
  1010   void
  1011   DisconnectMessagePort(uint64_t aMessagePortSerial);
  1013   MessagePort*
  1014   GetMessagePort(uint64_t aMessagePortSerial);
  1016   JSObject*
  1017   CreateGlobalScope(JSContext* aCx);
  1019   bool
  1020   RegisterBindings(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
  1022   bool
  1023   DumpEnabled() const
  1025     AssertIsOnWorkerThread();
  1026     return mPreferences[WORKERPREF_DUMP];
  1029   bool
  1030   OnLine() const
  1032     AssertIsOnWorkerThread();
  1033     return mOnLine;
  1036   void
  1037   StopSyncLoop(nsIEventTarget* aSyncLoopTarget, bool aResult);
  1039   bool
  1040   AllPendingRunnablesShouldBeCanceled() const
  1042     return mCancelAllPendingRunnables;
  1045   void
  1046   OnProcessNextEvent(uint32_t aRecursionDepth);
  1048   void
  1049   AfterProcessNextEvent(uint32_t aRecursionDepth);
  1051   void
  1052   AssertValidSyncLoop(nsIEventTarget* aSyncLoopTarget)
  1053 #ifdef DEBUG
  1055 #else
  1056   { }
  1057 #endif
  1059 private:
  1060   WorkerPrivate(JSContext* aCx, WorkerPrivate* aParent,
  1061                 const nsAString& aScriptURL, bool aIsChromeWorker,
  1062                 WorkerType aWorkerType, const nsACString& aSharedWorkerName,
  1063                 LoadInfo& aLoadInfo);
  1065   void
  1066   ClearMainEventQueue(WorkerRanOrNot aRanOrNot);
  1068   bool
  1069   MayContinueRunning()
  1071     AssertIsOnWorkerThread();
  1073     Status status;
  1075       MutexAutoLock lock(mMutex);
  1076       status = mStatus;
  1079     if (status >= Killing) {
  1080       return false;
  1082     if (status >= Running) {
  1083       return mKillTime.IsNull() || RemainingRunTimeMS() > 0;
  1085     return true;
  1088   uint32_t
  1089   RemainingRunTimeMS() const;
  1091   void
  1092   CancelAllTimeouts(JSContext* aCx);
  1094   bool
  1095   ScheduleKillCloseEventRunnable(JSContext* aCx);
  1097   bool
  1098   ProcessAllControlRunnables()
  1100     MutexAutoLock lock(mMutex);
  1101     return ProcessAllControlRunnablesLocked();
  1104   bool
  1105   ProcessAllControlRunnablesLocked();
  1107   void
  1108   EnableMemoryReporter();
  1110   void
  1111   DisableMemoryReporter();
  1113   void
  1114   WaitForWorkerEvents(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT);
  1116   void
  1117   PostMessageToParentInternal(JSContext* aCx,
  1118                               JS::Handle<JS::Value> aMessage,
  1119                               const Optional<Sequence<JS::Value>>& aTransferable,
  1120                               bool aToMessagePort,
  1121                               uint64_t aMessagePortSerial,
  1122                               ErrorResult& aRv);
  1124   void
  1125   GetAllPreferences(bool aPreferences[WORKERPREF_COUNT]) const
  1127     AssertIsOnWorkerThread();
  1128     memcpy(aPreferences, mPreferences, WORKERPREF_COUNT * sizeof(bool));
  1131   already_AddRefed<nsIEventTarget>
  1132   CreateNewSyncLoop();
  1134   bool
  1135   RunCurrentSyncLoop();
  1137   bool
  1138   DestroySyncLoop(uint32_t aLoopIndex, nsIThreadInternal* aThread = nullptr);
  1140   void
  1141   InitializeGCTimers();
  1143   void
  1144   SetGCTimerMode(GCTimerMode aMode);
  1146   void
  1147   ShutdownGCTimers();
  1148 };
  1150 // This class is only used to trick the DOM bindings.  We never create
  1151 // instances of it, and static_casting to it is fine since it doesn't add
  1152 // anything to WorkerPrivate.
  1153 class ChromeWorkerPrivate : public WorkerPrivate
  1155 public:
  1156   static already_AddRefed<ChromeWorkerPrivate>
  1157   Constructor(const GlobalObject& aGlobal, const nsAString& aScriptURL,
  1158               ErrorResult& rv);
  1160   static bool
  1161   WorkerAvailable(JSContext* /* unused */, JSObject* /* unused */);
  1163 private:
  1164   ChromeWorkerPrivate() MOZ_DELETE;
  1165   ChromeWorkerPrivate(const ChromeWorkerPrivate& aRHS) MOZ_DELETE;
  1166   ChromeWorkerPrivate& operator =(const ChromeWorkerPrivate& aRHS) MOZ_DELETE;
  1167 };
  1169 WorkerPrivate*
  1170 GetWorkerPrivateFromContext(JSContext* aCx);
  1172 WorkerPrivate*
  1173 GetCurrentThreadWorkerPrivate();
  1175 bool
  1176 IsCurrentThreadRunningChromeWorker();
  1178 JSContext*
  1179 GetCurrentThreadJSContext();
  1181 enum WorkerStructuredDataType
  1183   DOMWORKER_SCTAG_FILE = SCTAG_DOM_MAX,
  1184   DOMWORKER_SCTAG_BLOB,
  1186   DOMWORKER_SCTAG_END
  1187 };
  1189 JSStructuredCloneCallbacks*
  1190 WorkerStructuredCloneCallbacks(bool aMainRuntime);
  1192 JSStructuredCloneCallbacks*
  1193 ChromeWorkerStructuredCloneCallbacks(bool aMainRuntime);
  1195 class AutoSyncLoopHolder
  1197   WorkerPrivate* mWorkerPrivate;
  1198   nsCOMPtr<nsIEventTarget> mTarget;
  1199   uint32_t mIndex;
  1201 public:
  1202   AutoSyncLoopHolder(WorkerPrivate* aWorkerPrivate)
  1203   : mWorkerPrivate(aWorkerPrivate)
  1204   , mTarget(aWorkerPrivate->CreateNewSyncLoop())
  1205   , mIndex(aWorkerPrivate->mSyncLoopStack.Length() - 1)
  1207     aWorkerPrivate->AssertIsOnWorkerThread();
  1210   ~AutoSyncLoopHolder()
  1212     if (mWorkerPrivate) {
  1213       mWorkerPrivate->AssertIsOnWorkerThread();
  1214       mWorkerPrivate->StopSyncLoop(mTarget, false);
  1215       mWorkerPrivate->DestroySyncLoop(mIndex);
  1219   bool
  1220   Run()
  1222     WorkerPrivate* workerPrivate = mWorkerPrivate;
  1223     mWorkerPrivate = nullptr;
  1225     workerPrivate->AssertIsOnWorkerThread();
  1227     return workerPrivate->RunCurrentSyncLoop();
  1230   nsIEventTarget*
  1231   EventTarget() const
  1233     return mTarget;
  1235 };
  1237 END_WORKERS_NAMESPACE
  1239 #endif /* mozilla_dom_workers_workerprivate_h__ */

mercurial