Bug 1366089 Make EventTargetFor() support worker threads. r=baku

This commit is contained in:
Ben Kelly 2017-06-29 11:28:56 -07:00
Родитель f660d24cb3
Коммит 227c73cd89
3 изменённых файлов: 96 добавлений и 13 удалений

Просмотреть файл

@ -2067,7 +2067,7 @@ public:
{
MutexAutoLock lock(mMutex);
MOZ_ASSERT(mWorkerPrivate);
// Note, Disable() can be called more than once safely.
mWorkerPrivate = nullptr;
mNestedEventTarget.swap(nestedEventTarget);
}
@ -2981,22 +2981,34 @@ WorkerPrivateParent<Derived>::GetEventTarget()
nsCOMPtr<nsISerialEventTarget> target;
bool needAutoDisable = false;
{
MutexAutoLock lock(mMutex);
if (!mEventTarget &&
ParentStatus() <= Running &&
self->mStatus <= Running) {
if (!mEventTarget) {
mEventTarget = new EventTarget(self);
// If the worker is already shutting down then we want to
// immediately disable the event target. This will cause
// the Dispatch() method to fail, but the event target
// will still exist.
if (self->mStatus > Running) {
needAutoDisable = true;
}
}
target = mEventTarget;
}
NS_WARNING_ASSERTION(
target,
"Requested event target for a worker that is already shutting down!");
// Make sure to call Disable() outside of the mutex since it
// also internally locks a mutex.
if (needAutoDisable) {
mEventTarget->Disable();
}
MOZ_DIAGNOSTIC_ASSERT(target);
return target.forget();
}
@ -6134,7 +6146,6 @@ WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus)
MutexAutoLock lock(mMutex);
if (mStatus >= aStatus) {
MOZ_ASSERT(!mEventTarget);
return true;
}
@ -6147,18 +6158,16 @@ WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus)
Close();
}
mEventTarget.swap(eventTarget);
eventTarget = mEventTarget;
}
// Now that mStatus > Running, no-one can create a new WorkerEventTarget or
// WorkerCrossThreadDispatcher if we don't already have one.
// Disable the event target, if it exists.
if (eventTarget) {
// Since we'll no longer process events, make sure we no longer allow anyone
// to post them. We have to do this without mMutex held, since our mutex
// must be acquired *after* the WorkerEventTarget's mutex when they're both
// held.
eventTarget->Disable();
eventTarget = nullptr;
}
if (mCrossThreadDispatcher) {

Просмотреть файл

@ -72,10 +72,14 @@ using mozilla::dom::cache::CacheStorage;
using mozilla::ipc::PrincipalInfo;
WorkerGlobalScope::WorkerGlobalScope(WorkerPrivate* aWorkerPrivate)
: mWindowInteractionsAllowed(0)
: mSerialEventTarget(aWorkerPrivate->GetEventTarget())
, mWindowInteractionsAllowed(0)
, mWorkerPrivate(aWorkerPrivate)
{
mWorkerPrivate->AssertIsOnWorkerThread();
// We should always have an event target when the global is created.
MOZ_DIAGNOSTIC_ASSERT(mSerialEventTarget);
}
WorkerGlobalScope::~WorkerGlobalScope()
@ -489,6 +493,26 @@ WorkerGlobalScope::CreateImageBitmap(JSContext* aCx,
}
}
nsresult
WorkerGlobalScope::Dispatch(const char* aName, TaskCategory aCategory,
already_AddRefed<nsIRunnable>&& aRunnable)
{
return EventTargetFor(aCategory)->Dispatch(Move(aRunnable),
NS_DISPATCH_NORMAL);
}
nsISerialEventTarget*
WorkerGlobalScope::EventTargetFor(TaskCategory aCategory) const
{
return mSerialEventTarget;
}
AbstractThread*
WorkerGlobalScope::AbstractMainThreadFor(TaskCategory aCategory)
{
MOZ_CRASH("AbstractMainThreadFor not supported for workers.");
}
DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate,
const nsString& aName)
: WorkerGlobalScope(aWorkerPrivate)
@ -836,8 +860,12 @@ ServiceWorkerGlobalScope::OpenWindowEnabled(JSContext* aCx, JSObject* aObj)
WorkerDebuggerGlobalScope::WorkerDebuggerGlobalScope(
WorkerPrivate* aWorkerPrivate)
: mWorkerPrivate(aWorkerPrivate)
, mSerialEventTarget(aWorkerPrivate->GetEventTarget())
{
mWorkerPrivate->AssertIsOnWorkerThread();
// We should always have an event target when the global is created.
MOZ_DIAGNOSTIC_ASSERT(mSerialEventTarget);
}
WorkerDebuggerGlobalScope::~WorkerDebuggerGlobalScope()
@ -1051,6 +1079,26 @@ WorkerDebuggerGlobalScope::Dump(JSContext* aCx,
}
}
nsresult
WorkerDebuggerGlobalScope::Dispatch(const char* aName, TaskCategory aCategory,
already_AddRefed<nsIRunnable>&& aRunnable)
{
return EventTargetFor(aCategory)->Dispatch(Move(aRunnable),
NS_DISPATCH_NORMAL);
}
nsISerialEventTarget*
WorkerDebuggerGlobalScope::EventTargetFor(TaskCategory aCategory) const
{
return mSerialEventTarget;
}
AbstractThread*
WorkerDebuggerGlobalScope::AbstractMainThreadFor(TaskCategory aCategory)
{
MOZ_CRASH("AbstractMainThreadFor not supported for workers.");
}
BEGIN_WORKERS_NAMESPACE
bool

Просмотреть файл

@ -58,6 +58,7 @@ class WorkerGlobalScope : public DOMEventTargetHelper,
RefPtr<Performance> mPerformance;
RefPtr<IDBFactory> mIndexedDB;
RefPtr<cache::CacheStorage> mCacheStorage;
nsCOMPtr<nsISerialEventTarget> mSerialEventTarget;
uint32_t mWindowInteractionsAllowed;
@ -203,6 +204,18 @@ public:
MOZ_ASSERT(mWindowInteractionsAllowed > 0);
mWindowInteractionsAllowed--;
}
// Override DispatchTrait API to target the worker thread. Dispatch may
// return failure if the worker thread is not alive.
nsresult
Dispatch(const char* aName, TaskCategory aCategory,
already_AddRefed<nsIRunnable>&& aRunnable) override;
nsISerialEventTarget*
EventTargetFor(TaskCategory aCategory) const override;
AbstractThread*
AbstractMainThreadFor(TaskCategory aCategory) override;
};
class DedicatedWorkerGlobalScope final : public WorkerGlobalScope
@ -328,6 +341,7 @@ class WorkerDebuggerGlobalScope final : public DOMEventTargetHelper,
WorkerPrivate* mWorkerPrivate;
RefPtr<Console> mConsole;
nsCOMPtr<nsISerialEventTarget> mSerialEventTarget;
public:
explicit WorkerDebuggerGlobalScope(WorkerPrivate* aWorkerPrivate);
@ -404,6 +418,18 @@ public:
void
Dump(JSContext* aCx, const Optional<nsAString>& aString) const;
// Override DispatchTrait API to target the worker thread. Dispatch may
// return failure if the worker thread is not alive.
nsresult
Dispatch(const char* aName, TaskCategory aCategory,
already_AddRefed<nsIRunnable>&& aRunnable) override;
nsISerialEventTarget*
EventTargetFor(TaskCategory aCategory) const override;
AbstractThread*
AbstractMainThreadFor(TaskCategory aCategory) override;
private:
virtual ~WorkerDebuggerGlobalScope();
};