Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / extensions / browser / api / storage / storage_frontend.cc
blobbc3687c7ccd46aee7d0d430ea0e64d87cebb96de
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.
5 #include "extensions/browser/api/storage/storage_frontend.h"
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 "base/metrics/histogram_macros.h"
13 #include "base/trace_event/trace_event.h"
14 #include "content/public/browser/browser_context.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "extensions/browser/api/extensions_api_client.h"
17 #include "extensions/browser/api/storage/leveldb_settings_storage_factory.h"
18 #include "extensions/browser/api/storage/local_value_store_cache.h"
19 #include "extensions/browser/event_router.h"
20 #include "extensions/browser/extension_registry.h"
21 #include "extensions/common/api/storage.h"
23 using content::BrowserContext;
24 using content::BrowserThread;
26 namespace extensions {
28 namespace {
30 base::LazyInstance<BrowserContextKeyedAPIFactory<StorageFrontend> > g_factory =
31 LAZY_INSTANCE_INITIALIZER;
33 // Settings change Observer which forwards changes on to the extension
34 // processes for |context| and its incognito partner if it exists.
35 class DefaultObserver : public SettingsObserver {
36 public:
37 explicit DefaultObserver(BrowserContext* context)
38 : browser_context_(context) {}
40 // SettingsObserver implementation.
41 void OnSettingsChanged(const std::string& extension_id,
42 settings_namespace::Namespace settings_namespace,
43 const std::string& change_json) override {
44 // TODO(gdk): This is a temporary hack while the refactoring for
45 // string-based event payloads is removed. http://crbug.com/136045
46 scoped_ptr<base::ListValue> args(new base::ListValue());
47 args->Append(base::JSONReader::Read(change_json));
48 args->Append(new base::StringValue(settings_namespace::ToString(
49 settings_namespace)));
50 scoped_ptr<Event> event(new Event(events::STORAGE_ON_CHANGED,
51 api::storage::OnChanged::kEventName,
52 args.Pass()));
53 EventRouter::Get(browser_context_)
54 ->DispatchEventToExtension(extension_id, event.Pass());
57 private:
58 BrowserContext* const browser_context_;
61 } // namespace
63 // static
64 StorageFrontend* StorageFrontend::Get(BrowserContext* context) {
65 return BrowserContextKeyedAPIFactory<StorageFrontend>::Get(context);
68 // static
69 scoped_ptr<StorageFrontend> StorageFrontend::CreateForTesting(
70 const scoped_refptr<SettingsStorageFactory>& storage_factory,
71 BrowserContext* context) {
72 return make_scoped_ptr(new StorageFrontend(storage_factory, context));
75 StorageFrontend::StorageFrontend(BrowserContext* context)
76 : browser_context_(context) {
77 Init(new LeveldbSettingsStorageFactory());
80 StorageFrontend::StorageFrontend(
81 const scoped_refptr<SettingsStorageFactory>& factory,
82 BrowserContext* context)
83 : browser_context_(context) {
84 Init(factory);
87 void StorageFrontend::Init(
88 const scoped_refptr<SettingsStorageFactory>& factory) {
89 TRACE_EVENT0("browser,startup", "StorageFrontend::Init")
90 SCOPED_UMA_HISTOGRAM_TIMER("Extensions.StorageFrontendInitTime");
92 observers_ = new SettingsObserverList();
93 browser_context_observer_.reset(new DefaultObserver(browser_context_));
94 DCHECK_CURRENTLY_ON(BrowserThread::UI);
95 DCHECK(!browser_context_->IsOffTheRecord());
97 observers_->AddObserver(browser_context_observer_.get());
99 caches_[settings_namespace::LOCAL] =
100 new LocalValueStoreCache(factory, browser_context_->GetPath());
102 // Add any additional caches the embedder supports (for example, caches
103 // for chrome.storage.managed and chrome.storage.sync).
104 ExtensionsAPIClient::Get()->AddAdditionalValueStoreCaches(
105 browser_context_, factory, observers_, &caches_);
108 StorageFrontend::~StorageFrontend() {
109 DCHECK_CURRENTLY_ON(BrowserThread::UI);
110 observers_->RemoveObserver(browser_context_observer_.get());
111 for (CacheMap::iterator it = caches_.begin(); it != caches_.end(); ++it) {
112 ValueStoreCache* cache = it->second;
113 cache->ShutdownOnUI();
114 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, cache);
118 ValueStoreCache* StorageFrontend::GetValueStoreCache(
119 settings_namespace::Namespace settings_namespace) const {
120 CacheMap::const_iterator it = caches_.find(settings_namespace);
121 if (it != caches_.end())
122 return it->second;
123 return NULL;
126 bool StorageFrontend::IsStorageEnabled(
127 settings_namespace::Namespace settings_namespace) const {
128 return caches_.find(settings_namespace) != caches_.end();
131 void StorageFrontend::RunWithStorage(
132 scoped_refptr<const Extension> extension,
133 settings_namespace::Namespace settings_namespace,
134 const ValueStoreCache::StorageCallback& callback) {
135 DCHECK_CURRENTLY_ON(BrowserThread::UI);
136 CHECK(extension.get());
138 ValueStoreCache* cache = caches_[settings_namespace];
139 CHECK(cache);
141 BrowserThread::PostTask(
142 BrowserThread::FILE, FROM_HERE,
143 base::Bind(&ValueStoreCache::RunWithValueStoreForExtension,
144 base::Unretained(cache), callback, extension));
147 void StorageFrontend::DeleteStorageSoon(const std::string& extension_id) {
148 DCHECK_CURRENTLY_ON(BrowserThread::UI);
149 for (CacheMap::iterator it = caches_.begin(); it != caches_.end(); ++it) {
150 ValueStoreCache* cache = it->second;
151 BrowserThread::PostTask(
152 BrowserThread::FILE, FROM_HERE,
153 base::Bind(&ValueStoreCache::DeleteStorageSoon,
154 base::Unretained(cache),
155 extension_id));
159 scoped_refptr<SettingsObserverList> StorageFrontend::GetObservers() {
160 DCHECK_CURRENTLY_ON(BrowserThread::UI);
161 return observers_;
164 void StorageFrontend::DisableStorageForTesting(
165 settings_namespace::Namespace settings_namespace) {
166 CacheMap::iterator it = caches_.find(settings_namespace);
167 if (it != caches_.end()) {
168 ValueStoreCache* cache = it->second;
169 cache->ShutdownOnUI();
170 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, cache);
171 caches_.erase(it);
175 // BrowserContextKeyedAPI implementation.
177 // static
178 BrowserContextKeyedAPIFactory<StorageFrontend>*
179 StorageFrontend::GetFactoryInstance() {
180 return g_factory.Pointer();
183 // static
184 const char* StorageFrontend::service_name() { return "StorageFrontend"; }
186 } // namespace extensions