- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / storage / settings_frontend.cc
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/extensions/api/storage/settings_frontend.h"
6
7 #include <limits>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/files/file_path.h"
12 #include "base/json/json_reader.h"
13 #include "chrome/browser/extensions/api/storage/leveldb_settings_storage_factory.h"
14 #include "chrome/browser/extensions/api/storage/settings_backend.h"
15 #include "chrome/browser/extensions/api/storage/sync_or_local_value_store_cache.h"
16 #include "chrome/browser/extensions/event_names.h"
17 #include "chrome/browser/extensions/event_router.h"
18 #include "chrome/browser/extensions/extension_service.h"
19 #include "chrome/browser/extensions/extension_system.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/common/extensions/api/storage.h"
22 #include "content/public/browser/browser_thread.h"
23
24 #if defined(ENABLE_CONFIGURATION_POLICY)
25 #include "chrome/browser/extensions/api/storage/managed_value_store_cache.h"
26 #endif
27
28 using content::BrowserThread;
29
30 namespace extensions {
31
32 namespace storage = api::storage;
33
34 namespace {
35
36 // Settings change Observer which forwards changes on to the extension
37 // processes for |profile| and its incognito partner if it exists.
38 class DefaultObserver : public SettingsObserver {
39  public:
40   explicit DefaultObserver(Profile* profile) : profile_(profile) {}
41
42   // SettingsObserver implementation.
43   virtual void OnSettingsChanged(
44       const std::string& extension_id,
45       settings_namespace::Namespace settings_namespace,
46       const std::string& change_json) OVERRIDE {
47     // TODO(gdk): This is a temporary hack while the refactoring for
48     // string-based event payloads is removed. http://crbug.com/136045
49     scoped_ptr<base::ListValue> args(new base::ListValue());
50     args->Append(base::JSONReader::Read(change_json));
51     args->Append(new base::StringValue(settings_namespace::ToString(
52         settings_namespace)));
53     scoped_ptr<Event> event(new Event(
54         storage::OnChanged::kEventName, args.Pass()));
55     ExtensionSystem::Get(profile_)->event_router()->
56         DispatchEventToExtension(extension_id, event.Pass());
57   }
58
59  private:
60   Profile* const profile_;
61 };
62
63 SettingsStorageQuotaEnforcer::Limits GetLocalLimits() {
64   SettingsStorageQuotaEnforcer::Limits limits = {
65     static_cast<size_t>(api::storage::local::QUOTA_BYTES),
66     std::numeric_limits<size_t>::max(),
67     std::numeric_limits<size_t>::max()
68   };
69   return limits;
70 }
71
72 SettingsStorageQuotaEnforcer::Limits GetSyncLimits() {
73   SettingsStorageQuotaEnforcer::Limits limits = {
74     static_cast<size_t>(api::storage::sync::QUOTA_BYTES),
75     static_cast<size_t>(api::storage::sync::QUOTA_BYTES_PER_ITEM),
76     static_cast<size_t>(api::storage::sync::MAX_ITEMS)
77   };
78   return limits;
79 }
80
81 }  // namespace
82
83 // static
84 SettingsFrontend* SettingsFrontend::Create(Profile* profile) {
85   return new SettingsFrontend(new LeveldbSettingsStorageFactory(), profile);
86 }
87
88 // static
89 SettingsFrontend* SettingsFrontend::Create(
90     const scoped_refptr<SettingsStorageFactory>& storage_factory,
91     Profile* profile) {
92   return new SettingsFrontend(storage_factory, profile);
93 }
94
95 SettingsFrontend::SettingsFrontend(
96     const scoped_refptr<SettingsStorageFactory>& factory, Profile* profile)
97     : local_quota_limit_(GetLocalLimits()),
98       sync_quota_limit_(GetSyncLimits()),
99       profile_(profile),
100       observers_(new SettingsObserverList()),
101       profile_observer_(new DefaultObserver(profile)) {
102   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
103   DCHECK(!profile->IsOffTheRecord());
104
105   observers_->AddObserver(profile_observer_.get());
106
107   const base::FilePath& profile_path = profile->GetPath();
108   caches_[settings_namespace::LOCAL] =
109       new SyncOrLocalValueStoreCache(
110           settings_namespace::LOCAL,
111           factory,
112           local_quota_limit_,
113           observers_,
114           profile_path);
115   caches_[settings_namespace::SYNC] =
116       new SyncOrLocalValueStoreCache(
117           settings_namespace::SYNC,
118           factory,
119           sync_quota_limit_,
120           observers_,
121           profile_path);
122
123 #if defined(ENABLE_CONFIGURATION_POLICY)
124   caches_[settings_namespace::MANAGED] =
125       new ManagedValueStoreCache(
126           profile,
127           factory,
128           observers_);
129 #endif
130 }
131
132 SettingsFrontend::~SettingsFrontend() {
133   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
134   observers_->RemoveObserver(profile_observer_.get());
135   for (CacheMap::iterator it = caches_.begin(); it != caches_.end(); ++it) {
136     ValueStoreCache* cache = it->second;
137     cache->ShutdownOnUI();
138     BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, cache);
139   }
140 }
141
142 syncer::SyncableService* SettingsFrontend::GetBackendForSync(
143     syncer::ModelType type) const {
144   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
145   CacheMap::const_iterator it = caches_.find(settings_namespace::SYNC);
146   DCHECK(it != caches_.end());
147   const SyncOrLocalValueStoreCache* sync_cache =
148       static_cast<const SyncOrLocalValueStoreCache*>(it->second);
149   switch (type) {
150     case syncer::APP_SETTINGS:
151       return sync_cache->GetAppBackend();
152     case syncer::EXTENSION_SETTINGS:
153       return sync_cache->GetExtensionBackend();
154     default:
155       NOTREACHED();
156       return NULL;
157   }
158 }
159
160 bool SettingsFrontend::IsStorageEnabled(
161     settings_namespace::Namespace settings_namespace) const {
162   return caches_.find(settings_namespace) != caches_.end();
163 }
164
165 void SettingsFrontend::RunWithStorage(
166     const std::string& extension_id,
167     settings_namespace::Namespace settings_namespace,
168     const ValueStoreCache::StorageCallback& callback) {
169   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
170
171   ValueStoreCache* cache = caches_[settings_namespace];
172   CHECK(cache);
173
174   // The |extension| has already been referenced earlier in the stack, so it
175   // can't be gone here.
176   // TODO(kalman): change RunWithStorage() to take a
177   // scoped_refptr<const Extension> instead.
178   scoped_refptr<const Extension> extension =
179       extensions::ExtensionSystem::Get(profile_)->extension_service()->
180           GetExtensionById(extension_id, true);
181   CHECK(extension.get());
182
183   BrowserThread::PostTask(
184       BrowserThread::FILE, FROM_HERE,
185       base::Bind(&ValueStoreCache::RunWithValueStoreForExtension,
186                  base::Unretained(cache), callback, extension));
187 }
188
189 void SettingsFrontend::DeleteStorageSoon(
190     const std::string& extension_id) {
191   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
192   for (CacheMap::iterator it = caches_.begin(); it != caches_.end(); ++it) {
193     ValueStoreCache* cache = it->second;
194     BrowserThread::PostTask(
195         BrowserThread::FILE, FROM_HERE,
196         base::Bind(&ValueStoreCache::DeleteStorageSoon,
197                    base::Unretained(cache),
198                    extension_id));
199   }
200 }
201
202 scoped_refptr<SettingsObserverList> SettingsFrontend::GetObservers() {
203   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
204   return observers_;
205 }
206
207 void SettingsFrontend::DisableStorageForTesting(
208     settings_namespace::Namespace settings_namespace) {
209   CacheMap::iterator it = caches_.find(settings_namespace);
210   if (it != caches_.end()) {
211     ValueStoreCache* cache = it->second;
212     cache->ShutdownOnUI();
213     BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, cache);
214     caches_.erase(it);
215   }
216 }
217
218 }  // namespace extensions