blob: 38775307a146a3e570acf2981976edc785c6623d [file] [log] [blame]
// 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 CONTENT_BROWSER_WORKER_HOST_WORKER_SCRIPT_FETCHER_H_
#define CONTENT_BROWSER_WORKER_HOST_WORKER_SCRIPT_FETCHER_H_
#include "base/callback.h"
#include "content/browser/navigation_subresource_loader_params.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/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/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom.h"
#include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
#include "third_party/blink/public/mojom/worker/worker_main_script_load_params.mojom.h"
namespace net {
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 ServiceWorkerObjectHost;
class StoragePartitionImpl;
class WorkerScriptLoaderFactory;
struct SubresourceLoaderParams;
// 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 completion.
//
// - `subresource_loader_factories` is never nullptr.
// - `main_script_load_params` is nullptr iff the fetch failed. Otherwise, it
// always contains `response_head` and `response_head->parsed_headers`.
// - `controller` and `controller_service_worker_object_host` may be nullptr.
// - `final_response_url` specifies the script response URL.
using CompletionCallback = base::OnceCallback<void(
std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
subresource_loader_factories,
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
blink::mojom::ControllerServiceWorkerInfoPtr controller,
base::WeakPtr<ServiceWorkerObjectHost>
controller_service_worker_object_host,
const GURL& final_response_url)>;
// 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 any. If
// the worker being created is nested, then this is the ancestor of the
// creator worker. Otherwise, this is the creator frame. May be nullptr.
// For dedicated workers, `ancestor_render_frame_host` *should* always exist
// though due to the fact that `DedicatedWorkerHost` lifetimes do not align
// exactly with their parents (they are destroyed asynchronously via mojo),
// the ancestor frame might have been destroyed when the fetch starts.
// TODO(https://crbug.com/1177652): Amend the above comment once
// `DedicatedWorkerHost` lifetimes align with their creators'.
// - `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,
ukm::SourceId worker_source_id,
DevToolsAgentHostImpl* devtools_agent_host,
const base::UnguessableToken& devtools_worker_token,
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.
// - `subresource_loader_params` may be nullopt.
// - `completion_status` is nullptr.
//
// In case of error:
//
// - `main_script_load_params` is nullptr.
// - `subresource_loader_params` is nullopt.
// - `completion_status` is not nullptr.
using CreateAndStartCallback = base::OnceCallback<void(
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
absl::optional<SubresourceLoaderParams> subresource_loader_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,
ukm::SourceId worker_source_id,
DevToolsAgentHostImpl* devtools_agent_host,
const base::UnguessableToken& devtools_worker_token,
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,
absl::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_;
// URLLoader instance for handling a response received from the default
// network loader. This can be provided by an interceptor.
mojo::PendingRemote<network::mojom::URLLoader> response_url_loader_;
mojo::Receiver<network::mojom::URLLoaderClient> response_url_loader_receiver_{
this};
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params_;
absl::optional<SubresourceLoaderParams> subresource_loader_params_;
std::vector<net::RedirectInfo> redirect_infos_;
std::vector<network::mojom::URLResponseHeadPtr> redirect_response_heads_;
network::mojom::URLResponseHeadPtr response_head_;
base::WeakPtrFactory<WorkerScriptFetcher> weak_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_WORKER_HOST_WORKER_SCRIPT_FETCHER_H_