Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/extension_settings_frontend.h" | 5 #include "chrome/browser/extensions/extension_settings_frontend.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/file_path.h" | 8 #include "base/file_path.h" |
| 9 #include "chrome/browser/extensions/extension_event_names.h" | |
| 10 #include "chrome/browser/extensions/extension_event_router.h" | |
| 11 #include "chrome/browser/extensions/extension_service.h" | |
| 9 #include "chrome/browser/extensions/extension_settings_backend.h" | 12 #include "chrome/browser/extensions/extension_settings_backend.h" |
| 13 #include "chrome/browser/profiles/profile.h" | |
| 10 #include "content/browser/browser_thread.h" | 14 #include "content/browser/browser_thread.h" |
| 11 | 15 |
| 12 ExtensionSettingsFrontend::ExtensionSettingsFrontend( | 16 // Observer which sends events to a target profile iff the profile isn't the |
| 13 const FilePath& base_path) | 17 // originating profile for the event. |
| 14 : core_(new ExtensionSettingsFrontend::Core()) { | 18 class ExtensionSettingsFrontend::DefaultObserver |
| 19 : public ExtensionSettingsObserver { | |
| 20 public: | |
| 21 explicit DefaultObserver(Profile* profile) : target_profile_(profile) {} | |
| 22 virtual ~DefaultObserver() {} | |
| 23 | |
| 24 virtual void OnSettingsChanged( | |
| 25 const Profile* origin_profile, | |
| 26 const std::string& extension_id, | |
| 27 const ExtensionSettingChanges& changes) OVERRIDE { | |
|
akalin
2011/10/19 19:09:49
maybe DCHECK that origin_profile->OriginalProfile(
not at google - send to devlin
2011/10/19 22:59:36
I don't think this would be right though? target_
akalin
2011/10/19 23:17:00
Right, that's why I put 'vice versa', so something
not at google - send to devlin
2011/10/19 23:47:34
Don't know. Seems to be adding noise to a very si
| |
| 28 if (origin_profile != target_profile_) { | |
| 29 target_profile_->GetExtensionEventRouter()->DispatchEventToExtension( | |
| 30 extension_id, | |
| 31 extension_event_names::kOnSettingsChanged, | |
| 32 // This is the list of function arguments to pass to the onChanged | |
| 33 // handler of extensions, a single argument with the list of changes. | |
| 34 std::string("[") + changes.ToJson() + "]", | |
| 35 target_profile_, | |
| 36 GURL()); | |
| 37 } | |
| 38 } | |
| 39 | |
| 40 private: | |
| 41 Profile* target_profile_; | |
| 42 }; | |
| 43 | |
| 44 // Ref-counted container for the ExtensionSettingsBackend object. | |
| 45 class ExtensionSettingsFrontend::Core | |
| 46 : public base::RefCountedThreadSafe<Core> { | |
| 47 public: | |
| 48 explicit Core( | |
| 49 const scoped_refptr<ObserverListThreadSafe<ExtensionSettingsObserver> >& | |
| 50 observers) | |
| 51 : observers_(observers), backend_(NULL) { | |
| 52 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 53 } | |
| 54 | |
| 55 // Does any FILE thread specific initialization, such as construction of | |
| 56 // |backend_|. Must be called before any call to | |
| 57 // RunWithBackendOnFileThread(). | |
| 58 void InitOnFileThread(const FilePath& base_path) { | |
| 59 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 60 DCHECK(!backend_); | |
| 61 backend_ = new ExtensionSettingsBackend(base_path, observers_); | |
| 62 } | |
| 63 | |
| 64 // Runs |callback| with the extension backend. | |
| 65 void RunWithBackendOnFileThread(const BackendCallback& callback) { | |
| 66 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 67 DCHECK(backend_); | |
| 68 callback.Run(backend_); | |
| 69 } | |
| 70 | |
| 71 private: | |
| 72 virtual ~Core() { | |
| 73 if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) { | |
| 74 delete backend_; | |
| 75 } else if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
| 76 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, backend_); | |
| 77 } else { | |
| 78 NOTREACHED(); | |
| 79 } | |
| 80 } | |
| 81 | |
| 82 friend class base::RefCountedThreadSafe<Core>; | |
| 83 | |
| 84 // Observers to settings changes (thread safe). | |
| 85 scoped_refptr<ObserverListThreadSafe<ExtensionSettingsObserver> > | |
| 86 observers_; | |
| 87 | |
| 88 // Lives on the FILE thread. | |
| 89 ExtensionSettingsBackend* backend_; | |
| 90 | |
| 91 DISALLOW_COPY_AND_ASSIGN(Core); | |
| 92 }; | |
| 93 | |
| 94 ExtensionSettingsFrontend::ExtensionSettingsFrontend(Profile* profile) | |
| 95 : profile_(profile), | |
| 96 observers_(new ObserverListThreadSafe<ExtensionSettingsObserver>()), | |
| 97 core_(new ExtensionSettingsFrontend::Core(observers_.get())) { | |
| 15 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 98 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 99 | |
|
akalin
2011/10/19 19:09:49
possible to DCHECK that profile_ isn't an incognit
not at google - send to devlin
2011/10/19 22:59:36
Done.
| |
| 100 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, | |
|
akalin
2011/10/19 19:09:49
comment here about how even though you're listenin
not at google - send to devlin
2011/10/19 22:59:36
Done.
| |
| 101 NotificationService::AllBrowserContextsAndSources()); | |
| 102 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, | |
| 103 NotificationService::AllBrowserContextsAndSources()); | |
| 104 OnProfileCreated(profile); | |
| 105 | |
| 16 BrowserThread::PostTask( | 106 BrowserThread::PostTask( |
| 17 BrowserThread::FILE, | 107 BrowserThread::FILE, |
| 18 FROM_HERE, | 108 FROM_HERE, |
| 19 base::Bind( | 109 base::Bind( |
| 20 &ExtensionSettingsFrontend::Core::InitOnFileThread, | 110 &ExtensionSettingsFrontend::Core::InitOnFileThread, |
| 21 core_.get(), | 111 core_.get(), |
| 22 base_path)); | 112 profile->GetPath().AppendASCII( |
| 113 ExtensionService::kSettingsDirectoryName))); | |
| 114 } | |
| 115 | |
| 116 ExtensionSettingsFrontend::~ExtensionSettingsFrontend() { | |
| 117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 23 } | 118 } |
| 24 | 119 |
| 25 void ExtensionSettingsFrontend::RunWithBackend( | 120 void ExtensionSettingsFrontend::RunWithBackend( |
| 26 const BackendCallback& callback) { | 121 const BackendCallback& callback) { |
| 27 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 28 BrowserThread::PostTask( | 123 BrowserThread::PostTask( |
| 29 BrowserThread::FILE, | 124 BrowserThread::FILE, |
| 30 FROM_HERE, | 125 FROM_HERE, |
| 31 base::Bind( | 126 base::Bind( |
| 32 &ExtensionSettingsFrontend::Core::RunWithBackendOnFileThread, | 127 &ExtensionSettingsFrontend::Core::RunWithBackendOnFileThread, |
| 33 core_.get(), | 128 core_.get(), |
| 34 callback)); | 129 callback)); |
| 35 } | 130 } |
| 36 | 131 |
| 37 ExtensionSettingsFrontend::~ExtensionSettingsFrontend() { | 132 void ExtensionSettingsFrontend::AddObserver( |
| 38 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 133 ExtensionSettingsObserver* observer) { |
| 134 observers_->AddObserver(observer); | |
| 39 } | 135 } |
| 40 | 136 |
| 41 ExtensionSettingsFrontend::Core::Core() : backend_(NULL) { | 137 void ExtensionSettingsFrontend::RemoveObserver( |
| 42 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 138 ExtensionSettingsObserver* observer) { |
| 139 observers_->RemoveObserver(observer); | |
| 43 } | 140 } |
| 44 | 141 |
| 45 void ExtensionSettingsFrontend::Core::InitOnFileThread( | 142 void ExtensionSettingsFrontend::Observe( |
| 46 const FilePath& base_path) { | 143 int type, |
| 47 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 144 const NotificationSource& source, |
| 48 DCHECK(!backend_); | 145 const NotificationDetails& details) { |
| 49 backend_ = new ExtensionSettingsBackend(base_path); | 146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 147 switch (type) { | |
| 148 case chrome::NOTIFICATION_PROFILE_CREATED: | |
| 149 OnProfileCreated(Source<Profile>(source).ptr()); | |
| 150 break; | |
| 151 case chrome::NOTIFICATION_PROFILE_DESTROYED: | |
| 152 OnProfileDestroyed(Source<Profile>(source).ptr()); | |
| 153 break; | |
| 154 default: | |
| 155 NOTREACHED(); | |
| 156 } | |
| 50 } | 157 } |
| 51 | 158 |
| 52 void ExtensionSettingsFrontend::Core::RunWithBackendOnFileThread( | 159 void ExtensionSettingsFrontend::OnProfileCreated(Profile* new_profile) { |
| 53 const BackendCallback& callback) { | 160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 161 if (new_profile == profile_ && !profile_observer_.get()) { |
| 55 DCHECK(backend_); | 162 profile_observer_.reset(new DefaultObserver(profile_)); |
| 56 callback.Run(backend_); | 163 AddObserver(profile_observer_.get()); |
| 164 } else if (new_profile == profile_->GetOffTheRecordProfile() && | |
|
akalin
2011/10/19 19:09:49
hmm GetOffTheRecordProfile() may create one if one
not at google - send to devlin
2011/10/19 22:59:36
Yes you're right. This would work.
| |
| 165 !incognito_profile_observer_.get()) { | |
| 166 incognito_profile_observer_.reset(new DefaultObserver(new_profile)); | |
| 167 AddObserver(incognito_profile_observer_.get()); | |
| 168 } | |
| 57 } | 169 } |
| 58 | 170 |
| 59 ExtensionSettingsFrontend::Core::~Core() { | 171 void ExtensionSettingsFrontend::OnProfileDestroyed(Profile* old_profile) { |
| 60 if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) { | 172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 61 delete backend_; | 173 if (old_profile == profile_ && profile_observer_.get()) { |
| 62 } else if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 174 RemoveObserver(profile_observer_.get()); |
| 63 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, backend_); | 175 profile_observer_.reset(); |
| 64 } else { | 176 } else if (old_profile == profile_->GetOffTheRecordProfile() && |
|
akalin
2011/10/19 19:09:49
same here
not at google - send to devlin
2011/10/19 22:59:36
Done.
| |
| 65 NOTREACHED(); | 177 incognito_profile_observer_.get()) { |
| 178 RemoveObserver(incognito_profile_observer_.get()); | |
| 179 incognito_profile_observer_.reset(); | |
| 66 } | 180 } |
| 67 } | 181 } |
| OLD | NEW |