| Index: chrome/browser/extensions/extension_settings_frontend.cc
|
| diff --git a/chrome/browser/extensions/extension_settings_frontend.cc b/chrome/browser/extensions/extension_settings_frontend.cc
|
| index 4963e927ae92c67c77fb084f76387cce05297626..23d26c82536483c96b284a02ce4d9b493453d402 100644
|
| --- a/chrome/browser/extensions/extension_settings_frontend.cc
|
| +++ b/chrome/browser/extensions/extension_settings_frontend.cc
|
| @@ -6,20 +6,114 @@
|
|
|
| #include "base/bind.h"
|
| #include "base/file_path.h"
|
| +#include "chrome/browser/extensions/extension_event_names.h"
|
| +#include "chrome/browser/extensions/extension_event_router.h"
|
| +#include "chrome/browser/extensions/extension_service.h"
|
| #include "chrome/browser/extensions/extension_settings_backend.h"
|
| +#include "chrome/browser/profiles/profile.h"
|
| #include "content/browser/browser_thread.h"
|
|
|
| -ExtensionSettingsFrontend::ExtensionSettingsFrontend(
|
| - const FilePath& base_path)
|
| - : core_(new ExtensionSettingsFrontend::Core()) {
|
| +// Observer which sends events to a target profile iff the profile isn't the
|
| +// originating profile for the event.
|
| +class ExtensionSettingsFrontend::DefaultObserver
|
| + : public ExtensionSettingsObserver {
|
| + public:
|
| + explicit DefaultObserver(Profile* profile) : target_profile_(profile) {}
|
| + virtual ~DefaultObserver() {}
|
| +
|
| + virtual void OnSettingsChanged(
|
| + Profile* origin_profile,
|
| + const std::string& extension_id,
|
| + const ExtensionSettingsChanges& changes) OVERRIDE {
|
| + if (origin_profile != target_profile_) {
|
| + target_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.ToJson() + "]",
|
| + target_profile_,
|
| + GURL());
|
| + }
|
| + }
|
| +
|
| + private:
|
| + Profile* target_profile_;
|
| +};
|
| +
|
| +// Ref-counted container for the ExtensionSettingsBackend object.
|
| +class ExtensionSettingsFrontend::Core
|
| + : public base::RefCountedThreadSafe<Core> {
|
| + public:
|
| + explicit Core(
|
| + const scoped_refptr<ObserverListThreadSafe<ExtensionSettingsObserver> >&
|
| + observers)
|
| + : observers_(observers), backend_(NULL) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + }
|
| +
|
| + // Does any FILE thread specific initialization, such as construction of
|
| + // |backend_|. Must be called before any call to
|
| + // RunWithBackendOnFileThread().
|
| + void InitOnFileThread(const FilePath& base_path) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| + DCHECK(!backend_);
|
| + backend_ = new ExtensionSettingsBackend(base_path, observers_);
|
| + }
|
| +
|
| + // Runs |callback| with the extension backend.
|
| + void RunWithBackendOnFileThread(const BackendCallback& callback) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| + DCHECK(backend_);
|
| + callback.Run(backend_);
|
| + }
|
| +
|
| + private:
|
| + virtual ~Core() {
|
| + if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
|
| + delete backend_;
|
| + } else if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
|
| + BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, backend_);
|
| + } else {
|
| + NOTREACHED();
|
| + }
|
| + }
|
| +
|
| + friend class base::RefCountedThreadSafe<Core>;
|
| +
|
| + // Observers to settings changes (thread safe).
|
| + scoped_refptr<ObserverListThreadSafe<ExtensionSettingsObserver> >
|
| + observers_;
|
| +
|
| + // Lives on the FILE thread.
|
| + ExtensionSettingsBackend* backend_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(Core);
|
| +};
|
| +
|
| +ExtensionSettingsFrontend::ExtensionSettingsFrontend(Profile* profile)
|
| + : observers_(new ObserverListThreadSafe<ExtensionSettingsObserver>()),
|
| + core_(new ExtensionSettingsFrontend::Core(observers_.get())) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| +
|
| + registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED,
|
| + NotificationService::AllBrowserContextsAndSources());
|
| + registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
|
| + NotificationService::AllBrowserContextsAndSources());
|
| + OnProfileCreated(profile);
|
| +
|
| BrowserThread::PostTask(
|
| BrowserThread::FILE,
|
| FROM_HERE,
|
| base::Bind(
|
| &ExtensionSettingsFrontend::Core::InitOnFileThread,
|
| core_.get(),
|
| - base_path));
|
| + profile->GetPath().AppendASCII(
|
| + ExtensionService::kSettingsDirectoryName)));
|
| +}
|
| +
|
| +ExtensionSettingsFrontend::~ExtensionSettingsFrontend() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| }
|
|
|
| void ExtensionSettingsFrontend::RunWithBackend(
|
| @@ -34,34 +128,45 @@ void ExtensionSettingsFrontend::RunWithBackend(
|
| callback));
|
| }
|
|
|
| -ExtensionSettingsFrontend::~ExtensionSettingsFrontend() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| +void ExtensionSettingsFrontend::AddObserver(
|
| + ExtensionSettingsObserver* observer) {
|
| + observers_->AddObserver(observer);
|
| }
|
|
|
| -ExtensionSettingsFrontend::Core::Core() : backend_(NULL) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| +void ExtensionSettingsFrontend::RemoveObserver(
|
| + ExtensionSettingsObserver* observer) {
|
| + observers_->RemoveObserver(observer);
|
| }
|
|
|
| -void ExtensionSettingsFrontend::Core::InitOnFileThread(
|
| - const FilePath& base_path) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| - DCHECK(!backend_);
|
| - backend_ = new ExtensionSettingsBackend(base_path);
|
| +void ExtensionSettingsFrontend::Observe(
|
| + int type,
|
| + const NotificationSource& source,
|
| + const NotificationDetails& details) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + switch (type) {
|
| + case chrome::NOTIFICATION_PROFILE_CREATED:
|
| + OnProfileCreated(Source<Profile>(source).ptr());
|
| + break;
|
| + case chrome::NOTIFICATION_PROFILE_DESTROYED:
|
| + OnProfileDestroyed(Source<Profile>(source).ptr());
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + }
|
| }
|
|
|
| -void ExtensionSettingsFrontend::Core::RunWithBackendOnFileThread(
|
| - const BackendCallback& callback) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| - DCHECK(backend_);
|
| - callback.Run(backend_);
|
| +void ExtensionSettingsFrontend::OnProfileCreated(Profile* new_profile) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + DCHECK(profile_observers_.find(new_profile) == profile_observers_.end());
|
| + linked_ptr<DefaultObserver> new_observer(new DefaultObserver(new_profile));
|
| + profile_observers_[new_profile] = new_observer;
|
| + AddObserver(new_observer.get());
|
| }
|
|
|
| -ExtensionSettingsFrontend::Core::~Core() {
|
| - if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
|
| - delete backend_;
|
| - } else if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
|
| - BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, backend_);
|
| - } else {
|
| - NOTREACHED();
|
| - }
|
| +void ExtensionSettingsFrontend::OnProfileDestroyed(Profile* old_profile) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + linked_ptr<DefaultObserver> old_observer = profile_observers_[old_profile];
|
| + DCHECK(old_observer.get());
|
| + profile_observers_.erase(old_profile);
|
| + RemoveObserver(old_observer.get());
|
| }
|
|
|