| Index: chrome/browser/extensions/settings/settings_frontend.cc
|
| diff --git a/chrome/browser/extensions/settings/settings_frontend.cc b/chrome/browser/extensions/settings/settings_frontend.cc
|
| index 1117e55604e48354a864697a8b8ac37fd9ed6c08..6ac79fd7cf508a54f480a0194dee6db6aa38f27c 100644
|
| --- a/chrome/browser/extensions/settings/settings_frontend.cc
|
| +++ b/chrome/browser/extensions/settings/settings_frontend.cc
|
| @@ -10,68 +10,57 @@
|
| #include "chrome/browser/extensions/extension_event_router.h"
|
| #include "chrome/browser/extensions/extension_service.h"
|
| #include "chrome/browser/extensions/settings/settings_backend.h"
|
| +#include "chrome/browser/extensions/settings/settings_namespace.h"
|
| #include "chrome/browser/extensions/settings/settings_leveldb_storage.h"
|
| #include "chrome/browser/profiles/profile.h"
|
| #include "content/public/browser/browser_thread.h"
|
| #include "content/public/browser/notification_service.h"
|
|
|
| -namespace extensions {
|
| -
|
| using content::BrowserThread;
|
|
|
| +namespace extensions {
|
| +
|
| namespace {
|
|
|
| -struct Backends {
|
| - Backends(
|
| - // Ownership taken.
|
| - SettingsStorageFactory* storage_factory,
|
| - const FilePath& profile_path,
|
| - const scoped_refptr<SettingsObserverList>& observers)
|
| - : storage_factory_(storage_factory),
|
| - extensions_backend_(
|
| - storage_factory,
|
| - profile_path.AppendASCII(
|
| - ExtensionService::kExtensionSettingsDirectoryName),
|
| - observers),
|
| - apps_backend_(
|
| - storage_factory,
|
| - profile_path.AppendASCII(
|
| - ExtensionService::kAppSettingsDirectoryName),
|
| - observers) {}
|
| +// Settings change Observer which forwards changes on to the extension
|
| +// processes for |profile| and its incognito partner if it exists.
|
| +class DefaultObserver : public SettingsObserver {
|
| + public:
|
| + explicit DefaultObserver(Profile* profile) : profile_(profile) {}
|
| +
|
| + // SettingsObserver implementation.
|
| + virtual void OnSettingsChanged(
|
| + const std::string& extension_id,
|
| + settings_namespace::Namespace settings_namespace,
|
| + const std::string& change_json) OVERRIDE {
|
| + profile_->GetExtensionEventRouter()->DispatchEventToExtension(
|
| + extension_id,
|
| + extension_event_names::kOnSettingsChanged,
|
| + // This is the list of function arguments to pass to the onChanged
|
| + // handler of extensions, an array of [changes, settings_namespace].
|
| + std::string("[") + change_json + ",\"" +
|
| + settings_namespace::ToString(settings_namespace) + "\"]",
|
| + NULL,
|
| + GURL());
|
| + }
|
|
|
| - scoped_ptr<SettingsStorageFactory> storage_factory_;
|
| - SettingsBackend extensions_backend_;
|
| - SettingsBackend apps_backend_;
|
| + private:
|
| + Profile* const profile_;
|
| };
|
|
|
| -static void CallbackWithExtensionsBackend(
|
| +void CallbackWithSyncableService(
|
| const SettingsFrontend::SyncableServiceCallback& callback,
|
| - Backends* backends) {
|
| + SettingsBackend* backend) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| - callback.Run(&backends->extensions_backend_);
|
| + callback.Run(backend);
|
| }
|
|
|
| -void CallbackWithAppsBackend(
|
| - const SettingsFrontend::SyncableServiceCallback& callback,
|
| - Backends* backends) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| - callback.Run(&backends->apps_backend_);
|
| -}
|
| -
|
| -void CallbackWithExtensionsStorage(
|
| +void CallbackWithStorage(
|
| const std::string& extension_id,
|
| const SettingsFrontend::StorageCallback& callback,
|
| - Backends* backends) {
|
| + SettingsBackend* backend) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| - callback.Run(backends->extensions_backend_.GetStorage(extension_id));
|
| -}
|
| -
|
| -void CallbackWithAppsStorage(
|
| - const std::string& extension_id,
|
| - const SettingsFrontend::StorageCallback& callback,
|
| - Backends* backends) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| - callback.Run(backends->apps_backend_.GetStorage(extension_id));
|
| + callback.Run(backend->GetStorage(extension_id));
|
| }
|
|
|
| void CallbackWithNullStorage(
|
| @@ -81,103 +70,94 @@ void CallbackWithNullStorage(
|
| }
|
|
|
| void DeleteStorageOnFileThread(
|
| - const std::string& extension_id, Backends* backends) {
|
| + const std::string& extension_id, SettingsBackend* backend) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| - backends->extensions_backend_.DeleteStorage(extension_id);
|
| - backends->apps_backend_.DeleteStorage(extension_id);
|
| + backend->DeleteStorage(extension_id);
|
| }
|
|
|
| } // namespace
|
|
|
| -// DefaultObserver
|
| -
|
| -SettingsFrontend::DefaultObserver::DefaultObserver(Profile* profile)
|
| - : profile_(profile) {}
|
| -
|
| -SettingsFrontend::DefaultObserver::~DefaultObserver() {}
|
| -
|
| -void SettingsFrontend::DefaultObserver::OnSettingsChanged(
|
| - const std::string& extension_id, const std::string& changes_json) {
|
| - profile_->GetExtensionEventRouter()->DispatchEventToExtension(
|
| - extension_id,
|
| - extension_event_names::kOnSettingsChanged,
|
| - // This is the list of function arguments to pass to the onChanged
|
| - // handler of extensions, a single argument with the list of changes.
|
| - std::string("[") + changes_json + "]",
|
| - NULL,
|
| - GURL());
|
| -}
|
| -
|
| -// Core
|
| -
|
| -class SettingsFrontend::Core
|
| - : public base::RefCountedThreadSafe<Core> {
|
| +// Ref-counted container for a SettingsBackend object.
|
| +class SettingsFrontend::BackendWrapper
|
| + : public base::RefCountedThreadSafe<BackendWrapper> {
|
| public:
|
| - explicit Core(
|
| - // Ownership taken.
|
| - SettingsStorageFactory* storage_factory,
|
| - const scoped_refptr<SettingsObserverList>& observers)
|
| - : storage_factory_(storage_factory),
|
| - observers_(observers),
|
| - backends_(NULL) {
|
| + // Creates a new BackendWrapper and initializes it on the FILE thread.
|
| + static scoped_refptr<BackendWrapper> CreateAndInit(
|
| + const scoped_refptr<SettingsStorageFactory>& factory,
|
| + const scoped_refptr<SettingsObserverList>& observers,
|
| + const FilePath& path) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + scoped_refptr<BackendWrapper> backend_wrapper =
|
| + new BackendWrapper(factory, observers);
|
| + BrowserThread::PostTask(
|
| + BrowserThread::FILE,
|
| + FROM_HERE,
|
| + base::Bind(
|
| + &SettingsFrontend::BackendWrapper::InitOnFileThread,
|
| + backend_wrapper,
|
| + path));
|
| + return backend_wrapper;
|
| }
|
|
|
| - typedef base::Callback<void(Backends*)> BackendsCallback;
|
| -
|
| - // Does any FILE thread specific initialization, such as construction of
|
| - // |backend_|. Must be called before any call to
|
| - // RunWithBackendOnFileThread().
|
| - void InitOnFileThread(const FilePath& profile_path) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| - DCHECK(!backends_);
|
| - backends_ =
|
| - new Backends(
|
| - storage_factory_.release(), profile_path, observers_);
|
| - }
|
| + typedef base::Callback<void(SettingsBackend*)> BackendCallback;
|
|
|
| - // Runs |callback| with both the extensions and apps settings on the FILE
|
| - // thread.
|
| - void RunWithBackends(const BackendsCallback& callback) {
|
| + // 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(
|
| - &SettingsFrontend::Core::RunWithBackendsOnFileThread,
|
| + &SettingsFrontend::BackendWrapper::RunWithBackendOnFileThread,
|
| this,
|
| callback));
|
| }
|
|
|
| private:
|
| - void RunWithBackendsOnFileThread(const BackendsCallback& callback) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| - DCHECK(backends_);
|
| - callback.Run(backends_);
|
| + friend class base::RefCountedThreadSafe<BackendWrapper>;
|
| +
|
| + BackendWrapper(
|
| + const scoped_refptr<SettingsStorageFactory>& storage_factory,
|
| + const scoped_refptr<SettingsObserverList>& observers)
|
| + : storage_factory_(storage_factory),
|
| + observers_(observers),
|
| + backend_(NULL) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| }
|
|
|
| - virtual ~Core() {
|
| + virtual ~BackendWrapper() {
|
| if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
|
| - delete backends_;
|
| + delete backend_;
|
| } else if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
|
| - BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, backends_);
|
| + BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, backend_);
|
| } else {
|
| NOTREACHED();
|
| }
|
| }
|
|
|
| - friend class base::RefCountedThreadSafe<Core>;
|
| + void InitOnFileThread(const FilePath& path) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| + DCHECK(!backend_);
|
| + backend_ = new SettingsBackend(storage_factory_, path, observers_);
|
| + storage_factory_ = NULL;
|
| + observers_ = NULL;
|
| + }
|
|
|
| - // Leveldb storage area factory. Ownership passed to Backends on Init.
|
| - scoped_ptr<SettingsStorageFactory> storage_factory_;
|
| + void RunWithBackendOnFileThread(const BackendCallback& callback) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| + DCHECK(backend_);
|
| + callback.Run(backend_);
|
| + }
|
|
|
| - // Observers to settings changes (thread safe).
|
| + // Only need these until |backend_| exists.
|
| + scoped_refptr<SettingsStorageFactory> storage_factory_;
|
| scoped_refptr<SettingsObserverList> observers_;
|
|
|
| - // Backends for extensions and apps settings. Lives on FILE thread.
|
| - Backends* backends_;
|
| + // Wrapped Backend. Used exclusively on the FILE thread, and is created on
|
| + // the FILE thread in InitOnFileThread.
|
| + SettingsBackend* backend_;
|
|
|
| - DISALLOW_COPY_AND_ASSIGN(Core);
|
| + DISALLOW_COPY_AND_ASSIGN(BackendWrapper);
|
| };
|
|
|
| // SettingsFrontend
|
| @@ -189,54 +169,75 @@ SettingsFrontend* SettingsFrontend::Create(Profile* profile) {
|
|
|
| /* static */
|
| SettingsFrontend* SettingsFrontend::Create(
|
| - SettingsStorageFactory* storage_factory, Profile* profile) {
|
| + const scoped_refptr<SettingsStorageFactory>& storage_factory,
|
| + Profile* profile) {
|
| return new SettingsFrontend(storage_factory, profile);
|
| }
|
|
|
| SettingsFrontend::SettingsFrontend(
|
| - SettingsStorageFactory* storage_factory, Profile* profile)
|
| + const scoped_refptr<SettingsStorageFactory>& factory, Profile* profile)
|
| : profile_(profile),
|
| observers_(new SettingsObserverList()),
|
| - default_observer_(profile),
|
| - core_(new SettingsFrontend::Core(storage_factory, observers_)) {
|
| + profile_observer_(new DefaultObserver(profile)) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| DCHECK(!profile->IsOffTheRecord());
|
|
|
| - observers_->AddObserver(&default_observer_);
|
| + observers_->AddObserver(profile_observer_.get());
|
|
|
| - BrowserThread::PostTask(
|
| - BrowserThread::FILE,
|
| - FROM_HERE,
|
| - base::Bind(
|
| - &SettingsFrontend::Core::InitOnFileThread,
|
| - core_.get(),
|
| - profile->GetPath()));
|
| + const FilePath& profile_path = profile->GetPath();
|
| + backends_[settings_namespace::LOCAL].app =
|
| + BackendWrapper::CreateAndInit(
|
| + factory,
|
| + observers_,
|
| + profile_path.AppendASCII(
|
| + ExtensionService::kLocalAppSettingsDirectoryName));
|
| + backends_[settings_namespace::LOCAL].extension =
|
| + BackendWrapper::CreateAndInit(
|
| + factory,
|
| + observers_,
|
| + profile_path.AppendASCII(
|
| + ExtensionService::kLocalExtensionSettingsDirectoryName));
|
| + backends_[settings_namespace::SYNC].app =
|
| + BackendWrapper::CreateAndInit(
|
| + factory,
|
| + observers_,
|
| + profile_path.AppendASCII(
|
| + ExtensionService::kSyncAppSettingsDirectoryName));
|
| + backends_[settings_namespace::SYNC].extension =
|
| + BackendWrapper::CreateAndInit(
|
| + factory,
|
| + observers_,
|
| + profile_path.AppendASCII(
|
| + ExtensionService::kSyncExtensionSettingsDirectoryName));
|
| }
|
|
|
| SettingsFrontend::~SettingsFrontend() {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - observers_->RemoveObserver(&default_observer_);
|
| + observers_->RemoveObserver(profile_observer_.get());
|
| }
|
|
|
| void SettingsFrontend::RunWithSyncableService(
|
| syncable::ModelType model_type, const SyncableServiceCallback& callback) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + scoped_refptr<BackendWrapper> backend;
|
| switch (model_type) {
|
| - case syncable::EXTENSION_SETTINGS:
|
| - core_->RunWithBackends(
|
| - base::Bind(&CallbackWithExtensionsBackend, callback));
|
| - break;
|
| case syncable::APP_SETTINGS:
|
| - core_->RunWithBackends(
|
| - base::Bind(&CallbackWithAppsBackend, callback));
|
| + backend = backends_[settings_namespace::SYNC].app;
|
| break;
|
| +
|
| + case syncable::EXTENSION_SETTINGS:
|
| + backend = backends_[settings_namespace::SYNC].extension;
|
| + break;
|
| +
|
| default:
|
| NOTREACHED();
|
| }
|
| + backend->RunWithBackend(base::Bind(&CallbackWithSyncableService, callback));
|
| }
|
|
|
| void SettingsFrontend::RunWithStorage(
|
| const std::string& extension_id,
|
| + settings_namespace::Namespace settings_namespace,
|
| const StorageCallback& callback) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
|
|
| @@ -250,25 +251,36 @@ void SettingsFrontend::RunWithStorage(
|
| return;
|
| }
|
|
|
| + scoped_refptr<BackendWrapper> backend;
|
| if (extension->is_app()) {
|
| - core_->RunWithBackends(
|
| - base::Bind(&CallbackWithAppsStorage, extension_id, callback));
|
| + backend = backends_[settings_namespace].app;
|
| } else {
|
| - core_->RunWithBackends(
|
| - base::Bind(&CallbackWithExtensionsStorage, extension_id, callback));
|
| + backend = backends_[settings_namespace].extension;
|
| }
|
| + backend->RunWithBackend(
|
| + base::Bind(&CallbackWithStorage, extension_id, callback));
|
| }
|
|
|
| void SettingsFrontend::DeleteStorageSoon(
|
| const std::string& extension_id) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - core_->RunWithBackends(base::Bind(&DeleteStorageOnFileThread, extension_id));
|
| + SettingsFrontend::BackendWrapper::BackendCallback callback =
|
| + base::Bind(&DeleteStorageOnFileThread, extension_id);
|
| + for (std::map<settings_namespace::Namespace, BackendWrappers>::iterator it =
|
| + backends_.begin(); it != backends_.end(); ++it) {
|
| + it->second.app->RunWithBackend(callback);
|
| + it->second.extension->RunWithBackend(callback);
|
| + }
|
| }
|
|
|
| -scoped_refptr<SettingsObserverList>
|
| -SettingsFrontend::GetObservers() {
|
| +scoped_refptr<SettingsObserverList> SettingsFrontend::GetObservers() {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| return observers_;
|
| }
|
|
|
| +// BackendWrappers
|
| +
|
| +SettingsFrontend::BackendWrappers::BackendWrappers() {}
|
| +SettingsFrontend::BackendWrappers::~BackendWrappers() {}
|
| +
|
| } // namespace extensions
|
|
|