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_network_observer.h"
13 #include "content/browser/background_sync/background_sync_power_observer.h"
14 #include "content/browser/service_worker/service_worker_context_wrapper.h"
15 #include "content/browser/service_worker/service_worker_storage.h"
16 #include "content/public/browser/browser_thread.h"
18 #if defined(OS_ANDROID)
19 #include "content/browser/android/background_sync_launcher_android.h"
23 const char kBackgroundSyncUserDataKey
[] = "BackgroundSyncUserData";
28 const BackgroundSyncManager::BackgroundSyncRegistration::RegistrationId
29 BackgroundSyncManager::BackgroundSyncRegistration::kInvalidRegistrationId
=
32 const BackgroundSyncManager::BackgroundSyncRegistration::RegistrationId
33 BackgroundSyncManager::BackgroundSyncRegistration::kInitialId
= 0;
35 BackgroundSyncManager::BackgroundSyncRegistrations::
36 BackgroundSyncRegistrations()
37 : next_id(BackgroundSyncRegistration::kInitialId
) {
40 BackgroundSyncManager::BackgroundSyncRegistrations::
41 ~BackgroundSyncRegistrations() {
45 scoped_ptr
<BackgroundSyncManager
> BackgroundSyncManager::Create(
46 const scoped_refptr
<ServiceWorkerContextWrapper
>& service_worker_context
) {
47 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
49 BackgroundSyncManager
* sync_manager
=
50 new BackgroundSyncManager(service_worker_context
);
52 return make_scoped_ptr(sync_manager
);
55 BackgroundSyncManager::~BackgroundSyncManager() {
56 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
58 service_worker_context_
->RemoveObserver(this);
61 BackgroundSyncManager::RegistrationKey::RegistrationKey(
62 const BackgroundSyncRegistration
& registration
)
63 : RegistrationKey(registration
.tag
, registration
.periodicity
) {
66 BackgroundSyncManager::RegistrationKey::RegistrationKey(
67 const std::string
& tag
,
68 SyncPeriodicity periodicity
)
69 : value_(periodicity
== SYNC_ONE_SHOT
? "o_" + tag
: "p_" + tag
) {
72 void BackgroundSyncManager::Register(
73 int64 sw_registration_id
,
74 const BackgroundSyncRegistration
& sync_registration
,
75 const StatusAndRegistrationCallback
& callback
) {
76 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
77 DCHECK_EQ(BackgroundSyncRegistration::kInvalidRegistrationId
,
78 sync_registration
.id
);
81 base::ThreadTaskRunnerHandle::Get()->PostTask(
83 base::Bind(callback
, ERROR_TYPE_STORAGE
, BackgroundSyncRegistration()));
87 op_scheduler_
.ScheduleOperation(base::Bind(
88 &BackgroundSyncManager::RegisterImpl
, weak_ptr_factory_
.GetWeakPtr(),
89 sw_registration_id
, sync_registration
,
90 MakeStatusAndRegistrationCompletion(callback
)));
93 void BackgroundSyncManager::Unregister(
94 int64 sw_registration_id
,
95 const std::string
& sync_registration_tag
,
96 SyncPeriodicity periodicity
,
97 BackgroundSyncRegistration::RegistrationId sync_registration_id
,
98 const StatusCallback
& callback
) {
99 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
102 base::ThreadTaskRunnerHandle::Get()->PostTask(
103 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_STORAGE
));
107 RegistrationKey
registration_key(sync_registration_tag
, periodicity
);
109 op_scheduler_
.ScheduleOperation(base::Bind(
110 &BackgroundSyncManager::UnregisterImpl
, weak_ptr_factory_
.GetWeakPtr(),
111 sw_registration_id
, registration_key
, sync_registration_id
,
112 MakeStatusCompletion(callback
)));
115 void BackgroundSyncManager::GetRegistration(
116 int64 sw_registration_id
,
117 const std::string
& sync_registration_tag
,
118 SyncPeriodicity periodicity
,
119 const StatusAndRegistrationCallback
& callback
) {
120 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
123 base::ThreadTaskRunnerHandle::Get()->PostTask(
125 base::Bind(callback
, ERROR_TYPE_STORAGE
, BackgroundSyncRegistration()));
129 RegistrationKey
registration_key(sync_registration_tag
, periodicity
);
131 op_scheduler_
.ScheduleOperation(base::Bind(
132 &BackgroundSyncManager::GetRegistrationImpl
,
133 weak_ptr_factory_
.GetWeakPtr(), sw_registration_id
, registration_key
,
134 MakeStatusAndRegistrationCompletion(callback
)));
137 void BackgroundSyncManager::GetRegistrations(
138 int64 sw_registration_id
,
139 SyncPeriodicity periodicity
,
140 const StatusAndRegistrationsCallback
& callback
) {
141 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
144 base::ThreadTaskRunnerHandle::Get()->PostTask(
145 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_STORAGE
,
146 std::vector
<BackgroundSyncRegistration
>()));
150 op_scheduler_
.ScheduleOperation(
151 base::Bind(&BackgroundSyncManager::GetRegistrationsImpl
,
152 weak_ptr_factory_
.GetWeakPtr(), sw_registration_id
,
153 periodicity
, MakeStatusAndRegistrationsCompletion(callback
)));
156 void BackgroundSyncManager::OnRegistrationDeleted(int64 registration_id
,
157 const GURL
& pattern
) {
158 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
160 // Operations already in the queue will either fail when they write to storage
161 // or return stale results based on registrations loaded in memory. This is
162 // inconsequential since the service worker is gone.
163 op_scheduler_
.ScheduleOperation(base::Bind(
164 &BackgroundSyncManager::OnRegistrationDeletedImpl
,
165 weak_ptr_factory_
.GetWeakPtr(), registration_id
, MakeEmptyCompletion()));
168 void BackgroundSyncManager::OnStorageWiped() {
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 workers are gone.
174 op_scheduler_
.ScheduleOperation(
175 base::Bind(&BackgroundSyncManager::OnStorageWipedImpl
,
176 weak_ptr_factory_
.GetWeakPtr(), MakeEmptyCompletion()));
179 BackgroundSyncManager::BackgroundSyncManager(
180 const scoped_refptr
<ServiceWorkerContextWrapper
>& service_worker_context
)
181 : service_worker_context_(service_worker_context
),
183 weak_ptr_factory_(this) {
184 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
186 service_worker_context_
->AddObserver(this);
188 network_observer_
.reset(new BackgroundSyncNetworkObserver(
189 base::Bind(&BackgroundSyncManager::OnNetworkChanged
,
190 weak_ptr_factory_
.GetWeakPtr())));
191 power_observer_
.reset(new BackgroundSyncPowerObserver(base::Bind(
192 &BackgroundSyncManager::OnPowerChanged
, weak_ptr_factory_
.GetWeakPtr())));
195 void BackgroundSyncManager::Init() {
196 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
197 DCHECK(!op_scheduler_
.ScheduledOperations());
200 op_scheduler_
.ScheduleOperation(base::Bind(&BackgroundSyncManager::InitImpl
,
201 weak_ptr_factory_
.GetWeakPtr(),
202 MakeEmptyCompletion()));
205 void BackgroundSyncManager::InitImpl(const base::Closure
& callback
) {
206 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
209 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
210 base::Bind(callback
));
215 kBackgroundSyncUserDataKey
,
216 base::Bind(&BackgroundSyncManager::InitDidGetDataFromBackend
,
217 weak_ptr_factory_
.GetWeakPtr(), callback
));
220 void BackgroundSyncManager::InitDidGetDataFromBackend(
221 const base::Closure
& callback
,
222 const std::vector
<std::pair
<int64
, std::string
>>& user_data
,
223 ServiceWorkerStatusCode status
) {
224 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
226 if (status
!= SERVICE_WORKER_OK
&& status
!= SERVICE_WORKER_ERROR_NOT_FOUND
) {
227 LOG(ERROR
) << "BackgroundSync failed to init due to backend failure.";
228 DisableAndClearManager(base::Bind(callback
));
232 bool corruption_detected
= false;
233 for (const std::pair
<int64
, std::string
>& data
: user_data
) {
234 BackgroundSyncRegistrationsProto registrations_proto
;
235 if (registrations_proto
.ParseFromString(data
.second
)) {
236 BackgroundSyncRegistrations
* registrations
=
237 &sw_to_registrations_map_
[data
.first
];
238 registrations
->next_id
= registrations_proto
.next_registration_id();
239 registrations
->origin
= GURL(registrations_proto
.origin());
241 for (int i
= 0, max
= registrations_proto
.registration_size(); i
< max
;
243 const BackgroundSyncRegistrationProto
& registration_proto
=
244 registrations_proto
.registration(i
);
246 if (registration_proto
.id() >= registrations
->next_id
) {
247 corruption_detected
= true;
251 RegistrationKey
registration_key(registration_proto
.tag(),
252 registration_proto
.periodicity());
253 BackgroundSyncRegistration
* registration
=
254 ®istrations
->registration_map
[registration_key
];
256 registration
->id
= registration_proto
.id();
257 registration
->tag
= registration_proto
.tag();
258 registration
->periodicity
= registration_proto
.periodicity();
259 registration
->min_period
= registration_proto
.min_period();
260 registration
->network_state
= registration_proto
.network_state();
261 registration
->power_state
= registration_proto
.power_state();
262 registration
->sync_state
= registration_proto
.sync_state();
263 if (registration
->sync_state
== SYNC_STATE_FIRING
) {
264 // If the browser (or worker) closed while firing the event, consider
266 registration
->sync_state
= SYNC_STATE_PENDING
;
271 if (corruption_detected
)
275 if (corruption_detected
) {
276 LOG(ERROR
) << "Corruption detected in background sync backend";
277 DisableAndClearManager(base::Bind(callback
));
283 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
284 base::Bind(callback
));
287 void BackgroundSyncManager::RegisterImpl(
288 int64 sw_registration_id
,
289 const BackgroundSyncRegistration
& sync_registration
,
290 const StatusAndRegistrationCallback
& callback
) {
291 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
294 base::ThreadTaskRunnerHandle::Get()->PostTask(
296 base::Bind(callback
, ERROR_TYPE_STORAGE
, BackgroundSyncRegistration()));
300 const BackgroundSyncRegistration
* existing_registration
= LookupRegistration(
301 sw_registration_id
, RegistrationKey(sync_registration
));
302 if (existing_registration
&&
303 existing_registration
->Equals(sync_registration
)) {
304 base::ThreadTaskRunnerHandle::Get()->PostTask(
305 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_OK
, *existing_registration
));
309 BackgroundSyncRegistration new_registration
= sync_registration
;
310 BackgroundSyncRegistrations
* registrations
=
311 &sw_to_registrations_map_
[sw_registration_id
];
312 new_registration
.id
= registrations
->next_id
++;
314 ServiceWorkerRegistration
* sw_registration
=
315 service_worker_context_
->GetLiveRegistration(sw_registration_id
);
316 if (!sw_registration
|| !sw_registration
->active_version()) {
317 base::ThreadTaskRunnerHandle::Get()->PostTask(
318 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_NO_SERVICE_WORKER
,
319 BackgroundSyncRegistration()));
323 AddRegistrationToMap(sw_registration_id
,
324 sw_registration
->pattern().GetOrigin(),
329 base::Bind(&BackgroundSyncManager::RegisterDidStore
,
330 weak_ptr_factory_
.GetWeakPtr(), sw_registration_id
,
331 new_registration
, callback
));
334 void BackgroundSyncManager::DisableAndClearManager(
335 const base::Closure
& callback
) {
336 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
339 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
340 base::Bind(callback
));
345 sw_to_registrations_map_
.clear();
347 // Delete all backend entries. The memory representation of registered syncs
348 // may be out of sync with storage (e.g., due to corruption detection on
349 // loading from storage), so reload the registrations from storage again.
351 kBackgroundSyncUserDataKey
,
352 base::Bind(&BackgroundSyncManager::DisableAndClearDidGetRegistrations
,
353 weak_ptr_factory_
.GetWeakPtr(), callback
));
356 void BackgroundSyncManager::DisableAndClearDidGetRegistrations(
357 const base::Closure
& callback
,
358 const std::vector
<std::pair
<int64
, std::string
>>& user_data
,
359 ServiceWorkerStatusCode status
) {
360 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
362 if (status
!= SERVICE_WORKER_OK
|| user_data
.empty()) {
363 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
364 base::Bind(callback
));
368 base::Closure barrier_closure
=
369 base::BarrierClosure(user_data
.size(), base::Bind(callback
));
371 for (const auto& sw_id_and_regs
: user_data
) {
372 service_worker_context_
->ClearRegistrationUserData(
373 sw_id_and_regs
.first
, kBackgroundSyncUserDataKey
,
374 base::Bind(&BackgroundSyncManager::DisableAndClearManagerClearedOne
,
375 weak_ptr_factory_
.GetWeakPtr(), barrier_closure
));
379 void BackgroundSyncManager::DisableAndClearManagerClearedOne(
380 const base::Closure
& barrier_closure
,
381 ServiceWorkerStatusCode status
) {
382 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
384 // The status doesn't matter at this point, there is nothing else to be done.
385 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
386 base::Bind(barrier_closure
));
389 BackgroundSyncManager::BackgroundSyncRegistration
*
390 BackgroundSyncManager::LookupRegistration(
391 int64 sw_registration_id
,
392 const RegistrationKey
& registration_key
) {
393 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
395 SWIdToRegistrationsMap::iterator it
=
396 sw_to_registrations_map_
.find(sw_registration_id
);
397 if (it
== sw_to_registrations_map_
.end())
400 BackgroundSyncRegistrations
& registrations
= it
->second
;
401 DCHECK_LE(BackgroundSyncRegistration::kInitialId
, registrations
.next_id
);
402 DCHECK(!registrations
.origin
.is_empty());
404 auto key_and_registration_iter
=
405 registrations
.registration_map
.find(registration_key
);
406 if (key_and_registration_iter
== registrations
.registration_map
.end())
409 return &key_and_registration_iter
->second
;
412 void BackgroundSyncManager::StoreRegistrations(
413 int64 sw_registration_id
,
414 const ServiceWorkerStorage::StatusCallback
& callback
) {
415 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
417 // Serialize the data.
418 const BackgroundSyncRegistrations
& registrations
=
419 sw_to_registrations_map_
[sw_registration_id
];
420 BackgroundSyncRegistrationsProto registrations_proto
;
421 registrations_proto
.set_next_registration_id(registrations
.next_id
);
422 registrations_proto
.set_origin(registrations
.origin
.spec());
424 for (const auto& key_and_registration
: registrations
.registration_map
) {
425 const BackgroundSyncRegistration
& registration
=
426 key_and_registration
.second
;
427 BackgroundSyncRegistrationProto
* registration_proto
=
428 registrations_proto
.add_registration();
429 registration_proto
->set_id(registration
.id
);
430 registration_proto
->set_tag(registration
.tag
);
431 registration_proto
->set_periodicity(registration
.periodicity
);
432 registration_proto
->set_min_period(registration
.min_period
);
433 registration_proto
->set_network_state(registration
.network_state
);
434 registration_proto
->set_power_state(registration
.power_state
);
435 registration_proto
->set_sync_state(registration
.sync_state
);
437 std::string serialized
;
438 bool success
= registrations_proto
.SerializeToString(&serialized
);
441 StoreDataInBackend(sw_registration_id
, registrations
.origin
,
442 kBackgroundSyncUserDataKey
, serialized
, callback
);
445 void BackgroundSyncManager::RegisterDidStore(
446 int64 sw_registration_id
,
447 const BackgroundSyncRegistration
& new_registration
,
448 const StatusAndRegistrationCallback
& callback
,
449 ServiceWorkerStatusCode status
) {
450 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
452 if (status
== SERVICE_WORKER_ERROR_NOT_FOUND
) {
453 // The registration is gone.
454 sw_to_registrations_map_
.erase(sw_registration_id
);
455 base::ThreadTaskRunnerHandle::Get()->PostTask(
457 base::Bind(callback
, ERROR_TYPE_STORAGE
, BackgroundSyncRegistration()));
461 if (status
!= SERVICE_WORKER_OK
) {
462 LOG(ERROR
) << "BackgroundSync failed to store registration due to backend "
464 DisableAndClearManager(
465 base::Bind(callback
, ERROR_TYPE_STORAGE
, BackgroundSyncRegistration()));
470 base::ThreadTaskRunnerHandle::Get()->PostTask(
471 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_OK
, new_registration
));
474 void BackgroundSyncManager::RemoveRegistrationFromMap(
475 int64 sw_registration_id
,
476 const RegistrationKey
& registration_key
) {
477 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
478 DCHECK(LookupRegistration(sw_registration_id
, registration_key
));
480 BackgroundSyncRegistrations
* registrations
=
481 &sw_to_registrations_map_
[sw_registration_id
];
483 registrations
->registration_map
.erase(registration_key
);
486 void BackgroundSyncManager::AddRegistrationToMap(
487 int64 sw_registration_id
,
489 const BackgroundSyncRegistration
& sync_registration
) {
490 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
491 DCHECK_NE(BackgroundSyncRegistration::kInvalidRegistrationId
,
494 BackgroundSyncRegistrations
* registrations
=
495 &sw_to_registrations_map_
[sw_registration_id
];
496 registrations
->origin
= origin
;
498 RegistrationKey
registration_key(sync_registration
);
499 registrations
->registration_map
[registration_key
] = sync_registration
;
502 void BackgroundSyncManager::StoreDataInBackend(
503 int64 sw_registration_id
,
505 const std::string
& backend_key
,
506 const std::string
& data
,
507 const ServiceWorkerStorage::StatusCallback
& callback
) {
508 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
510 service_worker_context_
->StoreRegistrationUserData(
511 sw_registration_id
, origin
, backend_key
, data
, callback
);
514 void BackgroundSyncManager::GetDataFromBackend(
515 const std::string
& backend_key
,
516 const ServiceWorkerStorage::GetUserDataForAllRegistrationsCallback
&
518 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
520 service_worker_context_
->GetUserDataForAllRegistrations(backend_key
,
524 void BackgroundSyncManager::FireOneShotSync(
525 const scoped_refptr
<ServiceWorkerVersion
>& active_version
,
526 const ServiceWorkerVersion::StatusCallback
& callback
) {
527 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
529 active_version
->DispatchSyncEvent(callback
);
532 void BackgroundSyncManager::UnregisterImpl(
533 int64 sw_registration_id
,
534 const RegistrationKey
& registration_key
,
535 BackgroundSyncRegistration::RegistrationId sync_registration_id
,
536 const StatusCallback
& callback
) {
537 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
540 base::ThreadTaskRunnerHandle::Get()->PostTask(
541 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_STORAGE
));
545 const BackgroundSyncRegistration
* existing_registration
=
546 LookupRegistration(sw_registration_id
, registration_key
);
547 if (!existing_registration
||
548 existing_registration
->id
!= sync_registration_id
) {
549 base::ThreadTaskRunnerHandle::Get()->PostTask(
550 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_NOT_FOUND
));
554 RemoveRegistrationFromMap(sw_registration_id
, registration_key
);
558 base::Bind(&BackgroundSyncManager::UnregisterDidStore
,
559 weak_ptr_factory_
.GetWeakPtr(), sw_registration_id
, callback
));
562 void BackgroundSyncManager::UnregisterDidStore(
563 int64 sw_registration_id
,
564 const StatusCallback
& callback
,
565 ServiceWorkerStatusCode status
) {
566 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
568 if (status
== SERVICE_WORKER_ERROR_NOT_FOUND
) {
569 // ServiceWorker was unregistered.
570 sw_to_registrations_map_
.erase(sw_registration_id
);
571 base::ThreadTaskRunnerHandle::Get()->PostTask(
572 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_STORAGE
));
576 if (status
!= SERVICE_WORKER_OK
) {
577 LOG(ERROR
) << "BackgroundSync failed to unregister due to backend failure.";
578 DisableAndClearManager(base::Bind(callback
, ERROR_TYPE_STORAGE
));
582 base::ThreadTaskRunnerHandle::Get()->PostTask(
583 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_OK
));
586 void BackgroundSyncManager::GetRegistrationImpl(
587 int64 sw_registration_id
,
588 const RegistrationKey
& registration_key
,
589 const StatusAndRegistrationCallback
& callback
) {
590 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
593 base::ThreadTaskRunnerHandle::Get()->PostTask(
595 base::Bind(callback
, ERROR_TYPE_STORAGE
, BackgroundSyncRegistration()));
599 const BackgroundSyncRegistration
* out_registration
=
600 LookupRegistration(sw_registration_id
, registration_key
);
601 if (!out_registration
) {
602 base::ThreadTaskRunnerHandle::Get()->PostTask(
603 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_NOT_FOUND
,
604 BackgroundSyncRegistration()));
608 base::ThreadTaskRunnerHandle::Get()->PostTask(
609 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_OK
, *out_registration
));
612 void BackgroundSyncManager::GetRegistrationsImpl(
613 int64 sw_registration_id
,
614 SyncPeriodicity periodicity
,
615 const StatusAndRegistrationsCallback
& callback
) {
616 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
618 std::vector
<BackgroundSyncRegistration
> out_registrations
;
621 base::ThreadTaskRunnerHandle::Get()->PostTask(
622 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_STORAGE
, out_registrations
));
626 SWIdToRegistrationsMap::iterator it
=
627 sw_to_registrations_map_
.find(sw_registration_id
);
629 if (it
!= sw_to_registrations_map_
.end()) {
630 const BackgroundSyncRegistrations
& registrations
= it
->second
;
631 for (const auto& tag_and_registration
: registrations
.registration_map
) {
632 const BackgroundSyncRegistration
& registration
=
633 tag_and_registration
.second
;
634 if (registration
.periodicity
== periodicity
)
635 out_registrations
.push_back(registration
);
639 base::ThreadTaskRunnerHandle::Get()->PostTask(
640 FROM_HERE
, base::Bind(callback
, ERROR_TYPE_OK
, out_registrations
));
643 bool BackgroundSyncManager::IsRegistrationReadyToFire(
644 const BackgroundSyncRegistration
& registration
) {
645 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
647 // TODO(jkarlin): Add support for firing periodic registrations.
648 if (registration
.periodicity
== SYNC_PERIODIC
)
651 if (registration
.sync_state
!= SYNC_STATE_PENDING
)
654 DCHECK_EQ(SYNC_ONE_SHOT
, registration
.periodicity
);
656 return network_observer_
->NetworkSufficient(registration
.network_state
) &&
657 power_observer_
->PowerSufficient(registration
.power_state
);
660 void BackgroundSyncManager::SchedulePendingRegistrations() {
661 #if defined(OS_ANDROID)
662 bool keep_browser_alive_for_one_shot
= false;
664 for (const auto& sw_id_and_registrations
: sw_to_registrations_map_
) {
665 for (const auto& key_and_registration
:
666 sw_id_and_registrations
.second
.registration_map
) {
667 const BackgroundSyncRegistration
& registration
=
668 key_and_registration
.second
;
669 if (registration
.sync_state
== SYNC_STATE_PENDING
) {
670 if (registration
.periodicity
== SYNC_ONE_SHOT
) {
671 keep_browser_alive_for_one_shot
= true;
673 // TODO(jkarlin): Support keeping the browser alive for periodic
680 // TODO(jkarlin): Use the context's path instead of the 'this' pointer as an
681 // identifier. See crbug.com/489705.
682 BrowserThread::PostTask(
683 BrowserThread::UI
, FROM_HERE
,
684 base::Bind(&BackgroundSyncLauncherAndroid::LaunchBrowserWhenNextOnline
,
685 this, keep_browser_alive_for_one_shot
));
687 // TODO(jkarlin): Toggle Chrome's background mode.
691 void BackgroundSyncManager::FireReadyEvents() {
692 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
697 op_scheduler_
.ScheduleOperation(
698 base::Bind(&BackgroundSyncManager::FireReadyEventsImpl
,
699 weak_ptr_factory_
.GetWeakPtr(), MakeEmptyCompletion()));
702 void BackgroundSyncManager::FireReadyEventsImpl(const base::Closure
& callback
) {
703 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
706 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
707 base::Bind(callback
));
711 // Find the registrations that are ready to run.
712 std::vector
<std::pair
<int64
, RegistrationKey
>> sw_id_and_keys_to_fire
;
714 for (auto& sw_id_and_registrations
: sw_to_registrations_map_
) {
715 const int64 service_worker_id
= sw_id_and_registrations
.first
;
716 for (auto& key_and_registration
:
717 sw_id_and_registrations
.second
.registration_map
) {
718 BackgroundSyncRegistration
* registration
= &key_and_registration
.second
;
719 if (IsRegistrationReadyToFire(*registration
)) {
720 sw_id_and_keys_to_fire
.push_back(
721 std::make_pair(service_worker_id
, key_and_registration
.first
));
722 // The state change is not saved to persistent storage because
723 // if the sync event is killed mid-sync then it should return to
724 // SYNC_STATE_PENDING.
725 registration
->sync_state
= SYNC_STATE_FIRING
;
730 // Fire the sync event of the ready registrations and run |callback| once
732 base::Closure barrier_closure
=
733 base::BarrierClosure(sw_id_and_keys_to_fire
.size(), base::Bind(callback
));
735 for (const auto& sw_id_and_key
: sw_id_and_keys_to_fire
) {
736 int64 service_worker_id
= sw_id_and_key
.first
;
737 const BackgroundSyncRegistration
* registration
=
738 LookupRegistration(service_worker_id
, sw_id_and_key
.second
);
740 service_worker_context_
->FindRegistrationForId(
741 service_worker_id
, sw_to_registrations_map_
[service_worker_id
].origin
,
742 base::Bind(&BackgroundSyncManager::FireReadyEventsDidFindRegistration
,
743 weak_ptr_factory_
.GetWeakPtr(), sw_id_and_key
.second
,
744 registration
->id
, barrier_closure
));
747 SchedulePendingRegistrations();
750 void BackgroundSyncManager::FireReadyEventsDidFindRegistration(
751 const RegistrationKey
& registration_key
,
752 BackgroundSyncRegistration::RegistrationId registration_id
,
753 const base::Closure
& callback
,
754 ServiceWorkerStatusCode service_worker_status
,
755 const scoped_refptr
<ServiceWorkerRegistration
>&
756 service_worker_registration
) {
757 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
759 if (service_worker_status
!= SERVICE_WORKER_OK
) {
760 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
761 base::Bind(callback
));
766 service_worker_registration
->active_version(),
767 base::Bind(&BackgroundSyncManager::EventComplete
,
768 weak_ptr_factory_
.GetWeakPtr(), service_worker_registration
,
769 service_worker_registration
->id(), registration_key
,
772 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
773 base::Bind(callback
));
776 // |service_worker_registration| is just to keep the registration alive
777 // while the event is firing.
778 void BackgroundSyncManager::EventComplete(
779 const scoped_refptr
<ServiceWorkerRegistration
>& service_worker_registration
,
780 int64 service_worker_id
,
781 const RegistrationKey
& key
,
782 BackgroundSyncRegistration::RegistrationId sync_registration_id
,
783 ServiceWorkerStatusCode status_code
) {
784 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
789 op_scheduler_
.ScheduleOperation(
790 base::Bind(&BackgroundSyncManager::EventCompleteImpl
,
791 weak_ptr_factory_
.GetWeakPtr(), service_worker_id
, key
,
792 sync_registration_id
, status_code
, MakeEmptyCompletion()));
795 void BackgroundSyncManager::EventCompleteImpl(
796 int64 service_worker_id
,
797 const RegistrationKey
& key
,
798 BackgroundSyncRegistration::RegistrationId sync_registration_id
,
799 ServiceWorkerStatusCode status_code
,
800 const base::Closure
& callback
) {
801 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
804 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
805 base::Bind(callback
));
809 BackgroundSyncRegistration
* registration
=
810 LookupRegistration(service_worker_id
, key
);
811 if (!registration
|| registration
->id
!= sync_registration_id
) {
812 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
813 base::Bind(callback
));
817 if (registration
->periodicity
== SYNC_ONE_SHOT
) {
818 if (status_code
!= SERVICE_WORKER_OK
) {
819 // TODO(jkarlin) Fire the sync event on the next page load controlled by
820 // this registration. (crbug.com/479665)
821 registration
->sync_state
= SYNC_STATE_FAILED
;
823 registration
= nullptr;
824 RemoveRegistrationFromMap(service_worker_id
, key
);
827 // TODO(jkarlin): Add support for running periodic syncs. (crbug.com/479674)
833 base::Bind(&BackgroundSyncManager::EventCompleteDidStore
,
834 weak_ptr_factory_
.GetWeakPtr(), service_worker_id
, callback
));
837 void BackgroundSyncManager::EventCompleteDidStore(
838 int64 service_worker_id
,
839 const base::Closure
& callback
,
840 ServiceWorkerStatusCode status_code
) {
841 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
843 if (status_code
== SERVICE_WORKER_ERROR_NOT_FOUND
) {
844 // The registration is gone.
845 sw_to_registrations_map_
.erase(service_worker_id
);
846 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
847 base::Bind(callback
));
851 if (status_code
!= SERVICE_WORKER_OK
) {
852 LOG(ERROR
) << "BackgroundSync failed to store registration due to backend "
854 DisableAndClearManager(base::Bind(callback
));
858 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
859 base::Bind(callback
));
862 void BackgroundSyncManager::OnRegistrationDeletedImpl(
863 int64 registration_id
,
864 const base::Closure
& callback
) {
865 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
867 // The backend (ServiceWorkerStorage) will delete the data, so just delete the
868 // memory representation here.
869 sw_to_registrations_map_
.erase(registration_id
);
870 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
871 base::Bind(callback
));
874 void BackgroundSyncManager::OnStorageWipedImpl(const base::Closure
& callback
) {
875 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
877 sw_to_registrations_map_
.clear();
882 void BackgroundSyncManager::OnNetworkChanged() {
883 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
888 void BackgroundSyncManager::OnPowerChanged() {
889 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
894 template <typename CallbackT
, typename
... Params
>
895 void BackgroundSyncManager::CompleteOperationCallback(const CallbackT
& callback
,
896 Params
... parameters
) {
897 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
899 callback
.Run(parameters
...);
900 op_scheduler_
.CompleteOperationAndRunNext();
903 base::Closure
BackgroundSyncManager::MakeEmptyCompletion() {
904 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
907 &BackgroundSyncManager::CompleteOperationCallback
<base::Closure
>,
908 weak_ptr_factory_
.GetWeakPtr(), base::Bind(base::DoNothing
));
911 BackgroundSyncManager::StatusAndRegistrationCallback
912 BackgroundSyncManager::MakeStatusAndRegistrationCompletion(
913 const StatusAndRegistrationCallback
& callback
) {
914 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
916 return base::Bind(&BackgroundSyncManager::CompleteOperationCallback
<
917 StatusAndRegistrationCallback
, ErrorType
,
918 const BackgroundSyncRegistration
&>,
919 weak_ptr_factory_
.GetWeakPtr(), callback
);
922 BackgroundSyncManager::StatusAndRegistrationsCallback
923 BackgroundSyncManager::MakeStatusAndRegistrationsCompletion(
924 const StatusAndRegistrationsCallback
& callback
) {
925 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
927 return base::Bind(&BackgroundSyncManager::CompleteOperationCallback
<
928 StatusAndRegistrationsCallback
, ErrorType
,
929 const std::vector
<BackgroundSyncRegistration
>&>,
930 weak_ptr_factory_
.GetWeakPtr(), callback
);
933 BackgroundSyncManager::StatusCallback
934 BackgroundSyncManager::MakeStatusCompletion(const StatusCallback
& callback
) {
935 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
938 &BackgroundSyncManager::CompleteOperationCallback
<StatusCallback
,
940 weak_ptr_factory_
.GetWeakPtr(), callback
);
943 } // namespace content