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 |