Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(525)

Side by Side Diff: chrome/browser/extensions/settings/settings_frontend.cc

Issue 8670012: Extension Settings API: move the API functions into an object SettingsNamepace, (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix bug / sync Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/settings/settings_frontend.h" 5 #include "chrome/browser/extensions/settings/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/settings/settings_backend.h" 12 #include "chrome/browser/extensions/settings/settings_backend.h"
13 #include "chrome/browser/extensions/settings/settings_namespace.h"
13 #include "chrome/browser/extensions/settings/settings_leveldb_storage.h" 14 #include "chrome/browser/extensions/settings/settings_leveldb_storage.h"
14 #include "chrome/browser/profiles/profile.h" 15 #include "chrome/browser/profiles/profile.h"
15 #include "content/public/browser/browser_thread.h" 16 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/notification_service.h" 17 #include "content/public/browser/notification_service.h"
17 18
19 using content::BrowserThread;
20
18 namespace extensions { 21 namespace extensions {
19 22
20 using content::BrowserThread;
21
22 namespace { 23 namespace {
23 24
24 struct Backends { 25 // Settings change Observer which forwards changes on to the extension
25 Backends( 26 // processes for |profile| and its incognito partner if it exists.
26 // Ownership taken. 27 class DefaultObserver : public SettingsObserver {
27 SettingsStorageFactory* storage_factory, 28 public:
28 const FilePath& profile_path, 29 explicit DefaultObserver(Profile* profile) : profile_(profile) {}
29 const scoped_refptr<SettingsObserverList>& observers)
30 : storage_factory_(storage_factory),
31 extensions_backend_(
32 storage_factory,
33 profile_path.AppendASCII(
34 ExtensionService::kExtensionSettingsDirectoryName),
35 observers),
36 apps_backend_(
37 storage_factory,
38 profile_path.AppendASCII(
39 ExtensionService::kAppSettingsDirectoryName),
40 observers) {}
41 30
42 scoped_ptr<SettingsStorageFactory> storage_factory_; 31 // SettingsObserver implementation.
43 SettingsBackend extensions_backend_; 32 virtual void OnSettingsChanged(
44 SettingsBackend apps_backend_; 33 const std::string& extension_id,
34 settings_namespace::Namespace settings_namespace,
35 const std::string& change_json) OVERRIDE {
36 profile_->GetExtensionEventRouter()->DispatchEventToExtension(
37 extension_id,
38 extension_event_names::kOnSettingsChanged,
39 // This is the list of function arguments to pass to the onChanged
40 // handler of extensions, an array of [changes, settings_namespace].
41 std::string("[") + change_json + ",\"" +
42 settings_namespace::ToString(settings_namespace) + "\"]",
43 NULL,
44 GURL());
45 }
46
47 private:
48 Profile* const profile_;
45 }; 49 };
46 50
47 static void CallbackWithExtensionsBackend( 51 void CallbackWithSyncableService(
48 const SettingsFrontend::SyncableServiceCallback& callback, 52 const SettingsFrontend::SyncableServiceCallback& callback,
49 Backends* backends) { 53 SettingsBackend* backend) {
50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
51 callback.Run(&backends->extensions_backend_); 55 callback.Run(backend);
52 } 56 }
53 57
54 void CallbackWithAppsBackend( 58 void CallbackWithStorage(
55 const SettingsFrontend::SyncableServiceCallback& callback,
56 Backends* backends) {
57 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
58 callback.Run(&backends->apps_backend_);
59 }
60
61 void CallbackWithExtensionsStorage(
62 const std::string& extension_id, 59 const std::string& extension_id,
63 const SettingsFrontend::StorageCallback& callback, 60 const SettingsFrontend::StorageCallback& callback,
64 Backends* backends) { 61 SettingsBackend* backend) {
65 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 62 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
66 callback.Run(backends->extensions_backend_.GetStorage(extension_id)); 63 callback.Run(backend->GetStorage(extension_id));
67 }
68
69 void CallbackWithAppsStorage(
70 const std::string& extension_id,
71 const SettingsFrontend::StorageCallback& callback,
72 Backends* backends) {
73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
74 callback.Run(backends->apps_backend_.GetStorage(extension_id));
75 } 64 }
76 65
77 void CallbackWithNullStorage( 66 void CallbackWithNullStorage(
78 const SettingsFrontend::StorageCallback& callback) { 67 const SettingsFrontend::StorageCallback& callback) {
79 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
80 callback.Run(NULL); 69 callback.Run(NULL);
81 } 70 }
82 71
83 void DeleteStorageOnFileThread( 72 void DeleteStorageOnFileThread(
84 const std::string& extension_id, Backends* backends) { 73 const std::string& extension_id, SettingsBackend* backend) {
85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 74 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
86 backends->extensions_backend_.DeleteStorage(extension_id); 75 backend->DeleteStorage(extension_id);
87 backends->apps_backend_.DeleteStorage(extension_id);
88 } 76 }
89 77
90 } // namespace 78 } // namespace
91 79
92 // DefaultObserver 80 // Ref-counted container for a SettingsBackend object.
93 81 class SettingsFrontend::BackendWrapper
94 SettingsFrontend::DefaultObserver::DefaultObserver(Profile* profile) 82 : public base::RefCountedThreadSafe<BackendWrapper> {
95 : profile_(profile) {}
96
97 SettingsFrontend::DefaultObserver::~DefaultObserver() {}
98
99 void SettingsFrontend::DefaultObserver::OnSettingsChanged(
100 const std::string& extension_id, const std::string& changes_json) {
101 profile_->GetExtensionEventRouter()->DispatchEventToExtension(
102 extension_id,
103 extension_event_names::kOnSettingsChanged,
104 // This is the list of function arguments to pass to the onChanged
105 // handler of extensions, a single argument with the list of changes.
106 std::string("[") + changes_json + "]",
107 NULL,
108 GURL());
109 }
110
111 // Core
112
113 class SettingsFrontend::Core
114 : public base::RefCountedThreadSafe<Core> {
115 public: 83 public:
116 explicit Core( 84 // Creates a new BackendWrapper and initializes it on the FILE thread.
117 // Ownership taken. 85 static scoped_refptr<BackendWrapper> CreateAndInit(
118 SettingsStorageFactory* storage_factory, 86 const scoped_refptr<SettingsStorageFactory>& factory,
119 const scoped_refptr<SettingsObserverList>& observers) 87 const scoped_refptr<SettingsObserverList>& observers,
120 : storage_factory_(storage_factory), 88 const FilePath& path) {
121 observers_(observers),
122 backends_(NULL) {
123 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 89 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
90 scoped_refptr<BackendWrapper> backend_wrapper =
91 new BackendWrapper(factory, observers);
92 BrowserThread::PostTask(
93 BrowserThread::FILE,
94 FROM_HERE,
95 base::Bind(
96 &SettingsFrontend::BackendWrapper::InitOnFileThread,
97 backend_wrapper,
98 path));
99 return backend_wrapper;
124 } 100 }
125 101
126 typedef base::Callback<void(Backends*)> BackendsCallback; 102 typedef base::Callback<void(SettingsBackend*)> BackendCallback;
127 103
128 // Does any FILE thread specific initialization, such as construction of 104 // Runs |callback| with the wrapped Backend on the FILE thread.
129 // |backend_|. Must be called before any call to 105 void RunWithBackend(const BackendCallback& callback) {
130 // RunWithBackendOnFileThread().
131 void InitOnFileThread(const FilePath& profile_path) {
132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
133 DCHECK(!backends_);
134 backends_ =
135 new Backends(
136 storage_factory_.release(), profile_path, observers_);
137 }
138
139 // Runs |callback| with both the extensions and apps settings on the FILE
140 // thread.
141 void RunWithBackends(const BackendsCallback& callback) {
142 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
143 BrowserThread::PostTask( 107 BrowserThread::PostTask(
144 BrowserThread::FILE, 108 BrowserThread::FILE,
145 FROM_HERE, 109 FROM_HERE,
146 base::Bind( 110 base::Bind(
147 &SettingsFrontend::Core::RunWithBackendsOnFileThread, 111 &SettingsFrontend::BackendWrapper::RunWithBackendOnFileThread,
148 this, 112 this,
149 callback)); 113 callback));
150 } 114 }
151 115
152 private: 116 private:
153 void RunWithBackendsOnFileThread(const BackendsCallback& callback) { 117 friend class base::RefCountedThreadSafe<BackendWrapper>;
154 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 118
155 DCHECK(backends_); 119 BackendWrapper(
156 callback.Run(backends_); 120 const scoped_refptr<SettingsStorageFactory>& storage_factory,
121 const scoped_refptr<SettingsObserverList>& observers)
122 : storage_factory_(storage_factory),
123 observers_(observers),
124 backend_(NULL) {
125 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
157 } 126 }
158 127
159 virtual ~Core() { 128 virtual ~BackendWrapper() {
160 if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) { 129 if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
161 delete backends_; 130 delete backend_;
162 } else if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { 131 } else if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
163 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, backends_); 132 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, backend_);
164 } else { 133 } else {
165 NOTREACHED(); 134 NOTREACHED();
166 } 135 }
167 } 136 }
168 137
169 friend class base::RefCountedThreadSafe<Core>; 138 void InitOnFileThread(const FilePath& path) {
139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
140 DCHECK(!backend_);
141 backend_ = new SettingsBackend(storage_factory_, path, observers_);
142 storage_factory_ = NULL;
143 observers_ = NULL;
144 }
170 145
171 // Leveldb storage area factory. Ownership passed to Backends on Init. 146 void RunWithBackendOnFileThread(const BackendCallback& callback) {
172 scoped_ptr<SettingsStorageFactory> storage_factory_; 147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
148 DCHECK(backend_);
149 callback.Run(backend_);
150 }
173 151
174 // Observers to settings changes (thread safe). 152 // Only need these until |backend_| exists.
153 scoped_refptr<SettingsStorageFactory> storage_factory_;
175 scoped_refptr<SettingsObserverList> observers_; 154 scoped_refptr<SettingsObserverList> observers_;
176 155
177 // Backends for extensions and apps settings. Lives on FILE thread. 156 // Wrapped Backend. Used exclusively on the FILE thread, and is created on
178 Backends* backends_; 157 // the FILE thread in InitOnFileThread.
158 SettingsBackend* backend_;
179 159
180 DISALLOW_COPY_AND_ASSIGN(Core); 160 DISALLOW_COPY_AND_ASSIGN(BackendWrapper);
181 }; 161 };
182 162
183 // SettingsFrontend 163 // SettingsFrontend
184 164
185 /* static */ 165 /* static */
186 SettingsFrontend* SettingsFrontend::Create(Profile* profile) { 166 SettingsFrontend* SettingsFrontend::Create(Profile* profile) {
187 return new SettingsFrontend(new SettingsLeveldbStorage::Factory(), profile); 167 return new SettingsFrontend(new SettingsLeveldbStorage::Factory(), profile);
188 } 168 }
189 169
190 /* static */ 170 /* static */
191 SettingsFrontend* SettingsFrontend::Create( 171 SettingsFrontend* SettingsFrontend::Create(
192 SettingsStorageFactory* storage_factory, Profile* profile) { 172 const scoped_refptr<SettingsStorageFactory>& storage_factory,
173 Profile* profile) {
193 return new SettingsFrontend(storage_factory, profile); 174 return new SettingsFrontend(storage_factory, profile);
194 } 175 }
195 176
196 SettingsFrontend::SettingsFrontend( 177 SettingsFrontend::SettingsFrontend(
197 SettingsStorageFactory* storage_factory, Profile* profile) 178 const scoped_refptr<SettingsStorageFactory>& factory, Profile* profile)
198 : profile_(profile), 179 : profile_(profile),
199 observers_(new SettingsObserverList()), 180 observers_(new SettingsObserverList()),
200 default_observer_(profile), 181 profile_observer_(new DefaultObserver(profile)) {
201 core_(new SettingsFrontend::Core(storage_factory, observers_)) {
202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
203 DCHECK(!profile->IsOffTheRecord()); 183 DCHECK(!profile->IsOffTheRecord());
204 184
205 observers_->AddObserver(&default_observer_); 185 observers_->AddObserver(profile_observer_.get());
206 186
207 BrowserThread::PostTask( 187 const FilePath& profile_path = profile->GetPath();
208 BrowserThread::FILE, 188 backends_[settings_namespace::LOCAL].app =
209 FROM_HERE, 189 BackendWrapper::CreateAndInit(
210 base::Bind( 190 factory,
211 &SettingsFrontend::Core::InitOnFileThread, 191 observers_,
212 core_.get(), 192 profile_path.AppendASCII(
213 profile->GetPath())); 193 ExtensionService::kLocalAppSettingsDirectoryName));
194 backends_[settings_namespace::LOCAL].extension =
195 BackendWrapper::CreateAndInit(
196 factory,
197 observers_,
198 profile_path.AppendASCII(
199 ExtensionService::kLocalExtensionSettingsDirectoryName));
200 backends_[settings_namespace::SYNC].app =
201 BackendWrapper::CreateAndInit(
202 factory,
203 observers_,
204 profile_path.AppendASCII(
205 ExtensionService::kSyncAppSettingsDirectoryName));
206 backends_[settings_namespace::SYNC].extension =
207 BackendWrapper::CreateAndInit(
208 factory,
209 observers_,
210 profile_path.AppendASCII(
211 ExtensionService::kSyncExtensionSettingsDirectoryName));
214 } 212 }
215 213
216 SettingsFrontend::~SettingsFrontend() { 214 SettingsFrontend::~SettingsFrontend() {
217 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
218 observers_->RemoveObserver(&default_observer_); 216 observers_->RemoveObserver(profile_observer_.get());
219 } 217 }
220 218
221 void SettingsFrontend::RunWithSyncableService( 219 void SettingsFrontend::RunWithSyncableService(
222 syncable::ModelType model_type, const SyncableServiceCallback& callback) { 220 syncable::ModelType model_type, const SyncableServiceCallback& callback) {
223 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
222 scoped_refptr<BackendWrapper> backend;
224 switch (model_type) { 223 switch (model_type) {
224 case syncable::APP_SETTINGS:
225 backend = backends_[settings_namespace::SYNC].app;
226 break;
227
225 case syncable::EXTENSION_SETTINGS: 228 case syncable::EXTENSION_SETTINGS:
226 core_->RunWithBackends( 229 backend = backends_[settings_namespace::SYNC].extension;
227 base::Bind(&CallbackWithExtensionsBackend, callback));
228 break; 230 break;
229 case syncable::APP_SETTINGS: 231
230 core_->RunWithBackends(
231 base::Bind(&CallbackWithAppsBackend, callback));
232 break;
233 default: 232 default:
234 NOTREACHED(); 233 NOTREACHED();
235 } 234 }
235 backend->RunWithBackend(base::Bind(&CallbackWithSyncableService, callback));
236 } 236 }
237 237
238 void SettingsFrontend::RunWithStorage( 238 void SettingsFrontend::RunWithStorage(
239 const std::string& extension_id, 239 const std::string& extension_id,
240 settings_namespace::Namespace settings_namespace,
240 const StorageCallback& callback) { 241 const StorageCallback& callback) {
241 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 242 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
242 243
243 const Extension* extension = 244 const Extension* extension =
244 profile_->GetExtensionService()->GetExtensionById(extension_id, true); 245 profile_->GetExtensionService()->GetExtensionById(extension_id, true);
245 if (!extension) { 246 if (!extension) {
246 BrowserThread::PostTask( 247 BrowserThread::PostTask(
247 BrowserThread::FILE, 248 BrowserThread::FILE,
248 FROM_HERE, 249 FROM_HERE,
249 base::Bind(&CallbackWithNullStorage, callback)); 250 base::Bind(&CallbackWithNullStorage, callback));
250 return; 251 return;
251 } 252 }
252 253
254 scoped_refptr<BackendWrapper> backend;
253 if (extension->is_app()) { 255 if (extension->is_app()) {
254 core_->RunWithBackends( 256 backend = backends_[settings_namespace].app;
255 base::Bind(&CallbackWithAppsStorage, extension_id, callback));
256 } else { 257 } else {
257 core_->RunWithBackends( 258 backend = backends_[settings_namespace].extension;
258 base::Bind(&CallbackWithExtensionsStorage, extension_id, callback));
259 } 259 }
260 backend->RunWithBackend(
261 base::Bind(&CallbackWithStorage, extension_id, callback));
260 } 262 }
261 263
262 void SettingsFrontend::DeleteStorageSoon( 264 void SettingsFrontend::DeleteStorageSoon(
263 const std::string& extension_id) { 265 const std::string& extension_id) {
264 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 266 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
265 core_->RunWithBackends(base::Bind(&DeleteStorageOnFileThread, extension_id)); 267 SettingsFrontend::BackendWrapper::BackendCallback callback =
268 base::Bind(&DeleteStorageOnFileThread, extension_id);
269 for (std::map<settings_namespace::Namespace, BackendWrappers>::iterator it =
270 backends_.begin(); it != backends_.end(); ++it) {
271 it->second.app->RunWithBackend(callback);
272 it->second.extension->RunWithBackend(callback);
273 }
266 } 274 }
267 275
268 scoped_refptr<SettingsObserverList> 276 scoped_refptr<SettingsObserverList> SettingsFrontend::GetObservers() {
269 SettingsFrontend::GetObservers() {
270 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 277 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
271 return observers_; 278 return observers_;
272 } 279 }
273 280
281 // BackendWrappers
282
283 SettingsFrontend::BackendWrappers::BackendWrappers() {}
284 SettingsFrontend::BackendWrappers::~BackendWrappers() {}
285
274 } // namespace extensions 286 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698