1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
content / browser / worker_host / worker_script_fetcher.h [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_WORKER_HOST_WORKER_SCRIPT_FETCHER_H_
#define CONTENT_BROWSER_WORKER_HOST_WORKER_SCRIPT_FETCHER_H_
#include <optional>
#include "base/functional/callback.h"
#include "content/browser/renderer_host/policy_container_host.h"
#include "content/common/content_export.h"
#include "content/public/browser/service_worker_client_info.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "net/storage_access_api/status.h"
#include "net/url_request/redirect_info.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/client_security_state.mojom-forward.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom-forward.h"
#include "third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom.h"
#include "third_party/blink/public/mojom/worker/worker_main_script_load_params.mojom.h"
namespace net {
class IsolationInfo;
class SiteForCookies;
} // namespace net
namespace network {
struct ResourceRequest;
} // namespace network
namespace blink {
class PendingURLLoaderFactoryBundle;
class StorageKey;
class ThrottlingURLLoader;
class URLLoaderThrottle;
} // namespace blink
namespace content {
class DevToolsAgentHostImpl;
class RenderFrameHostImpl;
class ServiceWorkerContextWrapper;
class ServiceWorkerMainResourceHandle;
class StoragePartitionImpl;
class WorkerScriptLoaderFactory;
// Contains the result of successful worker script fetch. On fetch failure,
// `std::nullopt` is used instead.
struct CONTENT_EXPORT WorkerScriptFetcherResult final {
WorkerScriptFetcherResult(
std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
subresource_loader_factories,
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
PolicyContainerPolicies policy_container_policies,
const GURL& final_response_url);
~WorkerScriptFetcherResult();
WorkerScriptFetcherResult(WorkerScriptFetcherResult&& other);
WorkerScriptFetcherResult& operator=(WorkerScriptFetcherResult&& other);
// Sent to the renderer process and is to be used to request subresources
// where applicable. For example, this allows the dedicated worker to load
// chrome-extension:// URLs which the renderer's default loader factory can't
// load.
std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
subresource_loader_factories;
// Sent to the renderer process and to be used to load the worker main script
// pre-requested by the browser process.
// Always non-null and contains `response_head` and
// `response_head->parsed_headers`.
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params;
PolicyContainerPolicies policy_container_policies;
// The script response URL.
// https://fetch.spec.whatwg.org/#concept-response-url
GURL final_response_url;
};
// NetworkService (PlzWorker):
// This is an implementation of the URLLoaderClient for web worker's main script
// fetch. The loader and client bounded with this class are to be unbound and
// forwarded to the renderer process on OnReceiveResponse, and the
// resource loader in the renderer process will take them over.
//
// WorkerScriptFetcher deletes itself when the ownership of the loader and
// client is passed to the renderer, or on failure. It lives on the UI
// thread.
// TODO(asamidoi): Remove the manual memory management like `delete this` and
// use `unique_ptr` to create WorkerScriptFetcher in a caller side.
class WorkerScriptFetcher : public network::mojom::URLLoaderClient {
public:
// Called with the result of fetching a script upon response received.
using CompletionCallback =
base::OnceCallback<void(std::optional<WorkerScriptFetcherResult>)>;
// Used for specifying how URLLoaderFactoryBundle is used.
enum class LoaderType { kMainResource, kSubResource };
// Initiates a browser-side worker script fetch.
// Creates a `WorkerScriptFetcher` and starts it.
//
// Must be called on the UI thread.
//
// - `ancestor_render_frame_host` points to the ancestor frame. If
// the worker being created is nested, then this is the ancestor of the
// creator worker. Otherwise, this is the creator frame. Cannot be nullptr.
// For dedicated workers, when the lifetime of the `DedicatedWorkerHost`
// does not exactly align with the parents, and they are destroyed
// asynchronously via mojo by the time the fetch is about to start,
// this method must not be called.
// - `creator_render_frame_host` points to the creator frame, if any. May
// be nullptr if the worker being created is a nested dedicated worker.
// Since nested shared workers are not supported, for shared workers
// `ancestor_render_frame_host` and `creator_render_frame_host` are always
// equal.
// - `client_security_state` specifies parameters to be passed to the network
// service `URLLoaderFactory`, for use when loading the script. It must not
// be nullptr.
// - `callback` will be called with the result on the UI thread.
static void CreateAndStart(
int worker_process_id,
const DedicatedOrSharedWorkerToken& worker_token,
const GURL& initial_request_url,
RenderFrameHostImpl& ancestor_render_frame_host,
RenderFrameHostImpl* creator_render_frame_host,
const net::SiteForCookies& site_for_cookies,
const url::Origin& request_initiator,
const blink::StorageKey& request_initiator_storage_key,
const net::IsolationInfo& trusted_isolation_info,
network::mojom::ClientSecurityStatePtr client_security_state,
network::mojom::CredentialsMode credentials_mode,
blink::mojom::FetchClientSettingsObjectPtr
outside_fetch_client_settings_object,
network::mojom::RequestDestination request_destination,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
ServiceWorkerMainResourceHandle* service_worker_handle,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
scoped_refptr<network::SharedURLLoaderFactory>
url_loader_factory_override,
StoragePartitionImpl* storage_partition,
const std::string& storage_domain,
DevToolsAgentHostImpl* devtools_agent_host,
const base::UnguessableToken& devtools_worker_token,
bool require_cross_site_request_for_cookies,
net::StorageAccessApiStatus storage_access_api_status,
CompletionCallback callback);
// Creates a loader factory bundle. Must be called on the UI thread. For
// nested workers, |creator_render_frame_host| can be null.
static std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
CreateFactoryBundle(LoaderType loader_type,
int worker_process_id,
StoragePartitionImpl* storage_partition,
const std::string& storage_domain,
bool file_support,
bool filesystem_url_support,
RenderFrameHostImpl* creator_render_frame_host,
const blink::StorageKey& request_initiator_storage_key);
// Calculates the final response URL from the redirect chain, URLs fetched by
// the service worker and the initial request URL. The logic is mostly based
// on what blink::ResourceResponse::ResponseUrl() does.
//
// Exposed for testing.
CONTENT_EXPORT static GURL DetermineFinalResponseUrl(
const GURL& initial_request_url,
blink::mojom::WorkerMainScriptLoadParams* main_script_load_params);
private:
// Callback invoked by this instance when the load ends, successfully or not.
//
// In case of success:
//
// - `main_script_load_params` is not nullptr.
// - `completion_status` is nullptr.
//
// In case of error:
//
// - `main_script_load_params` is nullptr.
// - `completion_status` is not nullptr.
using CreateAndStartCallback = base::OnceCallback<void(
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
const network::URLLoaderCompletionStatus* completion_status)>;
WorkerScriptFetcher(
std::unique_ptr<WorkerScriptLoaderFactory> script_loader_factory,
std::unique_ptr<network::ResourceRequest> resource_request,
CreateAndStartCallback callback);
~WorkerScriptFetcher() override;
// Helper for `CreateAndStart()`.
static void CreateScriptLoader(
int worker_process_id,
const DedicatedOrSharedWorkerToken& worker_token,
const GURL& initial_request_url,
RenderFrameHostImpl& ancestor_render_frame_host,
RenderFrameHostImpl* creator_render_frame_host,
const net::IsolationInfo& trusted_isolation_info,
network::mojom::ClientSecurityStatePtr client_security_state,
std::unique_ptr<network::ResourceRequest> resource_request,
std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
factory_bundle_for_browser_info,
std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
subresource_loader_factories,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
ServiceWorkerMainResourceHandle* service_worker_handle,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
scoped_refptr<network::SharedURLLoaderFactory>
url_loader_factory_override,
DevToolsAgentHostImpl* devtools_agent_host,
const base::UnguessableToken& devtools_worker_token,
bool require_cross_site_request_for_cookies,
WorkerScriptFetcher::CompletionCallback callback);
void Start(std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles);
// network::mojom::URLLoaderClient
void OnReceiveEarlyHints(network::mojom::EarlyHintsPtr early_hints) override;
void OnReceiveResponse(
network::mojom::URLResponseHeadPtr head,
mojo::ScopedDataPipeConsumerHandle body,
std::optional<mojo_base::BigBuffer> cached_metadata) override;
void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
network::mojom::URLResponseHeadPtr head) override;
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback callback) override;
void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
void OnComplete(const network::URLLoaderCompletionStatus& status) override;
void DidParseHeaders(network::mojom::ParsedHeadersPtr parsed_headers);
std::unique_ptr<WorkerScriptLoaderFactory> script_loader_factory_;
// Request ID for a browser-initiated request.
const int request_id_;
std::unique_ptr<network::ResourceRequest> resource_request_;
CreateAndStartCallback callback_;
// URLLoader instance backed by a request interceptor or the network service.
std::unique_ptr<blink::ThrottlingURLLoader> url_loader_;
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params_;
std::vector<net::RedirectInfo> redirect_infos_;
std::vector<network::mojom::URLResponseHeadPtr> redirect_response_heads_;
base::WeakPtrFactory<WorkerScriptFetcher> weak_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_WORKER_HOST_WORKER_SCRIPT_FETCHER_H_