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