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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
content / browser / background_fetch / background_fetch_data_manager.h [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.
#ifndef CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_DATA_MANAGER_H_
#define CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_DATA_MANAGER_H_
#include <map>
#include <memory>
#include <set>
#include <string>
#include <tuple>
#include <vector>
#include "base/containers/queue.h"
#include "base/functional/callback_forward.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/sequence_checker.h"
#include "content/browser/background_fetch/background_fetch.pb.h"
#include "content/browser/background_fetch/background_fetch_registration_id.h"
#include "content/browser/background_fetch/background_fetch_scheduler.h"
#include "content/browser/background_fetch/storage/database_task.h"
#include "content/browser/background_fetch/storage/get_initialization_data_task.h"
#include "content/common/content_export.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 storage {
class BlobDataHandle;
class QuotaManagerProxy;
} // namespace storage
namespace content {
class BackgroundFetchDataManagerObserver;
class BackgroundFetchRequestInfo;
class BackgroundFetchRequestMatchParams;
class ChromeBlobStorageContext;
class ServiceWorkerContextWrapper;
class StoragePartitionImpl;
// The BackgroundFetchDataManager is a wrapper around persistent storage (the
// Service Worker database), exposing APIs for the read and write queries needed
// for Background Fetch.
//
// There must only be a single instance of this class per StoragePartition, and
// it must only be used on the UI thread, since it relies on there being no
// other code concurrently reading/writing the Background Fetch keys of the same
// Service Worker database (except for deletions, e.g. it's safe for the Service
// Worker code to remove a ServiceWorkerRegistration and all its keys).
//
// Storage schema is documented in storage/README.md
class CONTENT_EXPORT BackgroundFetchDataManager
: public background_fetch::DatabaseTaskHost {
public:
using GetInitializationDataCallback = base::OnceCallback<void(
blink::mojom::BackgroundFetchError,
std::vector<background_fetch::BackgroundFetchInitializationData>)>;
using SettledFetchesCallback = base::OnceCallback<void(
blink::mojom::BackgroundFetchError,
std::vector<blink::mojom::BackgroundFetchSettledFetchPtr>)>;
using CreateRegistrationCallback = base::OnceCallback<void(
blink::mojom::BackgroundFetchError,
blink::mojom::BackgroundFetchRegistrationDataPtr)>;
using GetRegistrationCallback = base::OnceCallback<void(
blink::mojom::BackgroundFetchError,
BackgroundFetchRegistrationId,
blink::mojom::BackgroundFetchRegistrationDataPtr)>;
using MarkRegistrationForDeletionCallback =
base::OnceCallback<void(blink::mojom::BackgroundFetchError,
blink::mojom::BackgroundFetchFailureReason)>;
using GetRequestBlobCallback =
base::OnceCallback<void(blink::mojom::BackgroundFetchError,
blink::mojom::SerializedBlobPtr)>;
using MarkRequestCompleteCallback =
base::OnceCallback<void(blink::mojom::BackgroundFetchError)>;
using NextRequestCallback =
base::OnceCallback<void(blink::mojom::BackgroundFetchError,
scoped_refptr<BackgroundFetchRequestInfo>)>;
BackgroundFetchDataManager(
base::WeakPtr<StoragePartitionImpl> storage_partition,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy);
BackgroundFetchDataManager(const BackgroundFetchDataManager&) = delete;
BackgroundFetchDataManager& operator=(const BackgroundFetchDataManager&) =
delete;
~BackgroundFetchDataManager() override;
// Grabs a reference to CacheStorageManager.
virtual void Initialize();
// Adds or removes the given |observer| to this data manager instance.
void AddObserver(BackgroundFetchDataManagerObserver* observer);
void RemoveObserver(BackgroundFetchDataManagerObserver* observer);
// Gets the required data to initialize BackgroundFetchContext with the
// appropriate JobControllers. This will be called when BackgroundFetchContext
// is being initialized.
void GetInitializationData(GetInitializationDataCallback callback);
// Creates and stores a new registration with the given properties. Will
// invoke the |callback| when the registration has been created, which may
// fail due to invalid input or storage errors.
void CreateRegistration(
const BackgroundFetchRegistrationId& registration_id,
std::vector<blink::mojom::FetchAPIRequestPtr> requests,
blink::mojom::BackgroundFetchOptionsPtr options,
const SkBitmap& icon,
bool start_paused,
const net::IsolationInfo& isolation_info,
CreateRegistrationCallback callback);
// Get the BackgroundFetchRegistration.
void GetRegistration(int64_t service_worker_registration_id,
const blink::StorageKey& storage_key,
const std::string& developer_id,
GetRegistrationCallback callback);
// Reads the settled fetches for the given |registration_id| based on
// |match_params|. Both the Request and Response objects will be initialised
// based on the stored data. Will invoke the |callback| when the list of
// fetches has been compiled.
void MatchRequests(
const BackgroundFetchRegistrationId& registration_id,
std::unique_ptr<BackgroundFetchRequestMatchParams> match_params,
SettledFetchesCallback callback);
// Retrieves the next pending request for |registration_id| and invoke
// |callback| with it.
void PopNextRequest(const BackgroundFetchRegistrationId& registration_id,
NextRequestCallback callback);
// Retrieves the request blob associated with |request_info|. THis should be
// called for requests that are known to have a blob.
void GetRequestBlob(
const BackgroundFetchRegistrationId& registration_id,
const scoped_refptr<BackgroundFetchRequestInfo>& request_info,
GetRequestBlobCallback callback);
// Marks |request_info| as complete and calls |callback| when done.
void MarkRequestAsComplete(
const BackgroundFetchRegistrationId& registration_id,
scoped_refptr<BackgroundFetchRequestInfo> request_info,
MarkRequestCompleteCallback callback);
// Marks that the
// backgroundfetchsuccess/backgroundfetchfail/backgroundfetchabort event is
// being dispatched. It's not possible to call DeleteRegistration at this
// point as JavaScript may hold a reference to a BackgroundFetchRegistration
// object and we need to keep the corresponding data around until the last
// such reference is released (or until shutdown). We can't just move the
// Background Fetch registration's data to RAM as it might consume too much
// memory. So instead this step disassociates the |developer_id| from the
// |unique_id|, so that existing JS objects with a reference to |unique_id|
// can still access the data, but it can no longer be reached using GetIds or
// GetRegistration. If |check_for_failure| is true, the task will also check
// whether there is any associated failure reason with the fetches. This
// helps figure out whether a success or fail event should be dispatched.
void MarkRegistrationForDeletion(
const BackgroundFetchRegistrationId& registration_id,
bool check_for_failure,
MarkRegistrationForDeletionCallback callback);
// Deletes the registration identified by |registration_id|. Should only be
// called once the refcount of JavaScript BackgroundFetchRegistration objects
// referring to this registration drops to zero. Will invoke the |callback|
// when the registration has been deleted from storage.
void DeleteRegistration(const BackgroundFetchRegistrationId& registration_id,
HandleBackgroundFetchErrorCallback callback);
// List all Background Fetch registration |developer_id|s for a Service
// Worker.
void GetDeveloperIdsForServiceWorker(
int64_t service_worker_registration_id,
const blink::StorageKey& storage_key,
blink::mojom::BackgroundFetchService::GetDeveloperIdsCallback callback);
const base::ObserverList<BackgroundFetchDataManagerObserver>::Unchecked&
observers() {
return observers_;
}
void Shutdown();
private:
FRIEND_TEST_ALL_PREFIXES(BackgroundFetchDataManagerTest, Cleanup);
friend class BackgroundFetchDataManagerTest;
friend class BackgroundFetchTestDataManager;
friend class background_fetch::DatabaseTask;
// Accessors for tests and DatabaseTasks.
ServiceWorkerContextWrapper* service_worker_context() const {
return service_worker_context_.get();
}
std::set<std::string>& ref_counted_unique_ids() {
return ref_counted_unique_ids_;
}
ChromeBlobStorageContext* blob_storage_context() const {
return blob_storage_context_.get();
}
const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy() const {
return quota_manager_proxy_;
}
void AddDatabaseTask(std::unique_ptr<background_fetch::DatabaseTask> task);
// DatabaseTaskHost implementation.
void OnTaskFinished(background_fetch::DatabaseTask* task) override;
BackgroundFetchDataManager* data_manager() override;
base::WeakPtr<background_fetch::DatabaseTaskHost> GetWeakPtr() override;
void Cleanup();
// Get a CacheStorage remote for the given |storage_key| and |unique_id|. This
// will either be a reference to an existing remote or will cause the
// CacheStorage to be opened. The BackgroundFetchDataManager owns this
// remote for the lifetime of the connection.
mojo::Remote<blink::mojom::CacheStorage>& GetOrOpenCacheStorage(
const blink::StorageKey& storage_key,
const std::string& unique_id);
void OpenCache(const blink::StorageKey& storage_key,
const std::string& unique_id,
int64_t trace_id,
blink::mojom::CacheStorage::OpenCallback callback);
void DeleteCache(const blink::StorageKey& storage_key,
const std::string& unique_id,
int64_t trace_id,
blink::mojom::CacheStorage::DeleteCallback callback);
void DidDeleteCache(const std::string& unique_id,
blink::mojom::CacheStorage::DeleteCallback callback,
blink::mojom::CacheStorageError result);
void HasCache(const blink::StorageKey& storage_key,
const std::string& unique_id,
int64_t trace_id,
blink::mojom::CacheStorage::HasCallback callback);
// Whether Shutdown was called on BackgroundFetchContext.
bool shutting_down_ = false;
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
base::WeakPtr<StoragePartitionImpl> storage_partition_;
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
// The blob storage request with which response information will be stored.
scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
// Pending database operations, serialized to ensure consistency.
// Invariant: the frontmost task, if any, has already been started.
base::queue<std::unique_ptr<background_fetch::DatabaseTask>> database_tasks_;
base::ObserverList<BackgroundFetchDataManagerObserver>::Unchecked observers_;
// The |unique_id|s of registrations that have been deactivated since the
// browser was last started. They will be automatically deleted when the
// refcount of JavaScript objects that refers to them goes to zero, unless
// the browser is shutdown first.
std::set<std::string> ref_counted_unique_ids_;
// A map of open CacheStorage remotes keyed by the registration
// |unique_id|. These remotes are created opportunistically in
// GetOrOpenCacheStorage(). They are cleared after the Cache has been
// deleted.
// TODO(crbug.com/40515511): Possibly update key when CORS support is added.
std::map<std::string, mojo::Remote<blink::mojom::CacheStorage>>
cache_storage_remote_map_;
mojo::Remote<blink::mojom::CacheStorage> null_remote_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<BackgroundFetchDataManager> weak_ptr_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_DATA_MANAGER_H_