Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / content / browser / background_sync / background_sync_manager.cc
blob6ba38b57924d1e0dbe2ded9e8775ea56e176531d
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.
5 #include "content/browser/background_sync/background_sync_manager.h"
7 #include "base/barrier_closure.h"
8 #include "base/bind.h"
9 #include "base/location.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "content/browser/background_sync/background_sync_metrics.h"
13 #include "content/browser/background_sync/background_sync_network_observer.h"
14 #include "content/browser/background_sync/background_sync_power_observer.h"
15 #include "content/browser/background_sync/background_sync_registration_options.h"
16 #include "content/browser/service_worker/service_worker_context_wrapper.h"
17 #include "content/browser/service_worker/service_worker_storage.h"
18 #include "content/public/browser/browser_thread.h"
20 #if defined(OS_ANDROID)
21 #include "content/browser/android/background_sync_launcher_android.h"
22 #endif
24 namespace {
25 const char kBackgroundSyncUserDataKey[] = "BackgroundSyncUserData";
28 namespace content {
30 BackgroundSyncManager::BackgroundSyncRegistrations::
31 BackgroundSyncRegistrations()
32 : next_id(BackgroundSyncRegistration::kInitialId) {
35 BackgroundSyncManager::BackgroundSyncRegistrations::
36 ~BackgroundSyncRegistrations() {
39 // static
40 scoped_ptr<BackgroundSyncManager> BackgroundSyncManager::Create(
41 const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context) {
42 DCHECK_CURRENTLY_ON(BrowserThread::IO);
44 BackgroundSyncManager* sync_manager =
45 new BackgroundSyncManager(service_worker_context);
46 sync_manager->Init();
47 return make_scoped_ptr(sync_manager);
50 BackgroundSyncManager::~BackgroundSyncManager() {
51 DCHECK_CURRENTLY_ON(BrowserThread::IO);
53 service_worker_context_->RemoveObserver(this);
56 BackgroundSyncManager::RegistrationKey::RegistrationKey(
57 const BackgroundSyncRegistration& registration)
58 : RegistrationKey(registration.options()->tag,
59 registration.options()->periodicity) {
62 BackgroundSyncManager::RegistrationKey::RegistrationKey(
63 const BackgroundSyncRegistrationOptions& options)
64 : RegistrationKey(options.tag, options.periodicity) {
67 BackgroundSyncManager::RegistrationKey::RegistrationKey(
68 const std::string& tag,
69 SyncPeriodicity periodicity)
70 : value_(periodicity == SYNC_ONE_SHOT ? "o_" + tag : "p_" + tag) {
73 void BackgroundSyncManager::Register(
74 int64 sw_registration_id,
75 const BackgroundSyncRegistrationOptions& options,
76 bool requested_from_service_worker,
77 const StatusAndRegistrationCallback& callback) {
78 DCHECK_CURRENTLY_ON(BrowserThread::IO);
80 // For UMA, determine here whether the sync could fire immediately
81 BackgroundSyncMetrics::RegistrationCouldFire registration_could_fire =
82 AreOptionConditionsMet(options)
83 ? BackgroundSyncMetrics::REGISTRATION_COULD_FIRE
84 : BackgroundSyncMetrics::REGISTRATION_COULD_NOT_FIRE;
86 if (disabled_) {
87 BackgroundSyncMetrics::CountRegister(
88 options.periodicity, registration_could_fire,
89 BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE,
90 BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
91 base::ThreadTaskRunnerHandle::Get()->PostTask(
92 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
93 BackgroundSyncRegistration()));
94 return;
97 op_scheduler_.ScheduleOperation(base::Bind(
98 &BackgroundSyncManager::RegisterImpl, weak_ptr_factory_.GetWeakPtr(),
99 sw_registration_id, options, requested_from_service_worker,
100 MakeStatusAndRegistrationCompletion(callback)));
103 void BackgroundSyncManager::Unregister(
104 int64 sw_registration_id,
105 const std::string& sync_registration_tag,
106 SyncPeriodicity periodicity,
107 BackgroundSyncRegistration::RegistrationId sync_registration_id,
108 const StatusCallback& callback) {
109 DCHECK_CURRENTLY_ON(BrowserThread::IO);
111 if (disabled_) {
112 BackgroundSyncMetrics::CountUnregister(
113 periodicity, BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
114 base::ThreadTaskRunnerHandle::Get()->PostTask(
115 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR));
116 return;
119 RegistrationKey registration_key(sync_registration_tag, periodicity);
121 op_scheduler_.ScheduleOperation(base::Bind(
122 &BackgroundSyncManager::UnregisterImpl, weak_ptr_factory_.GetWeakPtr(),
123 sw_registration_id, registration_key, sync_registration_id, periodicity,
124 MakeStatusCompletion(callback)));
127 void BackgroundSyncManager::GetRegistration(
128 int64 sw_registration_id,
129 const std::string& sync_registration_tag,
130 SyncPeriodicity periodicity,
131 const StatusAndRegistrationCallback& callback) {
132 DCHECK_CURRENTLY_ON(BrowserThread::IO);
134 if (disabled_) {
135 base::ThreadTaskRunnerHandle::Get()->PostTask(
136 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
137 BackgroundSyncRegistration()));
138 return;
141 RegistrationKey registration_key(sync_registration_tag, periodicity);
143 op_scheduler_.ScheduleOperation(base::Bind(
144 &BackgroundSyncManager::GetRegistrationImpl,
145 weak_ptr_factory_.GetWeakPtr(), sw_registration_id, registration_key,
146 MakeStatusAndRegistrationCompletion(callback)));
149 void BackgroundSyncManager::GetRegistrations(
150 int64 sw_registration_id,
151 SyncPeriodicity periodicity,
152 const StatusAndRegistrationsCallback& callback) {
153 DCHECK_CURRENTLY_ON(BrowserThread::IO);
155 if (disabled_) {
156 base::ThreadTaskRunnerHandle::Get()->PostTask(
157 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
158 std::vector<BackgroundSyncRegistration>()));
159 return;
162 op_scheduler_.ScheduleOperation(
163 base::Bind(&BackgroundSyncManager::GetRegistrationsImpl,
164 weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
165 periodicity, MakeStatusAndRegistrationsCompletion(callback)));
168 void BackgroundSyncManager::OnRegistrationDeleted(int64 registration_id,
169 const GURL& pattern) {
170 DCHECK_CURRENTLY_ON(BrowserThread::IO);
172 // Operations already in the queue will either fail when they write to storage
173 // or return stale results based on registrations loaded in memory. This is
174 // inconsequential since the service worker is gone.
175 op_scheduler_.ScheduleOperation(base::Bind(
176 &BackgroundSyncManager::OnRegistrationDeletedImpl,
177 weak_ptr_factory_.GetWeakPtr(), registration_id, MakeEmptyCompletion()));
180 void BackgroundSyncManager::OnStorageWiped() {
181 DCHECK_CURRENTLY_ON(BrowserThread::IO);
183 // Operations already in the queue will either fail when they write to storage
184 // or return stale results based on registrations loaded in memory. This is
185 // inconsequential since the service workers are gone.
186 op_scheduler_.ScheduleOperation(
187 base::Bind(&BackgroundSyncManager::OnStorageWipedImpl,
188 weak_ptr_factory_.GetWeakPtr(), MakeEmptyCompletion()));
191 BackgroundSyncManager::BackgroundSyncManager(
192 const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context)
193 : service_worker_context_(service_worker_context),
194 disabled_(false),
195 weak_ptr_factory_(this) {
196 DCHECK_CURRENTLY_ON(BrowserThread::IO);
198 service_worker_context_->AddObserver(this);
200 network_observer_.reset(new BackgroundSyncNetworkObserver(
201 base::Bind(&BackgroundSyncManager::OnNetworkChanged,
202 weak_ptr_factory_.GetWeakPtr())));
203 power_observer_.reset(new BackgroundSyncPowerObserver(base::Bind(
204 &BackgroundSyncManager::OnPowerChanged, weak_ptr_factory_.GetWeakPtr())));
207 void BackgroundSyncManager::Init() {
208 DCHECK_CURRENTLY_ON(BrowserThread::IO);
209 DCHECK(!op_scheduler_.ScheduledOperations());
210 DCHECK(!disabled_);
212 op_scheduler_.ScheduleOperation(base::Bind(&BackgroundSyncManager::InitImpl,
213 weak_ptr_factory_.GetWeakPtr(),
214 MakeEmptyCompletion()));
217 void BackgroundSyncManager::InitImpl(const base::Closure& callback) {
218 DCHECK_CURRENTLY_ON(BrowserThread::IO);
220 if (disabled_) {
221 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
222 base::Bind(callback));
223 return;
226 GetDataFromBackend(
227 kBackgroundSyncUserDataKey,
228 base::Bind(&BackgroundSyncManager::InitDidGetDataFromBackend,
229 weak_ptr_factory_.GetWeakPtr(), callback));
232 void BackgroundSyncManager::InitDidGetDataFromBackend(
233 const base::Closure& callback,
234 const std::vector<std::pair<int64, std::string>>& user_data,
235 ServiceWorkerStatusCode status) {
236 DCHECK_CURRENTLY_ON(BrowserThread::IO);
238 if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
239 LOG(ERROR) << "BackgroundSync failed to init due to backend failure.";
240 DisableAndClearManager(base::Bind(callback));
241 return;
244 bool corruption_detected = false;
245 for (const std::pair<int64, std::string>& data : user_data) {
246 BackgroundSyncRegistrationsProto registrations_proto;
247 if (registrations_proto.ParseFromString(data.second)) {
248 BackgroundSyncRegistrations* registrations =
249 &sw_to_registrations_map_[data.first];
250 registrations->next_id = registrations_proto.next_registration_id();
251 registrations->origin = GURL(registrations_proto.origin());
253 for (int i = 0, max = registrations_proto.registration_size(); i < max;
254 ++i) {
255 const BackgroundSyncRegistrationProto& registration_proto =
256 registrations_proto.registration(i);
258 if (registration_proto.id() >= registrations->next_id) {
259 corruption_detected = true;
260 break;
263 RegistrationKey registration_key(registration_proto.tag(),
264 registration_proto.periodicity());
265 BackgroundSyncRegistration* registration =
266 &registrations->registration_map[registration_key];
268 BackgroundSyncRegistrationOptions* options = registration->options();
269 options->tag = registration_proto.tag();
270 options->periodicity = registration_proto.periodicity();
271 options->min_period = registration_proto.min_period();
272 options->network_state = registration_proto.network_state();
273 options->power_state = registration_proto.power_state();
275 registration->set_id(registration_proto.id());
276 registration->set_sync_state(registration_proto.sync_state());
278 if (registration->sync_state() == SYNC_STATE_FIRING) {
279 // If the browser (or worker) closed while firing the event, consider
280 // it pending again>
281 registration->set_sync_state(SYNC_STATE_PENDING);
286 if (corruption_detected)
287 break;
290 if (corruption_detected) {
291 LOG(ERROR) << "Corruption detected in background sync backend";
292 DisableAndClearManager(base::Bind(callback));
293 return;
296 FireReadyEvents();
298 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
299 base::Bind(callback));
302 void BackgroundSyncManager::RegisterImpl(
303 int64 sw_registration_id,
304 const BackgroundSyncRegistrationOptions& options,
305 bool requested_from_service_worker,
306 const StatusAndRegistrationCallback& callback) {
307 DCHECK_CURRENTLY_ON(BrowserThread::IO);
309 // For UMA, determine here whether the sync could fire immediately
310 BackgroundSyncMetrics::RegistrationCouldFire registration_could_fire =
311 AreOptionConditionsMet(options)
312 ? BackgroundSyncMetrics::REGISTRATION_COULD_FIRE
313 : BackgroundSyncMetrics::REGISTRATION_COULD_NOT_FIRE;
315 if (disabled_) {
316 BackgroundSyncMetrics::CountRegister(
317 options.periodicity, registration_could_fire,
318 BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE,
319 BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
320 base::ThreadTaskRunnerHandle::Get()->PostTask(
321 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
322 BackgroundSyncRegistration()));
323 return;
326 ServiceWorkerRegistration* sw_registration =
327 service_worker_context_->GetLiveRegistration(sw_registration_id);
328 if (!sw_registration || !sw_registration->active_version()) {
329 BackgroundSyncMetrics::CountRegister(
330 options.periodicity, registration_could_fire,
331 BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE,
332 BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER);
333 base::ThreadTaskRunnerHandle::Get()->PostTask(
334 FROM_HERE,
335 base::Bind(callback, BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER,
336 BackgroundSyncRegistration()));
337 return;
340 if (requested_from_service_worker &&
341 !sw_registration->active_version()->HasWindowClients()) {
342 base::ThreadTaskRunnerHandle::Get()->PostTask(
343 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_NOT_ALLOWED,
344 BackgroundSyncRegistration()));
345 return;
348 BackgroundSyncRegistration* existing_registration =
349 LookupRegistration(sw_registration_id, RegistrationKey(options));
350 if (existing_registration &&
351 existing_registration->options()->Equals(options)) {
352 if (existing_registration->sync_state() == SYNC_STATE_FAILED) {
353 existing_registration->set_sync_state(SYNC_STATE_PENDING);
354 StoreRegistrations(
355 sw_registration_id,
356 base::Bind(&BackgroundSyncManager::RegisterDidStore,
357 weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
358 *existing_registration, callback));
359 return;
362 // Record the duplicated registration
363 BackgroundSyncMetrics::CountRegister(
364 existing_registration->options()->periodicity, registration_could_fire,
365 BackgroundSyncMetrics::REGISTRATION_IS_DUPLICATE,
366 BACKGROUND_SYNC_STATUS_OK);
368 base::ThreadTaskRunnerHandle::Get()->PostTask(
369 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_OK,
370 *existing_registration));
371 return;
374 BackgroundSyncRegistration new_registration;
375 *new_registration.options() = options;
377 BackgroundSyncRegistrations* registrations =
378 &sw_to_registrations_map_[sw_registration_id];
379 new_registration.set_id(registrations->next_id++);
381 AddRegistrationToMap(sw_registration_id,
382 sw_registration->pattern().GetOrigin(),
383 new_registration);
385 StoreRegistrations(
386 sw_registration_id,
387 base::Bind(&BackgroundSyncManager::RegisterDidStore,
388 weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
389 new_registration, callback));
392 void BackgroundSyncManager::DisableAndClearManager(
393 const base::Closure& callback) {
394 DCHECK_CURRENTLY_ON(BrowserThread::IO);
396 if (disabled_) {
397 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
398 base::Bind(callback));
399 return;
402 disabled_ = true;
403 sw_to_registrations_map_.clear();
405 // Delete all backend entries. The memory representation of registered syncs
406 // may be out of sync with storage (e.g., due to corruption detection on
407 // loading from storage), so reload the registrations from storage again.
408 GetDataFromBackend(
409 kBackgroundSyncUserDataKey,
410 base::Bind(&BackgroundSyncManager::DisableAndClearDidGetRegistrations,
411 weak_ptr_factory_.GetWeakPtr(), callback));
414 void BackgroundSyncManager::DisableAndClearDidGetRegistrations(
415 const base::Closure& callback,
416 const std::vector<std::pair<int64, std::string>>& user_data,
417 ServiceWorkerStatusCode status) {
418 DCHECK_CURRENTLY_ON(BrowserThread::IO);
420 if (status != SERVICE_WORKER_OK || user_data.empty()) {
421 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
422 base::Bind(callback));
423 return;
426 base::Closure barrier_closure =
427 base::BarrierClosure(user_data.size(), base::Bind(callback));
429 for (const auto& sw_id_and_regs : user_data) {
430 service_worker_context_->ClearRegistrationUserData(
431 sw_id_and_regs.first, kBackgroundSyncUserDataKey,
432 base::Bind(&BackgroundSyncManager::DisableAndClearManagerClearedOne,
433 weak_ptr_factory_.GetWeakPtr(), barrier_closure));
437 void BackgroundSyncManager::DisableAndClearManagerClearedOne(
438 const base::Closure& barrier_closure,
439 ServiceWorkerStatusCode status) {
440 DCHECK_CURRENTLY_ON(BrowserThread::IO);
442 // The status doesn't matter at this point, there is nothing else to be done.
443 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
444 base::Bind(barrier_closure));
447 BackgroundSyncRegistration* BackgroundSyncManager::LookupRegistration(
448 int64 sw_registration_id,
449 const RegistrationKey& registration_key) {
450 DCHECK_CURRENTLY_ON(BrowserThread::IO);
452 SWIdToRegistrationsMap::iterator it =
453 sw_to_registrations_map_.find(sw_registration_id);
454 if (it == sw_to_registrations_map_.end())
455 return nullptr;
457 BackgroundSyncRegistrations& registrations = it->second;
458 DCHECK_LE(BackgroundSyncRegistration::kInitialId, registrations.next_id);
459 DCHECK(!registrations.origin.is_empty());
461 auto key_and_registration_iter =
462 registrations.registration_map.find(registration_key);
463 if (key_and_registration_iter == registrations.registration_map.end())
464 return nullptr;
466 return &key_and_registration_iter->second;
469 void BackgroundSyncManager::StoreRegistrations(
470 int64 sw_registration_id,
471 const ServiceWorkerStorage::StatusCallback& callback) {
472 DCHECK_CURRENTLY_ON(BrowserThread::IO);
474 // Serialize the data.
475 const BackgroundSyncRegistrations& registrations =
476 sw_to_registrations_map_[sw_registration_id];
477 BackgroundSyncRegistrationsProto registrations_proto;
478 registrations_proto.set_next_registration_id(registrations.next_id);
479 registrations_proto.set_origin(registrations.origin.spec());
481 for (const auto& key_and_registration : registrations.registration_map) {
482 const BackgroundSyncRegistration& registration =
483 key_and_registration.second;
484 BackgroundSyncRegistrationProto* registration_proto =
485 registrations_proto.add_registration();
486 registration_proto->set_id(registration.id());
487 registration_proto->set_sync_state(registration.sync_state());
488 registration_proto->set_tag(registration.options()->tag);
489 registration_proto->set_periodicity(registration.options()->periodicity);
490 registration_proto->set_min_period(registration.options()->min_period);
491 registration_proto->set_network_state(
492 registration.options()->network_state);
493 registration_proto->set_power_state(registration.options()->power_state);
495 std::string serialized;
496 bool success = registrations_proto.SerializeToString(&serialized);
497 DCHECK(success);
499 StoreDataInBackend(sw_registration_id, registrations.origin,
500 kBackgroundSyncUserDataKey, serialized, callback);
503 void BackgroundSyncManager::RegisterDidStore(
504 int64 sw_registration_id,
505 const BackgroundSyncRegistration& new_registration,
506 const StatusAndRegistrationCallback& callback,
507 ServiceWorkerStatusCode status) {
508 DCHECK_CURRENTLY_ON(BrowserThread::IO);
510 // For UMA, determine here whether the sync could fire immediately
511 BackgroundSyncMetrics::RegistrationCouldFire registration_could_fire =
512 AreOptionConditionsMet(*new_registration.options())
513 ? BackgroundSyncMetrics::REGISTRATION_COULD_FIRE
514 : BackgroundSyncMetrics::REGISTRATION_COULD_NOT_FIRE;
516 if (status == SERVICE_WORKER_ERROR_NOT_FOUND) {
517 // The service worker registration is gone.
518 BackgroundSyncMetrics::CountRegister(
519 new_registration.options()->periodicity, registration_could_fire,
520 BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE,
521 BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
522 sw_to_registrations_map_.erase(sw_registration_id);
523 base::ThreadTaskRunnerHandle::Get()->PostTask(
524 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
525 BackgroundSyncRegistration()));
526 return;
529 if (status != SERVICE_WORKER_OK) {
530 LOG(ERROR) << "BackgroundSync failed to store registration due to backend "
531 "failure.";
532 BackgroundSyncMetrics::CountRegister(
533 new_registration.options()->periodicity, registration_could_fire,
534 BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE,
535 BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
536 DisableAndClearManager(base::Bind(callback,
537 BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
538 BackgroundSyncRegistration()));
539 return;
542 BackgroundSyncMetrics::CountRegister(
543 new_registration.options()->periodicity, registration_could_fire,
544 BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE,
545 BACKGROUND_SYNC_STATUS_OK);
546 FireReadyEvents();
547 base::ThreadTaskRunnerHandle::Get()->PostTask(
548 FROM_HERE,
549 base::Bind(callback, BACKGROUND_SYNC_STATUS_OK, new_registration));
552 void BackgroundSyncManager::RemoveRegistrationFromMap(
553 int64 sw_registration_id,
554 const RegistrationKey& registration_key) {
555 DCHECK_CURRENTLY_ON(BrowserThread::IO);
556 DCHECK(LookupRegistration(sw_registration_id, registration_key));
558 BackgroundSyncRegistrations* registrations =
559 &sw_to_registrations_map_[sw_registration_id];
561 registrations->registration_map.erase(registration_key);
564 void BackgroundSyncManager::AddRegistrationToMap(
565 int64 sw_registration_id,
566 const GURL& origin,
567 const BackgroundSyncRegistration& sync_registration) {
568 DCHECK_CURRENTLY_ON(BrowserThread::IO);
569 DCHECK(sync_registration.IsValid());
571 BackgroundSyncRegistrations* registrations =
572 &sw_to_registrations_map_[sw_registration_id];
573 registrations->origin = origin;
575 RegistrationKey registration_key(sync_registration);
576 registrations->registration_map[registration_key] = sync_registration;
579 void BackgroundSyncManager::StoreDataInBackend(
580 int64 sw_registration_id,
581 const GURL& origin,
582 const std::string& backend_key,
583 const std::string& data,
584 const ServiceWorkerStorage::StatusCallback& callback) {
585 DCHECK_CURRENTLY_ON(BrowserThread::IO);
587 service_worker_context_->StoreRegistrationUserData(
588 sw_registration_id, origin, backend_key, data, callback);
591 void BackgroundSyncManager::GetDataFromBackend(
592 const std::string& backend_key,
593 const ServiceWorkerStorage::GetUserDataForAllRegistrationsCallback&
594 callback) {
595 DCHECK_CURRENTLY_ON(BrowserThread::IO);
597 service_worker_context_->GetUserDataForAllRegistrations(backend_key,
598 callback);
601 void BackgroundSyncManager::FireOneShotSync(
602 const BackgroundSyncRegistration& registration,
603 const scoped_refptr<ServiceWorkerVersion>& active_version,
604 const ServiceWorkerVersion::StatusCallback& callback) {
605 DCHECK_CURRENTLY_ON(BrowserThread::IO);
607 active_version->DispatchSyncEvent(
608 mojo::ConvertTo<SyncRegistrationPtr>(registration), callback);
611 void BackgroundSyncManager::UnregisterImpl(
612 int64 sw_registration_id,
613 const RegistrationKey& registration_key,
614 BackgroundSyncRegistration::RegistrationId sync_registration_id,
615 SyncPeriodicity periodicity,
616 const StatusCallback& callback) {
617 DCHECK_CURRENTLY_ON(BrowserThread::IO);
619 if (disabled_) {
620 BackgroundSyncMetrics::CountUnregister(
621 periodicity, BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
622 base::ThreadTaskRunnerHandle::Get()->PostTask(
623 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR));
624 return;
627 const BackgroundSyncRegistration* existing_registration =
628 LookupRegistration(sw_registration_id, registration_key);
629 if (!existing_registration ||
630 existing_registration->id() != sync_registration_id) {
631 BackgroundSyncMetrics::CountUnregister(periodicity,
632 BACKGROUND_SYNC_STATUS_NOT_FOUND);
633 base::ThreadTaskRunnerHandle::Get()->PostTask(
634 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_NOT_FOUND));
635 return;
638 RemoveRegistrationFromMap(sw_registration_id, registration_key);
640 StoreRegistrations(sw_registration_id,
641 base::Bind(&BackgroundSyncManager::UnregisterDidStore,
642 weak_ptr_factory_.GetWeakPtr(),
643 sw_registration_id, periodicity, callback));
646 void BackgroundSyncManager::UnregisterDidStore(int64 sw_registration_id,
647 SyncPeriodicity periodicity,
648 const StatusCallback& callback,
649 ServiceWorkerStatusCode status) {
650 DCHECK_CURRENTLY_ON(BrowserThread::IO);
652 if (status == SERVICE_WORKER_ERROR_NOT_FOUND) {
653 // ServiceWorker was unregistered.
654 BackgroundSyncMetrics::CountUnregister(
655 periodicity, BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
656 sw_to_registrations_map_.erase(sw_registration_id);
657 base::ThreadTaskRunnerHandle::Get()->PostTask(
658 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR));
659 return;
662 if (status != SERVICE_WORKER_OK) {
663 LOG(ERROR) << "BackgroundSync failed to unregister due to backend failure.";
664 BackgroundSyncMetrics::CountUnregister(
665 periodicity, BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
666 DisableAndClearManager(
667 base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR));
668 return;
671 BackgroundSyncMetrics::CountUnregister(periodicity,
672 BACKGROUND_SYNC_STATUS_OK);
673 base::ThreadTaskRunnerHandle::Get()->PostTask(
674 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_OK));
677 void BackgroundSyncManager::GetRegistrationImpl(
678 int64 sw_registration_id,
679 const RegistrationKey& registration_key,
680 const StatusAndRegistrationCallback& callback) {
681 DCHECK_CURRENTLY_ON(BrowserThread::IO);
683 if (disabled_) {
684 base::ThreadTaskRunnerHandle::Get()->PostTask(
685 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
686 BackgroundSyncRegistration()));
687 return;
690 const BackgroundSyncRegistration* out_registration =
691 LookupRegistration(sw_registration_id, registration_key);
692 if (!out_registration) {
693 base::ThreadTaskRunnerHandle::Get()->PostTask(
694 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_NOT_FOUND,
695 BackgroundSyncRegistration()));
696 return;
699 base::ThreadTaskRunnerHandle::Get()->PostTask(
700 FROM_HERE,
701 base::Bind(callback, BACKGROUND_SYNC_STATUS_OK, *out_registration));
704 void BackgroundSyncManager::GetRegistrationsImpl(
705 int64 sw_registration_id,
706 SyncPeriodicity periodicity,
707 const StatusAndRegistrationsCallback& callback) {
708 DCHECK_CURRENTLY_ON(BrowserThread::IO);
710 std::vector<BackgroundSyncRegistration> out_registrations;
712 if (disabled_) {
713 base::ThreadTaskRunnerHandle::Get()->PostTask(
714 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
715 out_registrations));
716 return;
719 SWIdToRegistrationsMap::iterator it =
720 sw_to_registrations_map_.find(sw_registration_id);
722 if (it != sw_to_registrations_map_.end()) {
723 const BackgroundSyncRegistrations& registrations = it->second;
724 for (const auto& tag_and_registration : registrations.registration_map) {
725 const BackgroundSyncRegistration& registration =
726 tag_and_registration.second;
727 if (registration.options()->periodicity == periodicity)
728 out_registrations.push_back(registration);
732 base::ThreadTaskRunnerHandle::Get()->PostTask(
733 FROM_HERE,
734 base::Bind(callback, BACKGROUND_SYNC_STATUS_OK, out_registrations));
737 bool BackgroundSyncManager::AreOptionConditionsMet(
738 const BackgroundSyncRegistrationOptions& options) {
739 DCHECK_CURRENTLY_ON(BrowserThread::IO);
740 return network_observer_->NetworkSufficient(options.network_state) &&
741 power_observer_->PowerSufficient(options.power_state);
744 bool BackgroundSyncManager::IsRegistrationReadyToFire(
745 const BackgroundSyncRegistration& registration) {
746 DCHECK_CURRENTLY_ON(BrowserThread::IO);
748 // TODO(jkarlin): Add support for firing periodic registrations.
749 if (registration.options()->periodicity == SYNC_PERIODIC)
750 return false;
752 if (registration.sync_state() != SYNC_STATE_PENDING)
753 return false;
755 DCHECK_EQ(SYNC_ONE_SHOT, registration.options()->periodicity);
757 return AreOptionConditionsMet(*registration.options());
760 void BackgroundSyncManager::SchedulePendingRegistrations() {
761 #if defined(OS_ANDROID)
762 bool keep_browser_alive_for_one_shot = false;
764 for (const auto& sw_id_and_registrations : sw_to_registrations_map_) {
765 for (const auto& key_and_registration :
766 sw_id_and_registrations.second.registration_map) {
767 const BackgroundSyncRegistration& registration =
768 key_and_registration.second;
769 if (registration.sync_state() == SYNC_STATE_PENDING) {
770 if (registration.options()->periodicity == SYNC_ONE_SHOT) {
771 keep_browser_alive_for_one_shot = true;
772 } else {
773 // TODO(jkarlin): Support keeping the browser alive for periodic
774 // syncs.
780 // TODO(jkarlin): Use the context's path instead of the 'this' pointer as an
781 // identifier. See crbug.com/489705.
782 BrowserThread::PostTask(
783 BrowserThread::UI, FROM_HERE,
784 base::Bind(&BackgroundSyncLauncherAndroid::LaunchBrowserWhenNextOnline,
785 this, keep_browser_alive_for_one_shot));
786 #else
787 // TODO(jkarlin): Toggle Chrome's background mode.
788 #endif
791 void BackgroundSyncManager::FireReadyEvents() {
792 DCHECK_CURRENTLY_ON(BrowserThread::IO);
794 if (disabled_)
795 return;
797 op_scheduler_.ScheduleOperation(
798 base::Bind(&BackgroundSyncManager::FireReadyEventsImpl,
799 weak_ptr_factory_.GetWeakPtr(), MakeEmptyCompletion()));
802 void BackgroundSyncManager::FireReadyEventsImpl(const base::Closure& callback) {
803 DCHECK_CURRENTLY_ON(BrowserThread::IO);
805 if (disabled_) {
806 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
807 base::Bind(callback));
808 return;
811 // Find the registrations that are ready to run.
812 std::vector<std::pair<int64, RegistrationKey>> sw_id_and_keys_to_fire;
814 for (auto& sw_id_and_registrations : sw_to_registrations_map_) {
815 const int64 service_worker_id = sw_id_and_registrations.first;
816 for (auto& key_and_registration :
817 sw_id_and_registrations.second.registration_map) {
818 BackgroundSyncRegistration* registration = &key_and_registration.second;
819 if (IsRegistrationReadyToFire(*registration)) {
820 sw_id_and_keys_to_fire.push_back(
821 std::make_pair(service_worker_id, key_and_registration.first));
822 // The state change is not saved to persistent storage because
823 // if the sync event is killed mid-sync then it should return to
824 // SYNC_STATE_PENDING.
825 registration->set_sync_state(SYNC_STATE_FIRING);
830 // If there are no registrations currently ready, then just run |callback|.
831 // Otherwise, fire them all, and record the result when done.
832 if (sw_id_and_keys_to_fire.size() == 0) {
833 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
834 base::Bind(callback));
835 } else {
836 base::TimeTicks start_time = base::TimeTicks::Now();
838 // Fire the sync event of the ready registrations and run |callback| once
839 // they're all done.
840 base::Closure events_fired_barrier_closure = base::BarrierClosure(
841 sw_id_and_keys_to_fire.size(), base::Bind(callback));
843 // Record the total time taken after all events have run to completion.
844 base::Closure events_completed_barrier_closure =
845 base::BarrierClosure(sw_id_and_keys_to_fire.size(),
846 base::Bind(&OnAllSyncEventsCompleted, start_time,
847 sw_id_and_keys_to_fire.size()));
849 for (const auto& sw_id_and_key : sw_id_and_keys_to_fire) {
850 int64 service_worker_id = sw_id_and_key.first;
851 const BackgroundSyncRegistration* registration =
852 LookupRegistration(service_worker_id, sw_id_and_key.second);
854 service_worker_context_->FindRegistrationForId(
855 service_worker_id, sw_to_registrations_map_[service_worker_id].origin,
856 base::Bind(&BackgroundSyncManager::FireReadyEventsDidFindRegistration,
857 weak_ptr_factory_.GetWeakPtr(), sw_id_and_key.second,
858 registration->id(), events_fired_barrier_closure,
859 events_completed_barrier_closure));
863 SchedulePendingRegistrations();
866 void BackgroundSyncManager::FireReadyEventsDidFindRegistration(
867 const RegistrationKey& registration_key,
868 BackgroundSyncRegistration::RegistrationId registration_id,
869 const base::Closure& event_fired_callback,
870 const base::Closure& event_completed_callback,
871 ServiceWorkerStatusCode service_worker_status,
872 const scoped_refptr<ServiceWorkerRegistration>&
873 service_worker_registration) {
874 DCHECK_CURRENTLY_ON(BrowserThread::IO);
875 if (service_worker_status != SERVICE_WORKER_OK) {
876 base::ThreadTaskRunnerHandle::Get()->PostTask(
877 FROM_HERE, base::Bind(event_fired_callback));
878 base::ThreadTaskRunnerHandle::Get()->PostTask(
879 FROM_HERE, base::Bind(event_completed_callback));
880 return;
883 BackgroundSyncRegistration* registration =
884 LookupRegistration(service_worker_registration->id(), registration_key);
886 FireOneShotSync(
887 *registration, service_worker_registration->active_version(),
888 base::Bind(&BackgroundSyncManager::EventComplete,
889 weak_ptr_factory_.GetWeakPtr(), service_worker_registration,
890 service_worker_registration->id(), registration_key,
891 registration_id, event_completed_callback));
893 base::ThreadTaskRunnerHandle::Get()->PostTask(
894 FROM_HERE, base::Bind(event_fired_callback));
897 // |service_worker_registration| is just to keep the registration alive
898 // while the event is firing.
899 void BackgroundSyncManager::EventComplete(
900 const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
901 int64 service_worker_id,
902 const RegistrationKey& key,
903 BackgroundSyncRegistration::RegistrationId sync_registration_id,
904 const base::Closure& callback,
905 ServiceWorkerStatusCode status_code) {
906 DCHECK_CURRENTLY_ON(BrowserThread::IO);
907 if (disabled_)
908 return;
910 op_scheduler_.ScheduleOperation(base::Bind(
911 &BackgroundSyncManager::EventCompleteImpl, weak_ptr_factory_.GetWeakPtr(),
912 service_worker_id, key, sync_registration_id, status_code,
913 MakeClosureCompletion(callback)));
916 void BackgroundSyncManager::EventCompleteImpl(
917 int64 service_worker_id,
918 const RegistrationKey& key,
919 BackgroundSyncRegistration::RegistrationId sync_registration_id,
920 ServiceWorkerStatusCode status_code,
921 const base::Closure& callback) {
922 DCHECK_CURRENTLY_ON(BrowserThread::IO);
924 if (disabled_) {
925 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
926 base::Bind(callback));
927 return;
930 BackgroundSyncRegistration* registration =
931 LookupRegistration(service_worker_id, key);
932 if (!registration || registration->id() != sync_registration_id) {
933 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
934 base::Bind(callback));
935 return;
938 // The event ran to completion, we should count it, no matter what happens
939 // from here.
940 BackgroundSyncMetrics::RecordEventResult(registration->options()->periodicity,
941 status_code == SERVICE_WORKER_OK);
943 if (registration->options()->periodicity == SYNC_ONE_SHOT) {
944 if (status_code != SERVICE_WORKER_OK) {
945 // TODO(jkarlin) Fire the sync event on the next page load controlled by
946 // this registration. (crbug.com/479665)
947 registration->set_sync_state(SYNC_STATE_FAILED);
948 } else {
949 registration = nullptr;
950 RemoveRegistrationFromMap(service_worker_id, key);
952 } else {
953 // TODO(jkarlin): Add support for running periodic syncs. (crbug.com/479674)
954 NOTREACHED();
957 StoreRegistrations(
958 service_worker_id,
959 base::Bind(&BackgroundSyncManager::EventCompleteDidStore,
960 weak_ptr_factory_.GetWeakPtr(), service_worker_id, callback));
963 void BackgroundSyncManager::EventCompleteDidStore(
964 int64 service_worker_id,
965 const base::Closure& callback,
966 ServiceWorkerStatusCode status_code) {
967 DCHECK_CURRENTLY_ON(BrowserThread::IO);
969 if (status_code == SERVICE_WORKER_ERROR_NOT_FOUND) {
970 // The registration is gone.
971 sw_to_registrations_map_.erase(service_worker_id);
972 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
973 base::Bind(callback));
974 return;
977 if (status_code != SERVICE_WORKER_OK) {
978 LOG(ERROR) << "BackgroundSync failed to store registration due to backend "
979 "failure.";
980 DisableAndClearManager(base::Bind(callback));
981 return;
984 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
985 base::Bind(callback));
988 // static
989 void BackgroundSyncManager::OnAllSyncEventsCompleted(
990 const base::TimeTicks& start_time,
991 int number_of_batched_sync_events) {
992 // Record the combined time taken by all sync events.
993 BackgroundSyncMetrics::RecordBatchSyncEventComplete(
994 base::TimeTicks::Now() - start_time, number_of_batched_sync_events);
997 void BackgroundSyncManager::OnRegistrationDeletedImpl(
998 int64 registration_id,
999 const base::Closure& callback) {
1000 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1002 // The backend (ServiceWorkerStorage) will delete the data, so just delete the
1003 // memory representation here.
1004 sw_to_registrations_map_.erase(registration_id);
1005 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1006 base::Bind(callback));
1009 void BackgroundSyncManager::OnStorageWipedImpl(const base::Closure& callback) {
1010 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1012 sw_to_registrations_map_.clear();
1013 disabled_ = false;
1014 InitImpl(callback);
1017 void BackgroundSyncManager::OnNetworkChanged() {
1018 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1020 FireReadyEvents();
1023 void BackgroundSyncManager::OnPowerChanged() {
1024 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1026 FireReadyEvents();
1029 template <typename CallbackT, typename... Params>
1030 void BackgroundSyncManager::CompleteOperationCallback(const CallbackT& callback,
1031 Params... parameters) {
1032 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1034 callback.Run(parameters...);
1035 op_scheduler_.CompleteOperationAndRunNext();
1038 base::Closure BackgroundSyncManager::MakeEmptyCompletion() {
1039 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1041 return MakeClosureCompletion(base::Bind(base::DoNothing));
1044 base::Closure BackgroundSyncManager::MakeClosureCompletion(
1045 const base::Closure& callback) {
1046 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1048 return base::Bind(
1049 &BackgroundSyncManager::CompleteOperationCallback<base::Closure>,
1050 weak_ptr_factory_.GetWeakPtr(), callback);
1053 BackgroundSyncManager::StatusAndRegistrationCallback
1054 BackgroundSyncManager::MakeStatusAndRegistrationCompletion(
1055 const StatusAndRegistrationCallback& callback) {
1056 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1058 return base::Bind(&BackgroundSyncManager::CompleteOperationCallback<
1059 StatusAndRegistrationCallback, BackgroundSyncStatus,
1060 const BackgroundSyncRegistration&>,
1061 weak_ptr_factory_.GetWeakPtr(), callback);
1064 BackgroundSyncManager::StatusAndRegistrationsCallback
1065 BackgroundSyncManager::MakeStatusAndRegistrationsCompletion(
1066 const StatusAndRegistrationsCallback& callback) {
1067 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1069 return base::Bind(&BackgroundSyncManager::CompleteOperationCallback<
1070 StatusAndRegistrationsCallback, BackgroundSyncStatus,
1071 const std::vector<BackgroundSyncRegistration>&>,
1072 weak_ptr_factory_.GetWeakPtr(), callback);
1075 BackgroundSyncManager::StatusCallback
1076 BackgroundSyncManager::MakeStatusCompletion(const StatusCallback& callback) {
1077 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1079 return base::Bind(
1080 &BackgroundSyncManager::CompleteOperationCallback<StatusCallback,
1081 BackgroundSyncStatus>,
1082 weak_ptr_factory_.GetWeakPtr(), callback);
1085 } // namespace content