Chromium Code Reviews| 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 |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..e4ca38a1d2114680b1f4f866a4f692867b440a8f |
| --- /dev/null |
| +++ b/content/browser/background_sync/background_sync_manager.cc |
| @@ -0,0 +1,311 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "content/browser/background_sync/background_sync_manager.h" |
| + |
| +#include "base/barrier_closure.h" |
| +#include "base/bind.h" |
| +#include "content/browser/background_sync/background_sync.pb.h" |
| +#include "content/browser/service_worker/service_worker_context_wrapper.h" |
| +#include "content/browser/service_worker/service_worker_storage.h" |
| +#include "content/public/browser/browser_thread.h" |
| + |
| +namespace { |
| +const char kBackgroundSyncUserDataKey[] = "BackgroundSyncUserData"; |
| + |
| +void RunSoon(const tracked_objects::Location& from_here, |
|
jochen (gone - plz use gerrit)
2015/03/16 12:04:21
why not just post the task everywhere instead of t
jkarlin
2015/03/16 13:12:19
Done.
|
| + const base::Closure& closure) { |
| + base::MessageLoop::current()->PostTask(from_here, closure); |
| +} |
| +} |
| + |
| +namespace content { |
| + |
| +// static |
| +scoped_ptr<BackgroundSyncManager> BackgroundSyncManager::Create( |
| + const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context) { |
| + BackgroundSyncManager* sync_manager = |
| + new BackgroundSyncManager(service_worker_context); |
| + sync_manager->Init(); |
| + return make_scoped_ptr(sync_manager); |
| +} |
| + |
| +BackgroundSyncManager::~BackgroundSyncManager() { |
| +} |
| + |
| +void BackgroundSyncManager::Register( |
| + const GURL& origin, |
| + int64 sw_registration_id, |
| + const BackgroundSyncRegistration& sync_registration, |
| + const StatusAndRegistrationCallback& callback) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + |
| + StatusAndRegistrationCallback pending_callback = |
| + base::Bind(&BackgroundSyncManager::PendingStatusAndRegistrationCallback, |
| + weak_ptr_factory_.GetWeakPtr(), callback); |
| + |
| + op_scheduler_.ScheduleOperation(base::Bind( |
| + &BackgroundSyncManager::RegisterImpl, weak_ptr_factory_.GetWeakPtr(), |
| + origin, sw_registration_id, sync_registration, pending_callback)); |
| +} |
| + |
| +void BackgroundSyncManager::Unregister( |
| + const GURL& origin, |
| + int64 sw_registration_id, |
| + const BackgroundSyncRegistration& sync_registration, |
| + const StatusCallback& callback) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + |
| + StatusCallback pending_callback = |
| + base::Bind(&BackgroundSyncManager::PendingStatusCallback, |
| + weak_ptr_factory_.GetWeakPtr(), callback); |
| + |
| + op_scheduler_.ScheduleOperation(base::Bind( |
| + &BackgroundSyncManager::UnregisterImpl, weak_ptr_factory_.GetWeakPtr(), |
| + origin, sw_registration_id, sync_registration, pending_callback)); |
| +} |
| + |
| +void BackgroundSyncManager::GetRegistration( |
| + const GURL& origin, |
| + int64 sw_registration_id, |
| + const std::string sync_registration_id, |
| + const StatusAndRegistrationCallback& callback) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + |
| + StatusAndRegistrationCallback pending_callback = |
| + base::Bind(&BackgroundSyncManager::PendingStatusAndRegistrationCallback, |
| + weak_ptr_factory_.GetWeakPtr(), callback); |
| + |
| + op_scheduler_.ScheduleOperation( |
| + base::Bind(&BackgroundSyncManager::GetRegistrationImpl, |
| + weak_ptr_factory_.GetWeakPtr(), origin, sw_registration_id, |
| + sync_registration_id, pending_callback)); |
| +} |
| + |
| +BackgroundSyncManager::BackgroundSyncManager( |
| + const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context) |
| + : service_worker_context_(service_worker_context), weak_ptr_factory_(this) { |
| +} |
| + |
| +void BackgroundSyncManager::Init() { |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + DCHECK(!op_scheduler_.ScheduledOperations()); |
| + |
| + op_scheduler_.ScheduleOperation(base::Bind(&BackgroundSyncManager::InitImpl, |
| + weak_ptr_factory_.GetWeakPtr())); |
| +} |
| + |
| +void BackgroundSyncManager::InitImpl() { |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + |
| + service_worker_context_->context()->storage()->GetUserDataForAllRegistrations( |
| + kBackgroundSyncUserDataKey, |
| + base::Bind(&BackgroundSyncManager::InitDidGetUserData, |
| + weak_ptr_factory_.GetWeakPtr())); |
| +} |
| + |
| +void BackgroundSyncManager::InitDidGetUserData( |
| + const std::vector<std::pair<int64, std::string>>& user_data, |
| + ServiceWorkerStatusCode status) { |
| + for (const std::pair<int64, std::string>& data : user_data) { |
| + BackgroundSyncRegistrationsProto registrations_proto; |
| + if (registrations_proto.ParseFromString(data.second)) { |
| + for (int i = 0, max = registrations_proto.registration_size(); i < max; |
| + ++i) { |
| + const BackgroundSyncRegistrationProto& registration_proto = |
| + registrations_proto.registration(i); |
| + registration_map_[data.first].push_back( |
| + BackgroundSyncRegistration(registration_proto.id())); |
| + } |
| + } |
| + } |
| + |
| + // TODO(jkarlin): Call the scheduling algorithm here. |
| + |
| + op_scheduler_.CompleteOperationAndRunNext(); |
| +} |
| + |
| +void BackgroundSyncManager::RegisterImpl( |
| + const GURL& origin, |
| + int64 sw_registration_id, |
| + const BackgroundSyncRegistration& sync_registration, |
| + const StatusAndRegistrationCallback& callback) { |
| + // TODO(jkarlin): Check for permission. |
| + |
| + if (!AddRegistrationToMap(sw_registration_id, sync_registration)) { |
| + RunSoon(FROM_HERE, base::Bind(callback, ErrorTypeExists, |
| + BackgroundSyncRegistration(""))); |
| + return; |
| + } |
| + |
| + StoreRegistrations( |
| + origin, sw_registration_id, |
| + base::Bind(&BackgroundSyncManager::RegisterDidStore, |
| + weak_ptr_factory_.GetWeakPtr(), sw_registration_id, |
| + sync_registration, callback)); |
| +} |
| + |
| +bool BackgroundSyncManager::HasRegistration( |
| + int64 sw_registration_id, |
| + const BackgroundSyncRegistration& sync_registration) { |
| + IdToRegistrationMap::iterator it = registration_map_.find(sw_registration_id); |
| + if (it == registration_map_.end()) |
| + return false; |
| + |
| + for (const BackgroundSyncRegistration& reg : it->second) { |
| + if (sync_registration.id == reg.id) |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| +void BackgroundSyncManager::StoreRegistrations( |
| + const GURL& origin, |
| + int64 sw_registration_id, |
| + const ServiceWorkerStorage::StatusCallback& callback) { |
| + // Serialize the data. |
| + BackgroundSyncRegistrationsProto registrations_proto; |
| + for (const BackgroundSyncRegistration& sync_registration : |
| + registration_map_[sw_registration_id]) { |
| + BackgroundSyncRegistrationProto* registration_proto = |
| + registrations_proto.add_registration(); |
| + registration_proto->set_id(sync_registration.id); |
| + } |
| + std::string serialized; |
| + bool success = registrations_proto.SerializeToString(&serialized); |
| + DCHECK(success); |
| + |
| + // Store it. |
| + service_worker_context_->context()->storage()->StoreUserData( |
| + sw_registration_id, origin, kBackgroundSyncUserDataKey, serialized, |
| + callback); |
| +} |
| + |
| +void BackgroundSyncManager::RegisterDidStore( |
| + int64 sw_registration_id, |
| + const BackgroundSyncRegistration& sync_registration, |
| + const StatusAndRegistrationCallback& callback, |
| + ServiceWorkerStatusCode status) { |
| + if (status != SERVICE_WORKER_OK) { |
| + // Restore the previous state. |
| + RemoveRegistrationFromMap(sw_registration_id, sync_registration); |
| + RunSoon(FROM_HERE, base::Bind(callback, ErrorTypeStorage, |
| + BackgroundSyncRegistration())); |
| + return; |
| + } |
| + |
| + // TODO(jkarlin): Run the registration algorithm. |
| + RunSoon(FROM_HERE, base::Bind(callback, ErrorTypeOK, sync_registration)); |
| +} |
| + |
| +bool BackgroundSyncManager::RemoveRegistrationFromMap( |
| + int64 sw_registration_id, |
| + const BackgroundSyncRegistration& sync_registration) { |
| + IdToRegistrationMap::iterator it = registration_map_.find(sw_registration_id); |
| + |
| + if (it == registration_map_.end()) |
| + return false; |
| + |
| + std::list<BackgroundSyncRegistration>* registrations = &(it->second); |
| + for (std::list<BackgroundSyncRegistration>::iterator reg_iter = |
| + registrations->begin(); |
| + reg_iter != registrations->end(); ++reg_iter) { |
| + if (reg_iter->id == sync_registration.id) { |
| + registrations->erase(reg_iter); |
| + return true; |
| + } |
| + } |
| + |
| + return false; |
| +} |
| + |
| +bool BackgroundSyncManager::AddRegistrationToMap( |
| + int64 sw_registration_id, |
| + const BackgroundSyncRegistration& sync_registration) { |
| + if (HasRegistration(sw_registration_id, sync_registration)) |
| + return false; |
| + |
| + registration_map_[sw_registration_id].push_back(sync_registration); |
| + return true; |
| +} |
| + |
| +void BackgroundSyncManager::UnregisterImpl( |
| + const GURL& origin, |
| + int64 sw_registration_id, |
| + const BackgroundSyncRegistration& sync_registration, |
| + const StatusCallback& callback) { |
| + if (!RemoveRegistrationFromMap(sw_registration_id, sync_registration)) { |
| + RunSoon(FROM_HERE, base::Bind(callback, ErrorTypeNotFound)); |
| + return; |
| + } |
| + |
| + StoreRegistrations( |
| + origin, sw_registration_id, |
| + base::Bind(&BackgroundSyncManager::UnregisterDidStore, |
| + weak_ptr_factory_.GetWeakPtr(), sw_registration_id, |
| + sync_registration, callback)); |
| +} |
| + |
| +void BackgroundSyncManager::UnregisterDidStore( |
| + int64 sw_registration_id, |
| + const BackgroundSyncRegistration& sync_registration, |
| + const StatusCallback& callback, |
| + ServiceWorkerStatusCode status) { |
| + if (status != SERVICE_WORKER_OK) { |
| + // Restore the previous state. |
| + AddRegistrationToMap(sw_registration_id, sync_registration); |
| + RunSoon(FROM_HERE, base::Bind(callback, ErrorTypeStorage)); |
| + return; |
| + } |
| + |
| + // TODO(jkarlin): Run the registration algorithm. |
| + RunSoon(FROM_HERE, base::Bind(callback, ErrorTypeOK)); |
| +} |
| + |
| +void BackgroundSyncManager::GetRegistrationImpl( |
| + const GURL& origin, |
| + int64 sw_registration_id, |
| + const std::string sync_registration_id, |
| + const StatusAndRegistrationCallback& callback) { |
| + IdToRegistrationMap::iterator it = registration_map_.find(sw_registration_id); |
| + |
| + if (it == registration_map_.end()) { |
| + RunSoon(FROM_HERE, base::Bind(callback, ErrorTypeNotFound, |
| + BackgroundSyncRegistration())); |
| + return; |
| + } |
| + |
| + for (const BackgroundSyncRegistration& registration : it->second) { |
| + if (registration.id == sync_registration_id) { |
| + RunSoon(FROM_HERE, base::Bind(callback, ErrorTypeOK, registration)); |
| + return; |
| + } |
| + } |
| + |
| + RunSoon(FROM_HERE, base::Bind(callback, ErrorTypeNotFound, |
| + BackgroundSyncRegistration())); |
| +} |
| + |
| +void BackgroundSyncManager::PendingStatusAndRegistrationCallback( |
| + const StatusAndRegistrationCallback& callback, |
| + ErrorType error, |
| + const BackgroundSyncRegistration& sync_registration) { |
| + // 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); |
| + if (manager) |
| + op_scheduler_.CompleteOperationAndRunNext(); |
| +} |
| + |
| +void BackgroundSyncManager::PendingStatusCallback( |
| + const StatusCallback& callback, |
| + ErrorType error) { |
| + // 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); |
| + if (manager) |
| + op_scheduler_.CompleteOperationAndRunNext(); |
| +} |
| + |
| +} // namespace content |