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
content / browser / service_worker / service_worker_fetch_dispatcher.h [blame]
// Copyright 2014 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_SERVICE_WORKER_SERVICE_WORKER_FETCH_DISPATCHER_H_
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_FETCH_DISPATCHER_H_
#include <memory>
#include <string>
#include "base/functional/callback.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/common/content_export.h"
#include "content/public/browser/web_contents.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom.h"
#include "third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_fetch_response_callback.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_stream_handle.mojom.h"
namespace content {
class ServiceWorkerContextWrapper;
class ServiceWorkerVersion;
// A helper class to dispatch fetch event to a service worker.
class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
public:
// Indicates how the service worker handled a fetch event.
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class FetchEventResult {
// Browser should fallback to native fetch.
kShouldFallback = 0,
// Service worker provided a ServiceWorkerResponse.
kGotResponse = 1,
kMaxValue = kGotResponse,
};
using FetchCallback =
base::OnceCallback<void(blink::ServiceWorkerStatusCode,
FetchEventResult,
blink::mojom::FetchAPIResponsePtr,
blink::mojom::ServiceWorkerStreamHandlePtr,
blink::mojom::ServiceWorkerFetchEventTimingPtr,
scoped_refptr<ServiceWorkerVersion>)>;
using WebContentsGetter = base::RepeatingCallback<WebContents*()>;
ServiceWorkerFetchDispatcher(blink::mojom::FetchAPIRequestPtr request,
network::mojom::RequestDestination destination,
const std::string& client_id,
const std::string& resulting_client_id,
scoped_refptr<ServiceWorkerVersion> version,
base::OnceClosure prepare_callback,
FetchCallback fetch_callback);
ServiceWorkerFetchDispatcher(const ServiceWorkerFetchDispatcher&) = delete;
ServiceWorkerFetchDispatcher& operator=(const ServiceWorkerFetchDispatcher&) =
delete;
~ServiceWorkerFetchDispatcher();
static const char* FetchEventResultToSuffix(FetchEventResult result);
// If appropriate, starts the navigation preload request and creates
// |preload_handle_|. Returns true if it started navigation preload.
bool MaybeStartNavigationPreload(
const network::ResourceRequest& original_request,
scoped_refptr<ServiceWorkerContextWrapper> context_wrapper,
FrameTreeNodeId frame_tree_node_id);
// Dispatches a fetch event to the |version| given in ctor, and fires
// |fetch_callback_| (also given in ctor) once a response is received from the
// service worker. It runs |prepare_callback_| as an intermediate step once
// the version is activated and running.
void Run();
bool FetchCallbackIsNull() { return fetch_callback_.is_null(); }
static scoped_refptr<network::SharedURLLoaderFactory>
CreateNetworkURLLoaderFactory(
scoped_refptr<ServiceWorkerContextWrapper> context_wrapper,
FrameTreeNodeId frame_tree_node_id);
static void ForceDisableHighPriorityFetchResponseCallbackForTesting(
bool force_disable);
void set_race_network_request_token(base::UnguessableToken token) {
race_network_request_token_ = token;
}
void set_race_network_request_loader_factory(
mojo::PendingRemote<network::mojom::URLLoaderFactory> factory) {
race_network_request_loader_factory_ = std::move(factory);
}
private:
class ResponseCallback;
class URLLoaderAssets;
void DidWaitForActivation();
void StartWorker();
void DidStartWorker(blink::ServiceWorkerStatusCode status);
void DispatchFetchEvent();
void DidFailToDispatch(std::unique_ptr<ResponseCallback> callback,
blink::ServiceWorkerStatusCode status);
void DidFail(blink::ServiceWorkerStatusCode status);
void DidFinish(int request_id,
FetchEventResult fetch_result,
blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
blink::mojom::ServiceWorkerFetchEventTimingPtr timing);
void RunCallback(blink::ServiceWorkerStatusCode status,
FetchEventResult fetch_result,
blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
blink::mojom::ServiceWorkerFetchEventTimingPtr timing);
// The fetch event stays open until all respondWith() and waitUntil() promises
// are settled. This function is called once the renderer signals that
// happened. |fetch_callback_| can run before this, once respondWith() is
// settled.
static void OnFetchEventFinished(
base::WeakPtr<ServiceWorkerFetchDispatcher> fetch_dispatcher,
ServiceWorkerVersion* version,
int event_finish_id,
scoped_refptr<URLLoaderAssets> url_loader_assets,
blink::mojom::ServiceWorkerEventStatus status);
ServiceWorkerMetrics::EventType GetEventType() const;
bool IsEventDispatched() const;
blink::mojom::FetchAPIRequestPtr request_;
std::string client_id_;
std::string resulting_client_id_;
scoped_refptr<ServiceWorkerVersion> version_;
const network::mojom::RequestDestination destination_;
base::OnceClosure prepare_callback_;
FetchCallback fetch_callback_;
scoped_refptr<URLLoaderAssets> url_loader_assets_;
// Holds the URLLoaderClient for the service worker to receive the navigation
// preload response. It's passed to the service worker along with the fetch
// event.
mojo::PendingReceiver<network::mojom::URLLoaderClient>
preload_url_loader_client_receiver_;
base::UnguessableToken race_network_request_token_;
mojo::PendingRemote<network::mojom::URLLoaderFactory>
race_network_request_loader_factory_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<ServiceWorkerFetchDispatcher> weak_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_FETCH_DISPATCHER_H_