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..097456e76e7c6daaa85fb19fa18d95e22c77a1e2 |
--- /dev/null |
+++ b/content/browser/background_sync/background_sync_manager.cc |
@@ -0,0 +1,325 @@ |
+// 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 "base/strings/utf_string_conversions.h" |
+#include "content/browser/background_sync/background_sync.pb.h" |
+#include "content/browser/service_worker/service_worker_cache_scheduler.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"; |
+} |
+ |
+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); |
+ DCHECK(initialized_ || initializing_); |
+ |
+ 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); |
+ DCHECK(initialized_ || initializing_); |
+ |
+ 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 base::string16 sync_registration_id, |
+ const StatusAndRegistrationCallback& callback) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ DCHECK(initialized_ || initializing_); |
+ |
+ 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) |
+ : initialized_(false), |
+ initializing_(false), |
+ registration_map_(new IdToRegistrationMap()), |
+ op_scheduler_(new ServiceWorkerCacheScheduler()), |
+ service_worker_context_(service_worker_context), |
+ weak_ptr_factory_(this) { |
+} |
+ |
+void BackgroundSyncManager::Init() { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ DCHECK(!initialized_ && !initializing_); |
+ DCHECK(op_scheduler_->Empty()); |
+ |
+ initializing_ = true; |
+ op_scheduler_->ScheduleOperation(base::Bind(&BackgroundSyncManager::InitImpl, |
+ weak_ptr_factory_.GetWeakPtr())); |
+} |
+ |
+void BackgroundSyncManager::InitImpl() { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ DCHECK(!initialized_); |
+ DCHECK(initializing_); |
+ |
+ 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); |
+ base::string16 id = base::UTF8ToUTF16(registration_proto.id()); |
+ (*registration_map_)[data.first].push_back( |
+ BackgroundSyncRegistration(id)); |
+ } |
+ } |
+ } |
+ |
+ initializing_ = false; |
+ initialized_ = true; |
+ |
+ // 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)) { |
+ callback.Run(ErrorTypeExists, BackgroundSyncRegistration(base::string16())); |
+ 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) { |
michaeln
2015/02/27 02:56:30
thnx for not using const auto everywhere (or anywh
jkarlin
2015/02/27 16:30:38
I'm so not a fan of auto..
|
+ 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(); |
+ // TODO(jkarlin): This UTF conversion is incompatible with DOMString, we |
michaeln
2015/02/27 02:56:30
would it be reasonable for the spec to constrain i
jkarlin
2015/02/27 16:30:38
I've brought this up before. I'd much prefer utf8.
jkarlin
2015/03/02 14:41:03
Sticking with DOMString but WebString::utf8() will
|
+ // should store the string16 without conversion. |
+ registration_proto->set_id(base::UTF16ToUTF8(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); |
+ callback.Run(ErrorTypeStorage, BackgroundSyncRegistration()); |
+ return; |
+ } |
+ // TODO(jkarlin): Run the registration algorithm. |
+ callback.Run(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) { |
michaeln
2015/02/27 02:56:30
does a fancy for (const BackgroundSyncRegistration
jkarlin
2015/02/27 16:30:38
The foreach loop doesn't work because I need an it
michaeln
2015/02/28 00:34:23
awwww, no love for lambdas :)
|
+ 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)) { |
+ callback.Run(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); |
+ callback.Run(ErrorTypeStorage); |
+ return; |
+ } |
+ |
+ // TODO(jkarlin): Run the registration algorithm. |
+ callback.Run(ErrorTypeOK); |
+} |
+ |
+void BackgroundSyncManager::GetRegistrationImpl( |
+ const GURL& origin, |
+ int64 sw_registration_id, |
+ const base::string16 sync_registration_id, |
+ const StatusAndRegistrationCallback& callback) { |
+ IdToRegistrationMap::iterator it = |
+ registration_map_->find(sw_registration_id); |
+ |
+ if (it == registration_map_->end()) { |
+ callback.Run(ErrorTypeNotFound, BackgroundSyncRegistration()); |
+ return; |
+ } |
+ |
+ 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) { |
+ callback.Run(ErrorTypeOK, *reg_iter); |
+ return; |
+ } |
+ } |
+ |
+ callback.Run(ErrorTypeNotFound, BackgroundSyncRegistration()); |
+} |
+ |
+void BackgroundSyncManager::PendingStatusAndRegistrationCallback( |
+ const StatusAndRegistrationCallback& callback, |
+ ErrorType error, |
+ const BackgroundSyncRegistration& sync_registration) { |
+ 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) { |
+ base::WeakPtr<BackgroundSyncManager> manager = weak_ptr_factory_.GetWeakPtr(); |
+ callback.Run(error); |
+ if (manager) |
+ op_scheduler_->CompleteOperationAndRunNext(); |
+} |
+ |
+} // namespace content |