Bug 1492014 introduce WorkletImpl as an object to identify a worklet from parent and execution threads r=baku

Depends on D6100

Differential Revision: https://phabricator.services.mozilla.com/D6101

--HG--
rename : dom/worklet/Worklet.cpp => dom/worklet/WorkletImpl.cpp
rename : dom/worklet/Worklet.h => dom/worklet/WorkletImpl.h
extra : moz-landing-system : lando
This commit is contained in:
Karl Tomlinson 2018-09-18 09:36:38 +00:00
Родитель b1571dd6e0
Коммит 89c6ae2a56
8 изменённых файлов: 271 добавлений и 176 удалений

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

@ -241,6 +241,7 @@
#include "mozilla/dom/U2F.h"
#include "mozilla/dom/WebIDLGlobalNameHash.h"
#include "mozilla/dom/Worklet.h"
#include "mozilla/dom/WorkletImpl.h"
#ifdef HAVE_SIDEBAR
#include "mozilla/dom/ExternalBinding.h"
#endif
@ -7819,7 +7820,8 @@ nsGlobalWindowInner::GetPaintWorklet(ErrorResult& aRv)
return nullptr;
}
mPaintWorklet = new Worklet(this, principal, Worklet::ePaintWorklet);
mPaintWorklet =
WorkletImpl::CreateWorklet(this, principal, WorkletImpl::ePaintWorklet);
}
return mPaintWorklet;

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

@ -40,6 +40,7 @@
#include "mozilla/dom/StereoPannerNodeBinding.h"
#include "mozilla/dom/WaveShaperNodeBinding.h"
#include "mozilla/dom/Worklet.h"
#include "mozilla/dom/WorkletImpl.h"
#include "AudioBuffer.h"
#include "AudioBufferSourceNode.h"
@ -603,7 +604,8 @@ AudioContext::GetAudioWorklet(ErrorResult& aRv)
return nullptr;
}
mWorklet = new Worklet(window, principal, Worklet::eAudioWorklet);
mWorklet =
WorkletImpl::CreateWorklet(window, principal, WorkletImpl::eAudioWorklet);
}
return mWorklet;

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

@ -6,16 +6,11 @@
#include "Worklet.h"
#include "WorkletThread.h"
#include "AudioWorkletGlobalScope.h"
#include "PaintWorkletGlobalScope.h"
#include "mozilla/dom/WorkletBinding.h"
#include "mozilla/dom/AudioWorkletBinding.h"
#include "mozilla/dom/BlobBinding.h"
#include "mozilla/dom/DOMPrefs.h"
#include "mozilla/dom/Fetch.h"
#include "mozilla/dom/PromiseNativeHandler.h"
#include "mozilla/dom/RegisterWorkletBindings.h"
#include "mozilla/dom/Response.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/ScriptLoader.h"
@ -32,13 +27,13 @@ namespace dom {
class ExecutionRunnable final : public Runnable
{
public:
ExecutionRunnable(WorkletFetchHandler* aHandler, Worklet::WorkletType aType,
ExecutionRunnable(WorkletFetchHandler* aHandler, WorkletImpl* aWorkletImpl,
JS::UniqueTwoByteChars aScriptBuffer, size_t aScriptLength)
: Runnable("Worklet::ExecutionRunnable")
, mHandler(aHandler)
, mWorkletImpl(aWorkletImpl)
, mScriptBuffer(std::move(aScriptBuffer))
, mScriptLength(aScriptLength)
, mWorkletType(aType)
, mResult(NS_ERROR_FAILURE)
{
MOZ_ASSERT(NS_IsMainThread());
@ -55,9 +50,9 @@ private:
RunOnMainThread();
RefPtr<WorkletFetchHandler> mHandler;
RefPtr<WorkletImpl> mWorkletImpl;
JS::UniqueTwoByteChars mScriptBuffer;
size_t mScriptLength;
Worklet::WorkletType mWorkletType;
nsresult mResult;
};
@ -228,10 +223,10 @@ public:
// Moving the ownership of the buffer
nsCOMPtr<nsIRunnable> runnable =
new ExecutionRunnable(this, mWorklet->Type(), std::move(scriptTextBuf),
new ExecutionRunnable(this, mWorklet->mImpl, std::move(scriptTextBuf),
scriptTextLength);
RefPtr<WorkletThread> thread = mWorklet->GetOrCreateThread();
RefPtr<WorkletThread> thread = mWorklet->mImpl->GetOrCreateThread();
if (!thread) {
RejectPromises(NS_ERROR_FAILURE);
return NS_OK;
@ -386,7 +381,7 @@ ExecutionRunnable::RunOnWorkletThread()
jsapi.Init();
RefPtr<WorkletGlobalScope> globalScope =
Worklet::CreateGlobalScope(jsapi.cx(), mWorkletType);
mWorkletImpl->CreateGlobalScope(jsapi.cx());
MOZ_ASSERT(globalScope);
AutoEntryScript aes(globalScope, "Worklet");
@ -432,29 +427,6 @@ ExecutionRunnable::RunOnMainThread()
mHandler->ExecutionSucceeded();
}
// ---------------------------------------------------------------------------
// WorkletLoadInfo
WorkletLoadInfo::WorkletLoadInfo(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal)
: mInnerWindowID(aWindow->WindowID())
, mDumpEnabled(DOMPrefs::DumpEnabled())
, mOriginAttributes(BasePrincipal::Cast(aPrincipal)->OriginAttributesRef())
, mPrincipal(aPrincipal)
{
MOZ_ASSERT(NS_IsMainThread());
nsPIDOMWindowOuter* outerWindow = aWindow->GetOuterWindow();
if (outerWindow) {
mOuterWindowID = outerWindow->WindowID();
} else {
mOuterWindowID = 0;
}
}
WorkletLoadInfo::~WorkletLoadInfo()
{
MOZ_ASSERT(NS_IsMainThread());
}
// ---------------------------------------------------------------------------
// Worklet
@ -462,7 +434,7 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(Worklet)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Worklet)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
tmp->TerminateThread();
tmp->mImpl->TerminateThread();
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@ -480,14 +452,12 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Worklet)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
Worklet::Worklet(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal,
WorkletType aWorkletType)
Worklet::Worklet(nsPIDOMWindowInner* aWindow, RefPtr<WorkletImpl> aImpl)
: mWindow(aWindow)
, mWorkletType(aWorkletType)
, mWorkletLoadInfo(aWindow, aPrincipal)
, mImpl(std::move(aImpl))
{
MOZ_ASSERT(aWindow);
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(mImpl);
MOZ_ASSERT(NS_IsMainThread());
#ifdef RELEASE_OR_BETA
@ -497,18 +467,13 @@ Worklet::Worklet(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal,
Worklet::~Worklet()
{
TerminateThread();
mImpl->TerminateThread();
}
JSObject*
Worklet::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
MOZ_ASSERT(NS_IsMainThread());
if (mWorkletType == eAudioWorklet) {
return AudioWorklet_Binding::Wrap(aCx, this, aGivenProto);
} else {
return Worklet_Binding::Wrap(aCx, this, aGivenProto);
}
return mImpl->WrapWorklet(aCx, this, aGivenProto);
}
already_AddRefed<Promise>
@ -521,37 +486,6 @@ Worklet::AddModule(const nsAString& aModuleURL,
return WorkletFetchHandler::Fetch(this, aModuleURL, aOptions, aCallerType, aRv);
}
/* static */ already_AddRefed<WorkletGlobalScope>
Worklet::CreateGlobalScope(JSContext* aCx, WorkletType aWorkletType)
{
WorkletThread::AssertIsOnWorkletThread();
RefPtr<WorkletGlobalScope> scope;
switch (aWorkletType) {
case eAudioWorklet:
scope = new AudioWorkletGlobalScope();
break;
case ePaintWorklet:
scope = new PaintWorkletGlobalScope();
break;
}
JS::Rooted<JSObject*> global(aCx);
NS_ENSURE_TRUE(scope->WrapGlobalObject(aCx, &global), nullptr);
JSAutoRealm ar(aCx, global);
// Init Web IDL bindings
if (!RegisterWorkletBindings(aCx, global)) {
return nullptr;
}
JS_FireOnNewGlobalObject(aCx, global);
return scope.forget();
}
WorkletFetchHandler*
Worklet::GetImportFetchHandler(const nsACString& aURI)
{
@ -570,31 +504,5 @@ Worklet::AddImportFetchHandler(const nsACString& aURI,
mImportHandlers.Put(aURI, aHandler);
}
WorkletThread*
Worklet::GetOrCreateThread()
{
MOZ_ASSERT(NS_IsMainThread());
if (!mWorkletThread) {
// Thread creation. FIXME: this will change.
mWorkletThread = WorkletThread::Create(mWorkletLoadInfo);
}
return mWorkletThread;
}
void
Worklet::TerminateThread()
{
MOZ_ASSERT(NS_IsMainThread());
if (!mWorkletThread) {
return;
}
mWorkletThread->Terminate();
mWorkletThread = nullptr;
mWorkletLoadInfo.mPrincipal = nullptr;
}
} // dom namespace
} // mozilla namespace

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

@ -8,58 +8,24 @@
#define mozilla_dom_Worklet_h
#include "mozilla/Attributes.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/ErrorResult.h"
#include "nsRefPtrHashtable.h"
#include "nsWrapperCache.h"
#include "nsCOMPtr.h"
class nsPIDOMWindowInner;
class nsIPrincipal;
namespace mozilla {
class WorkletImpl;
namespace dom {
class Promise;
class Worklet;
class WorkletFetchHandler;
class WorkletGlobalScope;
struct WorkletOptions;
class WorkletThread;
enum class CallerType : uint32_t;
class WorkletLoadInfo
{
public:
WorkletLoadInfo(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal);
~WorkletLoadInfo();
uint64_t OuterWindowID() const { return mOuterWindowID; }
uint64_t InnerWindowID() const { return mInnerWindowID; }
bool DumpEnabled() const { return mDumpEnabled; }
const OriginAttributes& OriginAttributesRef() const
{
return mOriginAttributes;
}
nsIPrincipal* Principal() const
{
MOZ_ASSERT(NS_IsMainThread());
return mPrincipal;
}
private:
uint64_t mOuterWindowID;
uint64_t mInnerWindowID;
bool mDumpEnabled;
OriginAttributes mOriginAttributes;
nsCOMPtr<nsIPrincipal> mPrincipal;
friend class Worklet;
friend class WorkletThread;
};
class Worklet final : public nsISupports
, public nsWrapperCache
{
@ -67,13 +33,7 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Worklet)
enum WorkletType {
eAudioWorklet,
ePaintWorklet,
};
Worklet(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal,
WorkletType aWorkletType);
Worklet(nsPIDOMWindowInner* aWindow, RefPtr<WorkletImpl> aImpl);
nsPIDOMWindowInner* GetParentObject() const
{
@ -88,23 +48,6 @@ public:
const WorkletOptions& aOptions,
CallerType aCallerType, ErrorResult& aRv);
WorkletType Type() const
{
return mWorkletType;
}
static already_AddRefed<WorkletGlobalScope>
CreateGlobalScope(JSContext* aCx, WorkletType aWorkletType);
WorkletThread*
GetOrCreateThread();
const WorkletLoadInfo&
LoadInfo() const
{
return mWorkletLoadInfo;
}
private:
~Worklet();
@ -114,18 +57,11 @@ private:
void
AddImportFetchHandler(const nsACString& aURI, WorkletFetchHandler* aHandler);
void
TerminateThread();
nsCOMPtr<nsPIDOMWindowInner> mWindow;
WorkletType mWorkletType;
nsRefPtrHashtable<nsCStringHashKey, WorkletFetchHandler> mImportHandlers;
RefPtr<WorkletThread> mWorkletThread;
WorkletLoadInfo mWorkletLoadInfo;
const RefPtr<WorkletImpl> mImpl;
friend class WorkletFetchHandler;
};

138
dom/worklet/WorkletImpl.cpp Normal file
Просмотреть файл

@ -0,0 +1,138 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 https://mozilla.org/MPL/2.0/. */
#include "WorkletImpl.h"
#include "AudioWorkletGlobalScope.h"
#include "PaintWorkletGlobalScope.h"
#include "Worklet.h"
#include "WorkletThread.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/dom/AudioWorkletBinding.h"
#include "mozilla/dom/DOMPrefs.h"
#include "mozilla/dom/RegisterWorkletBindings.h"
#include "mozilla/dom/WorkletBinding.h"
namespace mozilla {
// ---------------------------------------------------------------------------
// WorkletLoadInfo
WorkletLoadInfo::WorkletLoadInfo(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal)
: mInnerWindowID(aWindow->WindowID())
, mDumpEnabled(dom::DOMPrefs::DumpEnabled())
, mOriginAttributes(BasePrincipal::Cast(aPrincipal)->OriginAttributesRef())
, mPrincipal(aPrincipal)
{
MOZ_ASSERT(NS_IsMainThread());
nsPIDOMWindowOuter* outerWindow = aWindow->GetOuterWindow();
if (outerWindow) {
mOuterWindowID = outerWindow->WindowID();
} else {
mOuterWindowID = 0;
}
}
WorkletLoadInfo::~WorkletLoadInfo()
{
MOZ_ASSERT(NS_IsMainThread());
}
// ---------------------------------------------------------------------------
// WorkletImpl
/* static */ already_AddRefed<dom::Worklet>
WorkletImpl::CreateWorklet(nsPIDOMWindowInner* aWindow,
nsIPrincipal* aPrincipal,
WorkletType aWorkletType)
{
MOZ_ASSERT(NS_IsMainThread());
RefPtr<WorkletImpl> impl = new WorkletImpl(aWindow, aPrincipal, aWorkletType);
return MakeAndAddRef<dom::Worklet>(aWindow, std::move(impl));
}
WorkletImpl::WorkletImpl(nsPIDOMWindowInner* aWindow,
nsIPrincipal* aPrincipal,
WorkletType aWorkletType)
: mWorkletLoadInfo(aWindow, aPrincipal)
, mWorkletType(aWorkletType)
{
}
WorkletImpl::~WorkletImpl() = default;
JSObject*
WorkletImpl::WrapWorklet(JSContext* aCx, dom::Worklet* aWorklet,
JS::Handle<JSObject*> aGivenProto)
{
MOZ_ASSERT(NS_IsMainThread());
if (mWorkletType == eAudioWorklet) {
return dom::AudioWorklet_Binding::Wrap(aCx, aWorklet, aGivenProto);
} else {
return dom::Worklet_Binding::Wrap(aCx, aWorklet, aGivenProto);
}
}
already_AddRefed<dom::WorkletGlobalScope>
WorkletImpl::CreateGlobalScope(JSContext* aCx)
{
dom::WorkletThread::AssertIsOnWorkletThread();
RefPtr<dom::WorkletGlobalScope> scope;
switch (mWorkletType) {
case eAudioWorklet:
scope = new dom::AudioWorkletGlobalScope();
break;
case ePaintWorklet:
scope = new dom::PaintWorkletGlobalScope();
break;
}
JS::Rooted<JSObject*> global(aCx);
NS_ENSURE_TRUE(scope->WrapGlobalObject(aCx, &global), nullptr);
JSAutoRealm ar(aCx, global);
// Init Web IDL bindings
if (!dom::RegisterWorkletBindings(aCx, global)) {
return nullptr;
}
JS_FireOnNewGlobalObject(aCx, global);
return scope.forget();
}
dom::WorkletThread*
WorkletImpl::GetOrCreateThread()
{
MOZ_ASSERT(NS_IsMainThread());
if (!mWorkletThread) {
// Thread creation. FIXME: this will change.
mWorkletThread = dom::WorkletThread::Create(mWorkletLoadInfo);
}
return mWorkletThread;
}
void
WorkletImpl::TerminateThread()
{
MOZ_ASSERT(NS_IsMainThread());
if (!mWorkletThread) {
return;
}
mWorkletThread->Terminate();
mWorkletThread = nullptr;
mWorkletLoadInfo.mPrincipal = nullptr;
}
} // namespace mozilla

107
dom/worklet/WorkletImpl.h Normal file
Просмотреть файл

@ -0,0 +1,107 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 https://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_worklet_WorkletImpl_h
#define mozilla_dom_worklet_WorkletImpl_h
#include "MainThreadUtils.h"
#include "mozilla/OriginAttributes.h"
class nsPIDOMWindowInner;
class nsIPrincipal;
namespace mozilla {
namespace dom {
class Worklet;
class WorkletGlobalScope;
class WorkletThread;
} // namespace dom
class WorkletLoadInfo
{
public:
WorkletLoadInfo(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal);
~WorkletLoadInfo();
uint64_t OuterWindowID() const { return mOuterWindowID; }
uint64_t InnerWindowID() const { return mInnerWindowID; }
bool DumpEnabled() const { return mDumpEnabled; }
const OriginAttributes& OriginAttributesRef() const
{
return mOriginAttributes;
}
nsIPrincipal* Principal() const
{
MOZ_ASSERT(NS_IsMainThread());
return mPrincipal;
}
private:
uint64_t mOuterWindowID;
uint64_t mInnerWindowID;
bool mDumpEnabled;
OriginAttributes mOriginAttributes;
nsCOMPtr<nsIPrincipal> mPrincipal;
friend class WorkletImpl;
friend class WorkletThread;
};
/**
* WorkletImpl is accessed from both the worklet's parent thread (on which the
* Worklet object lives) and the worklet's execution thread. It is owned by
* Worklet. No parent thread cycle collected objects are owned indefinitely
* by WorkletImpl because WorkletImpl is not cycle collected.
*/
class WorkletImpl
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WorkletImpl);
enum WorkletType {
eAudioWorklet,
ePaintWorklet,
};
// Methods for parent thread only:
static already_AddRefed<dom::Worklet>
CreateWorklet(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal,
WorkletType aWorkletType);
JSObject*
WrapWorklet(JSContext* aCx, dom::Worklet* aWorklet,
JS::Handle<JSObject*> aGivenProto);
dom::WorkletThread* GetOrCreateThread();
void TerminateThread();
// Execution thread only.
already_AddRefed<dom::WorkletGlobalScope> CreateGlobalScope(JSContext* aCx);
// Any thread.
const WorkletLoadInfo& LoadInfo() const { return mWorkletLoadInfo; }
private:
WorkletImpl(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal,
WorkletType aWorkletType);
~WorkletImpl();
WorkletLoadInfo mWorkletLoadInfo;
const WorkletType mWorkletType;
// Parent thread only.
RefPtr<dom::WorkletThread> mWorkletThread;
};
} // namespace mozilla
#endif // mozilla_dom_worklet_WorkletImpl_h

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

@ -9,7 +9,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/CondVar.h"
#include "mozilla/dom/Worklet.h"
#include "mozilla/dom/WorkletImpl.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/TimeStamp.h"

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

@ -12,6 +12,7 @@ EXPORTS.mozilla.dom += [
'PaintWorkletGlobalScope.h',
'Worklet.h',
'WorkletGlobalScope.h',
'WorkletImpl.h',
'WorkletPrincipal.h',
'WorkletThread.h',
]
@ -21,6 +22,7 @@ UNIFIED_SOURCES += [
'PaintWorkletGlobalScope.cpp',
'Worklet.cpp',
'WorkletGlobalScope.cpp',
'WorkletImpl.cpp',
'WorkletPrincipal.cpp',
'WorkletThread.cpp',
]