Chromium Code Reviews| 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 942252a3719501f572f82c0a445b0ba11acca366..bbe326e2ace2958b2333984b3ebc2818fc2d5c80 100644 |
| --- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.cpp |
| +++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.cpp |
| @@ -4,22 +4,180 @@ |
| #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 |
|
nhiroki
2017/06/07 14:43:52
We could factor out this class to share this with
|
| + : 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_); } |
| + |
| + private: |
| + RefPtr<WebTaskRunner> outside_settings_task_runner_; |
| + Member<WorkletPendingTasks> pending_tasks_; |
| + AudioWorkletMessagingProxy* proxy_; |
| +}; |
| + |
| AudioWorkletMessagingProxy::AudioWorkletMessagingProxy( |
| ExecutionContext* execution_context, |
| WorkerClients* worker_clients) |
| - : ThreadedWorkletMessagingProxy(execution_context, worker_clients) {} |
| + : ThreadedMessagingProxyBase(execution_context, worker_clients), |
| + weak_ptr_factory_(this) { |
| + worklet_object_proxy_ = AudioWorkletObjectProxy::Create( |
| + weak_ptr_factory_.CreateWeakPtr(), GetParentFrameTaskRunners()); |
| +} |
| AudioWorkletMessagingProxy::~AudioWorkletMessagingProxy() {} |
| +void AudioWorkletMessagingProxy::Initialize() { |
| + DCHECK(IsParentContextThread()); |
| + if (AskedToTerminate()) |
| + return; |
| + |
| + Document* document = ToDocument(GetExecutionContext()); |
| + SecurityOrigin* starter_origin = document->GetSecurityOrigin(); |
| + KURL script_url = document->Url(); |
| + |
| + ContentSecurityPolicy* csp = document->GetContentSecurityPolicy(); |
| + DCHECK(csp); |
| + |
| + 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)); |
| + GetWorkerInspectorProxy()->WorkerThreadCreated(document, GetWorkerThread(), |
|
nhiroki
2017/06/07 14:43:52
By the recent change, WorkerInspectorProxy::Worker
|
| + script_url); |
| +} |
| + |
| +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::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::kUnthrottled, 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) { |
| return AudioWorkletThread::Create(GetThreadableLoadingContext(), |
| WorkletObjectProxy()); |
| } |
| +WebThreadSupportingGC* AudioWorkletMessagingProxy::GetRenderingThread() { |
| + return &(GetWorkerThread()->GetWorkerBackingThread().BackingThread()); |
| +}; |
| + |
| } // namespace blink |