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

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

Issue 10784035: Refactored SettingsFrontend and forwarding of calls to the backends. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added comment Created 8 years, 5 months 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 <limits>
8
7 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
8 #include "base/file_path.h" 11 #include "base/file_path.h"
9 #include "base/string_number_conversions.h"
10 #include "chrome/browser/extensions/extension_event_names.h" 12 #include "chrome/browser/extensions/extension_event_names.h"
11 #include "chrome/browser/extensions/extension_event_router.h" 13 #include "chrome/browser/extensions/extension_event_router.h"
12 #include "chrome/browser/extensions/extension_service.h" 14 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/extensions/settings/leveldb_settings_storage_factory.h" 15 #include "chrome/browser/extensions/settings/leveldb_settings_storage_factory.h"
16 #include "chrome/browser/extensions/settings/managed_value_store_cache.h"
14 #include "chrome/browser/extensions/settings/settings_backend.h" 17 #include "chrome/browser/extensions/settings/settings_backend.h"
15 #include "chrome/browser/extensions/settings/settings_namespace.h" 18 #include "chrome/browser/extensions/settings/sync_or_local_value_store_cache.h"
16 #include "chrome/browser/extensions/settings/weak_unlimited_settings_storage.h"
17 #include "chrome/browser/profiles/profile.h" 19 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/value_store/leveldb_value_store.h"
19 #include "chrome/common/extensions/api/storage.h" 20 #include "chrome/common/extensions/api/storage.h"
20 #include "content/public/browser/browser_thread.h" 21 #include "content/public/browser/browser_thread.h"
21 #include "content/public/browser/notification_service.h"
22 22
23 using content::BrowserThread; 23 using content::BrowserThread;
24 24
25 namespace extensions { 25 namespace extensions {
26 26
27 namespace { 27 namespace {
28 28
29 // Settings change Observer which forwards changes on to the extension 29 // Settings change Observer which forwards changes on to the extension
30 // processes for |profile| and its incognito partner if it exists. 30 // processes for |profile| and its incognito partner if it exists.
31 class DefaultObserver : public SettingsObserver { 31 class DefaultObserver : public SettingsObserver {
(...skipping 13 matching lines...) Expand all
45 std::string("[") + change_json + ",\"" + 45 std::string("[") + change_json + ",\"" +
46 settings_namespace::ToString(settings_namespace) + "\"]", 46 settings_namespace::ToString(settings_namespace) + "\"]",
47 NULL, 47 NULL,
48 GURL()); 48 GURL());
49 } 49 }
50 50
51 private: 51 private:
52 Profile* const profile_; 52 Profile* const profile_;
53 }; 53 };
54 54
55 void CallbackWithSyncableService(
56 const SettingsFrontend::SyncableServiceCallback& callback,
57 SettingsBackend* backend) {
58 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
59 callback.Run(backend);
60 }
61
62 void CallbackWithStorage(
63 const std::string& extension_id,
64 const SettingsFrontend::StorageCallback& callback,
65 SettingsBackend* backend) {
66 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
67 callback.Run(backend->GetStorage(extension_id));
68 }
69
70 void CallbackWithNullStorage(
71 const SettingsFrontend::StorageCallback& callback) {
72 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
73 callback.Run(NULL);
74 }
75
76 void DeleteStorageOnFileThread(
77 const std::string& extension_id, SettingsBackend* backend) {
78 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
79 backend->DeleteStorage(extension_id);
80 }
81
82 void CallbackWithUnlimitedStorage(
83 const std::string& extension_id,
84 const SettingsFrontend::StorageCallback& callback,
85 SettingsBackend* backend) {
86 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
87 WeakUnlimitedSettingsStorage unlimited_storage(
88 backend->GetStorage(extension_id));
89 callback.Run(&unlimited_storage);
90 }
91
92 SettingsStorageQuotaEnforcer::Limits GetLocalLimits() { 55 SettingsStorageQuotaEnforcer::Limits GetLocalLimits() {
93 SettingsStorageQuotaEnforcer::Limits limits = { 56 SettingsStorageQuotaEnforcer::Limits limits = {
94 static_cast<size_t>(api::storage::local::QUOTA_BYTES), 57 static_cast<size_t>(api::storage::local::QUOTA_BYTES),
95 std::numeric_limits<size_t>::max(), 58 std::numeric_limits<size_t>::max(),
96 std::numeric_limits<size_t>::max() 59 std::numeric_limits<size_t>::max()
97 }; 60 };
98 return limits; 61 return limits;
99 } 62 }
100 63
101 SettingsStorageQuotaEnforcer::Limits GetSyncLimits() { 64 SettingsStorageQuotaEnforcer::Limits GetSyncLimits() {
102 SettingsStorageQuotaEnforcer::Limits limits = { 65 SettingsStorageQuotaEnforcer::Limits limits = {
103 static_cast<size_t>(api::storage::sync::QUOTA_BYTES), 66 static_cast<size_t>(api::storage::sync::QUOTA_BYTES),
104 static_cast<size_t>(api::storage::sync::QUOTA_BYTES_PER_ITEM), 67 static_cast<size_t>(api::storage::sync::QUOTA_BYTES_PER_ITEM),
105 static_cast<size_t>(api::storage::sync::MAX_ITEMS) 68 static_cast<size_t>(api::storage::sync::MAX_ITEMS)
106 }; 69 };
107 return limits; 70 return limits;
108 } 71 }
109 72
110 } // namespace 73 } // namespace
111 74
112 // Ref-counted container for a SettingsBackend object.
113 class SettingsFrontend::BackendWrapper
114 : public base::RefCountedThreadSafe<BackendWrapper> {
115 public:
116 // Creates a new BackendWrapper and initializes it on the FILE thread.
117 static scoped_refptr<BackendWrapper> CreateAndInit(
118 const scoped_refptr<SettingsStorageFactory>& factory,
119 const SettingsStorageQuotaEnforcer::Limits& quota,
120 const scoped_refptr<SettingsObserverList>& observers,
121 const FilePath& path) {
122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
123 scoped_refptr<BackendWrapper> backend_wrapper =
124 new BackendWrapper(factory, quota, observers);
125 BrowserThread::PostTask(
126 BrowserThread::FILE,
127 FROM_HERE,
128 base::Bind(
129 &SettingsFrontend::BackendWrapper::InitOnFileThread,
130 backend_wrapper,
131 path));
132 return backend_wrapper;
133 }
134
135 typedef base::Callback<void(SettingsBackend*)> BackendCallback;
136
137 // Runs |callback| with the wrapped Backend on the FILE thread.
138 void RunWithBackend(const BackendCallback& callback) {
139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
140 BrowserThread::PostTask(
141 BrowserThread::FILE,
142 FROM_HERE,
143 base::Bind(
144 &SettingsFrontend::BackendWrapper::RunWithBackendOnFileThread,
145 this,
146 callback));
147 }
148
149 SettingsBackend* GetBackend() const {
150 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
151 return backend_;
152 }
153
154 private:
155 friend class base::RefCountedThreadSafe<BackendWrapper>;
156
157 BackendWrapper(
158 const scoped_refptr<SettingsStorageFactory>& storage_factory,
159 const SettingsStorageQuotaEnforcer::Limits& quota,
160 const scoped_refptr<SettingsObserverList>& observers)
161 : storage_factory_(storage_factory),
162 quota_(quota),
163 observers_(observers),
164 backend_(NULL) {
165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
166 }
167
168 virtual ~BackendWrapper() {
169 if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
170 delete backend_;
171 } else if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
172 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, backend_);
173 } else {
174 NOTREACHED();
175 }
176 }
177
178 void InitOnFileThread(const FilePath& path) {
179 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
180 DCHECK(!backend_);
181 backend_ = new SettingsBackend(storage_factory_, path, quota_, observers_);
182 storage_factory_ = NULL;
183 observers_ = NULL;
184 }
185
186 void RunWithBackendOnFileThread(const BackendCallback& callback) {
187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
188 DCHECK(backend_);
189 callback.Run(backend_);
190 }
191
192 // Only need these until |backend_| exists.
193 scoped_refptr<SettingsStorageFactory> storage_factory_;
194 const SettingsStorageQuotaEnforcer::Limits quota_;
195 scoped_refptr<SettingsObserverList> observers_;
196
197 // Wrapped Backend. Used exclusively on the FILE thread, and is created on
198 // the FILE thread in InitOnFileThread.
199 SettingsBackend* backend_;
200
201 DISALLOW_COPY_AND_ASSIGN(BackendWrapper);
202 };
203
204 // SettingsFrontend
205
206 // static 75 // static
207 SettingsFrontend* SettingsFrontend::Create(Profile* profile) { 76 SettingsFrontend* SettingsFrontend::Create(Profile* profile) {
208 return new SettingsFrontend(new LeveldbSettingsStorageFactory(), profile); 77 return new SettingsFrontend(new LeveldbSettingsStorageFactory(), profile);
209 } 78 }
210 79
211 // static 80 // static
212 SettingsFrontend* SettingsFrontend::Create( 81 SettingsFrontend* SettingsFrontend::Create(
213 const scoped_refptr<SettingsStorageFactory>& storage_factory, 82 const scoped_refptr<SettingsStorageFactory>& storage_factory,
214 Profile* profile) { 83 Profile* profile) {
215 return new SettingsFrontend(storage_factory, profile); 84 return new SettingsFrontend(storage_factory, profile);
216 } 85 }
217 86
218 SettingsFrontend::SettingsFrontend( 87 SettingsFrontend::SettingsFrontend(
219 const scoped_refptr<SettingsStorageFactory>& factory, Profile* profile) 88 const scoped_refptr<SettingsStorageFactory>& factory, Profile* profile)
220 : local_quota_limit_(GetLocalLimits()), 89 : local_quota_limit_(GetLocalLimits()),
221 sync_quota_limit_(GetSyncLimits()), 90 sync_quota_limit_(GetSyncLimits()),
222 profile_(profile), 91 profile_(profile),
223 observers_(new SettingsObserverList()), 92 observers_(new SettingsObserverList()),
224 profile_observer_(new DefaultObserver(profile)) { 93 profile_observer_(new DefaultObserver(profile)) {
225 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 94 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
226 DCHECK(!profile->IsOffTheRecord()); 95 DCHECK(!profile->IsOffTheRecord());
227 96
228 observers_->AddObserver(profile_observer_.get()); 97 observers_->AddObserver(profile_observer_.get());
229 98
230 const FilePath& profile_path = profile->GetPath(); 99 const FilePath& profile_path = profile->GetPath();
231 backends_[settings_namespace::LOCAL].app = 100 caches_[settings_namespace::LOCAL] =
232 BackendWrapper::CreateAndInit( 101 new SyncOrLocalValueStoreCache(
102 settings_namespace::LOCAL,
233 factory, 103 factory,
234 local_quota_limit_, 104 local_quota_limit_,
235 observers_, 105 observers_,
236 profile_path.AppendASCII( 106 profile_path);
237 ExtensionService::kLocalAppSettingsDirectoryName)); 107 caches_[settings_namespace::SYNC] =
238 backends_[settings_namespace::LOCAL].extension = 108 new SyncOrLocalValueStoreCache(
239 BackendWrapper::CreateAndInit( 109 settings_namespace::SYNC,
240 factory,
241 local_quota_limit_,
242 observers_,
243 profile_path.AppendASCII(
244 ExtensionService::kLocalExtensionSettingsDirectoryName));
245 backends_[settings_namespace::SYNC].app =
246 BackendWrapper::CreateAndInit(
247 factory, 110 factory,
248 sync_quota_limit_, 111 sync_quota_limit_,
249 observers_, 112 observers_,
250 profile_path.AppendASCII( 113 profile_path);
251 ExtensionService::kSyncAppSettingsDirectoryName)); 114 caches_[settings_namespace::MANAGED] =
252 backends_[settings_namespace::SYNC].extension = 115 new ManagedValueStoreCache(profile->GetPolicyService());
253 BackendWrapper::CreateAndInit(
254 factory,
255 sync_quota_limit_,
256 observers_,
257 profile_path.AppendASCII(
258 ExtensionService::kSyncExtensionSettingsDirectoryName));
259 } 116 }
260 117
261 SettingsFrontend::~SettingsFrontend() { 118 SettingsFrontend::~SettingsFrontend() {
262 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
263 observers_->RemoveObserver(profile_observer_.get()); 120 observers_->RemoveObserver(profile_observer_.get());
121 // Destroy each cache in its preferred thread. The delete task will execute
122 // after any other task that might've been posted before.
123 for (CacheMap::iterator it = caches_.begin(); it != caches_.end(); ++it) {
124 ValueStoreCache* cache = it->second;
125 cache->GetMessageLoop()->DeleteSoon(FROM_HERE, cache);
126 }
264 } 127 }
265 128
266 syncer::SyncableService* SettingsFrontend::GetBackendForSync( 129 syncer::SyncableService* SettingsFrontend::GetBackendForSync(
267 syncer::ModelType type) const { 130 syncer::ModelType type) const {
268 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 131 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
269 std::map<settings_namespace::Namespace, BackendWrappers>::const_iterator 132 CacheMap::const_iterator it = caches_.find(settings_namespace::SYNC);
270 sync_backends = backends_.find(settings_namespace::SYNC); 133 DCHECK(it != caches_.end());
271 DCHECK(sync_backends != backends_.end()); 134 const SyncOrLocalValueStoreCache* sync_cache =
135 static_cast<const SyncOrLocalValueStoreCache*>(it->second);
272 switch (type) { 136 switch (type) {
273 case syncer::APP_SETTINGS: 137 case syncer::APP_SETTINGS:
274 return sync_backends->second.app->GetBackend(); 138 return sync_cache->GetAppBackend();
275 case syncer::EXTENSION_SETTINGS: 139 case syncer::EXTENSION_SETTINGS:
276 return sync_backends->second.extension->GetBackend(); 140 return sync_cache->GetExtensionBackend();
277 default: 141 default:
278 NOTREACHED(); 142 NOTREACHED();
279 return NULL; 143 return NULL;
280 } 144 }
281 } 145 }
282 146
283 void SettingsFrontend::RunWithStorage( 147 void SettingsFrontend::RunWithStorage(
284 const std::string& extension_id, 148 const std::string& extension_id,
285 settings_namespace::Namespace settings_namespace, 149 settings_namespace::Namespace settings_namespace,
286 const StorageCallback& callback) { 150 const ValueStoreCache::StorageCallback& callback) {
287 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
288 152
289 const Extension* extension = 153 ValueStoreCache* cache = caches_[settings_namespace];
154 CHECK(cache);
155
156 scoped_refptr<const Extension> extension =
290 profile_->GetExtensionService()->GetExtensionById(extension_id, true); 157 profile_->GetExtensionService()->GetExtensionById(extension_id, true);
291 if (!extension) { 158 if (!extension) {
292 BrowserThread::PostTask( 159 cache->GetMessageLoop()->PostTask(
293 BrowserThread::FILE,
294 FROM_HERE, 160 FROM_HERE,
295 base::Bind(&CallbackWithNullStorage, callback)); 161 base::Bind(callback, static_cast<ValueStore*>(NULL)));
296 return; 162 return;
297 } 163 }
298 164
299 // A neat way to implement unlimited storage; if the extension has the 165 cache->GetMessageLoop()->PostTask(
300 // unlimited storage permission, force through all calls to Set() (in the 166 FROM_HERE,
301 // same way that writes from sync ignore quota). 167 base::Bind(&ValueStoreCache::RunWithValueStoreForExtension,
302 // But only if it's local storage (bad stuff would happen if sync'ed 168 base::Unretained(cache), callback, extension));
303 // storage is allowed to be unlimited).
304 bool is_unlimited =
305 settings_namespace == settings_namespace::LOCAL &&
306 extension->HasAPIPermission(APIPermission::kUnlimitedStorage);
307
308 scoped_refptr<BackendWrapper> backend;
309 if (extension->is_app()) {
310 backend = backends_[settings_namespace].app;
311 } else {
312 backend = backends_[settings_namespace].extension;
313 }
314
315 backend->RunWithBackend(
316 base::Bind(
317 is_unlimited ?
318 &CallbackWithUnlimitedStorage : &CallbackWithStorage,
319 extension_id,
320 callback));
321 } 169 }
322 170
323 void SettingsFrontend::DeleteStorageSoon( 171 void SettingsFrontend::DeleteStorageSoon(
324 const std::string& extension_id) { 172 const std::string& extension_id) {
325 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 173 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
326 SettingsFrontend::BackendWrapper::BackendCallback callback = 174 for (CacheMap::iterator it = caches_.begin(); it != caches_.end(); ++it) {
327 base::Bind(&DeleteStorageOnFileThread, extension_id); 175 ValueStoreCache* cache = it->second;
328 for (std::map<settings_namespace::Namespace, BackendWrappers>::iterator it = 176 cache->GetMessageLoop()->PostTask(
329 backends_.begin(); it != backends_.end(); ++it) { 177 FROM_HERE,
330 it->second.app->RunWithBackend(callback); 178 base::Bind(&ValueStoreCache::DeleteStorageSoon,
331 it->second.extension->RunWithBackend(callback); 179 base::Unretained(cache),
180 extension_id));
332 } 181 }
333 } 182 }
334 183
335 scoped_refptr<SettingsObserverList> SettingsFrontend::GetObservers() { 184 scoped_refptr<SettingsObserverList> SettingsFrontend::GetObservers() {
336 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 185 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
337 return observers_; 186 return observers_;
338 } 187 }
339 188
340 // BackendWrappers
341
342 SettingsFrontend::BackendWrappers::BackendWrappers() {}
343 SettingsFrontend::BackendWrappers::~BackendWrappers() {}
344
345 } // namespace extensions 189 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698