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
|
// 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_LOADER_H_
#define CONTENT_BROWSER_WORKER_HOST_WORKER_SCRIPT_LOADER_H_
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "content/browser/loader/navigation_loader_interceptor.h"
#include "content/public/browser/service_worker_client_info.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/load_timing_info.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_request.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/single_request_url_loader_factory.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "third_party/blink/public/common/tokens/tokens.h"
namespace net {
class IsolationInfo;
} // namespace net
namespace content {
class BrowserContext;
class NavigationLoaderInterceptor;
class ServiceWorkerMainResourceHandle;
class ServiceWorkerMainResourceLoaderInterceptor;
// The URLLoader for loading a shared worker script. Only used for the main
// script request.
//
// This acts much like NavigationURLLoaderImpl. It allows a
// NavigationLoaderInterceptor to intercept the request with its own loader, and
// goes to |default_loader_factory| otherwise. Once a loader is started, this
// class acts as the URLLoaderClient for it, forwarding messages to the outer
// client. On redirects, it starts over with the new request URL, possibly
// starting a new loader and becoming the client of that.
//
// Lives on the UI thread.
class CONTENT_EXPORT WorkerScriptLoader
: public network::mojom::URLLoader,
public network::mojom::URLLoaderClient {
public:
// Returns the browser context, or nullptr during shutdown. Must be called on
// the UI thread.
using BrowserContextGetter = base::RepeatingCallback<BrowserContext*(void)>;
// |default_loader_factory| is used to load the script if the load is not
// intercepted by a service worker. Typically it will load the script from the
// NetworkService. However, it may internally contain non-NetworkService
// factories used for non-http(s) URLs, e.g., a chrome-extension:// URL.
WorkerScriptLoader(
int process_id,
const DedicatedOrSharedWorkerToken& worker_token,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& resource_request,
const net::IsolationInfo& isolation_info,
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
base::WeakPtr<ServiceWorkerMainResourceHandle> service_worker_handle,
const BrowserContextGetter& browser_context_getter,
scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation);
WorkerScriptLoader(const WorkerScriptLoader&) = delete;
WorkerScriptLoader& operator=(const WorkerScriptLoader&) = delete;
~WorkerScriptLoader() override;
// network::mojom::URLLoader:
void FollowRedirect(
const std::vector<std::string>& removed_headers,
const net::HttpRequestHeaders& modified_headers,
const net::HttpRequestHeaders& modified_cors_exempt_headers,
const std::optional<GURL>& new_url) override;
void SetPriority(net::RequestPriority priority,
int32_t intra_priority_value) override;
// network::mojom::URLLoaderClient:
void OnReceiveEarlyHints(network::mojom::EarlyHintsPtr early_hints) override;
void OnReceiveResponse(
network::mojom::URLResponseHeadPtr response_head,
mojo::ScopedDataPipeConsumerHandle body,
std::optional<mojo_base::BigBuffer> cached_metadata) override;
void OnReceiveRedirect(
const net::RedirectInfo& redirect_info,
network::mojom::URLResponseHeadPtr response_head) override;
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback ack_callback) override;
void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
void OnComplete(const network::URLLoaderCompletionStatus& status) override;
void OnFetcherCallbackCalled();
static network::mojom::URLLoaderFactory* Fallback(
base::WeakPtr<WorkerScriptLoader> self,
ResponseHeadUpdateParams);
base::WeakPtr<WorkerScriptLoader> GetWeakPtr();
private:
void Abort();
void Start();
void MaybeStartLoader(
ServiceWorkerMainResourceLoaderInterceptor* interceptor,
std::optional<NavigationLoaderInterceptor::Result> interceptor_result);
void LoadFromNetwork();
void CommitCompleted();
std::unique_ptr<ServiceWorkerMainResourceLoaderInterceptor> interceptor_;
const int32_t request_id_;
const uint32_t options_;
network::ResourceRequest resource_request_;
mojo::Remote<network::mojom::URLLoaderClient> client_;
base::WeakPtr<ServiceWorkerMainResourceHandle> service_worker_handle_;
BrowserContextGetter browser_context_getter_;
scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory_;
net::MutableNetworkTrafficAnnotationTag traffic_annotation_;
std::optional<net::RedirectInfo> redirect_info_;
int redirect_limit_ = net::URLRequest::kMaxRedirects;
mojo::Remote<network::mojom::URLLoader> url_loader_;
mojo::Receiver<network::mojom::URLLoaderClient> url_loader_client_receiver_{
this};
// The factory used to request the script. This is the same as
// |default_loader_factory_| if a service worker didn't elect to handle the
// request.
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
// Valid transitions:
// - kInitial -> kFetcherCallbackCalled or kOnCompleteCalled -> kCompleted
// - kInitial -> kCompleted (failure cases only)
// See the comment at the `CommitCompleted()` definition for more context.
enum class State {
kInitial,
// `WorkerScriptFetcher::callback_` was invoked.
kFetcherCallbackCalled,
// `WorkerScriptLoader::OnComplete()` was called.
kOnCompleteCalled,
// `WorkerScriptLoader::CommitCompleted()` was called.
kCompleted,
} state_{State::kInitial};
std::optional<network::URLLoaderCompletionStatus> complete_status_;
base::WeakPtrFactory<WorkerScriptLoader> weak_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_WORKER_HOST_WORKER_SCRIPT_LOADER_H_
|