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

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 fix 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 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);
}

Powered by Google App Engine
This is Rietveld 408576698