| Index: content/browser/background_sync/background_sync_manager.cc
|
| diff --git a/content/browser/background_sync/background_sync_manager.cc b/content/browser/background_sync/background_sync_manager.cc
|
| index 9bfa52e87926357a7276b55fae0fce21d49fa06c..9bc9052552177ea3d887452baf34334c4ede6c58 100644
|
| --- a/content/browser/background_sync/background_sync_manager.cc
|
| +++ b/content/browser/background_sync/background_sync_manager.cc
|
| @@ -140,6 +140,7 @@ void BackgroundSyncManager::OnRegistrationDeleted(int64 registration_id,
|
|
|
| void BackgroundSyncManager::OnStorageWiped() {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| // Operations already in the queue will either fail when they write to storage
|
| // or return stale results based on registrations loaded in memory. This is
|
| // inconsequential since the service workers are gone.
|
| @@ -190,6 +191,8 @@ void BackgroundSyncManager::InitDidGetDataFromBackend(
|
| const base::Closure& callback,
|
| const std::vector<std::pair<int64, std::string>>& user_data,
|
| ServiceWorkerStatusCode status) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
|
| LOG(ERROR) << "BackgroundSync failed to init due to backend failure.";
|
| DisableAndClearManager(base::Bind(callback));
|
| @@ -226,6 +229,12 @@ void BackgroundSyncManager::InitDidGetDataFromBackend(
|
| registration->min_period = registration_proto.min_period();
|
| registration->network_state = registration_proto.network_state();
|
| registration->power_state = registration_proto.power_state();
|
| + registration->sync_state = registration_proto.sync_state();
|
| + if (registration->sync_state == SYNC_STATE_FIRING) {
|
| + // If the browser (or worker) closed while firing the event, consider
|
| + // it pending again>
|
| + registration->sync_state = SYNC_STATE_PENDING;
|
| + }
|
| }
|
| }
|
|
|
| @@ -239,7 +248,7 @@ void BackgroundSyncManager::InitDidGetDataFromBackend(
|
| return;
|
| }
|
|
|
| - // TODO(jkarlin): Call the scheduling algorithm here.
|
| + FireReadyEvents();
|
|
|
| base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback));
|
| }
|
| @@ -248,6 +257,8 @@ void BackgroundSyncManager::RegisterImpl(
|
| int64 sw_registration_id,
|
| const BackgroundSyncRegistration& sync_registration,
|
| const StatusAndRegistrationCallback& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| if (disabled_) {
|
| base::MessageLoop::current()->PostTask(
|
| FROM_HERE,
|
| @@ -291,6 +302,8 @@ void BackgroundSyncManager::RegisterImpl(
|
|
|
| void BackgroundSyncManager::DisableAndClearManager(
|
| const base::Closure& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| if (disabled_) {
|
| base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback));
|
| return;
|
| @@ -312,6 +325,8 @@ void BackgroundSyncManager::DisableAndClearDidGetRegistrations(
|
| const base::Closure& callback,
|
| const std::vector<std::pair<int64, std::string>>& user_data,
|
| ServiceWorkerStatusCode status) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| if (status != SERVICE_WORKER_OK || user_data.empty()) {
|
| base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback));
|
| return;
|
| @@ -331,6 +346,8 @@ void BackgroundSyncManager::DisableAndClearDidGetRegistrations(
|
| void BackgroundSyncManager::DisableAndClearManagerClearedOne(
|
| const base::Closure& barrier_closure,
|
| ServiceWorkerStatusCode status) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| // The status doesn't matter at this point, there is nothing else to be done.
|
| base::MessageLoop::current()->PostTask(FROM_HERE,
|
| base::Bind(barrier_closure));
|
| @@ -340,6 +357,8 @@ BackgroundSyncManager::BackgroundSyncRegistration*
|
| BackgroundSyncManager::LookupRegistration(
|
| int64 sw_registration_id,
|
| const RegistrationKey& registration_key) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| SWIdToRegistrationsMap::iterator it =
|
| sw_to_registrations_map_.find(sw_registration_id);
|
| if (it == sw_to_registrations_map_.end())
|
| @@ -360,6 +379,8 @@ BackgroundSyncManager::LookupRegistration(
|
| void BackgroundSyncManager::StoreRegistrations(
|
| int64 sw_registration_id,
|
| const ServiceWorkerStorage::StatusCallback& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| // Serialize the data.
|
| const BackgroundSyncRegistrations& registrations =
|
| sw_to_registrations_map_[sw_registration_id];
|
| @@ -378,6 +399,7 @@ void BackgroundSyncManager::StoreRegistrations(
|
| registration_proto->set_min_period(registration.min_period);
|
| registration_proto->set_network_state(registration.network_state);
|
| registration_proto->set_power_state(registration.power_state);
|
| + registration_proto->set_sync_state(registration.sync_state);
|
| }
|
| std::string serialized;
|
| bool success = registrations_proto.SerializeToString(&serialized);
|
| @@ -392,6 +414,8 @@ void BackgroundSyncManager::RegisterDidStore(
|
| const BackgroundSyncRegistration& new_registration,
|
| const StatusAndRegistrationCallback& callback,
|
| ServiceWorkerStatusCode status) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| if (status == SERVICE_WORKER_ERROR_NOT_FOUND) {
|
| // The registration is gone.
|
| sw_to_registrations_map_.erase(sw_registration_id);
|
| @@ -409,7 +433,7 @@ void BackgroundSyncManager::RegisterDidStore(
|
| return;
|
| }
|
|
|
| - // TODO(jkarlin): Run the registration algorithm.
|
| + FireReadyEvents();
|
| base::MessageLoop::current()->PostTask(
|
| FROM_HERE, base::Bind(callback, ERROR_TYPE_OK, new_registration));
|
| }
|
| @@ -417,6 +441,7 @@ void BackgroundSyncManager::RegisterDidStore(
|
| void BackgroundSyncManager::RemoveRegistrationFromMap(
|
| int64 sw_registration_id,
|
| const RegistrationKey& registration_key) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| DCHECK(LookupRegistration(sw_registration_id, registration_key));
|
|
|
| BackgroundSyncRegistrations* registrations =
|
| @@ -429,6 +454,7 @@ void BackgroundSyncManager::AddRegistrationToMap(
|
| int64 sw_registration_id,
|
| const GURL& origin,
|
| const BackgroundSyncRegistration& sync_registration) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| DCHECK_NE(BackgroundSyncRegistration::kInvalidRegistrationId,
|
| sw_registration_id);
|
|
|
| @@ -446,6 +472,8 @@ void BackgroundSyncManager::StoreDataInBackend(
|
| const std::string& backend_key,
|
| const std::string& data,
|
| const ServiceWorkerStorage::StatusCallback& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| service_worker_context_->StoreRegistrationUserData(
|
| sw_registration_id, origin, backend_key, data, callback);
|
| }
|
| @@ -460,11 +488,21 @@ void BackgroundSyncManager::GetDataFromBackend(
|
| callback);
|
| }
|
|
|
| +void BackgroundSyncManager::FireOneShotSync(
|
| + const scoped_refptr<ServiceWorkerVersion>& active_version,
|
| + const ServiceWorkerVersion::StatusCallback& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + active_version->DispatchSyncEvent(callback);
|
| +}
|
| +
|
| void BackgroundSyncManager::UnregisterImpl(
|
| int64 sw_registration_id,
|
| const RegistrationKey& registration_key,
|
| BackgroundSyncRegistration::RegistrationId sync_registration_id,
|
| const StatusCallback& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| if (disabled_) {
|
| base::MessageLoop::current()->PostTask(
|
| FROM_HERE, base::Bind(callback, ERROR_TYPE_STORAGE));
|
| @@ -492,6 +530,8 @@ void BackgroundSyncManager::UnregisterDidStore(
|
| int64 sw_registration_id,
|
| const StatusCallback& callback,
|
| ServiceWorkerStatusCode status) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| if (status == SERVICE_WORKER_ERROR_NOT_FOUND) {
|
| // ServiceWorker was unregistered.
|
| sw_to_registrations_map_.erase(sw_registration_id);
|
| @@ -506,7 +546,6 @@ void BackgroundSyncManager::UnregisterDidStore(
|
| return;
|
| }
|
|
|
| - // TODO(jkarlin): Run the registration algorithm.
|
| base::MessageLoop::current()->PostTask(FROM_HERE,
|
| base::Bind(callback, ERROR_TYPE_OK));
|
| }
|
| @@ -515,6 +554,8 @@ void BackgroundSyncManager::GetRegistrationImpl(
|
| int64 sw_registration_id,
|
| const RegistrationKey& registration_key,
|
| const StatusAndRegistrationCallback& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| if (disabled_) {
|
| base::MessageLoop::current()->PostTask(
|
| FROM_HERE,
|
| @@ -535,9 +576,189 @@ void BackgroundSyncManager::GetRegistrationImpl(
|
| FROM_HERE, base::Bind(callback, ERROR_TYPE_OK, *out_registration));
|
| }
|
|
|
| +bool BackgroundSyncManager::IsRegistrationReadyToFire(
|
| + const BackgroundSyncRegistration& registration) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + // TODO(jkarlin): Add support for firing periodic registrations.
|
| + if (registration.periodicity == SYNC_PERIODIC)
|
| + return false;
|
| +
|
| + if (registration.sync_state != SYNC_STATE_PENDING)
|
| + return false;
|
| +
|
| + DCHECK_EQ(SYNC_ONE_SHOT, registration.periodicity);
|
| +
|
| + return network_observer_->NetworkSufficient(registration.network_state);
|
| +}
|
| +
|
| +void BackgroundSyncManager::FireReadyEvents() {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + if (disabled_)
|
| + return;
|
| +
|
| + op_scheduler_.ScheduleOperation(
|
| + base::Bind(&BackgroundSyncManager::FireReadyEventsImpl,
|
| + weak_ptr_factory_.GetWeakPtr(), MakeEmptyCompletion()));
|
| +}
|
| +
|
| +void BackgroundSyncManager::FireReadyEventsImpl(const base::Closure& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + if (disabled_) {
|
| + base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback));
|
| + return;
|
| + }
|
| +
|
| + // Find the registrations that are ready to run.
|
| + std::vector<std::pair<int64, RegistrationKey>> sw_id_and_keys_to_fire;
|
| +
|
| + for (auto& sw_id_and_registrations : sw_to_registrations_map_) {
|
| + const int64 service_worker_id = sw_id_and_registrations.first;
|
| + for (auto& key_and_registration :
|
| + sw_id_and_registrations.second.registration_map) {
|
| + BackgroundSyncRegistration* registration = &key_and_registration.second;
|
| + if (IsRegistrationReadyToFire(*registration)) {
|
| + sw_id_and_keys_to_fire.push_back(
|
| + std::make_pair(service_worker_id, key_and_registration.first));
|
| + // The state change is not saved to persistent storage because
|
| + // if the sync event is killed mid-sync then it should return to
|
| + // SYNC_STATE_PENDING.
|
| + registration->sync_state = SYNC_STATE_FIRING;
|
| + }
|
| + }
|
| + }
|
| +
|
| + // Fire the sync event of the ready registrations and run |callback| once
|
| + // they're all done.
|
| + base::Closure barrier_closure =
|
| + base::BarrierClosure(sw_id_and_keys_to_fire.size(), base::Bind(callback));
|
| +
|
| + for (const auto& sw_id_and_key : sw_id_and_keys_to_fire) {
|
| + int64 service_worker_id = sw_id_and_key.first;
|
| + const BackgroundSyncRegistration* registration =
|
| + LookupRegistration(service_worker_id, sw_id_and_key.second);
|
| +
|
| + service_worker_context_->FindRegistrationForId(
|
| + service_worker_id, sw_to_registrations_map_[service_worker_id].origin,
|
| + base::Bind(&BackgroundSyncManager::FireReadyEventsDidFindRegistration,
|
| + weak_ptr_factory_.GetWeakPtr(), sw_id_and_key.second,
|
| + registration->id, barrier_closure));
|
| + }
|
| +}
|
| +
|
| +void BackgroundSyncManager::FireReadyEventsDidFindRegistration(
|
| + const RegistrationKey& registration_key,
|
| + BackgroundSyncRegistration::RegistrationId registration_id,
|
| + const base::Closure& callback,
|
| + ServiceWorkerStatusCode service_worker_status,
|
| + const scoped_refptr<ServiceWorkerRegistration>&
|
| + service_worker_registration) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + if (service_worker_status != SERVICE_WORKER_OK) {
|
| + base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback));
|
| + return;
|
| + }
|
| +
|
| + FireOneShotSync(
|
| + service_worker_registration->active_version(),
|
| + base::Bind(&BackgroundSyncManager::EventComplete,
|
| + weak_ptr_factory_.GetWeakPtr(), service_worker_registration,
|
| + service_worker_registration->id(), registration_key,
|
| + registration_id));
|
| +
|
| + base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback));
|
| +}
|
| +
|
| +// |service_worker_registration| is just to keep the registration alive
|
| +// while the event is firing.
|
| +void BackgroundSyncManager::EventComplete(
|
| + const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
|
| + int64 service_worker_id,
|
| + const RegistrationKey& key,
|
| + BackgroundSyncRegistration::RegistrationId sync_registration_id,
|
| + ServiceWorkerStatusCode status_code) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + if (disabled_)
|
| + return;
|
| +
|
| + op_scheduler_.ScheduleOperation(
|
| + base::Bind(&BackgroundSyncManager::EventCompleteImpl,
|
| + weak_ptr_factory_.GetWeakPtr(), service_worker_id, key,
|
| + sync_registration_id, status_code, MakeEmptyCompletion()));
|
| +}
|
| +
|
| +void BackgroundSyncManager::EventCompleteImpl(
|
| + int64 service_worker_id,
|
| + const RegistrationKey& key,
|
| + BackgroundSyncRegistration::RegistrationId sync_registration_id,
|
| + ServiceWorkerStatusCode status_code,
|
| + const base::Closure& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + if (disabled_) {
|
| + base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback));
|
| + return;
|
| + }
|
| +
|
| + BackgroundSyncRegistration* registration =
|
| + LookupRegistration(service_worker_id, key);
|
| + if (!registration || registration->id != sync_registration_id) {
|
| + base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback));
|
| + return;
|
| + }
|
| +
|
| + if (registration->periodicity == SYNC_ONE_SHOT) {
|
| + if (status_code != SERVICE_WORKER_OK) {
|
| + // TODO(jkarlin) Fire the sync event on the next page load controlled by
|
| + // this registration. (crbug.com/479665)
|
| + registration->sync_state = SYNC_STATE_FAILED;
|
| + } else {
|
| + registration = nullptr;
|
| + RemoveRegistrationFromMap(service_worker_id, key);
|
| + }
|
| + } else {
|
| + // TODO(jkarlin): Add support for running periodic syncs. (crbug.com/479674)
|
| + NOTREACHED();
|
| + }
|
| +
|
| + StoreRegistrations(
|
| + service_worker_id,
|
| + base::Bind(&BackgroundSyncManager::EventCompleteDidStore,
|
| + weak_ptr_factory_.GetWeakPtr(), service_worker_id, callback));
|
| +}
|
| +
|
| +void BackgroundSyncManager::EventCompleteDidStore(
|
| + int64 service_worker_id,
|
| + const base::Closure& callback,
|
| + ServiceWorkerStatusCode status_code) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + if (status_code == SERVICE_WORKER_ERROR_NOT_FOUND) {
|
| + // The registration is gone.
|
| + sw_to_registrations_map_.erase(service_worker_id);
|
| + base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback));
|
| + return;
|
| + }
|
| +
|
| + if (status_code != SERVICE_WORKER_OK) {
|
| + LOG(ERROR) << "BackgroundSync failed to store registration due to backend "
|
| + "failure.";
|
| + DisableAndClearManager(base::Bind(callback));
|
| + return;
|
| + }
|
| +
|
| + base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback));
|
| +}
|
| +
|
| void BackgroundSyncManager::OnRegistrationDeletedImpl(
|
| int64 registration_id,
|
| const base::Closure& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| // The backend (ServiceWorkerStorage) will delete the data, so just delete the
|
| // memory representation here.
|
| sw_to_registrations_map_.erase(registration_id);
|
| @@ -545,20 +766,25 @@ void BackgroundSyncManager::OnRegistrationDeletedImpl(
|
| }
|
|
|
| void BackgroundSyncManager::OnStorageWipedImpl(const base::Closure& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| sw_to_registrations_map_.clear();
|
| disabled_ = false;
|
| InitImpl(callback);
|
| }
|
|
|
| void BackgroundSyncManager::OnNetworkChanged() {
|
| - // TODO(jkarlin): Run the scheduling algorithm here if initialized and not
|
| - // disabled.
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + FireReadyEvents();
|
| }
|
|
|
| void BackgroundSyncManager::PendingStatusAndRegistrationCallback(
|
| const StatusAndRegistrationCallback& callback,
|
| ErrorType error,
|
| const BackgroundSyncRegistration& sync_registration) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| // The callback might delete this object, so hang onto a weak ptr to find out.
|
| base::WeakPtr<BackgroundSyncManager> manager = weak_ptr_factory_.GetWeakPtr();
|
| callback.Run(error, sync_registration);
|
| @@ -569,6 +795,8 @@ void BackgroundSyncManager::PendingStatusAndRegistrationCallback(
|
| void BackgroundSyncManager::PendingStatusCallback(
|
| const StatusCallback& callback,
|
| ErrorType error) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| // The callback might delete this object, so hang onto a weak ptr to find out.
|
| base::WeakPtr<BackgroundSyncManager> manager = weak_ptr_factory_.GetWeakPtr();
|
| callback.Run(error);
|
| @@ -577,6 +805,8 @@ void BackgroundSyncManager::PendingStatusCallback(
|
| }
|
|
|
| void BackgroundSyncManager::PendingClosure(const base::Closure& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| // The callback might delete this object, so hang onto a weak ptr to find out.
|
| base::WeakPtr<BackgroundSyncManager> manager = weak_ptr_factory_.GetWeakPtr();
|
| callback.Run();
|
| @@ -585,6 +815,8 @@ void BackgroundSyncManager::PendingClosure(const base::Closure& callback) {
|
| }
|
|
|
| base::Closure BackgroundSyncManager::MakeEmptyCompletion() {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| return base::Bind(&BackgroundSyncManager::PendingClosure,
|
| weak_ptr_factory_.GetWeakPtr(),
|
| base::Bind(base::DoNothing));
|
| @@ -593,6 +825,8 @@ base::Closure BackgroundSyncManager::MakeEmptyCompletion() {
|
| BackgroundSyncManager::StatusAndRegistrationCallback
|
| BackgroundSyncManager::MakeStatusAndRegistrationCompletion(
|
| const StatusAndRegistrationCallback& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| return base::Bind(
|
| &BackgroundSyncManager::PendingStatusAndRegistrationCallback,
|
| weak_ptr_factory_.GetWeakPtr(), callback);
|
| @@ -600,6 +834,8 @@ BackgroundSyncManager::MakeStatusAndRegistrationCompletion(
|
|
|
| BackgroundSyncManager::StatusCallback
|
| BackgroundSyncManager::MakeStatusCompletion(const StatusCallback& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| return base::Bind(&BackgroundSyncManager::PendingStatusCallback,
|
| weak_ptr_factory_.GetWeakPtr(), callback);
|
| }
|
|
|