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
content / common / service_worker / service_worker_resource_loader.h [blame]
// Copyright 2023 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_COMMON_SERVICE_WORKER_SERVICE_WORKER_RESOURCE_LOADER_H_
#define CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_RESOURCE_LOADER_H_
#include <optional>
#include "base/check_op.h"
#include "content/common/content_export.h"
#include "services/network/public/mojom/service_worker_router_info.mojom-shared.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "third_party/blink/public/common/service_worker/service_worker_router_rule.h"
namespace content {
// A common interface in between:
// - ServiceWorkerMainResourceLoader in the browser
// - ServiceWorkerSubresourceLoader in the renderer
//
// Represents how to commit a response being fetch from ServiceWorker.
//
// To implement feature RaceNetworkRequest (crbug.com/1420517), we store into
// this common class whether the response came from the ServiceWorker fetch
// handler or from a direct network request.
class CONTENT_EXPORT ServiceWorkerResourceLoader {
public:
// Indicates where the response comes from.
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class FetchResponseFrom {
kNoResponseYet = 0,
kServiceWorker = 1,
kWithoutServiceWorker = 2,
// For subresources, the redirect mode is "follow". When redirects happen,
// the resource loader restarts the request process after FollowRedirect()
// is called. This value indicates that intermediate state. This state has
// to be updated to either |kServiceWorker| or |kWithoutServiceWorker| after
// receiving the final response.
kSubresourceLoaderIsHandlingRedirect = 3,
// When ServiceWorkerAutoPreload is enabled, in most cases the response from
// |kServiceWorker| is expected. However, when the fetch handler result is
// fallback, the browser tries to use the response from the network request.
// In this case |commit_responsibility_| is transitioned from
// |kServiceWorker| to |kWithoutServiceWorker|, but we don't want to permit
// that transition in normal cases. This state is a special intermediate
// state to bridge those states, which is used only to handle fallback with
// ServiceWorkerAutoPreload.
kAutoPreloadHandlingFallback = 4,
kMaxValue = kAutoPreloadHandlingFallback,
};
// Indicates what kind of preload request is dispatched before starting
// the ServiceWorker.
//
// kNone: No preload request is triggered. This is the default state.
// kRaceNetworkRequest:
// RaceNetworkRequest is triggered.
// TODO(crbug.com/40258805) This will be passed to the renderer and block
// the corresponding request from the ServiceWorker.
// kNavigationPreload:
// Enabled when Navigation Preload is triggered.
// kAutoPreload:
// AutoPreload is triggered. This is consumed in the fetch handler or
// the fallback request.
enum class DispatchedPreloadType {
kNone,
kRaceNetworkRequest,
kNavigationPreload,
kAutoPreload,
};
ServiceWorkerResourceLoader();
virtual ~ServiceWorkerResourceLoader();
void RecordFetchResponseFrom();
FetchResponseFrom commit_responsibility() { return commit_responsibility_; }
virtual void SetCommitResponsibility(FetchResponseFrom fetch_response_from);
DispatchedPreloadType dispatched_preload_type() {
return dispatched_preload_type_;
}
void SetDispatchedPreloadType(DispatchedPreloadType type);
// Tells if the class is main resource's class or not.
virtual bool IsMainResourceLoader() = 0;
// Calls url_loader_client_->OnReceiveResponse() with given |response_head|.
virtual void CommitResponseHeaders(
const network::mojom::URLResponseHeadPtr& response_head) = 0;
// Calls url_loader_client_->OnReceiveResponse() with |response_body| and
// |cached_metadata|.
virtual void CommitResponseBody(
const network::mojom::URLResponseHeadPtr& response_head,
mojo::ScopedDataPipeConsumerHandle response_body,
std::optional<mojo_base::BigBuffer> cached_metadata) = 0;
// Creates and sends an empty response's body with the net::OK status.
// Sends net::ERR_INSUFFICIENT_RESOURCES when it can't be created.
virtual void CommitEmptyResponseAndComplete() = 0;
// Calls url_loader_client_->OnComplete(). |reason| will be recorded as an
// argument of TRACE_EVENT.
virtual void CommitCompleted(int error_code, const char* reason) = 0;
// Calls url_loader_client_->OnReceiveRedirect().
virtual void HandleRedirect(
const net::RedirectInfo& redirect_info,
const network::mojom::URLResponseHeadPtr& response_head) = 0;
// Determine if the fetch start should be recorded, by checking the matched
// source type of ServiceWorker static routing API. If no source is matched,
// or the source is matched to `race` or `fetch-event`, we should record fetch
// start time since these cases will start the ServiceWorker and trigger fetch
// event.
bool ShouldRecordServiceWorkerFetchStart();
bool IsMatchedRouterSourceType(
network::mojom::ServiceWorkerRouterSourceType type);
void set_matched_router_source_type(
network::mojom::ServiceWorkerRouterSourceType type) {
matched_router_source_type_ = type;
}
private:
FetchResponseFrom commit_responsibility_ = FetchResponseFrom::kNoResponseYet;
DispatchedPreloadType dispatched_preload_type_ = DispatchedPreloadType::kNone;
std::optional<network::mojom::ServiceWorkerRouterSourceType>
matched_router_source_type_;
};
} // namespace content
#endif // CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_RESOURCE_LOADER_H_