Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(630)

Side by Side Diff: content/browser/background_sync/background_sync_manager.cc

Issue 950343006: [BackgroundSync] Initial land of the BackgroundSyncManager (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: CONTENT_EXPORT for nested classes Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/background_sync/background_sync_manager.h"
6
7 #include "base/barrier_closure.h"
8 #include "base/bind.h"
9 #include "content/browser/background_sync/background_sync.pb.h"
10 #include "content/browser/service_worker/service_worker_context_wrapper.h"
11 #include "content/browser/service_worker/service_worker_storage.h"
12 #include "content/public/browser/browser_thread.h"
13
14 namespace {
15 const char kBackgroundSyncUserDataKey[] = "BackgroundSyncUserData";
16 }
17
18 namespace content {
19
20 const BackgroundSyncManager::BackgroundSyncRegistration::RegistrationId
21 BackgroundSyncManager::BackgroundSyncRegistration::kInvalidRegistrationId =
22 -1;
23
24 const BackgroundSyncManager::BackgroundSyncRegistration::RegistrationId
25 BackgroundSyncManager::BackgroundSyncRegistrations::kInitialId = 0;
26
27 BackgroundSyncManager::BackgroundSyncRegistrations::
28 BackgroundSyncRegistrations()
29 : next_id(kInitialId) {
30 }
31 BackgroundSyncManager::BackgroundSyncRegistrations::BackgroundSyncRegistrations(
32 BackgroundSyncRegistration::RegistrationId next_id)
33 : next_id(next_id) {
34 }
35 BackgroundSyncManager::BackgroundSyncRegistrations::
36 ~BackgroundSyncRegistrations() {
37 }
38
39 // static
40 scoped_ptr<BackgroundSyncManager> BackgroundSyncManager::Create(
41 const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context) {
42 BackgroundSyncManager* sync_manager =
43 new BackgroundSyncManager(service_worker_context);
44 sync_manager->Init();
45 return make_scoped_ptr(sync_manager);
46 }
47
48 BackgroundSyncManager::~BackgroundSyncManager() {
49 }
50
51 void BackgroundSyncManager::Register(
52 const GURL& origin,
53 int64 sw_registration_id,
54 const BackgroundSyncRegistration& sync_registration,
55 const StatusAndRegistrationCallback& callback) {
56 DCHECK_CURRENTLY_ON(BrowserThread::IO);
57 DCHECK_EQ(BackgroundSyncRegistration::kInvalidRegistrationId,
58 sync_registration.id);
59
60 StatusAndRegistrationCallback pending_callback =
61 base::Bind(&BackgroundSyncManager::PendingStatusAndRegistrationCallback,
62 weak_ptr_factory_.GetWeakPtr(), callback);
63
64 op_scheduler_.ScheduleOperation(base::Bind(
65 &BackgroundSyncManager::RegisterImpl, weak_ptr_factory_.GetWeakPtr(),
66 origin, sw_registration_id, sync_registration, pending_callback));
67 }
68
69 void BackgroundSyncManager::Unregister(
70 const GURL& origin,
71 int64 sw_registration_id,
72 const std::string& sync_registration_name,
73 BackgroundSyncRegistration::RegistrationId sync_registration_id,
74 const StatusCallback& callback) {
75 DCHECK_CURRENTLY_ON(BrowserThread::IO);
76
77 StatusCallback pending_callback =
78 base::Bind(&BackgroundSyncManager::PendingStatusCallback,
79 weak_ptr_factory_.GetWeakPtr(), callback);
80
81 op_scheduler_.ScheduleOperation(base::Bind(
82 &BackgroundSyncManager::UnregisterImpl, weak_ptr_factory_.GetWeakPtr(),
83 origin, sw_registration_id, sync_registration_name, sync_registration_id,
84 pending_callback));
85 }
86
87 void BackgroundSyncManager::GetRegistration(
88 const GURL& origin,
89 int64 sw_registration_id,
90 const std::string sync_registration_name,
91 const StatusAndRegistrationCallback& callback) {
92 DCHECK_CURRENTLY_ON(BrowserThread::IO);
93
94 StatusAndRegistrationCallback pending_callback =
95 base::Bind(&BackgroundSyncManager::PendingStatusAndRegistrationCallback,
96 weak_ptr_factory_.GetWeakPtr(), callback);
97
98 op_scheduler_.ScheduleOperation(
99 base::Bind(&BackgroundSyncManager::GetRegistrationImpl,
100 weak_ptr_factory_.GetWeakPtr(), origin, sw_registration_id,
101 sync_registration_name, pending_callback));
102 }
103
104 BackgroundSyncManager::BackgroundSyncManager(
105 const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context)
106 : service_worker_context_(service_worker_context), weak_ptr_factory_(this) {
107 }
108
109 void BackgroundSyncManager::Init() {
110 DCHECK_CURRENTLY_ON(BrowserThread::IO);
111 DCHECK(!op_scheduler_.ScheduledOperations());
112
113 op_scheduler_.ScheduleOperation(base::Bind(&BackgroundSyncManager::InitImpl,
114 weak_ptr_factory_.GetWeakPtr()));
115 }
116
117 void BackgroundSyncManager::InitImpl() {
118 DCHECK_CURRENTLY_ON(BrowserThread::IO);
119
120 GetDataFromBackend(
121 kBackgroundSyncUserDataKey,
122 base::Bind(&BackgroundSyncManager::InitDidGetDataFromBackend,
123 weak_ptr_factory_.GetWeakPtr()));
124 }
125
126 void BackgroundSyncManager::InitDidGetDataFromBackend(
127 const std::vector<std::pair<int64, std::string>>& user_data,
128 ServiceWorkerStatusCode status) {
129 if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND)
130 LOG(ERROR) << "Background Sync Failed to load from backend.";
131
132 bool corruption_detected = false;
133 for (const std::pair<int64, std::string>& data : user_data) {
134 BackgroundSyncRegistrationsProto registrations_proto;
135 if (registrations_proto.ParseFromString(data.second)) {
136 sw_to_registrations_map_[data.first] = BackgroundSyncRegistrations(
137 registrations_proto.next_registration_id());
138 BackgroundSyncRegistrations* registrations =
139 &sw_to_registrations_map_[data.first];
140
141 for (int i = 0, max = registrations_proto.registration_size(); i < max;
142 ++i) {
143 const BackgroundSyncRegistrationProto& registration_proto =
144 registrations_proto.registration(i);
145
146 if (registration_proto.id() >= registrations->next_id) {
147 corruption_detected = true;
148 break;
149 }
150
151 BackgroundSyncRegistration registration(registration_proto.id(),
152 registration_proto.name());
153 if (registration_proto.has_min_period())
154 registration.min_period = registration_proto.min_period();
155 registrations->name_to_registration_map[registration_proto.name()] =
156 registration;
157 }
158 }
159
160 if (corruption_detected)
161 break;
162 }
163
164 if (corruption_detected) {
165 LOG(ERROR) << "Corruption detected in background sync backend";
166 sw_to_registrations_map_.clear();
167 }
168
169 // TODO(jkarlin): Call the scheduling algorithm here.
170
171 op_scheduler_.CompleteOperationAndRunNext();
172 }
173
174 void BackgroundSyncManager::RegisterImpl(
175 const GURL& origin,
176 int64 sw_registration_id,
177 const BackgroundSyncRegistration& sync_registration,
178 const StatusAndRegistrationCallback& callback) {
179 BackgroundSyncRegistration existing_registration;
180 if (LookupRegistration(sw_registration_id, sync_registration.name,
181 &existing_registration)) {
182 if (existing_registration.Equals(sync_registration)) {
183 base::MessageLoop::current()->PostTask(
184 FROM_HERE,
185 base::Bind(callback, ERROR_TYPE_OK, existing_registration));
186 return;
187 }
188 }
189
190 BackgroundSyncRegistration new_registration = sync_registration;
191 BackgroundSyncRegistrations* registrations =
192 &sw_to_registrations_map_[sw_registration_id];
193 new_registration.id = registrations->next_id++;
194
195 AddRegistrationToMap(sw_registration_id, new_registration);
196
197 StoreRegistrations(
198 origin, sw_registration_id,
199 base::Bind(&BackgroundSyncManager::RegisterDidStore,
200 weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
201 new_registration, existing_registration, callback));
202 }
203
204 bool BackgroundSyncManager::LookupRegistration(
205 int64 sw_registration_id,
206 const std::string& sync_registration_name,
207 BackgroundSyncRegistration* existing_registration) {
208 SWIdToRegistrationsMap::iterator it =
209 sw_to_registrations_map_.find(sw_registration_id);
210 if (it == sw_to_registrations_map_.end())
211 return false;
212
213 const BackgroundSyncRegistrations& registrations = it->second;
214 const auto name_and_registration_iter =
215 registrations.name_to_registration_map.find(sync_registration_name);
216 if (name_and_registration_iter ==
217 registrations.name_to_registration_map.end())
218 return false;
219
220 if (existing_registration)
221 *existing_registration = name_and_registration_iter->second;
222
223 return true;
224 }
225
226 void BackgroundSyncManager::StoreRegistrations(
227 const GURL& origin,
228 int64 sw_registration_id,
229 const ServiceWorkerStorage::StatusCallback& callback) {
230 // Serialize the data.
231 const BackgroundSyncRegistrations& registrations =
232 sw_to_registrations_map_[sw_registration_id];
233 BackgroundSyncRegistrationsProto registrations_proto;
234 registrations_proto.set_next_registration_id(registrations.next_id);
235
236 for (const auto& name_and_registration :
237 registrations.name_to_registration_map) {
238 const BackgroundSyncRegistration& registration =
239 name_and_registration.second;
240 BackgroundSyncRegistrationProto* registration_proto =
241 registrations_proto.add_registration();
242 registration_proto->set_id(registration.id);
243 registration_proto->set_name(registration.name);
244 if (registration.min_period != 0)
245 registration_proto->set_min_period(registration.min_period);
246 }
247 std::string serialized;
248 bool success = registrations_proto.SerializeToString(&serialized);
249 DCHECK(success);
250
251 StoreDataInBackend(sw_registration_id, origin, kBackgroundSyncUserDataKey,
252 serialized, callback);
253 }
254
255 void BackgroundSyncManager::RegisterDidStore(
256 int64 sw_registration_id,
257 const BackgroundSyncRegistration& new_registration,
258 const BackgroundSyncRegistration& previous_registration,
259 const StatusAndRegistrationCallback& callback,
260 ServiceWorkerStatusCode status) {
261 if (status != SERVICE_WORKER_OK) {
262 // Restore the previous state.
263 if (previous_registration.id !=
264 BackgroundSyncRegistration::kInvalidRegistrationId) {
265 AddRegistrationToMap(sw_registration_id, previous_registration);
266 } else {
267 RemoveRegistrationFromMap(sw_registration_id, new_registration.name,
268 nullptr);
269 }
270 base::MessageLoop::current()->PostTask(
271 FROM_HERE,
272 base::Bind(callback, ERROR_TYPE_STORAGE, BackgroundSyncRegistration()));
273 return;
274 }
275
276 // TODO(jkarlin): Run the registration algorithm.
277 base::MessageLoop::current()->PostTask(
278 FROM_HERE, base::Bind(callback, ERROR_TYPE_OK, new_registration));
279 }
280
281 void BackgroundSyncManager::RemoveRegistrationFromMap(
282 int64 sw_registration_id,
283 const std::string& sync_registration_name,
284 BackgroundSyncRegistration* old_registration) {
285 DCHECK(
286 LookupRegistration(sw_registration_id, sync_registration_name, nullptr));
287
288 BackgroundSyncRegistrations* registrations =
289 &sw_to_registrations_map_[sw_registration_id];
290
291 const auto name_and_registration_iter =
292 registrations->name_to_registration_map.find(sync_registration_name);
293 if (old_registration)
294 *old_registration = name_and_registration_iter->second;
295
296 registrations->name_to_registration_map.erase(name_and_registration_iter);
297 }
298
299 void BackgroundSyncManager::AddRegistrationToMap(
300 int64 sw_registration_id,
301 const BackgroundSyncRegistration& sync_registration) {
302 DCHECK_NE(BackgroundSyncRegistration::kInvalidRegistrationId,
303 sw_registration_id);
304
305 BackgroundSyncRegistrations* registrations =
306 &sw_to_registrations_map_[sw_registration_id];
307 registrations->name_to_registration_map[sync_registration.name] =
308 sync_registration;
309 }
310
311 void BackgroundSyncManager::StoreDataInBackend(
312 int64 sw_registration_id,
313 const GURL& origin,
314 const std::string& key,
315 const std::string& data,
316 const ServiceWorkerStorage::StatusCallback& callback) {
317 service_worker_context_->context()->storage()->StoreUserData(
318 sw_registration_id, origin, key, data, callback);
319 }
320
321 void BackgroundSyncManager::GetDataFromBackend(
322 const std::string& key,
323 const ServiceWorkerStorage::GetUserDataForAllRegistrationsCallback&
324 callback) {
325 DCHECK_CURRENTLY_ON(BrowserThread::IO);
326
327 service_worker_context_->context()->storage()->GetUserDataForAllRegistrations(
328 key, callback);
329 }
330
331 void BackgroundSyncManager::UnregisterImpl(
332 const GURL& origin,
333 int64 sw_registration_id,
334 const std::string& sync_registration_name,
335 BackgroundSyncRegistration::RegistrationId sync_registration_id,
336 const StatusCallback& callback) {
337 BackgroundSyncRegistration existing_registration;
338 if (!LookupRegistration(sw_registration_id, sync_registration_name,
339 &existing_registration) ||
340 existing_registration.id != sync_registration_id) {
341 base::MessageLoop::current()->PostTask(
342 FROM_HERE, base::Bind(callback, ERROR_TYPE_NOT_FOUND));
343 return;
344 }
345
346 BackgroundSyncRegistration old_sync_registration;
347 RemoveRegistrationFromMap(sw_registration_id, sync_registration_name,
348 &old_sync_registration);
349
350 StoreRegistrations(
351 origin, sw_registration_id,
352 base::Bind(&BackgroundSyncManager::UnregisterDidStore,
353 weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
354 old_sync_registration, callback));
355 }
356
357 void BackgroundSyncManager::UnregisterDidStore(
358 int64 sw_registration_id,
359 const BackgroundSyncRegistration& old_sync_registration,
360 const StatusCallback& callback,
361 ServiceWorkerStatusCode status) {
362 if (status != SERVICE_WORKER_OK) {
363 // Restore the previous state.
364 AddRegistrationToMap(sw_registration_id, old_sync_registration);
365 base::MessageLoop::current()->PostTask(
366 FROM_HERE, base::Bind(callback, ERROR_TYPE_STORAGE));
367 return;
368 }
369
370 // TODO(jkarlin): Run the registration algorithm.
371 base::MessageLoop::current()->PostTask(FROM_HERE,
372 base::Bind(callback, ERROR_TYPE_OK));
373 }
374
375 void BackgroundSyncManager::GetRegistrationImpl(
376 const GURL& origin,
377 int64 sw_registration_id,
378 const std::string sync_registration_name,
379 const StatusAndRegistrationCallback& callback) {
380 BackgroundSyncRegistration out_registration;
381 if (!LookupRegistration(sw_registration_id, sync_registration_name,
382 &out_registration)) {
383 base::MessageLoop::current()->PostTask(
384 FROM_HERE, base::Bind(callback, ERROR_TYPE_NOT_FOUND,
385 BackgroundSyncRegistration()));
386 return;
387 }
388
389 base::MessageLoop::current()->PostTask(
390 FROM_HERE, base::Bind(callback, ERROR_TYPE_OK, out_registration));
391 }
392
393 void BackgroundSyncManager::PendingStatusAndRegistrationCallback(
394 const StatusAndRegistrationCallback& callback,
395 ErrorType error,
396 const BackgroundSyncRegistration& sync_registration) {
397 // The callback might delete this object, so hang onto a weak ptr to find out.
398 base::WeakPtr<BackgroundSyncManager> manager = weak_ptr_factory_.GetWeakPtr();
399 callback.Run(error, sync_registration);
400 if (manager)
401 op_scheduler_.CompleteOperationAndRunNext();
402 }
403
404 void BackgroundSyncManager::PendingStatusCallback(
405 const StatusCallback& callback,
406 ErrorType error) {
407 // The callback might delete this object, so hang onto a weak ptr to find out.
408 base::WeakPtr<BackgroundSyncManager> manager = weak_ptr_factory_.GetWeakPtr();
409 callback.Run(error);
410 if (manager)
411 op_scheduler_.CompleteOperationAndRunNext();
412 }
413
414 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698