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
,
89 BACKGROUND_SYNC_STATUS_STORAGE_ERROR
);
90 base::ThreadTaskRunnerHandle::Get()->PostTask(
91 FROM_HERE
, base::Bind(callback
, BACKGROUND_SYNC_STATUS_STORAGE_ERROR
,
92 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(
112 periodicity
, BACKGROUND_SYNC_STATUS_STORAGE_ERROR
);
113 base::ThreadTaskRunnerHandle::Get()->PostTask(
114 FROM_HERE
, base::Bind(callback
, BACKGROUND_SYNC_STATUS_STORAGE_ERROR
));
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
);
134 base::ThreadTaskRunnerHandle::Get()->PostTask(
135 FROM_HERE
, base::Bind(callback
, BACKGROUND_SYNC_STATUS_STORAGE_ERROR
,
136 BackgroundSyncRegistration()));
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
);
155 base::ThreadTaskRunnerHandle::Get()->PostTask(
156 FROM_HERE
, base::Bind(callback
, BACKGROUND_SYNC_STATUS_STORAGE_ERROR
,
157 std::vector
<BackgroundSyncRegistration
>()));
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
),
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());
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
);
220 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
221 base::Bind(callback
));
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
));
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
;
254 const BackgroundSyncRegistrationProto
& registration_proto
=
255 registrations_proto
.registration(i
);
257 if (registration_proto
.id() >= registrations
->next_id
) {
258 corruption_detected
= true;
262 RegistrationKey
registration_key(registration_proto
.tag(),
263 registration_proto
.periodicity());
264 BackgroundSyncRegistration
* registration
=
265 ®istrations
->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
280 registration
->set_sync_state(SYNC_STATE_PENDING
);
285 if (corruption_detected
)
289 if (corruption_detected
) {
290 LOG(ERROR
) << "Corruption detected in background sync backend";
291 DisableAndClearManager(base::Bind(callback
));
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
;
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()));
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(
333 base::Bind(callback
, BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER
,
334 BackgroundSyncRegistration()));
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()));
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
);
353 base::Bind(&BackgroundSyncManager::RegisterDidStore
,
354 weak_ptr_factory_
.GetWeakPtr(), sw_registration_id
,
355 *existing_registration
, callback
));
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
));
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(),
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
);
394 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
395 base::Bind(callback
));
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.
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
));
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())
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())
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
);
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()));
526 if (status
!= SERVICE_WORKER_OK
) {
527 LOG(ERROR
) << "BackgroundSync failed to store registration due to backend "
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()));
539 BackgroundSyncMetrics::CountRegister(
540 new_registration
.options()->periodicity
, registration_could_fire
,
541 BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE
,
542 BACKGROUND_SYNC_STATUS_OK
);
544 base::ThreadTaskRunnerHandle::Get()->PostTask(
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
,
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
,
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
&
592 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
594 service_worker_context_
->GetUserDataForAllRegistrations(backend_key
,
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
);
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
));
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
));
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
));
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
));
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
);
681 base::ThreadTaskRunnerHandle::Get()->PostTask(
682 FROM_HERE
, base::Bind(callback
, BACKGROUND_SYNC_STATUS_STORAGE_ERROR
,
683 BackgroundSyncRegistration()));
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()));
696 base::ThreadTaskRunnerHandle::Get()->PostTask(
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
;
710 base::ThreadTaskRunnerHandle::Get()->PostTask(
711 FROM_HERE
, base::Bind(callback
, BACKGROUND_SYNC_STATUS_STORAGE_ERROR
,
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(
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
)
749 if (registration
.sync_state() != SYNC_STATE_PENDING
)
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;
770 // TODO(jkarlin): Support keeping the browser alive for periodic
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
));
784 // TODO(jkarlin): Toggle Chrome's background mode.
788 void BackgroundSyncManager::FireReadyEvents() {
789 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
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
);
803 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
804 base::Bind(callback
));
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
));
833 base::TimeTicks start_time
= base::TimeTicks::Now();
835 // Fire the sync event of the ready registrations and run |callback| once
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
));
880 BackgroundSyncRegistration
* registration
=
881 LookupRegistration(service_worker_registration
->id(), registration_key
);
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
);
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
);
922 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
923 base::Bind(callback
));
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
));
935 // The event ran to completion, we should count it, no matter what happens
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
);
946 registration
= nullptr;
947 RemoveRegistrationFromMap(service_worker_id
, key
);
950 // TODO(jkarlin): Add support for running periodic syncs. (crbug.com/479674)
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
));
974 if (status_code
!= SERVICE_WORKER_OK
) {
975 LOG(ERROR
) << "BackgroundSync failed to store registration due to backend "
977 DisableAndClearManager(base::Bind(callback
));
981 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
982 base::Bind(callback
));
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();
1014 void BackgroundSyncManager::OnNetworkChanged() {
1015 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
1020 void BackgroundSyncManager::OnPowerChanged() {
1021 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
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
);
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
);
1077 &BackgroundSyncManager::CompleteOperationCallback
<StatusCallback
,
1078 BackgroundSyncStatus
>,
1079 weak_ptr_factory_
.GetWeakPtr(), callback
);
1082 } // namespace content