2011-07-17 12:09:13 -07:00
|
|
|
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
2012-05-21 04:12:37 -07:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2011-07-17 12:09:13 -07:00
|
|
|
|
|
|
|
#ifndef mozilla_dom_workers_workerprivate_h__
|
|
|
|
#define mozilla_dom_workers_workerprivate_h__
|
|
|
|
|
|
|
|
#include "Workers.h"
|
|
|
|
|
|
|
|
#include "nsIRunnable.h"
|
|
|
|
#include "nsIThread.h"
|
|
|
|
#include "nsIThreadInternal.h"
|
|
|
|
|
|
|
|
#include "jsapi.h"
|
|
|
|
#include "mozilla/CondVar.h"
|
|
|
|
#include "mozilla/Mutex.h"
|
|
|
|
#include "mozilla/TimeStamp.h"
|
|
|
|
#include "nsAutoPtr.h"
|
|
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsEventQueue.h"
|
|
|
|
#include "nsStringGlue.h"
|
|
|
|
#include "nsTArray.h"
|
|
|
|
#include "nsTPriorityQueue.h"
|
2012-04-24 03:58:07 -07:00
|
|
|
#include "StructuredCloneTags.h"
|
2011-07-17 12:09:13 -07:00
|
|
|
|
|
|
|
#include "EventTarget.h"
|
|
|
|
#include "Queue.h"
|
|
|
|
#include "WorkerFeature.h"
|
|
|
|
|
|
|
|
class JSAutoStructuredCloneBuffer;
|
|
|
|
class nsIDocument;
|
|
|
|
class nsIPrincipal;
|
|
|
|
class nsIScriptContext;
|
|
|
|
class nsIURI;
|
|
|
|
class nsPIDOMWindow;
|
|
|
|
class nsITimer;
|
2012-05-04 00:22:18 -07:00
|
|
|
class nsIXPCScriptNotify;
|
2011-07-17 12:09:13 -07:00
|
|
|
|
|
|
|
BEGIN_WORKERS_NAMESPACE
|
|
|
|
|
2012-05-29 19:39:38 -07:00
|
|
|
class WorkerMemoryReporter;
|
2011-07-17 12:09:13 -07:00
|
|
|
class WorkerPrivate;
|
|
|
|
|
|
|
|
class WorkerRunnable : public nsIRunnable
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
enum Target { ParentThread, WorkerThread };
|
|
|
|
enum BusyBehavior { ModifyBusyCount, UnchangedBusyCount };
|
2012-02-09 20:54:47 -08:00
|
|
|
enum ClearingBehavior { SkipWhenClearing, RunWhenClearing };
|
2011-07-17 12:09:13 -07:00
|
|
|
|
|
|
|
protected:
|
|
|
|
WorkerPrivate* mWorkerPrivate;
|
|
|
|
Target mTarget;
|
2012-02-09 20:54:47 -08:00
|
|
|
BusyBehavior mBusyBehavior;
|
|
|
|
ClearingBehavior mClearingBehavior;
|
2011-07-17 12:09:13 -07:00
|
|
|
|
|
|
|
public:
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
|
|
|
bool
|
|
|
|
Dispatch(JSContext* aCx);
|
|
|
|
|
|
|
|
static bool
|
|
|
|
DispatchToMainThread(nsIRunnable*);
|
|
|
|
|
2012-02-09 20:54:47 -08:00
|
|
|
bool
|
|
|
|
WantsToRunDuringClear()
|
|
|
|
{
|
|
|
|
return mClearingBehavior == RunWhenClearing;
|
|
|
|
}
|
|
|
|
|
2011-07-17 12:09:13 -07:00
|
|
|
protected:
|
|
|
|
WorkerRunnable(WorkerPrivate* aWorkerPrivate, Target aTarget,
|
2012-02-09 20:54:47 -08:00
|
|
|
BusyBehavior aBusyBehavior,
|
|
|
|
ClearingBehavior aClearingBehavior)
|
2011-07-17 12:09:13 -07:00
|
|
|
#ifdef DEBUG
|
|
|
|
;
|
|
|
|
#else
|
|
|
|
: mWorkerPrivate(aWorkerPrivate), mTarget(aTarget),
|
2012-02-09 20:54:47 -08:00
|
|
|
mBusyBehavior(aBusyBehavior), mClearingBehavior(aClearingBehavior)
|
2011-07-17 12:09:13 -07:00
|
|
|
{ }
|
|
|
|
#endif
|
|
|
|
|
|
|
|
virtual ~WorkerRunnable()
|
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual bool
|
|
|
|
PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate);
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
PostDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
|
|
|
bool aDispatchResult);
|
|
|
|
|
|
|
|
virtual bool
|
|
|
|
DispatchInternal();
|
|
|
|
|
|
|
|
virtual bool
|
|
|
|
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) = 0;
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate, bool aRunResult);
|
|
|
|
|
2012-05-04 00:22:18 -07:00
|
|
|
void NotifyScriptExecutedIfNeeded() const;
|
|
|
|
|
2011-07-17 12:09:13 -07:00
|
|
|
private:
|
|
|
|
NS_DECL_NSIRUNNABLE
|
|
|
|
};
|
|
|
|
|
|
|
|
class WorkerSyncRunnable : public WorkerRunnable
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
PRUint32 mSyncQueueKey;
|
|
|
|
bool mBypassSyncQueue;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
friend class WorkerPrivate;
|
|
|
|
|
|
|
|
WorkerSyncRunnable(WorkerPrivate* aWorkerPrivate, PRUint32 aSyncQueueKey,
|
2012-02-09 20:54:47 -08:00
|
|
|
bool aBypassSyncQueue = false,
|
|
|
|
ClearingBehavior aClearingBehavior = SkipWhenClearing)
|
|
|
|
: WorkerRunnable(aWorkerPrivate, WorkerThread, UnchangedBusyCount,
|
2012-02-14 14:33:11 -08:00
|
|
|
aClearingBehavior),
|
2011-07-17 12:09:13 -07:00
|
|
|
mSyncQueueKey(aSyncQueueKey), mBypassSyncQueue(aBypassSyncQueue)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual ~WorkerSyncRunnable()
|
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual bool
|
|
|
|
DispatchInternal();
|
|
|
|
};
|
|
|
|
|
|
|
|
class WorkerControlRunnable : public WorkerRunnable
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
WorkerControlRunnable(WorkerPrivate* aWorkerPrivate, Target aTarget,
|
|
|
|
BusyBehavior aBusyBehavior)
|
2012-02-09 20:54:47 -08:00
|
|
|
: WorkerRunnable(aWorkerPrivate, aTarget, aBusyBehavior, SkipWhenClearing)
|
2011-07-17 12:09:13 -07:00
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual ~WorkerControlRunnable()
|
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual bool
|
|
|
|
DispatchInternal();
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class Derived>
|
2012-03-30 21:42:20 -07:00
|
|
|
class WorkerPrivateParent : public EventTarget
|
2011-07-17 12:09:13 -07:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
struct LocationInfo
|
|
|
|
{
|
|
|
|
nsCString mHref;
|
|
|
|
nsCString mProtocol;
|
|
|
|
nsCString mHost;
|
|
|
|
nsCString mHostname;
|
|
|
|
nsCString mPort;
|
|
|
|
nsCString mPathname;
|
|
|
|
nsCString mSearch;
|
|
|
|
nsCString mHash;
|
|
|
|
};
|
|
|
|
|
|
|
|
protected:
|
|
|
|
mozilla::Mutex mMutex;
|
|
|
|
mozilla::CondVar mCondVar;
|
|
|
|
|
|
|
|
private:
|
|
|
|
JSObject* mJSObject;
|
|
|
|
WorkerPrivate* mParent;
|
|
|
|
JSContext* mParentJSContext;
|
|
|
|
nsString mScriptURL;
|
|
|
|
nsCString mDomain;
|
|
|
|
LocationInfo mLocationInfo;
|
|
|
|
|
|
|
|
// Main-thread things.
|
|
|
|
nsCOMPtr<nsPIDOMWindow> mWindow;
|
|
|
|
nsCOMPtr<nsIScriptContext> mScriptContext;
|
2012-05-04 00:22:18 -07:00
|
|
|
nsCOMPtr<nsIXPCScriptNotify> mScriptNotify;
|
2011-07-17 12:09:13 -07:00
|
|
|
nsCOMPtr<nsIURI> mBaseURI;
|
|
|
|
nsCOMPtr<nsIURI> mScriptURI;
|
|
|
|
nsCOMPtr<nsIPrincipal> mPrincipal;
|
|
|
|
nsCOMPtr<nsIDocument> mDocument;
|
|
|
|
|
|
|
|
// Only used for top level workers.
|
|
|
|
nsTArray<nsRefPtr<WorkerRunnable> > mQueuedRunnables;
|
|
|
|
|
|
|
|
PRUint64 mBusyCount;
|
|
|
|
Status mParentStatus;
|
|
|
|
PRUint32 mJSContextOptions;
|
2012-01-04 11:11:32 -08:00
|
|
|
PRUint32 mJSRuntimeHeapSize;
|
2011-07-17 12:09:13 -07:00
|
|
|
PRUint8 mGCZeal;
|
|
|
|
bool mJSObjectRooted;
|
|
|
|
bool mParentSuspended;
|
|
|
|
bool mIsChromeWorker;
|
2011-08-15 20:40:38 -07:00
|
|
|
bool mPrincipalIsSystem;
|
2012-03-30 21:42:20 -07:00
|
|
|
bool mMainThreadObjectsForgotten;
|
2011-07-17 12:09:13 -07:00
|
|
|
|
|
|
|
protected:
|
|
|
|
WorkerPrivateParent(JSContext* aCx, JSObject* aObject, WorkerPrivate* aParent,
|
|
|
|
JSContext* aParentJSContext, const nsAString& aScriptURL,
|
|
|
|
bool aIsChromeWorker, const nsACString& aDomain,
|
|
|
|
nsCOMPtr<nsPIDOMWindow>& aWindow,
|
|
|
|
nsCOMPtr<nsIScriptContext>& aScriptContext,
|
|
|
|
nsCOMPtr<nsIURI>& aBaseURI,
|
|
|
|
nsCOMPtr<nsIPrincipal>& aPrincipal,
|
|
|
|
nsCOMPtr<nsIDocument>& aDocument);
|
|
|
|
|
|
|
|
~WorkerPrivateParent();
|
|
|
|
|
|
|
|
private:
|
|
|
|
Derived*
|
|
|
|
ParentAsWorkerPrivate() const
|
|
|
|
{
|
|
|
|
return static_cast<Derived*>(const_cast<WorkerPrivateParent*>(this));
|
|
|
|
}
|
|
|
|
|
2012-03-19 07:34:58 -07:00
|
|
|
// aCx is null when called from the finalizer
|
2011-12-29 10:28:13 -08:00
|
|
|
bool
|
2012-03-19 07:34:58 -07:00
|
|
|
NotifyPrivate(JSContext* aCx, Status aStatus);
|
2011-12-29 10:28:13 -08:00
|
|
|
|
2012-03-19 07:34:58 -07:00
|
|
|
// aCx is null when called from the finalizer
|
2011-12-29 10:28:13 -08:00
|
|
|
bool
|
2012-03-19 07:34:58 -07:00
|
|
|
TerminatePrivate(JSContext* aCx)
|
2011-12-29 10:28:13 -08:00
|
|
|
{
|
2012-03-19 07:34:58 -07:00
|
|
|
return NotifyPrivate(aCx, Terminating);
|
2011-12-29 10:28:13 -08:00
|
|
|
}
|
|
|
|
|
2011-07-17 12:09:13 -07:00
|
|
|
public:
|
|
|
|
// May be called on any thread...
|
|
|
|
bool
|
|
|
|
Start();
|
|
|
|
|
|
|
|
// Called on the parent thread.
|
|
|
|
bool
|
2011-12-29 10:28:13 -08:00
|
|
|
Notify(JSContext* aCx, Status aStatus)
|
|
|
|
{
|
2012-03-19 07:34:58 -07:00
|
|
|
return NotifyPrivate(aCx, aStatus);
|
2011-12-29 10:28:13 -08:00
|
|
|
}
|
2011-07-17 12:09:13 -07:00
|
|
|
|
|
|
|
bool
|
|
|
|
Cancel(JSContext* aCx)
|
|
|
|
{
|
|
|
|
return Notify(aCx, Canceling);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Kill(JSContext* aCx)
|
|
|
|
{
|
|
|
|
return Notify(aCx, Killing);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Suspend(JSContext* aCx);
|
|
|
|
|
|
|
|
bool
|
|
|
|
Resume(JSContext* aCx);
|
|
|
|
|
2012-03-30 21:42:20 -07:00
|
|
|
virtual void
|
2012-04-26 13:57:33 -07:00
|
|
|
_trace(JSTracer* aTrc) MOZ_OVERRIDE;
|
2012-03-30 21:42:20 -07:00
|
|
|
|
|
|
|
virtual void
|
2012-04-26 13:57:33 -07:00
|
|
|
_finalize(JSFreeOp* aFop) MOZ_OVERRIDE;
|
2012-03-30 21:42:20 -07:00
|
|
|
|
2011-07-17 12:09:13 -07:00
|
|
|
void
|
2012-03-30 21:42:20 -07:00
|
|
|
Finish(JSContext* aCx)
|
2011-07-17 12:09:13 -07:00
|
|
|
{
|
2012-03-30 21:42:20 -07:00
|
|
|
RootJSObject(aCx, false);
|
2011-07-17 12:09:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Terminate(JSContext* aCx)
|
|
|
|
{
|
2012-03-30 21:42:20 -07:00
|
|
|
AssertIsOnParentThread();
|
|
|
|
RootJSObject(aCx, false);
|
2012-03-19 07:34:58 -07:00
|
|
|
return TerminatePrivate(aCx);
|
2011-07-17 12:09:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Close(JSContext* aCx);
|
|
|
|
|
|
|
|
bool
|
|
|
|
ModifyBusyCount(JSContext* aCx, bool aIncrease);
|
|
|
|
|
|
|
|
bool
|
|
|
|
RootJSObject(JSContext* aCx, bool aRoot);
|
|
|
|
|
|
|
|
void
|
|
|
|
ForgetMainThreadObjects(nsTArray<nsCOMPtr<nsISupports> >& aDoomed);
|
|
|
|
|
|
|
|
bool
|
|
|
|
PostMessage(JSContext* aCx, jsval aMessage);
|
|
|
|
|
|
|
|
PRUint64
|
2011-08-24 13:44:35 -07:00
|
|
|
GetInnerWindowId();
|
2011-07-17 12:09:13 -07:00
|
|
|
|
|
|
|
void
|
|
|
|
UpdateJSContextOptions(JSContext* aCx, PRUint32 aOptions);
|
|
|
|
|
2012-01-04 11:11:32 -08:00
|
|
|
void
|
|
|
|
UpdateJSRuntimeHeapSize(JSContext* aCx, PRUint32 aJSRuntimeHeapSize);
|
|
|
|
|
2011-07-17 12:09:13 -07:00
|
|
|
#ifdef JS_GC_ZEAL
|
|
|
|
void
|
|
|
|
UpdateGCZeal(JSContext* aCx, PRUint8 aGCZeal);
|
|
|
|
#endif
|
|
|
|
|
2012-01-17 12:05:25 -08:00
|
|
|
void
|
|
|
|
GarbageCollect(JSContext* aCx, bool aShrinking);
|
|
|
|
|
2011-07-17 12:09:13 -07:00
|
|
|
void
|
|
|
|
QueueRunnable(WorkerRunnable* aRunnable)
|
|
|
|
{
|
|
|
|
AssertIsOnMainThread();
|
|
|
|
mQueuedRunnables.AppendElement(aRunnable);
|
|
|
|
}
|
|
|
|
|
|
|
|
WorkerPrivate*
|
|
|
|
GetParent() const
|
|
|
|
{
|
|
|
|
return mParent;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
IsSuspended() const
|
|
|
|
{
|
|
|
|
AssertIsOnParentThread();
|
|
|
|
return mParentSuspended;
|
|
|
|
}
|
|
|
|
|
2012-03-30 21:42:20 -07:00
|
|
|
bool
|
|
|
|
IsAcceptingEvents()
|
|
|
|
{
|
|
|
|
AssertIsOnParentThread();
|
|
|
|
bool acceptingEvents;
|
|
|
|
mMutex.Lock();
|
|
|
|
acceptingEvents = mParentStatus < Terminating;
|
|
|
|
mMutex.Unlock();
|
|
|
|
return acceptingEvents;
|
|
|
|
}
|
|
|
|
|
2011-07-17 12:09:13 -07:00
|
|
|
Status
|
|
|
|
ParentStatus() const
|
|
|
|
{
|
|
|
|
mMutex.AssertCurrentThreadOwns();
|
|
|
|
return mParentStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSContext*
|
|
|
|
ParentJSContext() const;
|
|
|
|
|
|
|
|
nsIScriptContext*
|
|
|
|
GetScriptContext() const
|
|
|
|
{
|
|
|
|
AssertIsOnMainThread();
|
|
|
|
return mScriptContext;
|
|
|
|
}
|
|
|
|
|
2012-05-04 00:22:18 -07:00
|
|
|
nsIXPCScriptNotify*
|
|
|
|
GetScriptNotify() const
|
|
|
|
{
|
|
|
|
AssertIsOnMainThread();
|
|
|
|
return mScriptNotify;
|
|
|
|
}
|
|
|
|
|
2011-07-17 12:09:13 -07:00
|
|
|
JSObject*
|
|
|
|
GetJSObject() const
|
|
|
|
{
|
|
|
|
return mJSObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
const nsString&
|
|
|
|
ScriptURL() const
|
|
|
|
{
|
|
|
|
return mScriptURL;
|
|
|
|
}
|
|
|
|
|
|
|
|
const nsCString&
|
|
|
|
Domain() const
|
|
|
|
{
|
|
|
|
return mDomain;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIURI*
|
|
|
|
GetBaseURI() const
|
|
|
|
{
|
|
|
|
AssertIsOnMainThread();
|
|
|
|
return mBaseURI;
|
|
|
|
}
|
|
|
|
|
2011-11-04 09:32:17 -07:00
|
|
|
void
|
2011-07-17 12:09:13 -07:00
|
|
|
SetBaseURI(nsIURI* aBaseURI);
|
|
|
|
|
|
|
|
nsIURI*
|
|
|
|
GetScriptURI() const
|
|
|
|
{
|
|
|
|
AssertIsOnMainThread();
|
|
|
|
return mScriptURI;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SetScriptURI(nsIURI* aScriptURI)
|
|
|
|
{
|
|
|
|
AssertIsOnMainThread();
|
|
|
|
mScriptURI = aScriptURI;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIPrincipal*
|
|
|
|
GetPrincipal() const
|
|
|
|
{
|
|
|
|
AssertIsOnMainThread();
|
|
|
|
return mPrincipal;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2011-08-15 20:40:38 -07:00
|
|
|
SetPrincipal(nsIPrincipal* aPrincipal);
|
|
|
|
|
|
|
|
bool
|
|
|
|
UsesSystemPrincipal() const
|
2011-07-17 12:09:13 -07:00
|
|
|
{
|
2011-08-15 20:40:38 -07:00
|
|
|
return mPrincipalIsSystem;
|
2011-07-17 12:09:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
nsIDocument*
|
|
|
|
GetDocument() const
|
|
|
|
{
|
|
|
|
AssertIsOnMainThread();
|
|
|
|
return mDocument;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SetDocument(nsIDocument* aDocument)
|
|
|
|
{
|
|
|
|
AssertIsOnMainThread();
|
|
|
|
mDocument = aDocument;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsPIDOMWindow*
|
|
|
|
GetWindow()
|
|
|
|
{
|
|
|
|
AssertIsOnMainThread();
|
|
|
|
return mWindow;
|
|
|
|
}
|
|
|
|
|
|
|
|
LocationInfo&
|
|
|
|
GetLocationInfo()
|
|
|
|
{
|
|
|
|
return mLocationInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRUint32
|
|
|
|
GetJSContextOptions() const
|
|
|
|
{
|
|
|
|
return mJSContextOptions;
|
|
|
|
}
|
|
|
|
|
2012-01-04 11:11:32 -08:00
|
|
|
PRUint32
|
|
|
|
GetJSRuntimeHeapSize() const
|
|
|
|
{
|
|
|
|
return mJSRuntimeHeapSize;
|
|
|
|
}
|
|
|
|
|
2011-07-17 12:09:13 -07:00
|
|
|
#ifdef JS_GC_ZEAL
|
|
|
|
PRUint8
|
|
|
|
GetGCZeal() const
|
|
|
|
{
|
|
|
|
return mGCZeal;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
bool
|
|
|
|
IsChromeWorker() const
|
|
|
|
{
|
|
|
|
return mIsChromeWorker;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
void
|
|
|
|
AssertIsOnParentThread() const;
|
|
|
|
|
|
|
|
void
|
|
|
|
AssertInnerWindowIsCorrect() const;
|
|
|
|
#else
|
|
|
|
void
|
|
|
|
AssertIsOnParentThread() const
|
|
|
|
{ }
|
|
|
|
|
|
|
|
void
|
|
|
|
AssertInnerWindowIsCorrect() const
|
|
|
|
{ }
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate>
|
|
|
|
{
|
|
|
|
friend class WorkerPrivateParent<WorkerPrivate>;
|
2012-05-29 19:39:38 -07:00
|
|
|
friend class WorkerMemoryReporter;
|
2011-07-17 12:09:13 -07:00
|
|
|
typedef WorkerPrivateParent<WorkerPrivate> ParentType;
|
|
|
|
|
|
|
|
struct TimeoutInfo;
|
|
|
|
|
2012-02-09 20:54:47 -08:00
|
|
|
typedef Queue<WorkerRunnable*, 50> EventQueue;
|
2011-07-17 12:09:13 -07:00
|
|
|
EventQueue mQueue;
|
|
|
|
EventQueue mControlQueue;
|
|
|
|
|
|
|
|
struct SyncQueue
|
|
|
|
{
|
2012-02-09 20:54:47 -08:00
|
|
|
Queue<WorkerRunnable*, 10> mQueue;
|
2011-07-17 12:09:13 -07:00
|
|
|
bool mComplete;
|
|
|
|
bool mResult;
|
|
|
|
|
|
|
|
SyncQueue()
|
|
|
|
: mComplete(false), mResult(false)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
~SyncQueue()
|
|
|
|
{
|
2012-02-09 20:54:47 -08:00
|
|
|
WorkerRunnable* event;
|
2011-07-17 12:09:13 -07:00
|
|
|
while (mQueue.Pop(event)) {
|
|
|
|
event->Release();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
nsTArray<nsAutoPtr<SyncQueue> > mSyncQueues;
|
|
|
|
|
|
|
|
// Touched on multiple threads, protected with mMutex.
|
|
|
|
JSContext* mJSContext;
|
2011-12-04 23:58:27 -08:00
|
|
|
nsRefPtr<WorkerCrossThreadDispatcher> mCrossThreadDispatcher;
|
2011-07-17 12:09:13 -07:00
|
|
|
|
|
|
|
// Things touched on worker thread only.
|
|
|
|
nsTArray<ParentType*> mChildWorkers;
|
|
|
|
nsTArray<WorkerFeature*> mFeatures;
|
|
|
|
nsTArray<nsAutoPtr<TimeoutInfo> > mTimeouts;
|
|
|
|
|
|
|
|
nsCOMPtr<nsITimer> mTimer;
|
2012-05-29 19:39:38 -07:00
|
|
|
nsRefPtr<WorkerMemoryReporter> mMemoryReporter;
|
2011-07-17 12:09:13 -07:00
|
|
|
|
|
|
|
mozilla::TimeStamp mKillTime;
|
|
|
|
PRUint32 mErrorHandlerRecursionCount;
|
|
|
|
PRUint32 mNextTimeoutId;
|
|
|
|
Status mStatus;
|
|
|
|
bool mSuspended;
|
|
|
|
bool mTimerRunning;
|
|
|
|
bool mRunningExpiredTimeouts;
|
|
|
|
bool mCloseHandlerStarted;
|
|
|
|
bool mCloseHandlerFinished;
|
2011-09-08 17:03:03 -07:00
|
|
|
bool mMemoryReporterRunning;
|
2011-07-17 12:09:13 -07:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
nsCOMPtr<nsIThread> mThread;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
public:
|
|
|
|
~WorkerPrivate();
|
|
|
|
|
2012-03-30 21:42:20 -07:00
|
|
|
static already_AddRefed<WorkerPrivate>
|
2011-07-17 12:09:13 -07:00
|
|
|
Create(JSContext* aCx, JSObject* aObj, WorkerPrivate* aParent,
|
|
|
|
JSString* aScriptURL, bool aIsChromeWorker);
|
|
|
|
|
|
|
|
void
|
|
|
|
DoRunLoop(JSContext* aCx);
|
|
|
|
|
|
|
|
bool
|
|
|
|
OperationCallback(JSContext* aCx);
|
|
|
|
|
|
|
|
bool
|
|
|
|
Dispatch(WorkerRunnable* aEvent)
|
|
|
|
{
|
|
|
|
return Dispatch(aEvent, &mQueue);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Dispatch(WorkerSyncRunnable* aEvent)
|
|
|
|
{
|
|
|
|
if (aEvent->mBypassSyncQueue) {
|
|
|
|
return Dispatch(aEvent, &mQueue);
|
|
|
|
}
|
|
|
|
|
|
|
|
return DispatchToSyncQueue(aEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Dispatch(WorkerControlRunnable* aEvent)
|
|
|
|
{
|
|
|
|
return Dispatch(aEvent, &mControlQueue);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
CloseInternal(JSContext* aCx)
|
|
|
|
{
|
|
|
|
AssertIsOnWorkerThread();
|
|
|
|
return NotifyInternal(aCx, Closing);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
SuspendInternal(JSContext* aCx);
|
|
|
|
|
|
|
|
bool
|
|
|
|
ResumeInternal(JSContext* aCx);
|
|
|
|
|
|
|
|
void
|
|
|
|
TraceInternal(JSTracer* aTrc);
|
|
|
|
|
|
|
|
bool
|
|
|
|
ModifyBusyCountFromWorker(JSContext* aCx, bool aIncrease);
|
|
|
|
|
|
|
|
bool
|
|
|
|
AddChildWorker(JSContext* aCx, ParentType* aChildWorker);
|
|
|
|
|
|
|
|
void
|
|
|
|
RemoveChildWorker(JSContext* aCx, ParentType* aChildWorker);
|
|
|
|
|
|
|
|
bool
|
|
|
|
AddFeature(JSContext* aCx, WorkerFeature* aFeature);
|
|
|
|
|
|
|
|
void
|
|
|
|
RemoveFeature(JSContext* aCx, WorkerFeature* aFeature);
|
|
|
|
|
|
|
|
void
|
|
|
|
NotifyFeatures(JSContext* aCx, Status aStatus);
|
|
|
|
|
|
|
|
bool
|
|
|
|
HasActiveFeatures()
|
|
|
|
{
|
|
|
|
return !(mChildWorkers.IsEmpty() && mTimeouts.IsEmpty() &&
|
|
|
|
mFeatures.IsEmpty());
|
|
|
|
}
|
|
|
|
|
|
|
|
PRUint32
|
|
|
|
CreateNewSyncLoop();
|
|
|
|
|
|
|
|
bool
|
|
|
|
RunSyncLoop(JSContext* aCx, PRUint32 aSyncLoopKey);
|
|
|
|
|
|
|
|
void
|
|
|
|
StopSyncLoop(PRUint32 aSyncLoopKey, bool aSyncResult);
|
|
|
|
|
|
|
|
bool
|
|
|
|
PostMessageToParent(JSContext* aCx, jsval aMessage);
|
|
|
|
|
|
|
|
bool
|
|
|
|
NotifyInternal(JSContext* aCx, Status aStatus);
|
|
|
|
|
|
|
|
void
|
|
|
|
ReportError(JSContext* aCx, const char* aMessage, JSErrorReport* aReport);
|
|
|
|
|
|
|
|
bool
|
2012-02-28 15:11:11 -08:00
|
|
|
SetTimeout(JSContext* aCx, unsigned aArgc, jsval* aVp, bool aIsInterval);
|
2011-07-17 12:09:13 -07:00
|
|
|
|
|
|
|
bool
|
|
|
|
ClearTimeout(JSContext* aCx, uint32 aId);
|
|
|
|
|
|
|
|
bool
|
|
|
|
RunExpiredTimeouts(JSContext* aCx);
|
|
|
|
|
|
|
|
bool
|
|
|
|
RescheduleTimeoutTimer(JSContext* aCx);
|
|
|
|
|
|
|
|
void
|
|
|
|
CloseHandlerStarted()
|
|
|
|
{
|
|
|
|
AssertIsOnWorkerThread();
|
|
|
|
mCloseHandlerStarted = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CloseHandlerFinished()
|
|
|
|
{
|
|
|
|
AssertIsOnWorkerThread();
|
|
|
|
mCloseHandlerFinished = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
UpdateJSContextOptionsInternal(JSContext* aCx, PRUint32 aOptions);
|
|
|
|
|
2012-01-04 11:11:32 -08:00
|
|
|
void
|
|
|
|
UpdateJSRuntimeHeapSizeInternal(JSContext* aCx, PRUint32 aJSRuntimeHeapSize);
|
|
|
|
|
2011-07-17 12:09:13 -07:00
|
|
|
void
|
|
|
|
ScheduleDeletion(bool aWasPending);
|
|
|
|
|
2011-08-06 18:03:46 -07:00
|
|
|
bool
|
2012-05-29 19:39:38 -07:00
|
|
|
BlockAndCollectRuntimeStats(bool isQuick, void* aData);
|
2011-09-08 17:03:03 -07:00
|
|
|
|
|
|
|
bool
|
|
|
|
DisableMemoryReporter();
|
2011-08-06 18:03:46 -07:00
|
|
|
|
2011-07-17 12:09:13 -07:00
|
|
|
#ifdef JS_GC_ZEAL
|
|
|
|
void
|
|
|
|
UpdateGCZealInternal(JSContext* aCx, PRUint8 aGCZeal);
|
|
|
|
#endif
|
|
|
|
|
2012-01-17 12:05:25 -08:00
|
|
|
void
|
|
|
|
GarbageCollectInternal(JSContext* aCx, bool aShrinking,
|
|
|
|
bool aCollectChildren);
|
|
|
|
|
2011-07-17 12:09:13 -07:00
|
|
|
JSContext*
|
|
|
|
GetJSContext() const
|
|
|
|
{
|
|
|
|
AssertIsOnWorkerThread();
|
|
|
|
return mJSContext;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
void
|
|
|
|
AssertIsOnWorkerThread() const;
|
|
|
|
|
|
|
|
void
|
|
|
|
SetThread(nsIThread* aThread)
|
|
|
|
{
|
|
|
|
mThread = aThread;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void
|
|
|
|
AssertIsOnWorkerThread() const
|
|
|
|
{ }
|
|
|
|
#endif
|
|
|
|
|
2011-12-04 23:58:27 -08:00
|
|
|
WorkerCrossThreadDispatcher*
|
|
|
|
GetCrossThreadDispatcher();
|
|
|
|
|
2011-07-17 12:09:13 -07:00
|
|
|
private:
|
|
|
|
WorkerPrivate(JSContext* aCx, JSObject* aObject, WorkerPrivate* aParent,
|
|
|
|
JSContext* aParentJSContext, const nsAString& aScriptURL,
|
|
|
|
bool aIsChromeWorker, const nsACString& aDomain,
|
|
|
|
nsCOMPtr<nsPIDOMWindow>& aWindow,
|
|
|
|
nsCOMPtr<nsIScriptContext>& aScriptContext,
|
|
|
|
nsCOMPtr<nsIURI>& aBaseURI, nsCOMPtr<nsIPrincipal>& aPrincipal,
|
|
|
|
nsCOMPtr<nsIDocument>& aDocument);
|
|
|
|
|
|
|
|
bool
|
|
|
|
Dispatch(WorkerRunnable* aEvent, EventQueue* aQueue);
|
|
|
|
|
|
|
|
bool
|
|
|
|
DispatchToSyncQueue(WorkerSyncRunnable* aEvent);
|
|
|
|
|
|
|
|
void
|
|
|
|
ClearQueue(EventQueue* aQueue);
|
|
|
|
|
|
|
|
bool
|
|
|
|
MayContinueRunning()
|
|
|
|
{
|
|
|
|
AssertIsOnWorkerThread();
|
|
|
|
|
|
|
|
Status status;
|
|
|
|
{
|
|
|
|
mozilla::MutexAutoLock lock(mMutex);
|
|
|
|
status = mStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status >= Killing) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (status >= Running) {
|
|
|
|
return mKillTime.IsNull() || RemainingRunTimeMS() > 0;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRUint32
|
|
|
|
RemainingRunTimeMS() const;
|
|
|
|
|
|
|
|
void
|
|
|
|
CancelAllTimeouts(JSContext* aCx);
|
|
|
|
|
|
|
|
bool
|
|
|
|
ScheduleKillCloseEventRunnable(JSContext* aCx);
|
|
|
|
|
|
|
|
void
|
|
|
|
StopAcceptingEvents()
|
|
|
|
{
|
|
|
|
AssertIsOnWorkerThread();
|
|
|
|
|
|
|
|
mozilla::MutexAutoLock lock(mMutex);
|
|
|
|
|
|
|
|
mStatus = Dead;
|
2012-07-30 07:20:58 -07:00
|
|
|
mJSContext = nullptr;
|
2011-07-17 12:09:13 -07:00
|
|
|
|
|
|
|
ClearQueue(&mControlQueue);
|
2012-02-09 20:54:47 -08:00
|
|
|
ClearQueue(&mQueue);
|
2011-07-17 12:09:13 -07:00
|
|
|
}
|
2011-09-08 17:03:03 -07:00
|
|
|
|
|
|
|
bool
|
|
|
|
ProcessAllControlRunnables();
|
2011-07-17 12:09:13 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
WorkerPrivate*
|
|
|
|
GetWorkerPrivateFromContext(JSContext* aCx);
|
|
|
|
|
2011-08-15 20:40:38 -07:00
|
|
|
enum WorkerStructuredDataType
|
|
|
|
{
|
2012-04-24 03:58:07 -07:00
|
|
|
DOMWORKER_SCTAG_FILE = SCTAG_DOM_MAX,
|
2011-08-15 20:40:38 -07:00
|
|
|
DOMWORKER_SCTAG_BLOB,
|
|
|
|
|
|
|
|
DOMWORKER_SCTAG_END
|
|
|
|
};
|
|
|
|
|
2011-07-17 12:09:13 -07:00
|
|
|
JSStructuredCloneCallbacks*
|
2011-08-15 20:40:38 -07:00
|
|
|
WorkerStructuredCloneCallbacks(bool aMainRuntime);
|
2011-07-17 12:09:13 -07:00
|
|
|
|
|
|
|
JSStructuredCloneCallbacks*
|
2011-08-15 20:40:38 -07:00
|
|
|
ChromeWorkerStructuredCloneCallbacks(bool aMainRuntime);
|
2011-07-17 12:09:13 -07:00
|
|
|
|
|
|
|
END_WORKERS_NAMESPACE
|
|
|
|
|
|
|
|
#endif /* mozilla_dom_workers_workerprivate_h__ */
|