Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / extensions / browser / api / storage / storage_frontend.cc
1 // Copyright 2014 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 "extensions/browser/api/storage/storage_frontend.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/files/file_path.h"
10 #include "base/json/json_reader.h"
11 #include "base/lazy_instance.h"
12 #include "content/public/browser/browser_context.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "extensions/browser/api/extensions_api_client.h"
15 #include "extensions/browser/api/storage/leveldb_settings_storage_factory.h"
16 #include "extensions/browser/api/storage/local_value_store_cache.h"
17 #include "extensions/browser/event_router.h"
18 #include "extensions/browser/extension_registry.h"
19 #include "extensions/common/api/storage.h"
20
21 using content::BrowserContext;
22 using content::BrowserThread;
23
24 namespace extensions {
25
26 namespace {
27
28 base::LazyInstance<BrowserContextKeyedAPIFactory<StorageFrontend> > g_factory =
29     LAZY_INSTANCE_INITIALIZER;
30
31 // Settings change Observer which forwards changes on to the extension
32 // processes for |context| and its incognito partner if it exists.
33 class DefaultObserver : public SettingsObserver {
34  public:
35   explicit DefaultObserver(BrowserContext* context)
36       : browser_context_(context) {}
37
38   // SettingsObserver implementation.
39   void OnSettingsChanged(const std::string& extension_id,
40                          settings_namespace::Namespace settings_namespace,
41                          const std::string& change_json) override {
42     // TODO(gdk): This is a temporary hack while the refactoring for
43     // string-based event payloads is removed. http://crbug.com/136045
44     scoped_ptr<base::ListValue> args(new base::ListValue());
45     args->Append(base::JSONReader::Read(change_json));
46     args->Append(new base::StringValue(settings_namespace::ToString(
47         settings_namespace)));
48     scoped_ptr<Event> event(new Event(
49         core_api::storage::OnChanged::kEventName, args.Pass()));
50     EventRouter::Get(browser_context_)
51         ->DispatchEventToExtension(extension_id, event.Pass());
52   }
53
54  private:
55   BrowserContext* const browser_context_;
56 };
57
58 }  // namespace
59
60 // static
61 StorageFrontend* StorageFrontend::Get(BrowserContext* context) {
62   return BrowserContextKeyedAPIFactory<StorageFrontend>::Get(context);
63 }
64
65 // static
66 StorageFrontend* StorageFrontend::CreateForTesting(
67     const scoped_refptr<SettingsStorageFactory>& storage_factory,
68     BrowserContext* context) {
69   return new StorageFrontend(storage_factory, context);
70 }
71
72 StorageFrontend::StorageFrontend(BrowserContext* context)
73     : browser_context_(context) {
74   Init(new LeveldbSettingsStorageFactory());
75 }
76
77 StorageFrontend::StorageFrontend(
78     const scoped_refptr<SettingsStorageFactory>& factory,
79     BrowserContext* context)
80     : browser_context_(context) {
81   Init(factory);
82 }
83
84 void StorageFrontend::Init(
85     const scoped_refptr<SettingsStorageFactory>& factory) {
86   observers_ = new SettingsObserverList();
87   browser_context_observer_.reset(new DefaultObserver(browser_context_));
88   DCHECK_CURRENTLY_ON(BrowserThread::UI);
89   DCHECK(!browser_context_->IsOffTheRecord());
90
91   observers_->AddObserver(browser_context_observer_.get());
92
93   caches_[settings_namespace::LOCAL] =
94       new LocalValueStoreCache(factory, browser_context_->GetPath());
95
96   // Add any additional caches the embedder supports (for example, caches
97   // for chrome.storage.managed and chrome.storage.sync).
98   ExtensionsAPIClient::Get()->AddAdditionalValueStoreCaches(
99       browser_context_, factory, observers_, &caches_);
100 }
101
102 StorageFrontend::~StorageFrontend() {
103   DCHECK_CURRENTLY_ON(BrowserThread::UI);
104   observers_->RemoveObserver(browser_context_observer_.get());
105   for (CacheMap::iterator it = caches_.begin(); it != caches_.end(); ++it) {
106     ValueStoreCache* cache = it->second;
107     cache->ShutdownOnUI();
108     BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, cache);
109   }
110 }
111
112 ValueStoreCache* StorageFrontend::GetValueStoreCache(
113     settings_namespace::Namespace settings_namespace) const {
114   CacheMap::const_iterator it = caches_.find(settings_namespace);
115   if (it != caches_.end())
116     return it->second;
117   return NULL;
118 }
119
120 bool StorageFrontend::IsStorageEnabled(
121     settings_namespace::Namespace settings_namespace) const {
122   return caches_.find(settings_namespace) != caches_.end();
123 }
124
125 void StorageFrontend::RunWithStorage(
126     scoped_refptr<const Extension> extension,
127     settings_namespace::Namespace settings_namespace,
128     const ValueStoreCache::StorageCallback& callback) {
129   DCHECK_CURRENTLY_ON(BrowserThread::UI);
130   CHECK(extension.get());
131
132   ValueStoreCache* cache = caches_[settings_namespace];
133   CHECK(cache);
134
135   BrowserThread::PostTask(
136       BrowserThread::FILE, FROM_HERE,
137       base::Bind(&ValueStoreCache::RunWithValueStoreForExtension,
138                  base::Unretained(cache), callback, extension));
139 }
140
141 void StorageFrontend::DeleteStorageSoon(const std::string& extension_id) {
142   DCHECK_CURRENTLY_ON(BrowserThread::UI);
143   for (CacheMap::iterator it = caches_.begin(); it != caches_.end(); ++it) {
144     ValueStoreCache* cache = it->second;
145     BrowserThread::PostTask(
146         BrowserThread::FILE, FROM_HERE,
147         base::Bind(&ValueStoreCache::DeleteStorageSoon,
148                    base::Unretained(cache),
149                    extension_id));
150   }
151 }
152
153 scoped_refptr<SettingsObserverList> StorageFrontend::GetObservers() {
154   DCHECK_CURRENTLY_ON(BrowserThread::UI);
155   return observers_;
156 }
157
158 void StorageFrontend::DisableStorageForTesting(
159     settings_namespace::Namespace settings_namespace) {
160   CacheMap::iterator it = caches_.find(settings_namespace);
161   if (it != caches_.end()) {
162     ValueStoreCache* cache = it->second;
163     cache->ShutdownOnUI();
164     BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, cache);
165     caches_.erase(it);
166   }
167 }
168
169 // BrowserContextKeyedAPI implementation.
170
171 // static
172 BrowserContextKeyedAPIFactory<StorageFrontend>*
173 StorageFrontend::GetFactoryInstance() {
174   return g_factory.Pointer();
175 }
176
177 // static
178 const char* StorageFrontend::service_name() { return "StorageFrontend"; }
179
180 }  // namespace extensions