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
|
// 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_
|