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" | 9 #include "chrome/browser/extensions/extension_event_names.h" |
| 10 #include "chrome/browser/extensions/extension_event_router.h" | 10 #include "chrome/browser/extensions/extension_event_router.h" |
| 11 #include "chrome/browser/extensions/extension_service.h" | 11 #include "chrome/browser/extensions/extension_service.h" |
| 12 #include "chrome/browser/extensions/extension_settings_backend.h" | 12 #include "chrome/browser/extensions/extension_settings_backend.h" |
| 13 #include "chrome/browser/profiles/profile.h" | 13 #include "chrome/browser/profiles/profile.h" |
| 14 #include "content/browser/browser_thread.h" | 14 #include "content/browser/browser_thread.h" |
| 15 #include "content/public/browser/notification_service.h" | 15 #include "content/public/browser/notification_service.h" |
| 16 | 16 |
| 17 namespace { | |
| 18 | |
| 19 struct Backends { | |
| 20 Backends( | |
| 21 const FilePath& profile_path, | |
| 22 const scoped_refptr<ExtensionSettingsObserverList>& observers) | |
| 23 : extensions_backend_( | |
| 24 profile_path.AppendASCII( | |
| 25 ExtensionService::kExtensionSettingsDirectoryName), | |
| 26 observers), | |
| 27 apps_backend_( | |
| 28 profile_path.AppendASCII( | |
| 29 ExtensionService::kAppSettingsDirectoryName), | |
| 30 observers) {} | |
| 31 | |
| 32 ExtensionSettingsBackend extensions_backend_; | |
| 33 ExtensionSettingsBackend apps_backend_; | |
| 34 }; | |
| 35 | |
| 36 static void CallbackWithExtensionsBackend( | |
| 37 const ExtensionSettingsFrontend::SyncableServiceCallback& callback, | |
| 38 Backends* backends) { | |
| 39 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 40 callback.Run(&backends->extensions_backend_); | |
| 41 } | |
| 42 | |
| 43 void CallbackWithAppsBackend( | |
| 44 const ExtensionSettingsFrontend::SyncableServiceCallback& callback, | |
| 45 Backends* backends) { | |
| 46 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 47 callback.Run(&backends->apps_backend_); | |
| 48 } | |
| 49 | |
| 50 void CallbackWithExtensionsStorage( | |
| 51 const std::string& extension_id, | |
| 52 const ExtensionSettingsFrontend::StorageCallback& callback, | |
| 53 Backends* backends) { | |
| 54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 55 callback.Run(backends->extensions_backend_.GetStorage(extension_id)); | |
| 56 } | |
| 57 | |
| 58 void CallbackWithAppsStorage( | |
| 59 const std::string& extension_id, | |
| 60 const ExtensionSettingsFrontend::StorageCallback& callback, | |
| 61 Backends* backends) { | |
| 62 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 63 callback.Run(backends->apps_backend_.GetStorage(extension_id)); | |
| 64 } | |
| 65 | |
| 66 void CallbackWithNullStorage( | |
| 67 const ExtensionSettingsFrontend::StorageCallback& callback) { | |
| 68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 69 callback.Run(NULL); | |
| 70 } | |
| 71 | |
| 72 void DeleteStorageOnFileThread( | |
| 73 const std::string& extension_id, Backends* backends) { | |
| 74 backends->extensions_backend_.DeleteStorage(extension_id); | |
|
akalin
2011/10/28 06:04:54
DCHECK FILE thread
not at google - send to devlin
2011/10/31 00:02:23
Done.
| |
| 75 backends->apps_backend_.DeleteStorage(extension_id); | |
| 76 } | |
| 77 | |
| 78 } // namespace | |
| 79 | |
| 17 class ExtensionSettingsFrontend::DefaultObserver | 80 class ExtensionSettingsFrontend::DefaultObserver |
| 18 : public ExtensionSettingsObserver { | 81 : public ExtensionSettingsObserver { |
| 19 public: | 82 public: |
| 20 explicit DefaultObserver(Profile* profile) : target_profile_(profile) {} | 83 explicit DefaultObserver(Profile* profile) : target_profile_(profile) {} |
| 21 virtual ~DefaultObserver() {} | 84 virtual ~DefaultObserver() {} |
| 22 | 85 |
| 23 virtual void OnSettingsChanged( | 86 virtual void OnSettingsChanged( |
| 24 const Profile* origin_profile, | 87 const Profile* origin_profile, |
| 25 const std::string& extension_id, | 88 const std::string& extension_id, |
| 26 const ExtensionSettingChanges& changes) OVERRIDE { | 89 const ExtensionSettingChanges& changes) OVERRIDE { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 37 } | 100 } |
| 38 | 101 |
| 39 private: | 102 private: |
| 40 Profile* target_profile_; | 103 Profile* target_profile_; |
| 41 }; | 104 }; |
| 42 | 105 |
| 43 class ExtensionSettingsFrontend::Core | 106 class ExtensionSettingsFrontend::Core |
| 44 : public base::RefCountedThreadSafe<Core> { | 107 : public base::RefCountedThreadSafe<Core> { |
| 45 public: | 108 public: |
| 46 explicit Core( | 109 explicit Core( |
| 47 const scoped_refptr<ObserverListThreadSafe<ExtensionSettingsObserver> >& | 110 const scoped_refptr<ExtensionSettingsObserverList>& observers) |
| 48 observers) | 111 : observers_(observers), backends_(NULL) { |
| 49 : observers_(observers), backend_(NULL) { | |
| 50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 51 } | 113 } |
| 52 | 114 |
| 115 typedef base::Callback<void(Backends*)> BackendsCallback; | |
| 116 | |
| 53 // Does any FILE thread specific initialization, such as construction of | 117 // Does any FILE thread specific initialization, such as construction of |
| 54 // |backend_|. Must be called before any call to | 118 // |backend_|. Must be called before any call to |
| 55 // RunWithBackendOnFileThread(). | 119 // RunWithBackendOnFileThread(). |
| 56 void InitOnFileThread(const FilePath& base_path) { | 120 void InitOnFileThread(const FilePath& profile_path) { |
| 57 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 121 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 58 DCHECK(!backend_); | 122 DCHECK(!backends_); |
| 59 backend_ = new ExtensionSettingsBackend(base_path, observers_); | 123 backends_ = new Backends(profile_path, observers_); |
| 60 } | 124 } |
| 61 | 125 |
| 62 // Runs |callback| with the extension backend. | 126 // Runs |callback| with both the extensions and apps settings on the FILE |
| 63 void RunWithBackendOnFileThread(const BackendCallback& callback) { | 127 // thread. |
| 64 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 128 void RunWithBackends(const BackendsCallback& callback) { |
| 65 DCHECK(backend_); | 129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 66 callback.Run(backend_); | 130 BrowserThread::PostTask( |
| 131 BrowserThread::FILE, | |
| 132 FROM_HERE, | |
| 133 base::Bind( | |
| 134 &ExtensionSettingsFrontend::Core::RunWithBackendsOnFileThread, | |
| 135 this, | |
| 136 callback)); | |
| 67 } | 137 } |
| 68 | 138 |
| 69 private: | 139 private: |
| 140 void RunWithBackendsOnFileThread(const BackendsCallback& callback) { | |
| 141 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 142 DCHECK(backends_); | |
| 143 callback.Run(backends_); | |
| 144 } | |
| 145 | |
| 70 virtual ~Core() { | 146 virtual ~Core() { |
| 71 if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) { | 147 if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) { |
| 72 delete backend_; | 148 delete backends_; |
| 73 } else if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 149 } else if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 74 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, backend_); | 150 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, backends_); |
| 75 } else { | 151 } else { |
| 76 NOTREACHED(); | 152 NOTREACHED(); |
| 77 } | 153 } |
| 78 } | 154 } |
| 79 | 155 |
| 80 friend class base::RefCountedThreadSafe<Core>; | 156 friend class base::RefCountedThreadSafe<Core>; |
| 81 | 157 |
| 82 // Observers to settings changes (thread safe). | 158 // Observers to settings changes (thread safe). |
| 83 scoped_refptr<ObserverListThreadSafe<ExtensionSettingsObserver> > | 159 scoped_refptr<ExtensionSettingsObserverList> observers_; |
| 84 observers_; | |
| 85 | 160 |
| 86 // Lives on the FILE thread. | 161 // Backends for extensions and apps settings. Lives on FILE thread. |
| 87 ExtensionSettingsBackend* backend_; | 162 Backends* backends_; |
| 88 | 163 |
| 89 DISALLOW_COPY_AND_ASSIGN(Core); | 164 DISALLOW_COPY_AND_ASSIGN(Core); |
| 90 }; | 165 }; |
| 91 | 166 |
| 92 ExtensionSettingsFrontend::ExtensionSettingsFrontend(Profile* profile) | 167 ExtensionSettingsFrontend::ExtensionSettingsFrontend(Profile* profile) |
| 93 : profile_(profile), | 168 : profile_(profile), |
| 94 observers_(new ObserverListThreadSafe<ExtensionSettingsObserver>()), | 169 observers_(new ExtensionSettingsObserverList()), |
| 95 core_(new ExtensionSettingsFrontend::Core(observers_.get())) { | 170 core_(new ExtensionSettingsFrontend::Core(observers_)) { |
| 96 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 171 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 97 DCHECK(!profile->IsOffTheRecord()); | 172 DCHECK(!profile->IsOffTheRecord()); |
| 98 | 173 |
| 99 // This class listens to all PROFILE_{CREATED,DESTROYED} events but we're | 174 // This class listens to all PROFILE_{CREATED,DESTROYED} events but we're |
| 100 // only interested in those for the original Profile given on construction | 175 // only interested in those for the original Profile given on construction |
| 101 // and its incognito version. | 176 // and its incognito version. |
| 102 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, | 177 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, |
| 103 content::NotificationService::AllBrowserContextsAndSources()); | 178 content::NotificationService::AllBrowserContextsAndSources()); |
| 104 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, | 179 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, |
| 105 content::NotificationService::AllBrowserContextsAndSources()); | 180 content::NotificationService::AllBrowserContextsAndSources()); |
| 106 OnProfileCreated(profile); | 181 OnProfileCreated(profile); |
| 107 | 182 |
| 108 BrowserThread::PostTask( | 183 BrowserThread::PostTask( |
| 109 BrowserThread::FILE, | 184 BrowserThread::FILE, |
| 110 FROM_HERE, | 185 FROM_HERE, |
| 111 base::Bind( | 186 base::Bind( |
| 112 &ExtensionSettingsFrontend::Core::InitOnFileThread, | 187 &ExtensionSettingsFrontend::Core::InitOnFileThread, |
| 113 core_.get(), | 188 core_.get(), |
| 114 profile->GetPath().AppendASCII( | 189 profile->GetPath())); |
| 115 ExtensionService::kSettingsDirectoryName))); | |
| 116 } | 190 } |
| 117 | 191 |
| 118 ExtensionSettingsFrontend::~ExtensionSettingsFrontend() { | 192 ExtensionSettingsFrontend::~ExtensionSettingsFrontend() { |
| 119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 120 } | 194 } |
| 121 | 195 |
| 122 void ExtensionSettingsFrontend::RunWithBackend( | 196 void ExtensionSettingsFrontend::RunWithSyncableService( |
| 123 const BackendCallback& callback) { | 197 syncable::ModelType model_type, const SyncableServiceCallback& callback) { |
| 124 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 125 BrowserThread::PostTask( | 199 switch (model_type) { |
| 126 BrowserThread::FILE, | 200 case syncable::EXTENSION_SETTINGS: |
| 127 FROM_HERE, | 201 core_->RunWithBackends( |
| 128 base::Bind( | 202 base::Bind(&CallbackWithExtensionsBackend, callback)); |
| 129 &ExtensionSettingsFrontend::Core::RunWithBackendOnFileThread, | 203 break; |
| 130 core_.get(), | 204 case syncable::APP_SETTINGS: |
| 131 callback)); | 205 core_->RunWithBackends( |
| 206 base::Bind(&CallbackWithAppsBackend, callback)); | |
| 207 break; | |
| 208 default: | |
| 209 NOTREACHED(); | |
| 210 } | |
| 132 } | 211 } |
| 133 | 212 |
| 134 void ExtensionSettingsFrontend::AddObserver( | 213 void ExtensionSettingsFrontend::RunWithStorage( |
| 135 ExtensionSettingsObserver* observer) { | 214 const std::string& extension_id, |
| 136 observers_->AddObserver(observer); | 215 const StorageCallback& callback) { |
| 216 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 217 | |
| 218 const Extension* extension = | |
| 219 profile_->GetExtensionService()->GetExtensionById(extension_id, true); | |
| 220 if (!extension) { | |
| 221 BrowserThread::PostTask( | |
| 222 BrowserThread::FILE, | |
| 223 FROM_HERE, | |
| 224 base::Bind(&CallbackWithNullStorage, callback)); | |
| 225 return; | |
| 226 } | |
| 227 | |
| 228 if (extension->is_app()) { | |
| 229 core_->RunWithBackends( | |
| 230 base::Bind(&CallbackWithAppsStorage, extension_id, callback)); | |
| 231 } else { | |
| 232 core_->RunWithBackends( | |
| 233 base::Bind(&CallbackWithExtensionsStorage, extension_id, callback)); | |
| 234 } | |
| 137 } | 235 } |
| 138 | 236 |
| 139 void ExtensionSettingsFrontend::RemoveObserver( | 237 void ExtensionSettingsFrontend::DeleteStorageSoon( |
| 140 ExtensionSettingsObserver* observer) { | 238 const std::string& extension_id) { |
| 141 observers_->RemoveObserver(observer); | 239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 240 core_->RunWithBackends(base::Bind(&DeleteStorageOnFileThread, extension_id)); | |
| 241 } | |
| 242 | |
| 243 scoped_refptr<ExtensionSettingsObserverList> | |
| 244 ExtensionSettingsFrontend::GetObservers() { | |
| 245 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 246 return observers_; | |
| 142 } | 247 } |
| 143 | 248 |
| 144 void ExtensionSettingsFrontend::Observe( | 249 void ExtensionSettingsFrontend::Observe( |
| 145 int type, | 250 int type, |
| 146 const content::NotificationSource& source, | 251 const content::NotificationSource& source, |
| 147 const content::NotificationDetails& details) { | 252 const content::NotificationDetails& details) { |
| 148 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 253 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 149 switch (type) { | 254 switch (type) { |
| 150 case chrome::NOTIFICATION_PROFILE_CREATED: | 255 case chrome::NOTIFICATION_PROFILE_CREATED: |
| 151 OnProfileCreated(content::Source<Profile>(source).ptr()); | 256 OnProfileCreated(content::Source<Profile>(source).ptr()); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 177 } else if (old_profile->GetOriginalProfile() == profile_) { | 282 } else if (old_profile->GetOriginalProfile() == profile_) { |
| 178 DCHECK(old_profile->IsOffTheRecord()); | 283 DCHECK(old_profile->IsOffTheRecord()); |
| 179 ClearDefaultObserver(&incognito_profile_observer_); | 284 ClearDefaultObserver(&incognito_profile_observer_); |
| 180 } | 285 } |
| 181 } | 286 } |
| 182 | 287 |
| 183 void ExtensionSettingsFrontend::SetDefaultObserver( | 288 void ExtensionSettingsFrontend::SetDefaultObserver( |
| 184 Profile* profile, scoped_ptr<DefaultObserver>* observer) { | 289 Profile* profile, scoped_ptr<DefaultObserver>* observer) { |
| 185 DCHECK(!observer->get()); | 290 DCHECK(!observer->get()); |
| 186 observer->reset(new DefaultObserver(profile)); | 291 observer->reset(new DefaultObserver(profile)); |
| 187 AddObserver(observer->get()); | 292 observers_->AddObserver(observer->get()); |
| 188 } | 293 } |
| 189 | 294 |
| 190 void ExtensionSettingsFrontend::ClearDefaultObserver( | 295 void ExtensionSettingsFrontend::ClearDefaultObserver( |
| 191 scoped_ptr<DefaultObserver>* observer) { | 296 scoped_ptr<DefaultObserver>* observer) { |
| 192 if (observer->get()) { | 297 if (observer->get()) { |
| 193 RemoveObserver(observer->get()); | 298 observers_->RemoveObserver(observer->get()); |
| 194 observer->reset(); | 299 observer->reset(); |
| 195 } | 300 } |
| 196 } | 301 } |
| OLD | NEW |