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"
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"
25 const char kBackgroundSyncUserDataKey
[] = "BackgroundSyncUserData";
30 BackgroundSyncManager::BackgroundSyncRegistrations::
31 BackgroundSyncRegistrations()
32 : next_id(BackgroundSyncRegistration::kInitialId
) {
35 BackgroundSyncManager::BackgroundSyncRegistrations::
36 ~BackgroundSyncRegistrations() {
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
);
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
;
86 BackgroundSyncMetrics::CountRegister(
87 options
.periodicity
, registration_could_fire
,
88 BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE
,
90 base::ThreadTaskRunnerHandle::Get()->PostTask(
92 base::Bind(callback
, ERROR_TYPE_STORAGE
, BackgroundSyncRegistration()));
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
);
111 BackgroundSyncMetrics::CountUnregister(periodicity
, ERROR_TYPE_STORAGE
);
112 base::ThreadTaskRunnerHandle::Get()->PostTask(
113 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_STORAGE
));
117 RegistrationKey
registration_key(sync_registration_tag
, periodicity
);
119 op_scheduler_
.ScheduleOperation(base::Bind(
120 &BackgroundSyncManager::UnregisterImpl
, weak_ptr_factory_
.GetWeakPtr(),
121 sw_registration_id
, registration_key
, sync_registration_id
, periodicity
,
122 MakeStatusCompletion(callback
)));
125 void BackgroundSyncManager::GetRegistration(
126 int64 sw_registration_id
,
127 const std::string
& sync_registration_tag
,
128 SyncPeriodicity periodicity
,
129 const StatusAndRegistrationCallback
& callback
) {
130 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
133 base::ThreadTaskRunnerHandle::Get()->PostTask(
135 base::Bind(callback
, ERROR_TYPE_STORAGE
, BackgroundSyncRegistration()));
139 RegistrationKey
registration_key(sync_registration_tag
, periodicity
);
141 op_scheduler_
.ScheduleOperation(base::Bind(
142 &BackgroundSyncManager::GetRegistrationImpl
,
143 weak_ptr_factory_
.GetWeakPtr(), sw_registration_id
, registration_key
,
144 MakeStatusAndRegistrationCompletion(callback
)));
147 void BackgroundSyncManager::GetRegistrations(
148 int64 sw_registration_id
,
149 SyncPeriodicity periodicity
,
150 const StatusAndRegistrationsCallback
& callback
) {
151 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
154 base::ThreadTaskRunnerHandle::Get()->PostTask(
155 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_STORAGE
,
156 std::vector
<BackgroundSyncRegistration
>()));
160 op_scheduler_
.ScheduleOperation(
161 base::Bind(&BackgroundSyncManager::GetRegistrationsImpl
,
162 weak_ptr_factory_
.GetWeakPtr(), sw_registration_id
,
163 periodicity
, MakeStatusAndRegistrationsCompletion(callback
)));
166 void BackgroundSyncManager::OnRegistrationDeleted(int64 registration_id
,
167 const GURL
& pattern
) {
168 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
170 // Operations already in the queue will either fail when they write to storage
171 // or return stale results based on registrations loaded in memory. This is
172 // inconsequential since the service worker is gone.
173 op_scheduler_
.ScheduleOperation(base::Bind(
174 &BackgroundSyncManager::OnRegistrationDeletedImpl
,
175 weak_ptr_factory_
.GetWeakPtr(), registration_id
, MakeEmptyCompletion()));
178 void BackgroundSyncManager::OnStorageWiped() {
179 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
181 // Operations already in the queue will either fail when they write to storage
182 // or return stale results based on registrations loaded in memory. This is
183 // inconsequential since the service workers are gone.
184 op_scheduler_
.ScheduleOperation(
185 base::Bind(&BackgroundSyncManager::OnStorageWipedImpl
,
186 weak_ptr_factory_
.GetWeakPtr(), MakeEmptyCompletion()));
189 BackgroundSyncManager::BackgroundSyncManager(
190 const scoped_refptr
<ServiceWorkerContextWrapper
>& service_worker_context
)
191 : service_worker_context_(service_worker_context
),
193 weak_ptr_factory_(this) {
194 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
196 service_worker_context_
->AddObserver(this);
198 network_observer_
.reset(new BackgroundSyncNetworkObserver(
199 base::Bind(&BackgroundSyncManager::OnNetworkChanged
,
200 weak_ptr_factory_
.GetWeakPtr())));
201 power_observer_
.reset(new BackgroundSyncPowerObserver(base::Bind(
202 &BackgroundSyncManager::OnPowerChanged
, weak_ptr_factory_
.GetWeakPtr())));
205 void BackgroundSyncManager::Init() {
206 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
207 DCHECK(!op_scheduler_
.ScheduledOperations());
210 op_scheduler_
.ScheduleOperation(base::Bind(&BackgroundSyncManager::InitImpl
,
211 weak_ptr_factory_
.GetWeakPtr(),
212 MakeEmptyCompletion()));
215 void BackgroundSyncManager::InitImpl(const base::Closure
& callback
) {
216 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
219 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
220 base::Bind(callback
));
225 kBackgroundSyncUserDataKey
,
226 base::Bind(&BackgroundSyncManager::InitDidGetDataFromBackend
,
227 weak_ptr_factory_
.GetWeakPtr(), callback
));
230 void BackgroundSyncManager::InitDidGetDataFromBackend(
231 const base::Closure
& callback
,
232 const std::vector
<std::pair
<int64
, std::string
>>& user_data
,
233 ServiceWorkerStatusCode status
) {
234 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
236 if (status
!= SERVICE_WORKER_OK
&& status
!= SERVICE_WORKER_ERROR_NOT_FOUND
) {
237 LOG(ERROR
) << "BackgroundSync failed to init due to backend failure.";
238 DisableAndClearManager(base::Bind(callback
));
242 bool corruption_detected
= false;
243 for (const std::pair
<int64
, std::string
>& data
: user_data
) {
244 BackgroundSyncRegistrationsProto registrations_proto
;
245 if (registrations_proto
.ParseFromString(data
.second
)) {
246 BackgroundSyncRegistrations
* registrations
=
247 &sw_to_registrations_map_
[data
.first
];
248 registrations
->next_id
= registrations_proto
.next_registration_id();
249 registrations
->origin
= GURL(registrations_proto
.origin());
251 for (int i
= 0, max
= registrations_proto
.registration_size(); i
< max
;
253 const BackgroundSyncRegistrationProto
& registration_proto
=
254 registrations_proto
.registration(i
);
256 if (registration_proto
.id() >= registrations
->next_id
) {
257 corruption_detected
= true;
261 RegistrationKey
registration_key(registration_proto
.tag(),
262 registration_proto
.periodicity());
263 BackgroundSyncRegistration
* registration
=
264 ®istrations
->registration_map
[registration_key
];
266 BackgroundSyncRegistrationOptions
* options
= registration
->options();
267 options
->tag
= registration_proto
.tag();
268 options
->periodicity
= registration_proto
.periodicity();
269 options
->min_period
= registration_proto
.min_period();
270 options
->network_state
= registration_proto
.network_state();
271 options
->power_state
= registration_proto
.power_state();
273 registration
->set_id(registration_proto
.id());
274 registration
->set_sync_state(registration_proto
.sync_state());
276 if (registration
->sync_state() == SYNC_STATE_FIRING
) {
277 // If the browser (or worker) closed while firing the event, consider
279 registration
->set_sync_state(SYNC_STATE_PENDING
);
284 if (corruption_detected
)
288 if (corruption_detected
) {
289 LOG(ERROR
) << "Corruption detected in background sync backend";
290 DisableAndClearManager(base::Bind(callback
));
296 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
297 base::Bind(callback
));
300 void BackgroundSyncManager::RegisterImpl(
301 int64 sw_registration_id
,
302 const BackgroundSyncRegistrationOptions
& options
,
303 const StatusAndRegistrationCallback
& callback
) {
304 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
306 // For UMA, determine here whether the sync could fire immediately
307 BackgroundSyncMetrics::RegistrationCouldFire registration_could_fire
=
308 AreOptionConditionsMet(options
)
309 ? BackgroundSyncMetrics::REGISTRATION_COULD_FIRE
310 : BackgroundSyncMetrics::REGISTRATION_COULD_NOT_FIRE
;
313 BackgroundSyncMetrics::CountRegister(
314 options
.periodicity
, registration_could_fire
,
315 BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE
,
317 base::ThreadTaskRunnerHandle::Get()->PostTask(
319 base::Bind(callback
, ERROR_TYPE_STORAGE
, BackgroundSyncRegistration()));
323 ServiceWorkerRegistration
* sw_registration
=
324 service_worker_context_
->GetLiveRegistration(sw_registration_id
);
325 if (!sw_registration
|| !sw_registration
->active_version()) {
326 BackgroundSyncMetrics::CountRegister(
327 options
.periodicity
, registration_could_fire
,
328 BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE
,
329 ERROR_TYPE_NO_SERVICE_WORKER
);
330 base::ThreadTaskRunnerHandle::Get()->PostTask(
331 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_NO_SERVICE_WORKER
,
332 BackgroundSyncRegistration()));
336 if (!sw_registration
->active_version()->HasWindowClients()) {
337 base::ThreadTaskRunnerHandle::Get()->PostTask(
338 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_NOT_ALLOWED
,
339 BackgroundSyncRegistration()));
343 BackgroundSyncRegistration
* existing_registration
=
344 LookupRegistration(sw_registration_id
, RegistrationKey(options
));
345 if (existing_registration
&&
346 existing_registration
->options()->Equals(options
)) {
347 if (existing_registration
->sync_state() == SYNC_STATE_FAILED
) {
348 existing_registration
->set_sync_state(SYNC_STATE_PENDING
);
351 base::Bind(&BackgroundSyncManager::RegisterDidStore
,
352 weak_ptr_factory_
.GetWeakPtr(), sw_registration_id
,
353 *existing_registration
, callback
));
357 // Record the duplicated registration
358 BackgroundSyncMetrics::CountRegister(
359 existing_registration
->options()->periodicity
, registration_could_fire
,
360 BackgroundSyncMetrics::REGISTRATION_IS_DUPLICATE
, ERROR_TYPE_OK
);
362 base::ThreadTaskRunnerHandle::Get()->PostTask(
363 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_OK
, *existing_registration
));
367 BackgroundSyncRegistration new_registration
;
368 *new_registration
.options() = options
;
370 BackgroundSyncRegistrations
* registrations
=
371 &sw_to_registrations_map_
[sw_registration_id
];
372 new_registration
.set_id(registrations
->next_id
++);
374 AddRegistrationToMap(sw_registration_id
,
375 sw_registration
->pattern().GetOrigin(),
380 base::Bind(&BackgroundSyncManager::RegisterDidStore
,
381 weak_ptr_factory_
.GetWeakPtr(), sw_registration_id
,
382 new_registration
, callback
));
385 void BackgroundSyncManager::DisableAndClearManager(
386 const base::Closure
& callback
) {
387 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
390 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
391 base::Bind(callback
));
396 sw_to_registrations_map_
.clear();
398 // Delete all backend entries. The memory representation of registered syncs
399 // may be out of sync with storage (e.g., due to corruption detection on
400 // loading from storage), so reload the registrations from storage again.
402 kBackgroundSyncUserDataKey
,
403 base::Bind(&BackgroundSyncManager::DisableAndClearDidGetRegistrations
,
404 weak_ptr_factory_
.GetWeakPtr(), callback
));
407 void BackgroundSyncManager::DisableAndClearDidGetRegistrations(
408 const base::Closure
& callback
,
409 const std::vector
<std::pair
<int64
, std::string
>>& user_data
,
410 ServiceWorkerStatusCode status
) {
411 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
413 if (status
!= SERVICE_WORKER_OK
|| user_data
.empty()) {
414 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
415 base::Bind(callback
));
419 base::Closure barrier_closure
=
420 base::BarrierClosure(user_data
.size(), base::Bind(callback
));
422 for (const auto& sw_id_and_regs
: user_data
) {
423 service_worker_context_
->ClearRegistrationUserData(
424 sw_id_and_regs
.first
, kBackgroundSyncUserDataKey
,
425 base::Bind(&BackgroundSyncManager::DisableAndClearManagerClearedOne
,
426 weak_ptr_factory_
.GetWeakPtr(), barrier_closure
));
430 void BackgroundSyncManager::DisableAndClearManagerClearedOne(
431 const base::Closure
& barrier_closure
,
432 ServiceWorkerStatusCode status
) {
433 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
435 // The status doesn't matter at this point, there is nothing else to be done.
436 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
437 base::Bind(barrier_closure
));
440 BackgroundSyncRegistration
* BackgroundSyncManager::LookupRegistration(
441 int64 sw_registration_id
,
442 const RegistrationKey
& registration_key
) {
443 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
445 SWIdToRegistrationsMap::iterator it
=
446 sw_to_registrations_map_
.find(sw_registration_id
);
447 if (it
== sw_to_registrations_map_
.end())
450 BackgroundSyncRegistrations
& registrations
= it
->second
;
451 DCHECK_LE(BackgroundSyncRegistration::kInitialId
, registrations
.next_id
);
452 DCHECK(!registrations
.origin
.is_empty());
454 auto key_and_registration_iter
=
455 registrations
.registration_map
.find(registration_key
);
456 if (key_and_registration_iter
== registrations
.registration_map
.end())
459 return &key_and_registration_iter
->second
;
462 void BackgroundSyncManager::StoreRegistrations(
463 int64 sw_registration_id
,
464 const ServiceWorkerStorage::StatusCallback
& callback
) {
465 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
467 // Serialize the data.
468 const BackgroundSyncRegistrations
& registrations
=
469 sw_to_registrations_map_
[sw_registration_id
];
470 BackgroundSyncRegistrationsProto registrations_proto
;
471 registrations_proto
.set_next_registration_id(registrations
.next_id
);
472 registrations_proto
.set_origin(registrations
.origin
.spec());
474 for (const auto& key_and_registration
: registrations
.registration_map
) {
475 const BackgroundSyncRegistration
& registration
=
476 key_and_registration
.second
;
477 BackgroundSyncRegistrationProto
* registration_proto
=
478 registrations_proto
.add_registration();
479 registration_proto
->set_id(registration
.id());
480 registration_proto
->set_sync_state(registration
.sync_state());
481 registration_proto
->set_tag(registration
.options()->tag
);
482 registration_proto
->set_periodicity(registration
.options()->periodicity
);
483 registration_proto
->set_min_period(registration
.options()->min_period
);
484 registration_proto
->set_network_state(
485 registration
.options()->network_state
);
486 registration_proto
->set_power_state(registration
.options()->power_state
);
488 std::string serialized
;
489 bool success
= registrations_proto
.SerializeToString(&serialized
);
492 StoreDataInBackend(sw_registration_id
, registrations
.origin
,
493 kBackgroundSyncUserDataKey
, serialized
, callback
);
496 void BackgroundSyncManager::RegisterDidStore(
497 int64 sw_registration_id
,
498 const BackgroundSyncRegistration
& new_registration
,
499 const StatusAndRegistrationCallback
& callback
,
500 ServiceWorkerStatusCode status
) {
501 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
503 // For UMA, determine here whether the sync could fire immediately
504 BackgroundSyncMetrics::RegistrationCouldFire registration_could_fire
=
505 AreOptionConditionsMet(*new_registration
.options())
506 ? BackgroundSyncMetrics::REGISTRATION_COULD_FIRE
507 : BackgroundSyncMetrics::REGISTRATION_COULD_NOT_FIRE
;
509 if (status
== SERVICE_WORKER_ERROR_NOT_FOUND
) {
510 // The service worker registration is gone.
511 BackgroundSyncMetrics::CountRegister(
512 new_registration
.options()->periodicity
, registration_could_fire
,
513 BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE
,
515 sw_to_registrations_map_
.erase(sw_registration_id
);
516 base::ThreadTaskRunnerHandle::Get()->PostTask(
518 base::Bind(callback
, ERROR_TYPE_STORAGE
, BackgroundSyncRegistration()));
522 if (status
!= SERVICE_WORKER_OK
) {
523 LOG(ERROR
) << "BackgroundSync failed to store registration due to backend "
525 BackgroundSyncMetrics::CountRegister(
526 new_registration
.options()->periodicity
, registration_could_fire
,
527 BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE
,
529 DisableAndClearManager(
530 base::Bind(callback
, ERROR_TYPE_STORAGE
, BackgroundSyncRegistration()));
534 BackgroundSyncMetrics::CountRegister(
535 new_registration
.options()->periodicity
, registration_could_fire
,
536 BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE
, ERROR_TYPE_OK
);
538 base::ThreadTaskRunnerHandle::Get()->PostTask(
539 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_OK
, new_registration
));
542 void BackgroundSyncManager::RemoveRegistrationFromMap(
543 int64 sw_registration_id
,
544 const RegistrationKey
& registration_key
) {
545 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
546 DCHECK(LookupRegistration(sw_registration_id
, registration_key
));
548 BackgroundSyncRegistrations
* registrations
=
549 &sw_to_registrations_map_
[sw_registration_id
];
551 registrations
->registration_map
.erase(registration_key
);
554 void BackgroundSyncManager::AddRegistrationToMap(
555 int64 sw_registration_id
,
557 const BackgroundSyncRegistration
& sync_registration
) {
558 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
559 DCHECK(sync_registration
.IsValid());
561 BackgroundSyncRegistrations
* registrations
=
562 &sw_to_registrations_map_
[sw_registration_id
];
563 registrations
->origin
= origin
;
565 RegistrationKey
registration_key(sync_registration
);
566 registrations
->registration_map
[registration_key
] = sync_registration
;
569 void BackgroundSyncManager::StoreDataInBackend(
570 int64 sw_registration_id
,
572 const std::string
& backend_key
,
573 const std::string
& data
,
574 const ServiceWorkerStorage::StatusCallback
& callback
) {
575 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
577 service_worker_context_
->StoreRegistrationUserData(
578 sw_registration_id
, origin
, backend_key
, data
, callback
);
581 void BackgroundSyncManager::GetDataFromBackend(
582 const std::string
& backend_key
,
583 const ServiceWorkerStorage::GetUserDataForAllRegistrationsCallback
&
585 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
587 service_worker_context_
->GetUserDataForAllRegistrations(backend_key
,
591 void BackgroundSyncManager::FireOneShotSync(
592 const BackgroundSyncRegistration
& registration
,
593 const scoped_refptr
<ServiceWorkerVersion
>& active_version
,
594 const ServiceWorkerVersion::StatusCallback
& callback
) {
595 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
597 active_version
->DispatchSyncEvent(
598 mojo::ConvertTo
<SyncRegistrationPtr
>(registration
), callback
);
601 void BackgroundSyncManager::UnregisterImpl(
602 int64 sw_registration_id
,
603 const RegistrationKey
& registration_key
,
604 BackgroundSyncRegistration::RegistrationId sync_registration_id
,
605 SyncPeriodicity periodicity
,
606 const StatusCallback
& callback
) {
607 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
610 BackgroundSyncMetrics::CountUnregister(periodicity
, ERROR_TYPE_STORAGE
);
611 base::ThreadTaskRunnerHandle::Get()->PostTask(
612 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_STORAGE
));
616 const BackgroundSyncRegistration
* existing_registration
=
617 LookupRegistration(sw_registration_id
, registration_key
);
618 if (!existing_registration
||
619 existing_registration
->id() != sync_registration_id
) {
620 BackgroundSyncMetrics::CountUnregister(periodicity
, ERROR_TYPE_NOT_FOUND
);
621 base::ThreadTaskRunnerHandle::Get()->PostTask(
622 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_NOT_FOUND
));
626 RemoveRegistrationFromMap(sw_registration_id
, registration_key
);
628 StoreRegistrations(sw_registration_id
,
629 base::Bind(&BackgroundSyncManager::UnregisterDidStore
,
630 weak_ptr_factory_
.GetWeakPtr(),
631 sw_registration_id
, periodicity
, callback
));
634 void BackgroundSyncManager::UnregisterDidStore(int64 sw_registration_id
,
635 SyncPeriodicity periodicity
,
636 const StatusCallback
& callback
,
637 ServiceWorkerStatusCode status
) {
638 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
640 if (status
== SERVICE_WORKER_ERROR_NOT_FOUND
) {
641 // ServiceWorker was unregistered.
642 BackgroundSyncMetrics::CountUnregister(periodicity
, ERROR_TYPE_STORAGE
);
643 sw_to_registrations_map_
.erase(sw_registration_id
);
644 base::ThreadTaskRunnerHandle::Get()->PostTask(
645 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_STORAGE
));
649 if (status
!= SERVICE_WORKER_OK
) {
650 LOG(ERROR
) << "BackgroundSync failed to unregister due to backend failure.";
651 BackgroundSyncMetrics::CountUnregister(periodicity
, ERROR_TYPE_STORAGE
);
652 DisableAndClearManager(base::Bind(callback
, ERROR_TYPE_STORAGE
));
656 BackgroundSyncMetrics::CountUnregister(periodicity
, ERROR_TYPE_OK
);
657 base::ThreadTaskRunnerHandle::Get()->PostTask(
658 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_OK
));
661 void BackgroundSyncManager::GetRegistrationImpl(
662 int64 sw_registration_id
,
663 const RegistrationKey
& registration_key
,
664 const StatusAndRegistrationCallback
& callback
) {
665 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
668 base::ThreadTaskRunnerHandle::Get()->PostTask(
670 base::Bind(callback
, ERROR_TYPE_STORAGE
, BackgroundSyncRegistration()));
674 const BackgroundSyncRegistration
* out_registration
=
675 LookupRegistration(sw_registration_id
, registration_key
);
676 if (!out_registration
) {
677 base::ThreadTaskRunnerHandle::Get()->PostTask(
678 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_NOT_FOUND
,
679 BackgroundSyncRegistration()));
683 base::ThreadTaskRunnerHandle::Get()->PostTask(
684 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_OK
, *out_registration
));
687 void BackgroundSyncManager::GetRegistrationsImpl(
688 int64 sw_registration_id
,
689 SyncPeriodicity periodicity
,
690 const StatusAndRegistrationsCallback
& callback
) {
691 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
693 std::vector
<BackgroundSyncRegistration
> out_registrations
;
696 base::ThreadTaskRunnerHandle::Get()->PostTask(
697 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_STORAGE
, out_registrations
));
701 SWIdToRegistrationsMap::iterator it
=
702 sw_to_registrations_map_
.find(sw_registration_id
);
704 if (it
!= sw_to_registrations_map_
.end()) {
705 const BackgroundSyncRegistrations
& registrations
= it
->second
;
706 for (const auto& tag_and_registration
: registrations
.registration_map
) {
707 const BackgroundSyncRegistration
& registration
=
708 tag_and_registration
.second
;
709 if (registration
.options()->periodicity
== periodicity
)
710 out_registrations
.push_back(registration
);
714 base::ThreadTaskRunnerHandle::Get()->PostTask(
715 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_OK
, out_registrations
));
718 bool BackgroundSyncManager::AreOptionConditionsMet(
719 const BackgroundSyncRegistrationOptions
& options
) {
720 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
721 return network_observer_
->NetworkSufficient(options
.network_state
) &&
722 power_observer_
->PowerSufficient(options
.power_state
);
725 bool BackgroundSyncManager::IsRegistrationReadyToFire(
726 const BackgroundSyncRegistration
& registration
) {
727 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
729 // TODO(jkarlin): Add support for firing periodic registrations.
730 if (registration
.options()->periodicity
== SYNC_PERIODIC
)
733 if (registration
.sync_state() != SYNC_STATE_PENDING
)
736 DCHECK_EQ(SYNC_ONE_SHOT
, registration
.options()->periodicity
);
738 return AreOptionConditionsMet(*registration
.options());
741 void BackgroundSyncManager::SchedulePendingRegistrations() {
742 #if defined(OS_ANDROID)
743 bool keep_browser_alive_for_one_shot
= false;
745 for (const auto& sw_id_and_registrations
: sw_to_registrations_map_
) {
746 for (const auto& key_and_registration
:
747 sw_id_and_registrations
.second
.registration_map
) {
748 const BackgroundSyncRegistration
& registration
=
749 key_and_registration
.second
;
750 if (registration
.sync_state() == SYNC_STATE_PENDING
) {
751 if (registration
.options()->periodicity
== SYNC_ONE_SHOT
) {
752 keep_browser_alive_for_one_shot
= true;
754 // TODO(jkarlin): Support keeping the browser alive for periodic
761 // TODO(jkarlin): Use the context's path instead of the 'this' pointer as an
762 // identifier. See crbug.com/489705.
763 BrowserThread::PostTask(
764 BrowserThread::UI
, FROM_HERE
,
765 base::Bind(&BackgroundSyncLauncherAndroid::LaunchBrowserWhenNextOnline
,
766 this, keep_browser_alive_for_one_shot
));
768 // TODO(jkarlin): Toggle Chrome's background mode.
772 void BackgroundSyncManager::FireReadyEvents() {
773 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
778 op_scheduler_
.ScheduleOperation(
779 base::Bind(&BackgroundSyncManager::FireReadyEventsImpl
,
780 weak_ptr_factory_
.GetWeakPtr(), MakeEmptyCompletion()));
783 void BackgroundSyncManager::FireReadyEventsImpl(const base::Closure
& callback
) {
784 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
787 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
788 base::Bind(callback
));
792 // Find the registrations that are ready to run.
793 std::vector
<std::pair
<int64
, RegistrationKey
>> sw_id_and_keys_to_fire
;
795 for (auto& sw_id_and_registrations
: sw_to_registrations_map_
) {
796 const int64 service_worker_id
= sw_id_and_registrations
.first
;
797 for (auto& key_and_registration
:
798 sw_id_and_registrations
.second
.registration_map
) {
799 BackgroundSyncRegistration
* registration
= &key_and_registration
.second
;
800 if (IsRegistrationReadyToFire(*registration
)) {
801 sw_id_and_keys_to_fire
.push_back(
802 std::make_pair(service_worker_id
, key_and_registration
.first
));
803 // The state change is not saved to persistent storage because
804 // if the sync event is killed mid-sync then it should return to
805 // SYNC_STATE_PENDING.
806 registration
->set_sync_state(SYNC_STATE_FIRING
);
811 // If there are no registrations currently ready, then just run |callback|.
812 // Otherwise, fire them all, and record the result when done.
813 if (sw_id_and_keys_to_fire
.size() == 0) {
814 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
815 base::Bind(callback
));
817 base::TimeTicks start_time
= base::TimeTicks::Now();
819 // Fire the sync event of the ready registrations and run |callback| once
821 base::Closure events_fired_barrier_closure
= base::BarrierClosure(
822 sw_id_and_keys_to_fire
.size(), base::Bind(callback
));
824 // Record the total time taken after all events have run to completion.
825 base::Closure events_completed_barrier_closure
=
826 base::BarrierClosure(sw_id_and_keys_to_fire
.size(),
827 base::Bind(&OnAllSyncEventsCompleted
, start_time
,
828 sw_id_and_keys_to_fire
.size()));
830 for (const auto& sw_id_and_key
: sw_id_and_keys_to_fire
) {
831 int64 service_worker_id
= sw_id_and_key
.first
;
832 const BackgroundSyncRegistration
* registration
=
833 LookupRegistration(service_worker_id
, sw_id_and_key
.second
);
835 service_worker_context_
->FindRegistrationForId(
836 service_worker_id
, sw_to_registrations_map_
[service_worker_id
].origin
,
837 base::Bind(&BackgroundSyncManager::FireReadyEventsDidFindRegistration
,
838 weak_ptr_factory_
.GetWeakPtr(), sw_id_and_key
.second
,
839 registration
->id(), events_fired_barrier_closure
,
840 events_completed_barrier_closure
));
844 SchedulePendingRegistrations();
847 void BackgroundSyncManager::FireReadyEventsDidFindRegistration(
848 const RegistrationKey
& registration_key
,
849 BackgroundSyncRegistration::RegistrationId registration_id
,
850 const base::Closure
& event_fired_callback
,
851 const base::Closure
& event_completed_callback
,
852 ServiceWorkerStatusCode service_worker_status
,
853 const scoped_refptr
<ServiceWorkerRegistration
>&
854 service_worker_registration
) {
855 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
856 if (service_worker_status
!= SERVICE_WORKER_OK
) {
857 base::ThreadTaskRunnerHandle::Get()->PostTask(
858 FROM_HERE
, base::Bind(event_fired_callback
));
859 base::ThreadTaskRunnerHandle::Get()->PostTask(
860 FROM_HERE
, base::Bind(event_completed_callback
));
864 BackgroundSyncRegistration
* registration
=
865 LookupRegistration(service_worker_registration
->id(), registration_key
);
868 *registration
, service_worker_registration
->active_version(),
869 base::Bind(&BackgroundSyncManager::EventComplete
,
870 weak_ptr_factory_
.GetWeakPtr(), service_worker_registration
,
871 service_worker_registration
->id(), registration_key
,
872 registration_id
, event_completed_callback
));
874 base::ThreadTaskRunnerHandle::Get()->PostTask(
875 FROM_HERE
, base::Bind(event_fired_callback
));
878 // |service_worker_registration| is just to keep the registration alive
879 // while the event is firing.
880 void BackgroundSyncManager::EventComplete(
881 const scoped_refptr
<ServiceWorkerRegistration
>& service_worker_registration
,
882 int64 service_worker_id
,
883 const RegistrationKey
& key
,
884 BackgroundSyncRegistration::RegistrationId sync_registration_id
,
885 const base::Closure
& callback
,
886 ServiceWorkerStatusCode status_code
) {
887 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
891 op_scheduler_
.ScheduleOperation(base::Bind(
892 &BackgroundSyncManager::EventCompleteImpl
, weak_ptr_factory_
.GetWeakPtr(),
893 service_worker_id
, key
, sync_registration_id
, status_code
,
894 MakeClosureCompletion(callback
)));
897 void BackgroundSyncManager::EventCompleteImpl(
898 int64 service_worker_id
,
899 const RegistrationKey
& key
,
900 BackgroundSyncRegistration::RegistrationId sync_registration_id
,
901 ServiceWorkerStatusCode status_code
,
902 const base::Closure
& callback
) {
903 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
906 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
907 base::Bind(callback
));
911 BackgroundSyncRegistration
* registration
=
912 LookupRegistration(service_worker_id
, key
);
913 if (!registration
|| registration
->id() != sync_registration_id
) {
914 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
915 base::Bind(callback
));
919 // The event ran to completion, we should count it, no matter what happens
921 BackgroundSyncMetrics::RecordEventResult(registration
->options()->periodicity
,
922 status_code
== SERVICE_WORKER_OK
);
924 if (registration
->options()->periodicity
== SYNC_ONE_SHOT
) {
925 if (status_code
!= SERVICE_WORKER_OK
) {
926 // TODO(jkarlin) Fire the sync event on the next page load controlled by
927 // this registration. (crbug.com/479665)
928 registration
->set_sync_state(SYNC_STATE_FAILED
);
930 registration
= nullptr;
931 RemoveRegistrationFromMap(service_worker_id
, key
);
934 // TODO(jkarlin): Add support for running periodic syncs. (crbug.com/479674)
940 base::Bind(&BackgroundSyncManager::EventCompleteDidStore
,
941 weak_ptr_factory_
.GetWeakPtr(), service_worker_id
, callback
));
944 void BackgroundSyncManager::EventCompleteDidStore(
945 int64 service_worker_id
,
946 const base::Closure
& callback
,
947 ServiceWorkerStatusCode status_code
) {
948 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
950 if (status_code
== SERVICE_WORKER_ERROR_NOT_FOUND
) {
951 // The registration is gone.
952 sw_to_registrations_map_
.erase(service_worker_id
);
953 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
954 base::Bind(callback
));
958 if (status_code
!= SERVICE_WORKER_OK
) {
959 LOG(ERROR
) << "BackgroundSync failed to store registration due to backend "
961 DisableAndClearManager(base::Bind(callback
));
965 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
966 base::Bind(callback
));
970 void BackgroundSyncManager::OnAllSyncEventsCompleted(
971 const base::TimeTicks
& start_time
,
972 int number_of_batched_sync_events
) {
973 // Record the combined time taken by all sync events.
974 BackgroundSyncMetrics::RecordBatchSyncEventComplete(
975 base::TimeTicks::Now() - start_time
, number_of_batched_sync_events
);
978 void BackgroundSyncManager::OnRegistrationDeletedImpl(
979 int64 registration_id
,
980 const base::Closure
& callback
) {
981 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
983 // The backend (ServiceWorkerStorage) will delete the data, so just delete the
984 // memory representation here.
985 sw_to_registrations_map_
.erase(registration_id
);
986 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
987 base::Bind(callback
));
990 void BackgroundSyncManager::OnStorageWipedImpl(const base::Closure
& callback
) {
991 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
993 sw_to_registrations_map_
.clear();
998 void BackgroundSyncManager::OnNetworkChanged() {
999 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
1004 void BackgroundSyncManager::OnPowerChanged() {
1005 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
1010 template <typename CallbackT
, typename
... Params
>
1011 void BackgroundSyncManager::CompleteOperationCallback(const CallbackT
& callback
,
1012 Params
... parameters
) {
1013 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
1015 callback
.Run(parameters
...);
1016 op_scheduler_
.CompleteOperationAndRunNext();
1019 base::Closure
BackgroundSyncManager::MakeEmptyCompletion() {
1020 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
1022 return MakeClosureCompletion(base::Bind(base::DoNothing
));
1025 base::Closure
BackgroundSyncManager::MakeClosureCompletion(
1026 const base::Closure
& callback
) {
1027 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
1030 &BackgroundSyncManager::CompleteOperationCallback
<base::Closure
>,
1031 weak_ptr_factory_
.GetWeakPtr(), callback
);
1034 BackgroundSyncManager::StatusAndRegistrationCallback
1035 BackgroundSyncManager::MakeStatusAndRegistrationCompletion(
1036 const StatusAndRegistrationCallback
& callback
) {
1037 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
1039 return base::Bind(&BackgroundSyncManager::CompleteOperationCallback
<
1040 StatusAndRegistrationCallback
, ErrorType
,
1041 const BackgroundSyncRegistration
&>,
1042 weak_ptr_factory_
.GetWeakPtr(), callback
);
1045 BackgroundSyncManager::StatusAndRegistrationsCallback
1046 BackgroundSyncManager::MakeStatusAndRegistrationsCompletion(
1047 const StatusAndRegistrationsCallback
& callback
) {
1048 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
1050 return base::Bind(&BackgroundSyncManager::CompleteOperationCallback
<
1051 StatusAndRegistrationsCallback
, ErrorType
,
1052 const std::vector
<BackgroundSyncRegistration
>&>,
1053 weak_ptr_factory_
.GetWeakPtr(), callback
);
1056 BackgroundSyncManager::StatusCallback
1057 BackgroundSyncManager::MakeStatusCompletion(const StatusCallback
& callback
) {
1058 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
1061 &BackgroundSyncManager::CompleteOperationCallback
<StatusCallback
,
1063 weak_ptr_factory_
.GetWeakPtr(), callback
);
1066 } // namespace content