| Index: third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.cpp
|
| diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.cpp
|
| index b21ac7a467953cb7aa26ab4728aaecea4559e277..8fe3f152db5f8bab7f5a23723745bb46fb0c7c9d 100644
|
| --- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.cpp
|
| +++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.cpp
|
| @@ -4,17 +4,178 @@
|
|
|
| #include "modules/webaudio/AudioWorkletMessagingProxy.h"
|
|
|
| -#include "core/workers/ThreadedWorkletObjectProxy.h"
|
| +#include "bindings/core/v8/ScriptSourceCode.h"
|
| +#include "core/dom/Document.h"
|
| +#include "core/dom/SecurityContext.h"
|
| +#include "core/dom/TaskRunnerHelper.h"
|
| +#include "core/frame/csp/ContentSecurityPolicy.h"
|
| +#include "core/loader/WorkletScriptLoader.h"
|
| +#include "core/origin_trials/OriginTrialContext.h"
|
| +#include "core/workers/WorkerInspectorProxy.h"
|
| +#include "core/workers/WorkerThreadStartupData.h"
|
| +#include "core/workers/WorkletGlobalScope.h"
|
| +#include "core/workers/WorkletPendingTasks.h"
|
| +#include "modules/webaudio/AudioWorkletNode.h"
|
| +#include "modules/webaudio/AudioWorkletObjectProxy.h"
|
| #include "modules/webaudio/AudioWorkletThread.h"
|
| +#include "platform/CrossThreadFunctional.h"
|
| +#include "platform/WaitableEvent.h"
|
| +#include "platform/WebTaskRunner.h"
|
|
|
| namespace blink {
|
|
|
| +class AudioWorkletMessagingProxy::LoaderClient final
|
| + : public GarbageCollectedFinalized<
|
| + AudioWorkletMessagingProxy::LoaderClient>,
|
| + public WorkletScriptLoader::Client {
|
| + USING_GARBAGE_COLLECTED_MIXIN(LoaderClient);
|
| +
|
| + public:
|
| + LoaderClient(RefPtr<WebTaskRunner> outside_settings_task_runner,
|
| + WorkletPendingTasks* pending_tasks,
|
| + AudioWorkletMessagingProxy* proxy)
|
| + : outside_settings_task_runner_(std::move(outside_settings_task_runner)),
|
| + pending_tasks_(pending_tasks),
|
| + proxy_(proxy) {}
|
| +
|
| + // Implementation of the second half of the "fetch and invoke a worklet
|
| + // script" algorithm:
|
| + // https://drafts.css-houdini.org/worklets/#fetch-and-invoke-a-worklet-script
|
| + void NotifyWorkletScriptLoadingFinished(
|
| + WorkletScriptLoader* loader,
|
| + const ScriptSourceCode& source_code) final {
|
| + DCHECK(IsMainThread());
|
| + proxy_->NotifyLoadingFinished(loader);
|
| +
|
| + if (!loader->WasScriptLoadSuccessful()) {
|
| + // Step 3: "If script is null, then queue a task on outsideSettings's
|
| + // responsible event loop to run these steps:"
|
| + // The steps are implemented in WorkletPendingTasks::Abort().
|
| + outside_settings_task_runner_->PostTask(
|
| + BLINK_FROM_HERE, WTF::Bind(&WorkletPendingTasks::Abort,
|
| + WrapPersistent(pending_tasks_.Get())));
|
| + return;
|
| + }
|
| +
|
| + // Step 4: "Run a module script given script."
|
| + proxy_->EvaluateScript(source_code);
|
| +
|
| + // Step 5: "Queue a task on outsideSettings's responsible event loop to run
|
| + // these steps:"
|
| + // The steps are implemented in WorkletPendingTasks::DecrementCounter().
|
| + outside_settings_task_runner_->PostTask(
|
| + BLINK_FROM_HERE, WTF::Bind(&WorkletPendingTasks::DecrementCounter,
|
| + WrapPersistent(pending_tasks_.Get())));
|
| + }
|
| +
|
| + DEFINE_INLINE_TRACE() {
|
| + visitor->Trace(pending_tasks_);
|
| + visitor->Trace(proxy_);
|
| + }
|
| +
|
| + private:
|
| + RefPtr<WebTaskRunner> outside_settings_task_runner_;
|
| + Member<WorkletPendingTasks> pending_tasks_;
|
| + Member<AudioWorkletMessagingProxy> proxy_;
|
| +};
|
| +
|
| AudioWorkletMessagingProxy::AudioWorkletMessagingProxy(
|
| ExecutionContext* execution_context,
|
| WorkerClients* worker_clients)
|
| - : ThreadedWorkletMessagingProxy(execution_context, worker_clients) {}
|
| + : ThreadedMessagingProxyBase(execution_context, worker_clients) {
|
| + worklet_object_proxy_ =
|
| + AudioWorkletObjectProxy::Create(this, GetParentFrameTaskRunners());
|
| +}
|
| +
|
| +void AudioWorkletMessagingProxy::Initialize() {
|
| + DCHECK(IsMainThread());
|
| + if (AskedToTerminate())
|
| + return;
|
| +
|
| + Document* document = ToDocument(GetExecutionContext());
|
| + SecurityOrigin* starter_origin = document->GetSecurityOrigin();
|
| + KURL script_url = document->Url();
|
| +
|
| + ContentSecurityPolicy* csp = document->GetContentSecurityPolicy();
|
| + DCHECK(csp);
|
|
|
| -AudioWorkletMessagingProxy::~AudioWorkletMessagingProxy() {}
|
| + WorkerThreadStartMode start_mode =
|
| + GetWorkerInspectorProxy()->WorkerStartMode(document);
|
| + std::unique_ptr<WorkerSettings> worker_settings =
|
| + WTF::WrapUnique(new WorkerSettings(document->GetSettings()));
|
| +
|
| + // TODO(ikilpatrick): Decide on sensible a value for referrerPolicy.
|
| + std::unique_ptr<WorkerThreadStartupData> startup_data =
|
| + WorkerThreadStartupData::Create(
|
| + script_url, document->UserAgent(), String(), nullptr, start_mode,
|
| + csp->Headers().get(), /* referrerPolicy */ String(), starter_origin,
|
| + ReleaseWorkerClients(), document->AddressSpace(),
|
| + OriginTrialContext::GetTokens(document).get(),
|
| + std::move(worker_settings), WorkerV8Settings::Default());
|
| + InitializeWorkerThread(std::move(startup_data), script_url);
|
| +}
|
| +
|
| +DEFINE_TRACE(AudioWorkletMessagingProxy) {
|
| + visitor->Trace(loaders_);
|
| + ThreadedMessagingProxyBase::Trace(visitor);
|
| +}
|
| +
|
| +void AudioWorkletMessagingProxy::FetchAndInvokeScript(
|
| + const KURL& module_url_record,
|
| + WebURLRequest::FetchCredentialsMode credentials_mode,
|
| + RefPtr<WebTaskRunner> outside_settings_task_runner,
|
| + WorkletPendingTasks* pending_tasks) {
|
| + DCHECK(IsMainThread());
|
| + LoaderClient* client = new LoaderClient(
|
| + std::move(outside_settings_task_runner), pending_tasks, this);
|
| + WorkletScriptLoader* loader = WorkletScriptLoader::Create(
|
| + ToDocument(GetExecutionContext())->Fetcher(), client);
|
| + loaders_.insert(loader);
|
| + loader->FetchScript(module_url_record);
|
| +}
|
| +
|
| +void AudioWorkletMessagingProxy::WorkletObjectDestroyed() {
|
| + DCHECK(IsMainThread());
|
| + ParentObjectDestroyed();
|
| +}
|
| +
|
| +void AudioWorkletMessagingProxy::TerminateWorkletGlobalScope() {
|
| + DCHECK(IsMainThread());
|
| + for (const auto& loader : loaders_)
|
| + loader->Cancel();
|
| + loaders_.clear();
|
| + TerminateGlobalScope();
|
| +}
|
| +
|
| +void AudioWorkletMessagingProxy::NotifyLoadingFinished(
|
| + WorkletScriptLoader* loader) {
|
| + loaders_.erase(loader);
|
| +}
|
| +
|
| +void AudioWorkletMessagingProxy::EvaluateScript(
|
| + const ScriptSourceCode& script_source_code) {
|
| + DCHECK(IsMainThread());
|
| + TaskRunnerHelper::Get(TaskType::kMiscPlatformAPI, GetWorkerThread())
|
| + ->PostTask(
|
| + BLINK_FROM_HERE,
|
| + CrossThreadBind(&AudioWorkletObjectProxy::EvaluateScript,
|
| + CrossThreadUnretained(worklet_object_proxy_.get()),
|
| + script_source_code.Source(), script_source_code.Url(),
|
| + CrossThreadUnretained(GetWorkerThread())));
|
| +}
|
| +
|
| +void AudioWorkletMessagingProxy::CreateProcessorInstance(
|
| + const String& name, AudioWorkletHandler* handler, WaitableEvent* done) {
|
| + TaskRunnerHelper::Get(TaskType::kUnthrottled, GetWorkerThread())
|
| + ->PostTask(
|
| + BLINK_FROM_HERE,
|
| + CrossThreadBind(&AudioWorkletObjectProxy::CreateProcessorInstance,
|
| + CrossThreadUnretained(worklet_object_proxy_.get()),
|
| + name,
|
| + CrossThreadUnretained(handler),
|
| + CrossThreadUnretained(done),
|
| + CrossThreadUnretained(GetWorkerThread())));
|
| +}
|
|
|
| std::unique_ptr<WorkerThread> AudioWorkletMessagingProxy::CreateWorkerThread(
|
| double origin_time) {
|
| @@ -22,4 +183,8 @@ std::unique_ptr<WorkerThread> AudioWorkletMessagingProxy::CreateWorkerThread(
|
| WorkletObjectProxy());
|
| }
|
|
|
| +WebThreadSupportingGC* AudioWorkletMessagingProxy::GetRenderingThread() {
|
| + return &(GetWorkerThread()->GetWorkerBackingThread().BackingThread());
|
| +};
|
| +
|
| } // namespace blink
|
|
|