Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(114)

Unified Diff: content/browser/background_sync/background_sync_manager.cc

Issue 1106523002: [BackgroundSync] Fire one-shot sync events (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@store_origin
Patch Set: Rebase Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 a23792f161076cfa4f7ef3f3039c9a3688408ba7..9b4f5c83fa7b0801908b3db0595d148a135f771c 100644
--- a/content/browser/background_sync/background_sync_manager.cc
+++ b/content/browser/background_sync/background_sync_manager.cc
@@ -229,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;
+ }
}
}
@@ -242,7 +248,7 @@ void BackgroundSyncManager::InitDidGetDataFromBackend(
return;
}
- // TODO(jkarlin): Call the scheduling algorithm here.
+ FireReadyEvents();
base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback));
}
@@ -371,6 +377,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);
@@ -402,7 +409,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));
}
@@ -453,6 +460,14 @@ 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(
const GURL& origin,
int64 sw_registration_id,
@@ -500,7 +515,6 @@ void BackgroundSyncManager::UnregisterDidStore(
return;
}
- // TODO(jkarlin): Run the registration algorithm.
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(callback, ERROR_TYPE_OK));
}
@@ -546,8 +560,7 @@ void BackgroundSyncManager::OnStorageWipedImpl(const base::Closure& callback) {
}
void BackgroundSyncManager::OnNetworkChanged() {
- // TODO(jkarlin): Run the scheduling algorithm here if initialized and not
- // disabled.
+ FireReadyEvents();
}
void BackgroundSyncManager::PendingStatusAndRegistrationCallback(
@@ -579,6 +592,178 @@ void BackgroundSyncManager::PendingClosure(const base::Closure& callback) {
op_scheduler_.CompleteOperationAndRunNext();
}
+bool BackgroundSyncManager::IsRegistrationReadyToFire(
+ const BackgroundSyncRegistration& registration) {
+ // 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) {
+ 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) {
+ if (service_worker_status != SERVICE_WORKER_OK) {
+ base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback));
+ return;
+ }
+
+ ServiceWorkerVersion* active_version =
+ service_worker_registration->active_version();
+ if (!active_version) {
+ base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback));
iclelland 2015/04/28 02:48:53 Will this happen if the service worker is still ac
jkarlin 2015/04/28 14:41:00 Ah, good point. I'll check for active registration
jkarlin 2015/04/28 16:39:22 Followup CL is here: https://crrev.com/1110993003
+ return;
+ }
+
+ FireOneShotSync(active_version,
+ base::Bind(&BackgroundSyncManager::EventComplete,
+ weak_ptr_factory_.GetWeakPtr(),
+ service_worker_registration->id(),
+ registration_key, registration_id));
+
+ base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback));
+}
+
+void BackgroundSyncManager::EventComplete(
+ 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(
iclelland 2015/04/28 02:48:53 It looks like there are situations here where the
jkarlin 2015/04/28 14:41:00 Are you referring to the early returns below? In a
iclelland 2015/04/28 18:50:39 Yes, those ones. So if I'm following the code corr
jkarlin 2015/04/28 21:00:08 We should be good. If it's disabled_ then all memo
+ 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) {
+ 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));
+}
+
base::Closure BackgroundSyncManager::MakeEmptyCompletion() {
return base::Bind(&BackgroundSyncManager::PendingClosure,
weak_ptr_factory_.GetWeakPtr(),

Powered by Google App Engine
This is Rietveld 408576698