Chromium Code Reviews| Index: chrome/browser/extensions/settings/settings_storage_frontend.cc |
| diff --git a/chrome/browser/extensions/settings/settings_storage_frontend.cc b/chrome/browser/extensions/settings/settings_storage_frontend.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..0cbe13d78061a5caf871692eef876d778b4907d5 |
| --- /dev/null |
| +++ b/chrome/browser/extensions/settings/settings_storage_frontend.cc |
| @@ -0,0 +1,190 @@ |
| +// Copyright (c) 2012 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 "chrome/browser/extensions/settings/settings_storage_frontend.h" |
| + |
| +#include "base/bind.h" |
| +#include "base/callback.h" |
| +#include "base/file_path.h" |
| +#include "chrome/browser/extensions/extension_service.h" |
| +#include "chrome/browser/extensions/settings/settings_backend.h" |
| +#include "chrome/browser/extensions/settings/settings_storage_quota_enforcer.h" |
| +#include "chrome/browser/extensions/settings/weak_unlimited_settings_storage.h" |
| +#include "chrome/common/extensions/extension.h" |
| +#include "content/public/browser/browser_thread.h" |
| + |
| +using content::BrowserThread; |
| + |
| +namespace extensions { |
| + |
| +namespace { |
| + |
|
not at google - send to devlin
2012/07/18 07:46:18
Yeah, so I think a lot of this file will change/si
Joao da Silva
2012/07/18 21:40:25
Yep, managed to do away with the BackendWrapper on
|
| +void CallbackWithStorage( |
| + const std::string& extension_id, |
| + const SettingsNamespaceFrontend::StorageCallback& callback, |
| + SettingsBackend* backend) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| + callback.Run(backend->GetStorage(extension_id)); |
| +} |
| + |
| +void CallbackWithUnlimitedStorage( |
| + const std::string& extension_id, |
| + const SettingsNamespaceFrontend::StorageCallback& callback, |
| + SettingsBackend* backend) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| + WeakUnlimitedSettingsStorage unlimited_storage( |
|
not at google - send to devlin
2012/07/18 07:46:18
If it's made synchronous then this WeakUnlimited t
Joao da Silva
2012/07/18 21:40:25
I'm not entirely sure of what you're proposing to
not at google - send to devlin
2012/07/19 06:43:17
Oh, I remember now. Yeah, ignore this.
|
| + backend->GetStorage(extension_id)); |
| + callback.Run(&unlimited_storage); |
| +} |
| + |
| +void DeleteStorageOnFileThread( |
| + const std::string& extension_id, SettingsBackend* backend) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| + backend->DeleteStorage(extension_id); |
| +} |
| + |
| +} // namespace |
| + |
| +// Ref-counted container for a SettingsBackend object. |
| +class SettingsStorageFrontend::BackendWrapper |
| + : public base::RefCountedThreadSafe<BackendWrapper> { |
| + public: |
| + // Creates a new BackendWrapper and initializes it on the FILE thread. |
| + static scoped_refptr<BackendWrapper> CreateAndInit( |
| + const scoped_refptr<SettingsStorageFactory>& factory, |
| + const SettingsStorageQuotaEnforcer::Limits& quota, |
| + const scoped_refptr<SettingsObserverList>& observers, |
| + const FilePath& path) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + scoped_refptr<BackendWrapper> backend_wrapper = new BackendWrapper(); |
| + BrowserThread::PostTask( |
| + BrowserThread::FILE, FROM_HERE, |
| + base::Bind( |
| + &BackendWrapper::InitOnFileThread, |
| + backend_wrapper, factory, quota, observers, path)); |
| + return backend_wrapper; |
| + } |
| + |
| + typedef base::Callback<void(SettingsBackend*)> BackendCallback; |
| + |
| + // Runs |callback| with the wrapped Backend on the FILE thread. |
| + void RunWithBackend(const BackendCallback& callback) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + BrowserThread::PostTask( |
| + BrowserThread::FILE, FROM_HERE, |
| + base::Bind( |
| + &BackendWrapper::RunWithBackendOnFileThread, this, callback)); |
| + } |
| + |
| + SettingsBackend* GetBackend() const { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| + return backend_; |
| + } |
| + |
| + private: |
| + friend class base::RefCountedThreadSafe<BackendWrapper>; |
| + |
| + BackendWrapper() : backend_(NULL) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + } |
| + |
| + virtual ~BackendWrapper() { |
| + if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) { |
| + delete backend_; |
| + } else if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| + BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, backend_); |
| + } else { |
| + NOTREACHED(); |
| + } |
| + } |
| + |
| + void InitOnFileThread( |
| + const scoped_refptr<SettingsStorageFactory>& storage_factory, |
| + const SettingsStorageQuotaEnforcer::Limits& quota, |
| + const scoped_refptr<SettingsObserverList>& observers, |
| + const FilePath& path) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| + DCHECK(!backend_); |
| + backend_ = new SettingsBackend(storage_factory, path, quota, observers); |
| + } |
| + |
| + void RunWithBackendOnFileThread(const BackendCallback& callback) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| + DCHECK(backend_); |
| + callback.Run(backend_); |
| + } |
| + |
| + // Wrapped Backend. Used exclusively on the FILE thread, and is created on |
| + // the FILE thread in InitOnFileThread. |
| + SettingsBackend* backend_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(BackendWrapper); |
| +}; |
| + |
| +SettingsStorageFrontend::SettingsStorageFrontend( |
| + settings_namespace::Namespace settings_namespace, |
| + const scoped_refptr<SettingsStorageFactory>& factory, |
| + const SettingsStorageQuotaEnforcer::Limits& quota, |
| + const scoped_refptr<SettingsObserverList>& observers, |
| + const FilePath& profile_path) |
| + : settings_namespace_(settings_namespace) { |
| + DCHECK(settings_namespace_ == settings_namespace::LOCAL || |
| + settings_namespace_ == settings_namespace::SYNC); |
| + const bool local = settings_namespace_ == settings_namespace::LOCAL; |
| + const FilePath app_path = profile_path.AppendASCII( |
| + local ? ExtensionService::kLocalAppSettingsDirectoryName |
| + : ExtensionService::kSyncAppSettingsDirectoryName); |
| + const FilePath extension_path = profile_path.AppendASCII( |
| + local ? ExtensionService::kLocalExtensionSettingsDirectoryName |
| + : ExtensionService::kSyncExtensionSettingsDirectoryName); |
| + app_backend_ = |
| + BackendWrapper::CreateAndInit(factory, quota, observers, app_path); |
| + extension_backend_ = |
| + BackendWrapper::CreateAndInit(factory, quota, observers, extension_path); |
| +} |
| + |
| +SettingsStorageFrontend::~SettingsStorageFrontend() {} |
| + |
| +void SettingsStorageFrontend::RunWithStorage(const Extension* extension, |
| + const StorageCallback& callback) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + // A neat way to implement unlimited storage; if the extension has the |
| + // unlimited storage permission, force through all calls to Set() (in the |
| + // same way that writes from sync ignore quota). |
| + // But only if it's local storage (bad stuff would happen if sync'ed |
| + // storage is allowed to be unlimited). |
| + bool is_unlimited = |
| + settings_namespace_ == settings_namespace::LOCAL && |
| + extension->HasAPIPermission(APIPermission::kUnlimitedStorage); |
| + |
| + scoped_refptr<BackendWrapper> backend = |
| + extension->is_app() ? app_backend_ : extension_backend_; |
| + |
| + backend->RunWithBackend( |
| + base::Bind( |
| + is_unlimited ? &CallbackWithUnlimitedStorage : &CallbackWithStorage, |
| + extension->id(), |
| + callback)); |
| +} |
| + |
| +void SettingsStorageFrontend::DeleteStorageSoon( |
| + const std::string& extension_id) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + BackendWrapper::BackendCallback callback = |
| + base::Bind(&DeleteStorageOnFileThread, extension_id); |
| + app_backend_->RunWithBackend(callback); |
| + extension_backend_->RunWithBackend(callback); |
| +} |
| + |
| +SettingsBackend* SettingsStorageFrontend::GetAppBackend() const { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| + return app_backend_->GetBackend(); |
| +} |
| + |
| +SettingsBackend* SettingsStorageFrontend::GetExtensionBackend() const { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| + return extension_backend_->GetBackend(); |
| +} |
| + |
| +} // namespace extensions |