| 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 7ea194f1af92dd463d56a59fbc1527c99842d81f..d67aa7d4dbe286b9cc825bc7e2e2494ebf3d03ea 100644
|
| --- a/content/browser/background_sync/background_sync_manager.cc
|
| +++ b/content/browser/background_sync/background_sync_manager.cc
|
| @@ -46,6 +46,7 @@ scoped_ptr<BackgroundSyncManager> BackgroundSyncManager::Create(
|
| }
|
|
|
| BackgroundSyncManager::~BackgroundSyncManager() {
|
| + service_worker_context_->RemoveObserver(this);
|
| }
|
|
|
| void BackgroundSyncManager::Register(
|
| @@ -57,13 +58,17 @@ void BackgroundSyncManager::Register(
|
| DCHECK_EQ(BackgroundSyncRegistration::kInvalidRegistrationId,
|
| sync_registration.id);
|
|
|
| - StatusAndRegistrationCallback pending_callback =
|
| - base::Bind(&BackgroundSyncManager::PendingStatusAndRegistrationCallback,
|
| - weak_ptr_factory_.GetWeakPtr(), callback);
|
| + if (disabled_) {
|
| + base::MessageLoop::current()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(callback, ERROR_TYPE_STORAGE, BackgroundSyncRegistration()));
|
| + return;
|
| + }
|
|
|
| op_scheduler_.ScheduleOperation(base::Bind(
|
| &BackgroundSyncManager::RegisterImpl, weak_ptr_factory_.GetWeakPtr(),
|
| - origin, sw_registration_id, sync_registration, pending_callback));
|
| + origin, sw_registration_id, sync_registration,
|
| + MakeStatusAndRegistrationCompletion(callback)));
|
| }
|
|
|
| void BackgroundSyncManager::Unregister(
|
| @@ -74,14 +79,16 @@ void BackgroundSyncManager::Unregister(
|
| const StatusCallback& callback) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
|
|
| - StatusCallback pending_callback =
|
| - base::Bind(&BackgroundSyncManager::PendingStatusCallback,
|
| - weak_ptr_factory_.GetWeakPtr(), callback);
|
| + if (disabled_) {
|
| + base::MessageLoop::current()->PostTask(
|
| + FROM_HERE, base::Bind(callback, ERROR_TYPE_STORAGE));
|
| + return;
|
| + }
|
|
|
| op_scheduler_.ScheduleOperation(base::Bind(
|
| &BackgroundSyncManager::UnregisterImpl, weak_ptr_factory_.GetWeakPtr(),
|
| origin, sw_registration_id, sync_registration_name, sync_registration_id,
|
| - pending_callback));
|
| + MakeStatusCompletion(callback)));
|
| }
|
|
|
| void BackgroundSyncManager::GetRegistration(
|
| @@ -91,43 +98,82 @@ void BackgroundSyncManager::GetRegistration(
|
| const StatusAndRegistrationCallback& callback) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
|
|
| - StatusAndRegistrationCallback pending_callback =
|
| - base::Bind(&BackgroundSyncManager::PendingStatusAndRegistrationCallback,
|
| - weak_ptr_factory_.GetWeakPtr(), callback);
|
| + if (disabled_) {
|
| + base::MessageLoop::current()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(callback, ERROR_TYPE_STORAGE, BackgroundSyncRegistration()));
|
| + return;
|
| + }
|
| +
|
| + op_scheduler_.ScheduleOperation(base::Bind(
|
| + &BackgroundSyncManager::GetRegistrationImpl,
|
| + weak_ptr_factory_.GetWeakPtr(), origin, sw_registration_id,
|
| + sync_registration_name, MakeStatusAndRegistrationCompletion(callback)));
|
| +}
|
| +
|
| +void BackgroundSyncManager::OnRegistrationDeleted(int64 registration_id,
|
| + const GURL& pattern) {
|
| + 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 worker is gone.
|
| + op_scheduler_.ScheduleOperation(base::Bind(
|
| + &BackgroundSyncManager::OnRegistrationDeletedImpl,
|
| + weak_ptr_factory_.GetWeakPtr(), registration_id, MakeEmptyCompletion()));
|
| +}
|
|
|
| +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.
|
| op_scheduler_.ScheduleOperation(
|
| - base::Bind(&BackgroundSyncManager::GetRegistrationImpl,
|
| - weak_ptr_factory_.GetWeakPtr(), origin, sw_registration_id,
|
| - sync_registration_name, pending_callback));
|
| + base::Bind(&BackgroundSyncManager::OnStorageWipedImpl,
|
| + weak_ptr_factory_.GetWeakPtr(), MakeEmptyCompletion()));
|
| }
|
|
|
| BackgroundSyncManager::BackgroundSyncManager(
|
| const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context)
|
| - : service_worker_context_(service_worker_context), weak_ptr_factory_(this) {
|
| + : service_worker_context_(service_worker_context),
|
| + disabled_(false),
|
| + weak_ptr_factory_(this) {
|
| + service_worker_context_->AddObserver(this);
|
| }
|
|
|
| void BackgroundSyncManager::Init() {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| DCHECK(!op_scheduler_.ScheduledOperations());
|
| + DCHECK(!disabled_);
|
|
|
| op_scheduler_.ScheduleOperation(base::Bind(&BackgroundSyncManager::InitImpl,
|
| - weak_ptr_factory_.GetWeakPtr()));
|
| + weak_ptr_factory_.GetWeakPtr(),
|
| + MakeEmptyCompletion()));
|
| }
|
|
|
| -void BackgroundSyncManager::InitImpl() {
|
| +void BackgroundSyncManager::InitImpl(const base::Closure& callback) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
|
|
| + if (disabled_) {
|
| + base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback));
|
| + return;
|
| + }
|
| +
|
| GetDataFromBackend(
|
| kBackgroundSyncUserDataKey,
|
| base::Bind(&BackgroundSyncManager::InitDidGetDataFromBackend,
|
| - weak_ptr_factory_.GetWeakPtr()));
|
| + weak_ptr_factory_.GetWeakPtr(), callback));
|
| }
|
|
|
| void BackgroundSyncManager::InitDidGetDataFromBackend(
|
| + const base::Closure& callback,
|
| const std::vector<std::pair<int64, std::string>>& user_data,
|
| ServiceWorkerStatusCode status) {
|
| - if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND)
|
| - LOG(ERROR) << "Background Sync Failed to load from backend.";
|
| + 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));
|
| + return;
|
| + }
|
|
|
| bool corruption_detected = false;
|
| for (const std::pair<int64, std::string>& data : user_data) {
|
| @@ -163,12 +209,13 @@ void BackgroundSyncManager::InitDidGetDataFromBackend(
|
|
|
| if (corruption_detected) {
|
| LOG(ERROR) << "Corruption detected in background sync backend";
|
| - sw_to_registrations_map_.clear();
|
| + DisableAndClearManager(base::Bind(callback));
|
| + return;
|
| }
|
|
|
| // TODO(jkarlin): Call the scheduling algorithm here.
|
|
|
| - op_scheduler_.CompleteOperationAndRunNext();
|
| + base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback));
|
| }
|
|
|
| void BackgroundSyncManager::RegisterImpl(
|
| @@ -176,6 +223,13 @@ void BackgroundSyncManager::RegisterImpl(
|
| int64 sw_registration_id,
|
| const BackgroundSyncRegistration& sync_registration,
|
| const StatusAndRegistrationCallback& callback) {
|
| + if (disabled_) {
|
| + base::MessageLoop::current()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(callback, ERROR_TYPE_STORAGE, BackgroundSyncRegistration()));
|
| + return;
|
| + }
|
| +
|
| BackgroundSyncRegistration existing_registration;
|
| if (LookupRegistration(sw_registration_id, sync_registration.name,
|
| &existing_registration)) {
|
| @@ -198,7 +252,54 @@ void BackgroundSyncManager::RegisterImpl(
|
| origin, sw_registration_id,
|
| base::Bind(&BackgroundSyncManager::RegisterDidStore,
|
| weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
|
| - new_registration, existing_registration, callback));
|
| + new_registration, callback));
|
| +}
|
| +
|
| +void BackgroundSyncManager::DisableAndClearManager(
|
| + const base::Closure& callback) {
|
| + if (disabled_) {
|
| + base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback));
|
| + return;
|
| + }
|
| +
|
| + disabled_ = true;
|
| + sw_to_registrations_map_.clear();
|
| +
|
| + // Delete all backend entries. The memory representation of registered syncs
|
| + // may be out of sync with storage (e.g., due to corruption detection on
|
| + // loading from storage), so reload the registrations from storage again.
|
| + GetDataFromBackend(
|
| + kBackgroundSyncUserDataKey,
|
| + base::Bind(&BackgroundSyncManager::DisableAndClearDidGetRegistrations,
|
| + weak_ptr_factory_.GetWeakPtr(), callback));
|
| +}
|
| +
|
| +void BackgroundSyncManager::DisableAndClearDidGetRegistrations(
|
| + const base::Closure& callback,
|
| + const std::vector<std::pair<int64, std::string>>& user_data,
|
| + ServiceWorkerStatusCode status) {
|
| + if (status != SERVICE_WORKER_OK || user_data.empty()) {
|
| + base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback));
|
| + return;
|
| + }
|
| +
|
| + base::Closure barrier_closure =
|
| + base::BarrierClosure(user_data.size(), base::Bind(callback));
|
| +
|
| + for (const auto& sw_id_and_regs : user_data) {
|
| + service_worker_context_->context()->storage()->ClearUserData(
|
| + sw_id_and_regs.first, kBackgroundSyncUserDataKey,
|
| + base::Bind(&BackgroundSyncManager::DisableAndClearManagerClearedOne,
|
| + weak_ptr_factory_.GetWeakPtr(), barrier_closure));
|
| + }
|
| +}
|
| +
|
| +void BackgroundSyncManager::DisableAndClearManagerClearedOne(
|
| + const base::Closure& barrier_closure,
|
| + ServiceWorkerStatusCode status) {
|
| + // 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));
|
| }
|
|
|
| bool BackgroundSyncManager::LookupRegistration(
|
| @@ -255,24 +356,25 @@ void BackgroundSyncManager::StoreRegistrations(
|
| void BackgroundSyncManager::RegisterDidStore(
|
| int64 sw_registration_id,
|
| const BackgroundSyncRegistration& new_registration,
|
| - const BackgroundSyncRegistration& previous_registration,
|
| const StatusAndRegistrationCallback& callback,
|
| ServiceWorkerStatusCode status) {
|
| - if (status != SERVICE_WORKER_OK) {
|
| - // Restore the previous state.
|
| - if (previous_registration.id !=
|
| - BackgroundSyncRegistration::kInvalidRegistrationId) {
|
| - AddRegistrationToMap(sw_registration_id, previous_registration);
|
| - } else {
|
| - RemoveRegistrationFromMap(sw_registration_id, new_registration.name,
|
| - nullptr);
|
| - }
|
| + if (status == SERVICE_WORKER_ERROR_NOT_FOUND) {
|
| + // The registration is gone.
|
| + sw_to_registrations_map_.erase(sw_registration_id);
|
| base::MessageLoop::current()->PostTask(
|
| FROM_HERE,
|
| base::Bind(callback, ERROR_TYPE_STORAGE, BackgroundSyncRegistration()));
|
| return;
|
| }
|
|
|
| + if (status != SERVICE_WORKER_OK) {
|
| + LOG(ERROR) << "BackgroundSync failed to store registration due to backend "
|
| + "failure.";
|
| + DisableAndClearManager(
|
| + base::Bind(callback, ERROR_TYPE_STORAGE, BackgroundSyncRegistration()));
|
| + return;
|
| + }
|
| +
|
| // TODO(jkarlin): Run the registration algorithm.
|
| base::MessageLoop::current()->PostTask(
|
| FROM_HERE, base::Bind(callback, ERROR_TYPE_OK, new_registration));
|
| @@ -334,6 +436,12 @@ void BackgroundSyncManager::UnregisterImpl(
|
| const std::string& sync_registration_name,
|
| BackgroundSyncRegistration::RegistrationId sync_registration_id,
|
| const StatusCallback& callback) {
|
| + if (disabled_) {
|
| + base::MessageLoop::current()->PostTask(
|
| + FROM_HERE, base::Bind(callback, ERROR_TYPE_STORAGE));
|
| + return;
|
| + }
|
| +
|
| BackgroundSyncRegistration existing_registration;
|
| if (!LookupRegistration(sw_registration_id, sync_registration_name,
|
| &existing_registration) ||
|
| @@ -359,14 +467,20 @@ void BackgroundSyncManager::UnregisterDidStore(
|
| const BackgroundSyncRegistration& old_sync_registration,
|
| const StatusCallback& callback,
|
| ServiceWorkerStatusCode status) {
|
| - if (status != SERVICE_WORKER_OK) {
|
| - // Restore the previous state.
|
| - AddRegistrationToMap(sw_registration_id, old_sync_registration);
|
| + if (status == SERVICE_WORKER_ERROR_NOT_FOUND) {
|
| + // ServiceWorker was unregistered.
|
| + sw_to_registrations_map_.erase(sw_registration_id);
|
| base::MessageLoop::current()->PostTask(
|
| FROM_HERE, base::Bind(callback, ERROR_TYPE_STORAGE));
|
| return;
|
| }
|
|
|
| + if (status != SERVICE_WORKER_OK) {
|
| + LOG(ERROR) << "BackgroundSync failed to unregister due to backend failure.";
|
| + DisableAndClearManager(base::Bind(callback, ERROR_TYPE_STORAGE));
|
| + return;
|
| + }
|
| +
|
| // TODO(jkarlin): Run the registration algorithm.
|
| base::MessageLoop::current()->PostTask(FROM_HERE,
|
| base::Bind(callback, ERROR_TYPE_OK));
|
| @@ -377,6 +491,13 @@ void BackgroundSyncManager::GetRegistrationImpl(
|
| int64 sw_registration_id,
|
| const std::string sync_registration_name,
|
| const StatusAndRegistrationCallback& callback) {
|
| + if (disabled_) {
|
| + base::MessageLoop::current()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(callback, ERROR_TYPE_STORAGE, BackgroundSyncRegistration()));
|
| + return;
|
| + }
|
| +
|
| BackgroundSyncRegistration out_registration;
|
| if (!LookupRegistration(sw_registration_id, sync_registration_name,
|
| &out_registration)) {
|
| @@ -390,6 +511,21 @@ void BackgroundSyncManager::GetRegistrationImpl(
|
| FROM_HERE, base::Bind(callback, ERROR_TYPE_OK, out_registration));
|
| }
|
|
|
| +void BackgroundSyncManager::OnRegistrationDeletedImpl(
|
| + int64 registration_id,
|
| + const base::Closure& callback) {
|
| + // The backend (ServiceWorkerStorage) will delete the data, so just delete the
|
| + // memory representation here.
|
| + sw_to_registrations_map_.erase(registration_id);
|
| + base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback));
|
| +}
|
| +
|
| +void BackgroundSyncManager::OnStorageWipedImpl(const base::Closure& callback) {
|
| + sw_to_registrations_map_.clear();
|
| + disabled_ = false;
|
| + InitImpl(callback);
|
| +}
|
| +
|
| void BackgroundSyncManager::PendingStatusAndRegistrationCallback(
|
| const StatusAndRegistrationCallback& callback,
|
| ErrorType error,
|
| @@ -411,4 +547,32 @@ void BackgroundSyncManager::PendingStatusCallback(
|
| op_scheduler_.CompleteOperationAndRunNext();
|
| }
|
|
|
| +void BackgroundSyncManager::PendingClosure(const base::Closure& callback) {
|
| + // 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();
|
| + if (manager)
|
| + op_scheduler_.CompleteOperationAndRunNext();
|
| +}
|
| +
|
| +base::Closure BackgroundSyncManager::MakeEmptyCompletion() {
|
| + return base::Bind(&BackgroundSyncManager::PendingClosure,
|
| + weak_ptr_factory_.GetWeakPtr(),
|
| + base::Bind(base::DoNothing));
|
| +}
|
| +
|
| +BackgroundSyncManager::StatusAndRegistrationCallback
|
| +BackgroundSyncManager::MakeStatusAndRegistrationCompletion(
|
| + const StatusAndRegistrationCallback& callback) {
|
| + return base::Bind(
|
| + &BackgroundSyncManager::PendingStatusAndRegistrationCallback,
|
| + weak_ptr_factory_.GetWeakPtr(), callback);
|
| +}
|
| +
|
| +BackgroundSyncManager::StatusCallback
|
| +BackgroundSyncManager::MakeStatusCompletion(const StatusCallback& callback) {
|
| + return base::Bind(&BackgroundSyncManager::PendingStatusCallback,
|
| + weak_ptr_factory_.GetWeakPtr(), callback);
|
| +}
|
| +
|
| } // namespace content
|
|
|