Update broken references to image assets
[chromium-blink-merge.git] / content / browser / background_sync / background_sync_manager.cc
blob018bbae5ab270ecfc3905a191a9fbb48dd63cb93
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 const StatusAndRegistrationCallback& callback) {
77 DCHECK_CURRENTLY_ON(BrowserThread::IO);
79 // For UMA, determine here whether the sync could fire immediately
80 BackgroundSyncMetrics::RegistrationCouldFire registration_could_fire =
81 AreOptionConditionsMet(options)
82 ? BackgroundSyncMetrics::REGISTRATION_COULD_FIRE
83 : BackgroundSyncMetrics::REGISTRATION_COULD_NOT_FIRE;
85 if (disabled_) {
86 BackgroundSyncMetrics::CountRegister(
87 options.periodicity, registration_could_fire,
88 BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE,
89 BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
90 base::ThreadTaskRunnerHandle::Get()->PostTask(
91 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
92 BackgroundSyncRegistration()));
93 return;
96 op_scheduler_.ScheduleOperation(
97 base::Bind(&BackgroundSyncManager::RegisterImpl,
98 weak_ptr_factory_.GetWeakPtr(), sw_registration_id, options,
99 MakeStatusAndRegistrationCompletion(callback)));
102 void BackgroundSyncManager::Unregister(
103 int64 sw_registration_id,
104 const std::string& sync_registration_tag,
105 SyncPeriodicity periodicity,
106 BackgroundSyncRegistration::RegistrationId sync_registration_id,
107 const StatusCallback& callback) {
108 DCHECK_CURRENTLY_ON(BrowserThread::IO);
110 if (disabled_) {
111 BackgroundSyncMetrics::CountUnregister(
112 periodicity, BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
113 base::ThreadTaskRunnerHandle::Get()->PostTask(
114 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR));
115 return;
118 RegistrationKey registration_key(sync_registration_tag, periodicity);
120 op_scheduler_.ScheduleOperation(base::Bind(
121 &BackgroundSyncManager::UnregisterImpl, weak_ptr_factory_.GetWeakPtr(),
122 sw_registration_id, registration_key, sync_registration_id, periodicity,
123 MakeStatusCompletion(callback)));
126 void BackgroundSyncManager::GetRegistration(
127 int64 sw_registration_id,
128 const std::string& sync_registration_tag,
129 SyncPeriodicity periodicity,
130 const StatusAndRegistrationCallback& callback) {
131 DCHECK_CURRENTLY_ON(BrowserThread::IO);
133 if (disabled_) {
134 base::ThreadTaskRunnerHandle::Get()->PostTask(
135 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
136 BackgroundSyncRegistration()));
137 return;
140 RegistrationKey registration_key(sync_registration_tag, periodicity);
142 op_scheduler_.ScheduleOperation(base::Bind(
143 &BackgroundSyncManager::GetRegistrationImpl,
144 weak_ptr_factory_.GetWeakPtr(), sw_registration_id, registration_key,
145 MakeStatusAndRegistrationCompletion(callback)));
148 void BackgroundSyncManager::GetRegistrations(
149 int64 sw_registration_id,
150 SyncPeriodicity periodicity,
151 const StatusAndRegistrationsCallback& callback) {
152 DCHECK_CURRENTLY_ON(BrowserThread::IO);
154 if (disabled_) {
155 base::ThreadTaskRunnerHandle::Get()->PostTask(
156 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
157 std::vector<BackgroundSyncRegistration>()));
158 return;
161 op_scheduler_.ScheduleOperation(
162 base::Bind(&BackgroundSyncManager::GetRegistrationsImpl,
163 weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
164 periodicity, MakeStatusAndRegistrationsCompletion(callback)));
167 void BackgroundSyncManager::OnRegistrationDeleted(int64 registration_id,
168 const GURL& pattern) {
169 DCHECK_CURRENTLY_ON(BrowserThread::IO);
171 // Operations already in the queue will either fail when they write to storage
172 // or return stale results based on registrations loaded in memory. This is
173 // inconsequential since the service worker is gone.
174 op_scheduler_.ScheduleOperation(base::Bind(
175 &BackgroundSyncManager::OnRegistrationDeletedImpl,
176 weak_ptr_factory_.GetWeakPtr(), registration_id, MakeEmptyCompletion()));
179 void BackgroundSyncManager::OnStorageWiped() {
180 DCHECK_CURRENTLY_ON(BrowserThread::IO);
182 // Operations already in the queue will either fail when they write to storage
183 // or return stale results based on registrations loaded in memory. This is
184 // inconsequential since the service workers are gone.
185 op_scheduler_.ScheduleOperation(
186 base::Bind(&BackgroundSyncManager::OnStorageWipedImpl,
187 weak_ptr_factory_.GetWeakPtr(), MakeEmptyCompletion()));
190 BackgroundSyncManager::BackgroundSyncManager(
191 const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context)
192 : service_worker_context_(service_worker_context),
193 disabled_(false),
194 weak_ptr_factory_(this) {
195 DCHECK_CURRENTLY_ON(BrowserThread::IO);
197 service_worker_context_->AddObserver(this);
199 network_observer_.reset(new BackgroundSyncNetworkObserver(
200 base::Bind(&BackgroundSyncManager::OnNetworkChanged,
201 weak_ptr_factory_.GetWeakPtr())));
202 power_observer_.reset(new BackgroundSyncPowerObserver(base::Bind(
203 &BackgroundSyncManager::OnPowerChanged, weak_ptr_factory_.GetWeakPtr())));
206 void BackgroundSyncManager::Init() {
207 DCHECK_CURRENTLY_ON(BrowserThread::IO);
208 DCHECK(!op_scheduler_.ScheduledOperations());
209 DCHECK(!disabled_);
211 op_scheduler_.ScheduleOperation(base::Bind(&BackgroundSyncManager::InitImpl,
212 weak_ptr_factory_.GetWeakPtr(),
213 MakeEmptyCompletion()));
216 void BackgroundSyncManager::InitImpl(const base::Closure& callback) {
217 DCHECK_CURRENTLY_ON(BrowserThread::IO);
219 if (disabled_) {
220 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
221 base::Bind(callback));
222 return;
225 GetDataFromBackend(
226 kBackgroundSyncUserDataKey,
227 base::Bind(&BackgroundSyncManager::InitDidGetDataFromBackend,
228 weak_ptr_factory_.GetWeakPtr(), callback));
231 void BackgroundSyncManager::InitDidGetDataFromBackend(
232 const base::Closure& callback,
233 const std::vector<std::pair<int64, std::string>>& user_data,
234 ServiceWorkerStatusCode status) {
235 DCHECK_CURRENTLY_ON(BrowserThread::IO);
237 if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
238 LOG(ERROR) << "BackgroundSync failed to init due to backend failure.";
239 DisableAndClearManager(base::Bind(callback));
240 return;
243 bool corruption_detected = false;
244 for (const std::pair<int64, std::string>& data : user_data) {
245 BackgroundSyncRegistrationsProto registrations_proto;
246 if (registrations_proto.ParseFromString(data.second)) {
247 BackgroundSyncRegistrations* registrations =
248 &sw_to_registrations_map_[data.first];
249 registrations->next_id = registrations_proto.next_registration_id();
250 registrations->origin = GURL(registrations_proto.origin());
252 for (int i = 0, max = registrations_proto.registration_size(); i < max;
253 ++i) {
254 const BackgroundSyncRegistrationProto& registration_proto =
255 registrations_proto.registration(i);
257 if (registration_proto.id() >= registrations->next_id) {
258 corruption_detected = true;
259 break;
262 RegistrationKey registration_key(registration_proto.tag(),
263 registration_proto.periodicity());
264 BackgroundSyncRegistration* registration =
265 &registrations->registration_map[registration_key];
267 BackgroundSyncRegistrationOptions* options = registration->options();
268 options->tag = registration_proto.tag();
269 options->periodicity = registration_proto.periodicity();
270 options->min_period = registration_proto.min_period();
271 options->network_state = registration_proto.network_state();
272 options->power_state = registration_proto.power_state();
274 registration->set_id(registration_proto.id());
275 registration->set_sync_state(registration_proto.sync_state());
277 if (registration->sync_state() == SYNC_STATE_FIRING) {
278 // If the browser (or worker) closed while firing the event, consider
279 // it pending again>
280 registration->set_sync_state(SYNC_STATE_PENDING);
285 if (corruption_detected)
286 break;
289 if (corruption_detected) {
290 LOG(ERROR) << "Corruption detected in background sync backend";
291 DisableAndClearManager(base::Bind(callback));
292 return;
295 FireReadyEvents();
297 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
298 base::Bind(callback));
301 void BackgroundSyncManager::RegisterImpl(
302 int64 sw_registration_id,
303 const BackgroundSyncRegistrationOptions& options,
304 const StatusAndRegistrationCallback& callback) {
305 DCHECK_CURRENTLY_ON(BrowserThread::IO);
307 // For UMA, determine here whether the sync could fire immediately
308 BackgroundSyncMetrics::RegistrationCouldFire registration_could_fire =
309 AreOptionConditionsMet(options)
310 ? BackgroundSyncMetrics::REGISTRATION_COULD_FIRE
311 : BackgroundSyncMetrics::REGISTRATION_COULD_NOT_FIRE;
313 if (disabled_) {
314 BackgroundSyncMetrics::CountRegister(
315 options.periodicity, registration_could_fire,
316 BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE,
317 BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
318 base::ThreadTaskRunnerHandle::Get()->PostTask(
319 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
320 BackgroundSyncRegistration()));
321 return;
324 ServiceWorkerRegistration* sw_registration =
325 service_worker_context_->GetLiveRegistration(sw_registration_id);
326 if (!sw_registration || !sw_registration->active_version()) {
327 BackgroundSyncMetrics::CountRegister(
328 options.periodicity, registration_could_fire,
329 BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE,
330 BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER);
331 base::ThreadTaskRunnerHandle::Get()->PostTask(
332 FROM_HERE,
333 base::Bind(callback, BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER,
334 BackgroundSyncRegistration()));
335 return;
338 if (!sw_registration->active_version()->HasWindowClients()) {
339 base::ThreadTaskRunnerHandle::Get()->PostTask(
340 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_NOT_ALLOWED,
341 BackgroundSyncRegistration()));
342 return;
345 BackgroundSyncRegistration* existing_registration =
346 LookupRegistration(sw_registration_id, RegistrationKey(options));
347 if (existing_registration &&
348 existing_registration->options()->Equals(options)) {
349 if (existing_registration->sync_state() == SYNC_STATE_FAILED) {
350 existing_registration->set_sync_state(SYNC_STATE_PENDING);
351 StoreRegistrations(
352 sw_registration_id,
353 base::Bind(&BackgroundSyncManager::RegisterDidStore,
354 weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
355 *existing_registration, callback));
356 return;
359 // Record the duplicated registration
360 BackgroundSyncMetrics::CountRegister(
361 existing_registration->options()->periodicity, registration_could_fire,
362 BackgroundSyncMetrics::REGISTRATION_IS_DUPLICATE,
363 BACKGROUND_SYNC_STATUS_OK);
365 base::ThreadTaskRunnerHandle::Get()->PostTask(
366 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_OK,
367 *existing_registration));
368 return;
371 BackgroundSyncRegistration new_registration;
372 *new_registration.options() = options;
374 BackgroundSyncRegistrations* registrations =
375 &sw_to_registrations_map_[sw_registration_id];
376 new_registration.set_id(registrations->next_id++);
378 AddRegistrationToMap(sw_registration_id,
379 sw_registration->pattern().GetOrigin(),
380 new_registration);
382 StoreRegistrations(
383 sw_registration_id,
384 base::Bind(&BackgroundSyncManager::RegisterDidStore,
385 weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
386 new_registration, callback));
389 void BackgroundSyncManager::DisableAndClearManager(
390 const base::Closure& callback) {
391 DCHECK_CURRENTLY_ON(BrowserThread::IO);
393 if (disabled_) {
394 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
395 base::Bind(callback));
396 return;
399 disabled_ = true;
400 sw_to_registrations_map_.clear();
402 // Delete all backend entries. The memory representation of registered syncs
403 // may be out of sync with storage (e.g., due to corruption detection on
404 // loading from storage), so reload the registrations from storage again.
405 GetDataFromBackend(
406 kBackgroundSyncUserDataKey,
407 base::Bind(&BackgroundSyncManager::DisableAndClearDidGetRegistrations,
408 weak_ptr_factory_.GetWeakPtr(), callback));
411 void BackgroundSyncManager::DisableAndClearDidGetRegistrations(
412 const base::Closure& callback,
413 const std::vector<std::pair<int64, std::string>>& user_data,
414 ServiceWorkerStatusCode status) {
415 DCHECK_CURRENTLY_ON(BrowserThread::IO);
417 if (status != SERVICE_WORKER_OK || user_data.empty()) {
418 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
419 base::Bind(callback));
420 return;
423 base::Closure barrier_closure =
424 base::BarrierClosure(user_data.size(), base::Bind(callback));
426 for (const auto& sw_id_and_regs : user_data) {
427 service_worker_context_->ClearRegistrationUserData(
428 sw_id_and_regs.first, kBackgroundSyncUserDataKey,
429 base::Bind(&BackgroundSyncManager::DisableAndClearManagerClearedOne,
430 weak_ptr_factory_.GetWeakPtr(), barrier_closure));
434 void BackgroundSyncManager::DisableAndClearManagerClearedOne(
435 const base::Closure& barrier_closure,
436 ServiceWorkerStatusCode status) {
437 DCHECK_CURRENTLY_ON(BrowserThread::IO);
439 // The status doesn't matter at this point, there is nothing else to be done.
440 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
441 base::Bind(barrier_closure));
444 BackgroundSyncRegistration* BackgroundSyncManager::LookupRegistration(
445 int64 sw_registration_id,
446 const RegistrationKey& registration_key) {
447 DCHECK_CURRENTLY_ON(BrowserThread::IO);
449 SWIdToRegistrationsMap::iterator it =
450 sw_to_registrations_map_.find(sw_registration_id);
451 if (it == sw_to_registrations_map_.end())
452 return nullptr;
454 BackgroundSyncRegistrations& registrations = it->second;
455 DCHECK_LE(BackgroundSyncRegistration::kInitialId, registrations.next_id);
456 DCHECK(!registrations.origin.is_empty());
458 auto key_and_registration_iter =
459 registrations.registration_map.find(registration_key);
460 if (key_and_registration_iter == registrations.registration_map.end())
461 return nullptr;
463 return &key_and_registration_iter->second;
466 void BackgroundSyncManager::StoreRegistrations(
467 int64 sw_registration_id,
468 const ServiceWorkerStorage::StatusCallback& callback) {
469 DCHECK_CURRENTLY_ON(BrowserThread::IO);
471 // Serialize the data.
472 const BackgroundSyncRegistrations& registrations =
473 sw_to_registrations_map_[sw_registration_id];
474 BackgroundSyncRegistrationsProto registrations_proto;
475 registrations_proto.set_next_registration_id(registrations.next_id);
476 registrations_proto.set_origin(registrations.origin.spec());
478 for (const auto& key_and_registration : registrations.registration_map) {
479 const BackgroundSyncRegistration& registration =
480 key_and_registration.second;
481 BackgroundSyncRegistrationProto* registration_proto =
482 registrations_proto.add_registration();
483 registration_proto->set_id(registration.id());
484 registration_proto->set_sync_state(registration.sync_state());
485 registration_proto->set_tag(registration.options()->tag);
486 registration_proto->set_periodicity(registration.options()->periodicity);
487 registration_proto->set_min_period(registration.options()->min_period);
488 registration_proto->set_network_state(
489 registration.options()->network_state);
490 registration_proto->set_power_state(registration.options()->power_state);
492 std::string serialized;
493 bool success = registrations_proto.SerializeToString(&serialized);
494 DCHECK(success);
496 StoreDataInBackend(sw_registration_id, registrations.origin,
497 kBackgroundSyncUserDataKey, serialized, callback);
500 void BackgroundSyncManager::RegisterDidStore(
501 int64 sw_registration_id,
502 const BackgroundSyncRegistration& new_registration,
503 const StatusAndRegistrationCallback& callback,
504 ServiceWorkerStatusCode status) {
505 DCHECK_CURRENTLY_ON(BrowserThread::IO);
507 // For UMA, determine here whether the sync could fire immediately
508 BackgroundSyncMetrics::RegistrationCouldFire registration_could_fire =
509 AreOptionConditionsMet(*new_registration.options())
510 ? BackgroundSyncMetrics::REGISTRATION_COULD_FIRE
511 : BackgroundSyncMetrics::REGISTRATION_COULD_NOT_FIRE;
513 if (status == SERVICE_WORKER_ERROR_NOT_FOUND) {
514 // The service worker registration is gone.
515 BackgroundSyncMetrics::CountRegister(
516 new_registration.options()->periodicity, registration_could_fire,
517 BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE,
518 BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
519 sw_to_registrations_map_.erase(sw_registration_id);
520 base::ThreadTaskRunnerHandle::Get()->PostTask(
521 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
522 BackgroundSyncRegistration()));
523 return;
526 if (status != SERVICE_WORKER_OK) {
527 LOG(ERROR) << "BackgroundSync failed to store registration due to backend "
528 "failure.";
529 BackgroundSyncMetrics::CountRegister(
530 new_registration.options()->periodicity, registration_could_fire,
531 BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE,
532 BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
533 DisableAndClearManager(base::Bind(callback,
534 BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
535 BackgroundSyncRegistration()));
536 return;
539 BackgroundSyncMetrics::CountRegister(
540 new_registration.options()->periodicity, registration_could_fire,
541 BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE,
542 BACKGROUND_SYNC_STATUS_OK);
543 FireReadyEvents();
544 base::ThreadTaskRunnerHandle::Get()->PostTask(
545 FROM_HERE,
546 base::Bind(callback, BACKGROUND_SYNC_STATUS_OK, new_registration));
549 void BackgroundSyncManager::RemoveRegistrationFromMap(
550 int64 sw_registration_id,
551 const RegistrationKey& registration_key) {
552 DCHECK_CURRENTLY_ON(BrowserThread::IO);
553 DCHECK(LookupRegistration(sw_registration_id, registration_key));
555 BackgroundSyncRegistrations* registrations =
556 &sw_to_registrations_map_[sw_registration_id];
558 registrations->registration_map.erase(registration_key);
561 void BackgroundSyncManager::AddRegistrationToMap(
562 int64 sw_registration_id,
563 const GURL& origin,
564 const BackgroundSyncRegistration& sync_registration) {
565 DCHECK_CURRENTLY_ON(BrowserThread::IO);
566 DCHECK(sync_registration.IsValid());
568 BackgroundSyncRegistrations* registrations =
569 &sw_to_registrations_map_[sw_registration_id];
570 registrations->origin = origin;
572 RegistrationKey registration_key(sync_registration);
573 registrations->registration_map[registration_key] = sync_registration;
576 void BackgroundSyncManager::StoreDataInBackend(
577 int64 sw_registration_id,
578 const GURL& origin,
579 const std::string& backend_key,
580 const std::string& data,
581 const ServiceWorkerStorage::StatusCallback& callback) {
582 DCHECK_CURRENTLY_ON(BrowserThread::IO);
584 service_worker_context_->StoreRegistrationUserData(
585 sw_registration_id, origin, backend_key, data, callback);
588 void BackgroundSyncManager::GetDataFromBackend(
589 const std::string& backend_key,
590 const ServiceWorkerStorage::GetUserDataForAllRegistrationsCallback&
591 callback) {
592 DCHECK_CURRENTLY_ON(BrowserThread::IO);
594 service_worker_context_->GetUserDataForAllRegistrations(backend_key,
595 callback);
598 void BackgroundSyncManager::FireOneShotSync(
599 const BackgroundSyncRegistration& registration,
600 const scoped_refptr<ServiceWorkerVersion>& active_version,
601 const ServiceWorkerVersion::StatusCallback& callback) {
602 DCHECK_CURRENTLY_ON(BrowserThread::IO);
604 active_version->DispatchSyncEvent(
605 mojo::ConvertTo<SyncRegistrationPtr>(registration), callback);
608 void BackgroundSyncManager::UnregisterImpl(
609 int64 sw_registration_id,
610 const RegistrationKey& registration_key,
611 BackgroundSyncRegistration::RegistrationId sync_registration_id,
612 SyncPeriodicity periodicity,
613 const StatusCallback& callback) {
614 DCHECK_CURRENTLY_ON(BrowserThread::IO);
616 if (disabled_) {
617 BackgroundSyncMetrics::CountUnregister(
618 periodicity, BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
619 base::ThreadTaskRunnerHandle::Get()->PostTask(
620 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR));
621 return;
624 const BackgroundSyncRegistration* existing_registration =
625 LookupRegistration(sw_registration_id, registration_key);
626 if (!existing_registration ||
627 existing_registration->id() != sync_registration_id) {
628 BackgroundSyncMetrics::CountUnregister(periodicity,
629 BACKGROUND_SYNC_STATUS_NOT_FOUND);
630 base::ThreadTaskRunnerHandle::Get()->PostTask(
631 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_NOT_FOUND));
632 return;
635 RemoveRegistrationFromMap(sw_registration_id, registration_key);
637 StoreRegistrations(sw_registration_id,
638 base::Bind(&BackgroundSyncManager::UnregisterDidStore,
639 weak_ptr_factory_.GetWeakPtr(),
640 sw_registration_id, periodicity, callback));
643 void BackgroundSyncManager::UnregisterDidStore(int64 sw_registration_id,
644 SyncPeriodicity periodicity,
645 const StatusCallback& callback,
646 ServiceWorkerStatusCode status) {
647 DCHECK_CURRENTLY_ON(BrowserThread::IO);
649 if (status == SERVICE_WORKER_ERROR_NOT_FOUND) {
650 // ServiceWorker was unregistered.
651 BackgroundSyncMetrics::CountUnregister(
652 periodicity, BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
653 sw_to_registrations_map_.erase(sw_registration_id);
654 base::ThreadTaskRunnerHandle::Get()->PostTask(
655 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR));
656 return;
659 if (status != SERVICE_WORKER_OK) {
660 LOG(ERROR) << "BackgroundSync failed to unregister due to backend failure.";
661 BackgroundSyncMetrics::CountUnregister(
662 periodicity, BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
663 DisableAndClearManager(
664 base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR));
665 return;
668 BackgroundSyncMetrics::CountUnregister(periodicity,
669 BACKGROUND_SYNC_STATUS_OK);
670 base::ThreadTaskRunnerHandle::Get()->PostTask(
671 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_OK));
674 void BackgroundSyncManager::GetRegistrationImpl(
675 int64 sw_registration_id,
676 const RegistrationKey& registration_key,
677 const StatusAndRegistrationCallback& callback) {
678 DCHECK_CURRENTLY_ON(BrowserThread::IO);
680 if (disabled_) {
681 base::ThreadTaskRunnerHandle::Get()->PostTask(
682 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
683 BackgroundSyncRegistration()));
684 return;
687 const BackgroundSyncRegistration* out_registration =
688 LookupRegistration(sw_registration_id, registration_key);
689 if (!out_registration) {
690 base::ThreadTaskRunnerHandle::Get()->PostTask(
691 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_NOT_FOUND,
692 BackgroundSyncRegistration()));
693 return;
696 base::ThreadTaskRunnerHandle::Get()->PostTask(
697 FROM_HERE,
698 base::Bind(callback, BACKGROUND_SYNC_STATUS_OK, *out_registration));
701 void BackgroundSyncManager::GetRegistrationsImpl(
702 int64 sw_registration_id,
703 SyncPeriodicity periodicity,
704 const StatusAndRegistrationsCallback& callback) {
705 DCHECK_CURRENTLY_ON(BrowserThread::IO);
707 std::vector<BackgroundSyncRegistration> out_registrations;
709 if (disabled_) {
710 base::ThreadTaskRunnerHandle::Get()->PostTask(
711 FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
712 out_registrations));
713 return;
716 SWIdToRegistrationsMap::iterator it =
717 sw_to_registrations_map_.find(sw_registration_id);
719 if (it != sw_to_registrations_map_.end()) {
720 const BackgroundSyncRegistrations& registrations = it->second;
721 for (const auto& tag_and_registration : registrations.registration_map) {
722 const BackgroundSyncRegistration& registration =
723 tag_and_registration.second;
724 if (registration.options()->periodicity == periodicity)
725 out_registrations.push_back(registration);
729 base::ThreadTaskRunnerHandle::Get()->PostTask(
730 FROM_HERE,
731 base::Bind(callback, BACKGROUND_SYNC_STATUS_OK, out_registrations));
734 bool BackgroundSyncManager::AreOptionConditionsMet(
735 const BackgroundSyncRegistrationOptions& options) {
736 DCHECK_CURRENTLY_ON(BrowserThread::IO);
737 return network_observer_->NetworkSufficient(options.network_state) &&
738 power_observer_->PowerSufficient(options.power_state);
741 bool BackgroundSyncManager::IsRegistrationReadyToFire(
742 const BackgroundSyncRegistration& registration) {
743 DCHECK_CURRENTLY_ON(BrowserThread::IO);
745 // TODO(jkarlin): Add support for firing periodic registrations.
746 if (registration.options()->periodicity == SYNC_PERIODIC)
747 return false;
749 if (registration.sync_state() != SYNC_STATE_PENDING)
750 return false;
752 DCHECK_EQ(SYNC_ONE_SHOT, registration.options()->periodicity);
754 return AreOptionConditionsMet(*registration.options());
757 void BackgroundSyncManager::SchedulePendingRegistrations() {
758 #if defined(OS_ANDROID)
759 bool keep_browser_alive_for_one_shot = false;
761 for (const auto& sw_id_and_registrations : sw_to_registrations_map_) {
762 for (const auto& key_and_registration :
763 sw_id_and_registrations.second.registration_map) {
764 const BackgroundSyncRegistration& registration =
765 key_and_registration.second;
766 if (registration.sync_state() == SYNC_STATE_PENDING) {
767 if (registration.options()->periodicity == SYNC_ONE_SHOT) {
768 keep_browser_alive_for_one_shot = true;
769 } else {
770 // TODO(jkarlin): Support keeping the browser alive for periodic
771 // syncs.
777 // TODO(jkarlin): Use the context's path instead of the 'this' pointer as an
778 // identifier. See crbug.com/489705.
779 BrowserThread::PostTask(
780 BrowserThread::UI, FROM_HERE,
781 base::Bind(&BackgroundSyncLauncherAndroid::LaunchBrowserWhenNextOnline,
782 this, keep_browser_alive_for_one_shot));
783 #else
784 // TODO(jkarlin): Toggle Chrome's background mode.
785 #endif
788 void BackgroundSyncManager::FireReadyEvents() {
789 DCHECK_CURRENTLY_ON(BrowserThread::IO);
791 if (disabled_)
792 return;
794 op_scheduler_.ScheduleOperation(
795 base::Bind(&BackgroundSyncManager::FireReadyEventsImpl,
796 weak_ptr_factory_.GetWeakPtr(), MakeEmptyCompletion()));
799 void BackgroundSyncManager::FireReadyEventsImpl(const base::Closure& callback) {
800 DCHECK_CURRENTLY_ON(BrowserThread::IO);
802 if (disabled_) {
803 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
804 base::Bind(callback));
805 return;
808 // Find the registrations that are ready to run.
809 std::vector<std::pair<int64, RegistrationKey>> sw_id_and_keys_to_fire;
811 for (auto& sw_id_and_registrations : sw_to_registrations_map_) {
812 const int64 service_worker_id = sw_id_and_registrations.first;
813 for (auto& key_and_registration :
814 sw_id_and_registrations.second.registration_map) {
815 BackgroundSyncRegistration* registration = &key_and_registration.second;
816 if (IsRegistrationReadyToFire(*registration)) {
817 sw_id_and_keys_to_fire.push_back(
818 std::make_pair(service_worker_id, key_and_registration.first));
819 // The state change is not saved to persistent storage because
820 // if the sync event is killed mid-sync then it should return to
821 // SYNC_STATE_PENDING.
822 registration->set_sync_state(SYNC_STATE_FIRING);
827 // If there are no registrations currently ready, then just run |callback|.
828 // Otherwise, fire them all, and record the result when done.
829 if (sw_id_and_keys_to_fire.size() == 0) {
830 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
831 base::Bind(callback));
832 } else {
833 base::TimeTicks start_time = base::TimeTicks::Now();
835 // Fire the sync event of the ready registrations and run |callback| once
836 // they're all done.
837 base::Closure events_fired_barrier_closure = base::BarrierClosure(
838 sw_id_and_keys_to_fire.size(), base::Bind(callback));
840 // Record the total time taken after all events have run to completion.
841 base::Closure events_completed_barrier_closure =
842 base::BarrierClosure(sw_id_and_keys_to_fire.size(),
843 base::Bind(&OnAllSyncEventsCompleted, start_time,
844 sw_id_and_keys_to_fire.size()));
846 for (const auto& sw_id_and_key : sw_id_and_keys_to_fire) {
847 int64 service_worker_id = sw_id_and_key.first;
848 const BackgroundSyncRegistration* registration =
849 LookupRegistration(service_worker_id, sw_id_and_key.second);
851 service_worker_context_->FindRegistrationForId(
852 service_worker_id, sw_to_registrations_map_[service_worker_id].origin,
853 base::Bind(&BackgroundSyncManager::FireReadyEventsDidFindRegistration,
854 weak_ptr_factory_.GetWeakPtr(), sw_id_and_key.second,
855 registration->id(), events_fired_barrier_closure,
856 events_completed_barrier_closure));
860 SchedulePendingRegistrations();
863 void BackgroundSyncManager::FireReadyEventsDidFindRegistration(
864 const RegistrationKey& registration_key,
865 BackgroundSyncRegistration::RegistrationId registration_id,
866 const base::Closure& event_fired_callback,
867 const base::Closure& event_completed_callback,
868 ServiceWorkerStatusCode service_worker_status,
869 const scoped_refptr<ServiceWorkerRegistration>&
870 service_worker_registration) {
871 DCHECK_CURRENTLY_ON(BrowserThread::IO);
872 if (service_worker_status != SERVICE_WORKER_OK) {
873 base::ThreadTaskRunnerHandle::Get()->PostTask(
874 FROM_HERE, base::Bind(event_fired_callback));
875 base::ThreadTaskRunnerHandle::Get()->PostTask(
876 FROM_HERE, base::Bind(event_completed_callback));
877 return;
880 BackgroundSyncRegistration* registration =
881 LookupRegistration(service_worker_registration->id(), registration_key);
883 FireOneShotSync(
884 *registration, service_worker_registration->active_version(),
885 base::Bind(&BackgroundSyncManager::EventComplete,
886 weak_ptr_factory_.GetWeakPtr(), service_worker_registration,
887 service_worker_registration->id(), registration_key,
888 registration_id, event_completed_callback));
890 base::ThreadTaskRunnerHandle::Get()->PostTask(
891 FROM_HERE, base::Bind(event_fired_callback));
894 // |service_worker_registration| is just to keep the registration alive
895 // while the event is firing.
896 void BackgroundSyncManager::EventComplete(
897 const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
898 int64 service_worker_id,
899 const RegistrationKey& key,
900 BackgroundSyncRegistration::RegistrationId sync_registration_id,
901 const base::Closure& callback,
902 ServiceWorkerStatusCode status_code) {
903 DCHECK_CURRENTLY_ON(BrowserThread::IO);
904 if (disabled_)
905 return;
907 op_scheduler_.ScheduleOperation(base::Bind(
908 &BackgroundSyncManager::EventCompleteImpl, weak_ptr_factory_.GetWeakPtr(),
909 service_worker_id, key, sync_registration_id, status_code,
910 MakeClosureCompletion(callback)));
913 void BackgroundSyncManager::EventCompleteImpl(
914 int64 service_worker_id,
915 const RegistrationKey& key,
916 BackgroundSyncRegistration::RegistrationId sync_registration_id,
917 ServiceWorkerStatusCode status_code,
918 const base::Closure& callback) {
919 DCHECK_CURRENTLY_ON(BrowserThread::IO);
921 if (disabled_) {
922 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
923 base::Bind(callback));
924 return;
927 BackgroundSyncRegistration* registration =
928 LookupRegistration(service_worker_id, key);
929 if (!registration || registration->id() != sync_registration_id) {
930 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
931 base::Bind(callback));
932 return;
935 // The event ran to completion, we should count it, no matter what happens
936 // from here.
937 BackgroundSyncMetrics::RecordEventResult(registration->options()->periodicity,
938 status_code == SERVICE_WORKER_OK);
940 if (registration->options()->periodicity == SYNC_ONE_SHOT) {
941 if (status_code != SERVICE_WORKER_OK) {
942 // TODO(jkarlin) Fire the sync event on the next page load controlled by
943 // this registration. (crbug.com/479665)
944 registration->set_sync_state(SYNC_STATE_FAILED);
945 } else {
946 registration = nullptr;
947 RemoveRegistrationFromMap(service_worker_id, key);
949 } else {
950 // TODO(jkarlin): Add support for running periodic syncs. (crbug.com/479674)
951 NOTREACHED();
954 StoreRegistrations(
955 service_worker_id,
956 base::Bind(&BackgroundSyncManager::EventCompleteDidStore,
957 weak_ptr_factory_.GetWeakPtr(), service_worker_id, callback));
960 void BackgroundSyncManager::EventCompleteDidStore(
961 int64 service_worker_id,
962 const base::Closure& callback,
963 ServiceWorkerStatusCode status_code) {
964 DCHECK_CURRENTLY_ON(BrowserThread::IO);
966 if (status_code == SERVICE_WORKER_ERROR_NOT_FOUND) {
967 // The registration is gone.
968 sw_to_registrations_map_.erase(service_worker_id);
969 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
970 base::Bind(callback));
971 return;
974 if (status_code != SERVICE_WORKER_OK) {
975 LOG(ERROR) << "BackgroundSync failed to store registration due to backend "
976 "failure.";
977 DisableAndClearManager(base::Bind(callback));
978 return;
981 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
982 base::Bind(callback));
985 // static
986 void BackgroundSyncManager::OnAllSyncEventsCompleted(
987 const base::TimeTicks& start_time,
988 int number_of_batched_sync_events) {
989 // Record the combined time taken by all sync events.
990 BackgroundSyncMetrics::RecordBatchSyncEventComplete(
991 base::TimeTicks::Now() - start_time, number_of_batched_sync_events);
994 void BackgroundSyncManager::OnRegistrationDeletedImpl(
995 int64 registration_id,
996 const base::Closure& callback) {
997 DCHECK_CURRENTLY_ON(BrowserThread::IO);
999 // The backend (ServiceWorkerStorage) will delete the data, so just delete the
1000 // memory representation here.
1001 sw_to_registrations_map_.erase(registration_id);
1002 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1003 base::Bind(callback));
1006 void BackgroundSyncManager::OnStorageWipedImpl(const base::Closure& callback) {
1007 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1009 sw_to_registrations_map_.clear();
1010 disabled_ = false;
1011 InitImpl(callback);
1014 void BackgroundSyncManager::OnNetworkChanged() {
1015 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1017 FireReadyEvents();
1020 void BackgroundSyncManager::OnPowerChanged() {
1021 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1023 FireReadyEvents();
1026 template <typename CallbackT, typename... Params>
1027 void BackgroundSyncManager::CompleteOperationCallback(const CallbackT& callback,
1028 Params... parameters) {
1029 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1031 callback.Run(parameters...);
1032 op_scheduler_.CompleteOperationAndRunNext();
1035 base::Closure BackgroundSyncManager::MakeEmptyCompletion() {
1036 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1038 return MakeClosureCompletion(base::Bind(base::DoNothing));
1041 base::Closure BackgroundSyncManager::MakeClosureCompletion(
1042 const base::Closure& callback) {
1043 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1045 return base::Bind(
1046 &BackgroundSyncManager::CompleteOperationCallback<base::Closure>,
1047 weak_ptr_factory_.GetWeakPtr(), callback);
1050 BackgroundSyncManager::StatusAndRegistrationCallback
1051 BackgroundSyncManager::MakeStatusAndRegistrationCompletion(
1052 const StatusAndRegistrationCallback& callback) {
1053 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1055 return base::Bind(&BackgroundSyncManager::CompleteOperationCallback<
1056 StatusAndRegistrationCallback, BackgroundSyncStatus,
1057 const BackgroundSyncRegistration&>,
1058 weak_ptr_factory_.GetWeakPtr(), callback);
1061 BackgroundSyncManager::StatusAndRegistrationsCallback
1062 BackgroundSyncManager::MakeStatusAndRegistrationsCompletion(
1063 const StatusAndRegistrationsCallback& callback) {
1064 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1066 return base::Bind(&BackgroundSyncManager::CompleteOperationCallback<
1067 StatusAndRegistrationsCallback, BackgroundSyncStatus,
1068 const std::vector<BackgroundSyncRegistration>&>,
1069 weak_ptr_factory_.GetWeakPtr(), callback);
1072 BackgroundSyncManager::StatusCallback
1073 BackgroundSyncManager::MakeStatusCompletion(const StatusCallback& callback) {
1074 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1076 return base::Bind(
1077 &BackgroundSyncManager::CompleteOperationCallback<StatusCallback,
1078 BackgroundSyncStatus>,
1079 weak_ptr_factory_.GetWeakPtr(), callback);
1082 } // namespace content