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 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
;
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()));
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
);
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
));
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
);
135 base::ThreadTaskRunnerHandle::Get()->PostTask(
136 FROM_HERE
, base::Bind(callback
, BACKGROUND_SYNC_STATUS_STORAGE_ERROR
,
137 BackgroundSyncRegistration()));
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
);
156 base::ThreadTaskRunnerHandle::Get()->PostTask(
157 FROM_HERE
, base::Bind(callback
, BACKGROUND_SYNC_STATUS_STORAGE_ERROR
,
158 std::vector
<BackgroundSyncRegistration
>()));
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
),
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());
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
);
221 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
222 base::Bind(callback
));
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
));
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
;
255 const BackgroundSyncRegistrationProto
& registration_proto
=
256 registrations_proto
.registration(i
);
258 if (registration_proto
.id() >= registrations
->next_id
) {
259 corruption_detected
= true;
263 RegistrationKey
registration_key(registration_proto
.tag(),
264 registration_proto
.periodicity());
265 BackgroundSyncRegistration
* registration
=
266 ®istrations
->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
281 registration
->set_sync_state(SYNC_STATE_PENDING
);
286 if (corruption_detected
)
290 if (corruption_detected
) {
291 LOG(ERROR
) << "Corruption detected in background sync backend";
292 DisableAndClearManager(base::Bind(callback
));
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
;
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()));
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(
335 base::Bind(callback
, BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER
,
336 BackgroundSyncRegistration()));
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()));
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
);
356 base::Bind(&BackgroundSyncManager::RegisterDidStore
,
357 weak_ptr_factory_
.GetWeakPtr(), sw_registration_id
,
358 *existing_registration
, callback
));
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
));
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(),
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
);
397 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
398 base::Bind(callback
));
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.
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
));
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())
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())
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
);
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()));
529 if (status
!= SERVICE_WORKER_OK
) {
530 LOG(ERROR
) << "BackgroundSync failed to store registration due to backend "
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()));
542 BackgroundSyncMetrics::CountRegister(
543 new_registration
.options()->periodicity
, registration_could_fire
,
544 BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE
,
545 BACKGROUND_SYNC_STATUS_OK
);
547 base::ThreadTaskRunnerHandle::Get()->PostTask(
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
,
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
,
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
&
595 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
597 service_worker_context_
->GetUserDataForAllRegistrations(backend_key
,
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
);
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
));
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
));
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
));
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
));
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
);
684 base::ThreadTaskRunnerHandle::Get()->PostTask(
685 FROM_HERE
, base::Bind(callback
, BACKGROUND_SYNC_STATUS_STORAGE_ERROR
,
686 BackgroundSyncRegistration()));
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()));
699 base::ThreadTaskRunnerHandle::Get()->PostTask(
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
;
713 base::ThreadTaskRunnerHandle::Get()->PostTask(
714 FROM_HERE
, base::Bind(callback
, BACKGROUND_SYNC_STATUS_STORAGE_ERROR
,
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(
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
)
752 if (registration
.sync_state() != SYNC_STATE_PENDING
)
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;
773 // TODO(jkarlin): Support keeping the browser alive for periodic
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
));
787 // TODO(jkarlin): Toggle Chrome's background mode.
791 void BackgroundSyncManager::FireReadyEvents() {
792 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
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
);
806 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
807 base::Bind(callback
));
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
));
836 base::TimeTicks start_time
= base::TimeTicks::Now();
838 // Fire the sync event of the ready registrations and run |callback| once
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
));
883 BackgroundSyncRegistration
* registration
=
884 LookupRegistration(service_worker_registration
->id(), registration_key
);
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
);
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
);
925 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
926 base::Bind(callback
));
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
));
938 // The event ran to completion, we should count it, no matter what happens
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
);
949 registration
= nullptr;
950 RemoveRegistrationFromMap(service_worker_id
, key
);
953 // TODO(jkarlin): Add support for running periodic syncs. (crbug.com/479674)
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
));
977 if (status_code
!= SERVICE_WORKER_OK
) {
978 LOG(ERROR
) << "BackgroundSync failed to store registration due to backend "
980 DisableAndClearManager(base::Bind(callback
));
984 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
985 base::Bind(callback
));
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();
1017 void BackgroundSyncManager::OnNetworkChanged() {
1018 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
1023 void BackgroundSyncManager::OnPowerChanged() {
1024 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
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
);
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
);
1080 &BackgroundSyncManager::CompleteOperationCallback
<StatusCallback
,
1081 BackgroundSyncStatus
>,
1082 weak_ptr_factory_
.GetWeakPtr(), callback
);
1085 } // namespace content