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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
content / browser / background_fetch / storage / database_helpers.cc [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/background_fetch/storage/database_helpers.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/background_fetch/background_fetch.mojom.h"
namespace content {
namespace background_fetch {
std::string ActiveRegistrationUniqueIdKey(const std::string& developer_id) {
// Allows looking up the active registration's |unique_id| by |developer_id|.
// Registrations are active from creation up until completed/failed/aborted.
// These database entries correspond to the active background fetches map:
// https://wicg.github.io/background-fetch/#service-worker-registration-active-background-fetches
return kActiveRegistrationUniqueIdKeyPrefix + developer_id;
}
std::string RegistrationKey(const std::string& unique_id) {
// Allows looking up a registration by |unique_id|.
return kRegistrationKeyPrefix + unique_id;
}
std::string UIOptionsKey(const std::string& unique_id) {
return kUIOptionsKeyPrefix + unique_id;
}
std::string PendingRequestKeyPrefix(const std::string& unique_id) {
return kPendingRequestKeyPrefix + unique_id + kSeparator;
}
std::string PendingRequestKey(const std::string& unique_id, int request_index) {
return PendingRequestKeyPrefix(unique_id) +
base::NumberToString(request_index);
}
std::string ActiveRequestKeyPrefix(const std::string& unique_id) {
return kActiveRequestKeyPrefix + unique_id + kSeparator;
}
std::string ActiveRequestKey(const std::string& unique_id, int request_index) {
return ActiveRequestKeyPrefix(unique_id) +
base::NumberToString(request_index);
}
std::string CompletedRequestKeyPrefix(const std::string& unique_id) {
return kCompletedRequestKeyPrefix + unique_id + kSeparator;
}
std::string CompletedRequestKey(const std::string& unique_id,
int request_index) {
return CompletedRequestKeyPrefix(unique_id) +
base::NumberToString(request_index);
}
std::string StorageVersionKey(const std::string& unique_id) {
return kStorageVersionKeyPrefix + unique_id;
}
DatabaseStatus ToDatabaseStatus(blink::ServiceWorkerStatusCode status) {
switch (status) {
case blink::ServiceWorkerStatusCode::kOk:
return DatabaseStatus::kOk;
case blink::ServiceWorkerStatusCode::kErrorFailed:
case blink::ServiceWorkerStatusCode::kErrorAbort:
case blink::ServiceWorkerStatusCode::kErrorStorageDisconnected:
case blink::ServiceWorkerStatusCode::kErrorStorageDataCorrupted:
// kErrorFailed is for invalid arguments (e.g. empty key) or database
// errors. kErrorAbort is for unexpected failures, e.g. because shutdown
// is in progress. kErrorStorageDisconnected is for the Storage Service
// disconnection. BackgroundFetchDataManager handles these the same way.
return DatabaseStatus::kFailed;
case blink::ServiceWorkerStatusCode::kErrorNotFound:
// This can also happen for writes, if the ServiceWorkerRegistration has
// been deleted.
return DatabaseStatus::kNotFound;
case blink::ServiceWorkerStatusCode::kErrorStartWorkerFailed:
case blink::ServiceWorkerStatusCode::kErrorProcessNotFound:
case blink::ServiceWorkerStatusCode::kErrorExists:
case blink::ServiceWorkerStatusCode::kErrorInstallWorkerFailed:
case blink::ServiceWorkerStatusCode::kErrorActivateWorkerFailed:
case blink::ServiceWorkerStatusCode::kErrorIpcFailed:
case blink::ServiceWorkerStatusCode::kErrorNetwork:
case blink::ServiceWorkerStatusCode::kErrorSecurity:
case blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected:
case blink::ServiceWorkerStatusCode::kErrorState:
case blink::ServiceWorkerStatusCode::kErrorTimeout:
case blink::ServiceWorkerStatusCode::kErrorScriptEvaluateFailed:
case blink::ServiceWorkerStatusCode::kErrorDiskCache:
case blink::ServiceWorkerStatusCode::kErrorRedundant:
case blink::ServiceWorkerStatusCode::kErrorDisallowed:
case blink::ServiceWorkerStatusCode::kErrorInvalidArguments:
break;
}
NOTREACHED_IN_MIGRATION();
return DatabaseStatus::kFailed;
}
bool ToBackgroundFetchRegistration(
const proto::BackgroundFetchMetadata& metadata_proto,
blink::mojom::BackgroundFetchRegistrationData* registration_data) {
DCHECK(registration_data);
const auto& registration_proto = metadata_proto.registration();
registration_data->developer_id = registration_proto.developer_id();
registration_data->upload_total = registration_proto.upload_total();
registration_data->uploaded = registration_proto.uploaded();
registration_data->download_total = registration_proto.download_total();
registration_data->downloaded = registration_proto.downloaded();
switch (registration_proto.result()) {
case proto::BackgroundFetchRegistration_BackgroundFetchResult_UNSET:
registration_data->result = blink::mojom::BackgroundFetchResult::UNSET;
break;
case proto::BackgroundFetchRegistration_BackgroundFetchResult_FAILURE:
registration_data->result = blink::mojom::BackgroundFetchResult::FAILURE;
break;
case proto::BackgroundFetchRegistration_BackgroundFetchResult_SUCCESS:
registration_data->result = blink::mojom::BackgroundFetchResult::SUCCESS;
break;
default:
NOTREACHED_IN_MIGRATION();
}
bool did_convert = MojoFailureReasonFromRegistrationProto(
registration_proto.failure_reason(), ®istration_data->failure_reason);
return did_convert;
}
blink::StorageKey GetMetadataStorageKey(
const proto::BackgroundFetchMetadata& metadata_proto) {
if (metadata_proto.has_storage_key()) {
auto storage_key =
blink::StorageKey::Deserialize(metadata_proto.storage_key());
if (storage_key.has_value()) {
return *storage_key;
}
}
// Fall back to the deprecated `origin` field.
if (metadata_proto.has_origin()) {
return blink::StorageKey::CreateFirstParty(
url::Origin::Create(GURL(metadata_proto.origin())));
}
// If neither field is set, the best we can do is an opaque StorageKey.
return blink::StorageKey();
}
bool MojoFailureReasonFromRegistrationProto(
proto::BackgroundFetchRegistration::BackgroundFetchFailureReason
proto_failure_reason,
blink::mojom::BackgroundFetchFailureReason* failure_reason) {
DCHECK(failure_reason);
switch (proto_failure_reason) {
case proto::BackgroundFetchRegistration::NONE:
*failure_reason = blink::mojom::BackgroundFetchFailureReason::NONE;
return true;
case proto::BackgroundFetchRegistration::CANCELLED_FROM_UI:
*failure_reason =
blink::mojom::BackgroundFetchFailureReason::CANCELLED_FROM_UI;
return true;
case proto::BackgroundFetchRegistration::CANCELLED_BY_DEVELOPER:
*failure_reason =
blink::mojom::BackgroundFetchFailureReason::CANCELLED_BY_DEVELOPER;
return true;
case proto::BackgroundFetchRegistration::SERVICE_WORKER_UNAVAILABLE:
*failure_reason = blink::mojom::BackgroundFetchFailureReason::
SERVICE_WORKER_UNAVAILABLE;
return true;
case proto::BackgroundFetchRegistration::QUOTA_EXCEEDED:
*failure_reason =
blink::mojom::BackgroundFetchFailureReason::QUOTA_EXCEEDED;
return true;
case proto::BackgroundFetchRegistration::DOWNLOAD_TOTAL_EXCEEDED:
*failure_reason =
blink::mojom::BackgroundFetchFailureReason::DOWNLOAD_TOTAL_EXCEEDED;
return true;
case proto::BackgroundFetchRegistration::FETCH_ERROR:
*failure_reason = blink::mojom::BackgroundFetchFailureReason::FETCH_ERROR;
return true;
case proto::BackgroundFetchRegistration::BAD_STATUS:
*failure_reason = blink::mojom::BackgroundFetchFailureReason::BAD_STATUS;
return true;
}
LOG(ERROR) << "BackgroundFetchFailureReason from the metadata proto doesn't"
<< " match any enum value. Possible database corruption.";
return false;
}
GURL MakeCacheUrlUnique(const GURL& url,
const std::string& unique_id,
size_t request_index) {
std::string query = url.query();
query += unique_id + base::NumberToString(request_index);
GURL::Replacements replacements;
replacements.SetQueryStr(query);
return url.ReplaceComponents(replacements);
}
GURL RemoveUniqueParamFromCacheURL(const GURL& url,
const std::string& unique_id) {
std::vector<std::string> split = base::SplitStringUsingSubstr(
url.query(), unique_id, base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
GURL::Replacements replacements;
if (split.size() == 1u)
replacements.ClearQuery();
else if (split.size() == 2u)
replacements.SetQueryStr(split[0]);
else
NOTREACHED_IN_MIGRATION();
return url.ReplaceComponents(replacements);
}
} // namespace background_fetch
} // namespace content