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
content / browser / worker_host / worker_script_loader.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_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 network {
class SharedURLLoaderFactory;
} // namespace network
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;
void PauseReadingBodyFromNet() override;
void ResumeReadingBodyFromNet() 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();
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_