Commit 3e01be57 authored by Hiroki Nakagawa's avatar Hiroki Nakagawa Committed by Commit Bot

Worker: Make worklets' module loading classes reusable for workers

As a preparation for module loading support for workers, this CL does mainly 2
things:

- This renames WorkletModuleScriptFetcher to WorkerOrWorkletModuleScriptFetcher,
  and WorkletModuleResponsesMapProxy to
  WorkerOrWorkletModuleFetchCoordinatorProxy. This enables workers can reuse
  worklets' module loading classes.

- This introduces WorkerOrWorkletModuleFetchCoordinator interface.
  Implementation of the interface is expected to fetch module scripts via
  DocumentModuleScriptFetcher, to manage inflight requests, and to notify
  completions of the requests to WorkerOrWorkletModuleScriptFetcher on the
  worker thread. For worklets, WorkletModuleResponsesMap inherits the interface.
  For workers, following CLs introduce a new class,
  WorkerModuleFetchCoordinator, because WorkletModuleResponsesMap have custom
  fetch logic for caching and it's not reusable for workers.

See the design doc for details:
https://docs.google.com/document/d/1IMGWAK7Wq37mLehwkbysNRBBnhQBo3z2MbYyMkViEnY/edit#heading=h.637avx8i5qtn

Bug: 680046
Change-Id: Iba7916bb9b5aefbc8c695ff9865bcbe756801412
Reviewed-on: https://chromium-review.googlesource.com/958801Reviewed-by: default avatarKouhei Ueno <kouhei@chromium.org>
Reviewed-by: default avatarMatt Falkenhagen <falken@chromium.org>
Commit-Queue: Hiroki Nakagawa <nhiroki@chromium.org>
Cr-Commit-Position: refs/heads/master@{#543026}
parent 883ad990
......@@ -96,8 +96,8 @@ blink_core_sources("loader") {
"modulescript/ModuleTreeLinker.h",
"modulescript/ModuleTreeLinkerRegistry.cpp",
"modulescript/ModuleTreeLinkerRegistry.h",
"modulescript/WorkletModuleScriptFetcher.cpp",
"modulescript/WorkletModuleScriptFetcher.h",
"modulescript/WorkerOrWorkletModuleScriptFetcher.cpp",
"modulescript/WorkerOrWorkletModuleScriptFetcher.h",
"private/FrameClientHintsPreferencesContext.cpp",
"private/FrameClientHintsPreferencesContext.h",
"private/PrerenderHandle.cpp",
......
......@@ -10,7 +10,6 @@
#include "core/loader/modulescript/ModuleScriptFetcher.h"
#include "core/loader/modulescript/ModuleScriptLoaderClient.h"
#include "core/loader/modulescript/ModuleScriptLoaderRegistry.h"
#include "core/loader/modulescript/WorkletModuleScriptFetcher.h"
#include "core/script/Modulator.h"
#include "core/script/ModuleScript.h"
#include "core/workers/MainThreadWorkletGlobalScope.h"
......
......@@ -11,7 +11,7 @@
#include "core/loader/modulescript/ModuleScriptFetchRequest.h"
#include "core/loader/modulescript/ModuleScriptLoaderClient.h"
#include "core/loader/modulescript/ModuleScriptLoaderRegistry.h"
#include "core/loader/modulescript/WorkletModuleScriptFetcher.h"
#include "core/loader/modulescript/WorkerOrWorkletModuleScriptFetcher.h"
#include "core/origin_trials/OriginTrialContext.h"
#include "core/script/Modulator.h"
#include "core/script/ModuleScript.h"
......@@ -20,6 +20,7 @@
#include "core/workers/GlobalScopeCreationParams.h"
#include "core/workers/MainThreadWorkletGlobalScope.h"
#include "core/workers/MainThreadWorkletReportingProxy.h"
#include "core/workers/WorkletModuleResponsesMap.h"
#include "platform/heap/Handle.h"
#include "platform/loader/fetch/ResourceFetcher.h"
#include "platform/loader/testing/FetchTestingPlatformSupport.h"
......@@ -109,8 +110,8 @@ class ModuleScriptLoaderTestModulator final : public DummyModulator {
if (execution_context->IsDocument())
return new DocumentModuleScriptFetcher(Fetcher());
auto* global_scope = ToWorkletGlobalScope(execution_context);
return new WorkletModuleScriptFetcher(
global_scope->ModuleResponsesMapProxy());
return new WorkerOrWorkletModuleScriptFetcher(
global_scope->ModuleFetchCoordinatorProxy());
}
ResourceFetcher* Fetcher() const { return fetcher_.Get(); }
......@@ -186,8 +187,8 @@ void ModuleScriptLoaderTest::InitializeForWorklet() {
modulator_ = new ModuleScriptLoaderTestModulator(
global_scope_->ScriptController()->GetScriptState(),
GetDocument().GetSecurityOrigin());
global_scope_->SetModuleResponsesMapProxyForTesting(
WorkletModuleResponsesMapProxy::Create(
global_scope_->SetModuleFetchCoordinatorProxyForTesting(
WorkerOrWorkletModuleFetchCoordinatorProxy::Create(
new WorkletModuleResponsesMap(modulator_->Fetcher()),
GetDocument().GetTaskRunner(TaskType::kInternalTest),
global_scope_->GetTaskRunner(TaskType::kInternalTest)));
......@@ -350,8 +351,8 @@ TEST_F(ModuleScriptLoaderTest, FetchURL_OnWorklet) {
EXPECT_FALSE(client->WasNotifyFinished())
<< "ModuleScriptLoader unexpectedly finished synchronously.";
// Advance until WorkletModuleScriptFetcher finishes looking up a cache in
// WorkletModuleResponsesMap and issues a fetch request so that
// Advance until WorkerOrWorkletModuleScriptFetcher finishes looking up a
// cache in WorkletModuleResponsesMap and issues a fetch request so that
// ServeAsynchronousRequests() can serve for the pending request.
platform_->RunUntilIdle();
platform_->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
......
......@@ -2,41 +2,42 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "core/loader/modulescript/WorkletModuleScriptFetcher.h"
#include "core/loader/modulescript/WorkerOrWorkletModuleScriptFetcher.h"
#include "platform/CrossThreadFunctional.h"
namespace blink {
WorkletModuleScriptFetcher::WorkletModuleScriptFetcher(
WorkletModuleResponsesMapProxy* module_responses_map_proxy)
: module_responses_map_proxy_(module_responses_map_proxy) {
DCHECK(module_responses_map_proxy_);
WorkerOrWorkletModuleScriptFetcher::WorkerOrWorkletModuleScriptFetcher(
WorkerOrWorkletModuleFetchCoordinatorProxy* coordinator_proxy)
: coordinator_proxy_(coordinator_proxy) {
DCHECK(coordinator_proxy_);
}
void WorkletModuleScriptFetcher::Trace(blink::Visitor* visitor) {
visitor->Trace(module_responses_map_proxy_);
void WorkerOrWorkletModuleScriptFetcher::Trace(blink::Visitor* visitor) {
visitor->Trace(coordinator_proxy_);
ModuleScriptFetcher::Trace(visitor);
}
void WorkletModuleScriptFetcher::Fetch(FetchParameters& fetch_params,
void WorkerOrWorkletModuleScriptFetcher::Fetch(
FetchParameters& fetch_params,
ModuleScriptFetcher::Client* client) {
SetClient(client);
module_responses_map_proxy_->ReadEntry(fetch_params, this);
coordinator_proxy_->Fetch(fetch_params, this);
}
void WorkletModuleScriptFetcher::OnRead(
void WorkerOrWorkletModuleScriptFetcher::OnFetched(
const ModuleScriptCreationParams& params) {
HeapVector<Member<ConsoleMessage>> error_messages;
Finalize(params, error_messages);
}
void WorkletModuleScriptFetcher::OnFailed() {
void WorkerOrWorkletModuleScriptFetcher::OnFailed() {
HeapVector<Member<ConsoleMessage>> error_messages;
Finalize(WTF::nullopt, error_messages);
}
void WorkletModuleScriptFetcher::Finalize(
void WorkerOrWorkletModuleScriptFetcher::Finalize(
const WTF::Optional<ModuleScriptCreationParams>& params,
const HeapVector<Member<ConsoleMessage>>& error_messages) {
NotifyFetchFinished(params, error_messages);
......
......@@ -2,37 +2,33 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef WorkletModuleScriptFetcher_h
#define WorkletModuleScriptFetcher_h
#ifndef WorkerOrWorkletModuleScriptFetcher_h
#define WorkerOrWorkletModuleScriptFetcher_h
#include "core/loader/modulescript/ModuleScriptFetcher.h"
#include "core/workers/WorkletModuleResponsesMap.h"
#include "core/workers/WorkletModuleResponsesMapProxy.h"
#include "core/workers/WorkerOrWorkletModuleFetchCoordinator.h"
#include "core/workers/WorkerOrWorkletModuleFetchCoordinatorProxy.h"
#include "platform/wtf/Optional.h"
namespace blink {
// WorkletModuleScriptFetcher implements the custom fetch logic for worklet's
// module loading defined in:
// https://drafts.css-houdini.org/worklets/#fetch-a-worklet-script
//
// WorkletModuleScriptFetcher does not initiate module fetch by itself. This
// asks WorkletModuleResponsesMap on the main thread via
// WorkletModuleResponsesMapProxy to read a cached module script or to fetch it
// via network. See comments on WorkletModuleResponsesMap for details.
class CORE_EXPORT WorkletModuleScriptFetcher final
// WorkerOrWorkletModuleScriptFetcher does not initiate module fetch by itself.
// Instead, this delegates it to WorkerOrWorkletModuleFetchCoordinator on the
// main thread via WorkerOrWorkletModuleFetchCoordinatorProxy.
class CORE_EXPORT WorkerOrWorkletModuleScriptFetcher final
: public ModuleScriptFetcher,
public WorkletModuleResponsesMap::Client {
USING_GARBAGE_COLLECTED_MIXIN(WorkletModuleScriptFetcher);
public WorkerOrWorkletModuleFetchCoordinator::Client {
USING_GARBAGE_COLLECTED_MIXIN(WorkerOrWorkletModuleScriptFetcher);
public:
explicit WorkletModuleScriptFetcher(WorkletModuleResponsesMapProxy*);
explicit WorkerOrWorkletModuleScriptFetcher(
WorkerOrWorkletModuleFetchCoordinatorProxy*);
// Implements ModuleScriptFetcher.
void Fetch(FetchParameters&, ModuleScriptFetcher::Client*) override;
// Implements WorkletModuleResponsesMap::Client.
void OnRead(const ModuleScriptCreationParams&) override;
// Implements WorkerOrWorkletModuleFetchCoordinator::Client.
void OnFetched(const ModuleScriptCreationParams&) override;
void OnFailed() override;
void Trace(blink::Visitor*) override;
......@@ -41,9 +37,9 @@ class CORE_EXPORT WorkletModuleScriptFetcher final
void Finalize(const WTF::Optional<ModuleScriptCreationParams>&,
const HeapVector<Member<ConsoleMessage>>& error_messages);
Member<WorkletModuleResponsesMapProxy> module_responses_map_proxy_;
Member<WorkerOrWorkletModuleFetchCoordinatorProxy> coordinator_proxy_;
};
} // namespace blink
#endif // WorkletModuleScriptFetcher_h
#endif // WorkerOrWorkletModuleScriptFetcher_h
......@@ -5,7 +5,7 @@
#include "core/script/WorkletModulatorImpl.h"
#include "bindings/core/v8/ScriptPromiseResolver.h"
#include "core/loader/modulescript/WorkletModuleScriptFetcher.h"
#include "core/loader/modulescript/WorkerOrWorkletModuleScriptFetcher.h"
#include "core/workers/WorkletGlobalScope.h"
#include "platform/bindings/V8ThrowException.h"
......@@ -26,8 +26,8 @@ const SecurityOrigin* WorkletModulatorImpl::GetSecurityOriginForFetch() {
ModuleScriptFetcher* WorkletModulatorImpl::CreateModuleScriptFetcher() {
auto global_scope = ToWorkletGlobalScope(GetExecutionContext());
return new WorkletModuleScriptFetcher(
global_scope->ModuleResponsesMapProxy());
return new WorkerOrWorkletModuleScriptFetcher(
global_scope->ModuleFetchCoordinatorProxy());
}
void WorkletModulatorImpl::ResolveDynamically(const String&,
......
......@@ -69,6 +69,9 @@ blink_core_sources("workers") {
"WorkerNavigator.h",
"WorkerOrWorkletGlobalScope.cpp",
"WorkerOrWorkletGlobalScope.h",
"WorkerOrWorkletModuleFetchCoordinator.h",
"WorkerOrWorkletModuleFetchCoordinatorProxy.cpp",
"WorkerOrWorkletModuleFetchCoordinatorProxy.h",
"WorkerReportingProxy.h",
"WorkerScriptLoader.cpp",
"WorkerScriptLoader.h",
......@@ -87,8 +90,6 @@ blink_core_sources("workers") {
"WorkletGlobalScopeProxy.h",
"WorkletModuleResponsesMap.cpp",
"WorkletModuleResponsesMap.h",
"WorkletModuleResponsesMapProxy.cpp",
"WorkletModuleResponsesMapProxy.h",
"WorkletModuleTreeClient.cpp",
"WorkletModuleTreeClient.h",
"WorkletPendingTasks.cpp",
......
......@@ -16,6 +16,7 @@
#include "core/workers/WorkerClients.h"
#include "core/workers/WorkerInspectorProxy.h"
#include "core/workers/WorkletGlobalScope.h"
#include "core/workers/WorkletModuleResponsesMap.h"
#include "core/workers/WorkletPendingTasks.h"
#include "platform/CrossThreadFunctional.h"
#include "platform/WebTaskRunner.h"
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef WorkerOrWorkletModuleFetchCoordinator_h
#define WorkerOrWorkletModuleFetchCoordinator_h
#include "core/CoreExport.h"
#include "core/loader/modulescript/ModuleScriptCreationParams.h"
#include "platform/loader/fetch/FetchParameters.h"
namespace blink {
// Subclasses are expected to fetch module scripts via
// DocumentModuleScriptFetcher on the main thread, to manage inflight requests,
// and to notify completions of the requests to
// WorkerOrWorkletModuleScriptFetcher on the worker or worklet context thread.
class WorkerOrWorkletModuleFetchCoordinator : public GarbageCollectedMixin {
public:
// Used for notifying results of Fetch().
class CORE_EXPORT Client : public GarbageCollectedMixin {
public:
virtual ~Client() = default;
virtual void OnFetched(const ModuleScriptCreationParams&) = 0;
virtual void OnFailed() = 0;
};
virtual ~WorkerOrWorkletModuleFetchCoordinator() = default;
virtual void Fetch(FetchParameters&, Client*) = 0;
};
} // namespace blink
#endif // WorkerOrWorkletModuleFetchCoordinator_h
......@@ -2,41 +2,44 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "core/workers/WorkletModuleResponsesMapProxy.h"
#include "core/workers/WorkerOrWorkletModuleFetchCoordinatorProxy.h"
#include "core/loader/modulescript/ModuleScriptCreationParams.h"
#include "platform/CrossThreadFunctional.h"
#include "platform/WebTaskRunner.h"
namespace blink {
namespace {
// ClientAdapter mediates WorkletModuleResponsesMap on the main thread and
// WorkletModuleResponsesMap::Client implementation on the worklet context
// thread as follows.
// ClientAdapter mediates WorkerOrWorkletModuleFetchCoordinator on the main
// thread and WorkerOrWorkletModuleFetchCoordinator::Client implementation on
// the worker or worklet context thread as follows.
//
// MapProxy (worklet thread) --> Map (main thread)
// Map::Client (worklet thread) <-- ClientAdapter (main thread)
// CoordinatorProxy (context thread) --> Coordinator (main thread)
// Coordinator::Client (context thread) <-- ClientAdapter (main thread)
//
// This lives on the main thread.
class ClientAdapter final : public GarbageCollectedFinalized<ClientAdapter>,
public WorkletModuleResponsesMap::Client {
class ClientAdapter final
: public GarbageCollectedFinalized<ClientAdapter>,
public WorkerOrWorkletModuleFetchCoordinator::Client {
USING_GARBAGE_COLLECTED_MIXIN(ClientAdapter);
public:
static ClientAdapter* Create(
WorkletModuleResponsesMap::Client* client,
WorkerOrWorkletModuleFetchCoordinator::Client* client,
scoped_refptr<base::SingleThreadTaskRunner> inside_settings_task_runner) {
return new ClientAdapter(client, std::move(inside_settings_task_runner));
}
~ClientAdapter() override = default;
void OnRead(const ModuleScriptCreationParams& params) override {
void OnFetched(const ModuleScriptCreationParams& params) override {
DCHECK(IsMainThread());
PostCrossThreadTask(
*inside_settings_task_runner_, FROM_HERE,
CrossThreadBind(&WorkletModuleResponsesMap::Client::OnRead, client_,
CrossThreadBind(
&WorkerOrWorkletModuleFetchCoordinator::Client::OnFetched, client_,
params));
}
......@@ -44,67 +47,73 @@ class ClientAdapter final : public GarbageCollectedFinalized<ClientAdapter>,
DCHECK(IsMainThread());
PostCrossThreadTask(
*inside_settings_task_runner_, FROM_HERE,
CrossThreadBind(&WorkletModuleResponsesMap::Client::OnFailed, client_));
CrossThreadBind(
&WorkerOrWorkletModuleFetchCoordinator::Client::OnFailed, client_));
}
void Trace(blink::Visitor* visitor) override {}
private:
ClientAdapter(
WorkletModuleResponsesMap::Client* client,
WorkerOrWorkletModuleFetchCoordinator::Client* client,
scoped_refptr<base::SingleThreadTaskRunner> inside_settings_task_runner)
: client_(client),
inside_settings_task_runner_(std::move(inside_settings_task_runner)) {}
CrossThreadPersistent<WorkletModuleResponsesMap::Client> client_;
CrossThreadPersistent<WorkerOrWorkletModuleFetchCoordinator::Client> client_;
scoped_refptr<base::SingleThreadTaskRunner> inside_settings_task_runner_;
};
} // namespace
WorkletModuleResponsesMapProxy* WorkletModuleResponsesMapProxy::Create(
WorkletModuleResponsesMap* module_responses_map,
WorkerOrWorkletModuleFetchCoordinatorProxy*
WorkerOrWorkletModuleFetchCoordinatorProxy::Create(
WorkerOrWorkletModuleFetchCoordinator* coordinator,
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> inside_settings_task_runner) {
return new WorkletModuleResponsesMapProxy(
module_responses_map, std::move(outside_settings_task_runner),
return new WorkerOrWorkletModuleFetchCoordinatorProxy(
coordinator, std::move(outside_settings_task_runner),
std::move(inside_settings_task_runner));
}
void WorkletModuleResponsesMapProxy::ReadEntry(
void WorkerOrWorkletModuleFetchCoordinatorProxy::Fetch(
const FetchParameters& fetch_params,
Client* client) {
DCHECK(inside_settings_task_runner_->RunsTasksInCurrentSequence());
PostCrossThreadTask(
*outside_settings_task_runner_, FROM_HERE,
CrossThreadBind(&WorkletModuleResponsesMapProxy::ReadEntryOnMainThread,
CrossThreadBind(
&WorkerOrWorkletModuleFetchCoordinatorProxy::FetchOnMainThread,
WrapCrossThreadPersistent(this), fetch_params,
WrapCrossThreadPersistent(client)));
}
void WorkletModuleResponsesMapProxy::Trace(blink::Visitor* visitor) {}
void WorkerOrWorkletModuleFetchCoordinatorProxy::Trace(
blink::Visitor* visitor) {}
WorkletModuleResponsesMapProxy::WorkletModuleResponsesMapProxy(
WorkletModuleResponsesMap* module_responses_map,
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
WorkerOrWorkletModuleFetchCoordinatorProxy::
WorkerOrWorkletModuleFetchCoordinatorProxy(
WorkerOrWorkletModuleFetchCoordinator* coordinator,
scoped_refptr<base::SingleThreadTaskRunner>
outside_settings_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> inside_settings_task_runner)
: module_responses_map_(module_responses_map),
: coordinator_(coordinator),
outside_settings_task_runner_(outside_settings_task_runner),
inside_settings_task_runner_(inside_settings_task_runner) {
DCHECK(module_responses_map_);
DCHECK(coordinator_);
DCHECK(outside_settings_task_runner_);
DCHECK(inside_settings_task_runner_);
DCHECK(inside_settings_task_runner_->RunsTasksInCurrentSequence());
}
void WorkletModuleResponsesMapProxy::ReadEntryOnMainThread(
void WorkerOrWorkletModuleFetchCoordinatorProxy::FetchOnMainThread(
std::unique_ptr<CrossThreadFetchParametersData> cross_thread_fetch_params,
Client* client) {
DCHECK(IsMainThread());
FetchParameters fetch_params(std::move(cross_thread_fetch_params));
ClientAdapter* wrapper =
ClientAdapter::Create(client, inside_settings_task_runner_);
module_responses_map_->ReadEntry(fetch_params, wrapper);
coordinator_->Fetch(fetch_params, wrapper);
}
} // namespace blink
......@@ -2,49 +2,50 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef WorkletModuleResponsesMapProxy_h
#define WorkletModuleResponsesMapProxy_h
#ifndef WorkerOrWorkletModuleFetchCoordinatorProxy_h
#define WorkerOrWorkletModuleFetchCoordinatorProxy_h
#include "base/single_thread_task_runner.h"
#include "core/CoreExport.h"
#include "core/workers/WorkletModuleResponsesMap.h"
#include "core/workers/WorkerOrWorkletModuleFetchCoordinator.h"
#include "platform/heap/Heap.h"
namespace blink {
// WorkletModuleResponsesMapProxy serves as a proxy to talk to
// WorkletModuleResponsesMap on the main thread (outside_settings) from
// WorkletGlobalScope on the worklet context thread (inside_settings). The
// constructor and all public functions must be called on the worklet context
// thread.
class CORE_EXPORT WorkletModuleResponsesMapProxy
: public GarbageCollectedFinalized<WorkletModuleResponsesMapProxy> {
// WorkerOrWorkletModuleFetchCoordinatorProxy serves as a proxy to talk to
// an implementation of WorkerOrWorkletModuleFetchCoordinator on the main thread
// (outside_settings) from the worker or worklet context thread
// (inside_settings). The constructor and all public functions must be called on
// the context thread.
class CORE_EXPORT WorkerOrWorkletModuleFetchCoordinatorProxy
: public GarbageCollectedFinalized<
WorkerOrWorkletModuleFetchCoordinatorProxy> {
public:
using Client = WorkletModuleResponsesMap::Client;
using Client = WorkerOrWorkletModuleFetchCoordinator::Client;
static WorkletModuleResponsesMapProxy* Create(
WorkletModuleResponsesMap*,
static WorkerOrWorkletModuleFetchCoordinatorProxy* Create(
WorkerOrWorkletModuleFetchCoordinator*,
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> inside_settings_task_runner);
void ReadEntry(const FetchParameters&, Client*);
void Fetch(const FetchParameters&, Client*);
void Trace(blink::Visitor*);
private:
WorkletModuleResponsesMapProxy(
WorkletModuleResponsesMap*,
WorkerOrWorkletModuleFetchCoordinatorProxy(
WorkerOrWorkletModuleFetchCoordinator*,
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> inside_settings_task_runner);
void ReadEntryOnMainThread(std::unique_ptr<CrossThreadFetchParametersData>,
void FetchOnMainThread(std::unique_ptr<CrossThreadFetchParametersData>,
Client*);
CrossThreadPersistent<WorkletModuleResponsesMap> module_responses_map_;
CrossThreadPersistent<WorkerOrWorkletModuleFetchCoordinator> coordinator_;
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> inside_settings_task_runner_;
};
} // namespace blink
#endif // WorkletModuleResponsesMapProxy_h
#endif // WorkerOrWorkletModuleFetchCoordinatorProxy_h
......@@ -81,10 +81,11 @@ void WorkletGlobalScope::FetchAndInvokeScript(
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
WorkletPendingTasks* pending_tasks) {
DCHECK(IsContextThread());
if (!module_responses_map_proxy_) {
if (!fetch_coordinator_proxy_) {
// |kUnspecedLoading| is used here because this is a part of script module
// loading and this usage is not explicitly spec'ed.
module_responses_map_proxy_ = WorkletModuleResponsesMapProxy::Create(
fetch_coordinator_proxy_ =
WorkerOrWorkletModuleFetchCoordinatorProxy::Create(
module_responses_map, outside_settings_task_runner,
GetTaskRunner(TaskType::kUnspecedLoading));
}
......@@ -105,17 +106,17 @@ void WorkletGlobalScope::FetchAndInvokeScript(
FetchModuleScript(module_url_record, credentials_mode, client);
}
WorkletModuleResponsesMapProxy* WorkletGlobalScope::ModuleResponsesMapProxy()
const {
WorkerOrWorkletModuleFetchCoordinatorProxy*
WorkletGlobalScope::ModuleFetchCoordinatorProxy() const {
DCHECK(IsContextThread());
DCHECK(module_responses_map_proxy_);
return module_responses_map_proxy_;
DCHECK(fetch_coordinator_proxy_);
return fetch_coordinator_proxy_;
}
void WorkletGlobalScope::SetModuleResponsesMapProxyForTesting(
WorkletModuleResponsesMapProxy* proxy) {
DCHECK(!module_responses_map_proxy_);
module_responses_map_proxy_ = proxy;
void WorkletGlobalScope::SetModuleFetchCoordinatorProxyForTesting(
WorkerOrWorkletModuleFetchCoordinatorProxy* proxy) {
DCHECK(!fetch_coordinator_proxy_);
fetch_coordinator_proxy_ = proxy;
}
KURL WorkletGlobalScope::CompleteURL(const String& url) const {
......@@ -129,7 +130,7 @@ KURL WorkletGlobalScope::CompleteURL(const String& url) const {
}
void WorkletGlobalScope::Trace(blink::Visitor* visitor) {
visitor->Trace(module_responses_map_proxy_);
visitor->Trace(fetch_coordinator_proxy_);
WorkerOrWorkletGlobalScope::Trace(visitor);
}
......
......@@ -12,7 +12,7 @@
#include "core/dom/ExecutionContext.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/workers/WorkerOrWorkletGlobalScope.h"
#include "core/workers/WorkletModuleResponsesMapProxy.h"
#include "core/workers/WorkerOrWorkletModuleFetchCoordinatorProxy.h"
#include "platform/bindings/ScriptWrappable.h"
#include "platform/bindings/TraceWrapperMember.h"
#include "platform/heap/Handle.h"
......@@ -69,8 +69,10 @@ class CORE_EXPORT WorkletGlobalScope
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
WorkletPendingTasks*);
WorkletModuleResponsesMapProxy* ModuleResponsesMapProxy() const;
void SetModuleResponsesMapProxyForTesting(WorkletModuleResponsesMapProxy*);
WorkerOrWorkletModuleFetchCoordinatorProxy* ModuleFetchCoordinatorProxy()
const;
void SetModuleFetchCoordinatorProxyForTesting(
WorkerOrWorkletModuleFetchCoordinatorProxy*);
const SecurityOrigin* DocumentSecurityOrigin() const {
return document_security_origin_.get();
......@@ -110,7 +112,7 @@ class CORE_EXPORT WorkletGlobalScope
// Used for origin trials, inherited from the parent Document.
const bool document_secure_context_;
Member<WorkletModuleResponsesMapProxy> module_responses_map_proxy_;
Member<WorkerOrWorkletModuleFetchCoordinatorProxy> fetch_coordinator_proxy_;
};
DEFINE_TYPE_CASTS(WorkletGlobalScope,
......
......@@ -37,7 +37,7 @@ class WorkletModuleResponsesMap::Entry final
State GetState() const { return state_; }
const ModuleScriptCreationParams& GetParams() const { return *params_; }
void AddClient(WorkletModuleResponsesMap::Client* client) {
void AddClient(WorkerOrWorkletModuleFetchCoordinator::Client* client) {
// Clients can be added only while a module script is being fetched.
DCHECK(state_ == State::kInitial || state_ == State::kFetching);
clients_.push_back(client);
......@@ -68,15 +68,15 @@ class WorkletModuleResponsesMap::Entry final
// Step 8: "Set the value of the entry in cache whose key is url to
// response, and asynchronously complete this algorithm with response."
params_.emplace(*params);
for (WorkletModuleResponsesMap::Client* client : clients_)
client->OnRead(*params);
for (WorkerOrWorkletModuleFetchCoordinator::Client* client : clients_)
client->OnFetched(*params);
clients_.clear();
module_fetcher_.Clear();
}
void NotifyFailure() {
AdvanceState(State::kFailed);
for (WorkletModuleResponsesMap::Client* client : clients_)
for (WorkerOrWorkletModuleFetchCoordinator::Client* client : clients_)
client->OnFailed();
clients_.clear();
module_fetcher_.Clear();
......@@ -109,7 +109,7 @@ class WorkletModuleResponsesMap::Entry final
Member<DocumentModuleScriptFetcher> module_fetcher_;
WTF::Optional<ModuleScriptCreationParams> params_;
HeapVector<Member<WorkletModuleResponsesMap::Client>> clients_;
HeapVector<Member<WorkerOrWorkletModuleFetchCoordinator::Client>> clients_;
};
WorkletModuleResponsesMap::WorkletModuleResponsesMap(ResourceFetcher* fetcher)
......@@ -122,7 +122,7 @@ WorkletModuleResponsesMap::WorkletModuleResponsesMap(ResourceFetcher* fetcher)
// "To perform the fetch given request, perform the following steps:"
// Step 1: "Let cache be the moduleResponsesMap."
// Step 2: "Let url be request's url."
void WorkletModuleResponsesMap::ReadEntry(FetchParameters& fetch_params,
void WorkletModuleResponsesMap::Fetch(FetchParameters& fetch_params,
Client* client) {
DCHECK(IsMainThread());
if (!is_available_ || !IsValidURL(fetch_params.Url())) {
......@@ -147,7 +147,7 @@ void WorkletModuleResponsesMap::ReadEntry(FetchParameters& fetch_params,
// Step 4: "If cache contains an entry with key url, asynchronously
// complete this algorithm with that entry's value, and abort these
// steps."
client->OnRead(entry->GetParams());
client->OnFetched(entry->GetParams());
return;
case Entry::State::kFailed:
// Module fetching failed before. Abort following steps.
......@@ -169,7 +169,7 @@ void WorkletModuleResponsesMap::ReadEntry(FetchParameters& fetch_params,
entry->Fetch(fetch_params, fetcher_.Get());
}
void WorkletModuleResponsesMap::InvalidateEntry(const KURL& url) {
void WorkletModuleResponsesMap::Invalidate(const KURL& url) {
DCHECK(IsMainThread());
DCHECK(IsValidURL(url));
if (!is_available_)
......
......@@ -7,6 +7,7 @@
#include "core/CoreExport.h"
#include "core/loader/modulescript/ModuleScriptCreationParams.h"
#include "core/workers/WorkerOrWorkletModuleFetchCoordinator.h"
#include "platform/heap/Heap.h"
#include "platform/heap/HeapAllocator.h"
#include "platform/loader/fetch/FetchParameters.h"
......@@ -23,36 +24,33 @@ namespace blink {
//
// This acts as a cache for creation params (including source code) of module
// scripts, but also performs fetch when needed. The creation params are added
// and retrieved using ReadEntry(). If a module script for a given URL has
// already been fetched, ReadEntry() returns the cached creation params.
// Otherwise, ReadEntry() internally creates DocumentModuleScriptFetcher with
// thie ResourceFetcher that is given to its ctor. Once the module script is
// fetched, its creation params are cached and ReadEntry() returns it.
// and retrieved using Fetch(). If a module script for a given URL has already
// been fetched, Fetch() returns the cached creation params. Otherwise, Fetch()
// internally creates DocumentModuleScriptFetcher with thie ResourceFetcher that
// is given to its ctor. Once the module script is fetched, its creation params
// are cached and Fetch() returns it.
//
// TODO(nhiroki): Rename this to WorkletModuleFetchCoordinator, and revise the
// class-level comment.
class CORE_EXPORT WorkletModuleResponsesMap
: public GarbageCollectedFinalized<WorkletModuleResponsesMap> {
public:
// Used for notifying results of ReadEntry(). See comments on the function for
// details.
class CORE_EXPORT Client : public GarbageCollectedMixin {
public:
virtual ~Client() = default;
virtual void OnRead(const ModuleScriptCreationParams&) = 0;
virtual void OnFailed() = 0;
};
: public GarbageCollectedFinalized<WorkletModuleResponsesMap>,
public WorkerOrWorkletModuleFetchCoordinator {
USING_GARBAGE_COLLECTED_MIXIN(WorkletModuleResponsesMap);
public:
explicit WorkletModuleResponsesMap(ResourceFetcher*);
// Reads an entry for the given URL. If the entry is already fetched,
// synchronously calls Client::OnRead(). Otherwise, it's called on the
// completion of the fetch. See also the class-level comment.
void ReadEntry(FetchParameters&, Client*);
// Fetches a module script. If the script is already fetched, synchronously
// calls Client::OnFetched(). Otherwise, it's called on the completion of the
// fetch. See also the class-level comment.
void Fetch(FetchParameters&, Client*);
// Invalidates the entry and calls OnFailed() for waiting clients.
void InvalidateEntry(const KURL&);
// Invalidates an inflight module script fetch, and calls OnFailed() for
// waiting clients.
void Invalidate(const KURL&);
// Called when the associated document is destroyed. Aborts all waiting
// clients and clears the map. Following read and write requests to the map
// are simply ignored.
// clients and clears the map. Following Fetch() calls are simply ignored.
void Dispose();
void Trace(blink::Visitor*);
......
......@@ -21,13 +21,13 @@ namespace blink {
namespace {
class ClientImpl final : public GarbageCollectedFinalized<ClientImpl>,
public WorkletModuleResponsesMap::Client {
public WorkerOrWorkletModuleFetchCoordinator::Client {
USING_GARBAGE_COLLECTED_MIXIN(ClientImpl);
public:
enum class Result { kInitial, kOK, kFailed };
void OnRead(const ModuleScriptCreationParams& params) override {
void OnFetched(const ModuleScriptCreationParams& params) override {
ASSERT_EQ(Result::kInitial, result_);
result_ = Result::kOK;
params_.emplace(params);
......@@ -63,10 +63,10 @@ class WorkletModuleResponsesMapTest : public ::testing::Test {
map_ = new WorkletModuleResponsesMap(fetcher_);
}
void ReadEntry(const KURL& url, ClientImpl* client) {
void Fetch(const KURL& url, ClientImpl* client) {
ResourceRequest resource_request(url);
FetchParameters fetch_params(resource_request);
map_->ReadEntry(fetch_params, client);
map_->Fetch(fetch_params, client);
}
protected:
......@@ -84,18 +84,18 @@ TEST_F(WorkletModuleResponsesMapTest, Basic) {
// An initial read call initiates a fetch request.
clients.push_back(new ClientImpl);
ReadEntry(kUrl, clients[0]);
Fetch(kUrl, clients[0]);
EXPECT_EQ(ClientImpl::Result::kInitial, clients[0]->GetResult());
EXPECT_FALSE(clients[0]->GetParams().has_value());
// The entry is now being fetched. Following read calls should wait for the
// completion.
clients.push_back(new ClientImpl);
ReadEntry(kUrl, clients[1]);
Fetch(kUrl, clients[1]);
EXPECT_EQ(ClientImpl::Result::kInitial, clients[1]->GetResult());
clients.push_back(new ClientImpl);
ReadEntry(kUrl, clients[2]);
Fetch(kUrl, clients[2]);
EXPECT_EQ(ClientImpl::Result::kInitial, clients[2]->GetResult());
// Serve the fetch request. This should notify the waiting clients.
......@@ -113,18 +113,18 @@ TEST_F(WorkletModuleResponsesMapTest, Failure) {
// An initial read call initiates a fetch request.
clients.push_back(new ClientImpl);
ReadEntry(kUrl, clients[0]);
Fetch(kUrl, clients[0]);
EXPECT_EQ(ClientImpl::Result::kInitial, clients[0]->GetResult());
EXPECT_FALSE(clients[0]->GetParams().has_value());
// The entry is now being fetched. Following read calls should wait for the
// completion.
clients.push_back(new ClientImpl);
ReadEntry(kUrl, clients[1]);
Fetch(kUrl, clients[1]);
EXPECT_EQ(ClientImpl::Result::kInitial, clients[1]->GetResult());
clients.push_back(new ClientImpl);
ReadEntry(kUrl, clients[2]);
Fetch(kUrl, clients[2]);
EXPECT_EQ(ClientImpl::Result::kInitial, clients[2]->GetResult());
// Serve the fetch request with 404. This should fail the waiting clients.
......@@ -145,26 +145,26 @@ TEST_F(WorkletModuleResponsesMapTest, Isolation) {
// An initial read call for |kUrl1| initiates a fetch request.
clients.push_back(new ClientImpl);
ReadEntry(kUrl1, clients[0]);
Fetch(kUrl1, clients[0]);
EXPECT_EQ(ClientImpl::Result::kInitial, clients[0]->GetResult());
EXPECT_FALSE(clients[0]->GetParams().has_value());
// The entry is now being fetched. Following read calls for |kUrl1| should
// wait for the completion.
clients.push_back(new ClientImpl);
ReadEntry(kUrl1, clients[1]);
Fetch(kUrl1, clients[1]);
EXPECT_EQ(ClientImpl::Result::kInitial, clients[1]->GetResult());
// An initial read call for |kUrl2| initiates a fetch request.
clients.push_back(new ClientImpl);
ReadEntry(kUrl2, clients[2]);
Fetch(kUrl2, clients[2]);
EXPECT_EQ(ClientImpl::Result::kInitial, clients[2]->GetResult());
EXPECT_FALSE(clients[2]->GetParams().has_value());
// The entry is now being fetched. Following read calls for |kUrl2| should
// wait for the completion.
clients.push_back(new ClientImpl);
ReadEntry(kUrl2, clients[3]);
Fetch(kUrl2, clients[3]);
EXPECT_EQ(ClientImpl::Result::kInitial, clients[3]->GetResult());
// The read call for |kUrl2| should not affect the other entry for |kUrl1|.
......@@ -186,21 +186,21 @@ TEST_F(WorkletModuleResponsesMapTest, InvalidURL) {
const KURL kEmptyURL;
ASSERT_TRUE(kEmptyURL.IsEmpty());
ClientImpl* client1 = new ClientImpl;
ReadEntry(kEmptyURL, client1);
Fetch(kEmptyURL, client1);
EXPECT_EQ(ClientImpl::Result::kFailed, client1->GetResult());
EXPECT_FALSE(client1->GetParams().has_value());
const KURL kNullURL = NullURL();
ASSERT_TRUE(kNullURL.IsNull());
ClientImpl* client2 = new ClientImpl;
ReadEntry(kNullURL, client2);
Fetch(kNullURL, client2);
EXPECT_EQ(ClientImpl::Result::kFailed, client2->GetResult());
EXPECT_FALSE(client2->GetParams().has_value());
const KURL kInvalidURL;
ASSERT_FALSE(kInvalidURL.IsValid());
ClientImpl* client3 = new ClientImpl;
ReadEntry(kInvalidURL, client3);
Fetch(kInvalidURL, client3);
EXPECT_EQ(ClientImpl::Result::kFailed, client3->GetResult());
EXPECT_FALSE(client3->GetParams().has_value());
}
......@@ -217,27 +217,27 @@ TEST_F(WorkletModuleResponsesMapTest, Dispose) {
// An initial read call for |kUrl1| creates a placeholder entry and asks the
// client to fetch a module script.
clients.push_back(new ClientImpl);
ReadEntry(kUrl1, clients[0]);
Fetch(kUrl1, clients[0]);
EXPECT_EQ(ClientImpl::Result::kInitial, clients[0]->GetResult());
EXPECT_FALSE(clients[0]->GetParams().has_value());
// The entry is now being fetched. Following read calls for |kUrl1| should
// wait for the completion.
clients.push_back(new ClientImpl);
ReadEntry(kUrl1, clients[1]);
Fetch(kUrl1, clients[1]);
EXPECT_EQ(ClientImpl::Result::kInitial, clients[1]->GetResult());
// An initial read call for |kUrl2| also creates a placeholder entry and asks
// the client to fetch a module script.
clients.push_back(new ClientImpl);
ReadEntry(kUrl2, clients[2]);
Fetch(kUrl2, clients[2]);
EXPECT_EQ(ClientImpl::Result::kInitial, clients[2]->GetResult());
EXPECT_FALSE(clients[2]->GetParams().has_value());
// The entry is now being fetched. Following read calls for |kUrl2| should
// wait for the completion.
clients.push_back(new ClientImpl);
ReadEntry(kUrl2, clients[3]);
Fetch(kUrl2, clients[3]);
EXPECT_EQ(ClientImpl::Result::kInitial, clients[3]->GetResult());
// Dispose() should notify to all waiting clients.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment