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

Side by Side Diff: chrome/browser/extensions/api/storage/managed_value_store_cache.cc

Issue 11826048: Revert 176015 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 7 years, 11 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
(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/managed_value_store_cache.h"
6
7 #include <set>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/callback.h"
12 #include "base/file_util.h"
13 #include "base/logging.h"
14 #include "base/message_loop_proxy.h"
15 #include "chrome/browser/extensions/api/storage/policy_value_store.h"
16 #include "chrome/browser/extensions/api/storage/settings_storage_factory.h"
17 #include "chrome/browser/extensions/event_names.h"
18 #include "chrome/browser/extensions/extension_service.h"
19 #include "chrome/browser/value_store/value_store_change.h"
20 #include "chrome/common/extensions/extension.h"
21 #include "content/public/browser/browser_thread.h"
22
23 using content::BrowserThread;
24
25 namespace extensions {
26
27 ManagedValueStoreCache::ManagedValueStoreCache(
28 policy::PolicyService* policy_service,
29 EventRouter* event_router,
30 const scoped_refptr<SettingsStorageFactory>& factory,
31 const scoped_refptr<SettingsObserverList>& observers,
32 const FilePath& profile_path)
33 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
34 weak_this_on_ui_(weak_factory_.GetWeakPtr()),
35 policy_service_(policy_service),
36 event_router_(event_router),
37 storage_factory_(factory),
38 observers_(observers),
39 base_path_(profile_path.AppendASCII(
40 ExtensionService::kManagedSettingsDirectoryName)) {
41 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
42 // |event_router| can be NULL on unit_tests.
43 if (event_router_)
44 event_router_->RegisterObserver(this, event_names::kOnSettingsChanged);
45 policy_service_->AddObserver(policy::POLICY_DOMAIN_EXTENSIONS, this);
46 }
47
48 ManagedValueStoreCache::~ManagedValueStoreCache() {
49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
50 DCHECK(!event_router_);
51 // Delete the PolicyValueStores on FILE.
52 store_map_.clear();
53 }
54
55 void ManagedValueStoreCache::ShutdownOnUI() {
56 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
57 policy_service_->RemoveObserver(policy::POLICY_DOMAIN_EXTENSIONS, this);
58 policy_service_ = NULL;
59 if (event_router_)
60 event_router_->UnregisterObserver(this);
61 event_router_ = NULL;
62 weak_factory_.InvalidateWeakPtrs();
63 }
64
65 void ManagedValueStoreCache::RunWithValueStoreForExtension(
66 const StorageCallback& callback,
67 scoped_refptr<const Extension> extension) {
68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
69 PolicyValueStore* store = GetStoreFor(extension->id());
70 if (store) {
71 callback.Run(store);
72 } else {
73 // First time that an extension calls storage.managed.get(). Create the
74 // store and load it with the current policy, and don't send event
75 // notifications.
76 CreateStoreFor(
77 extension->id(),
78 false,
79 base::Bind(&ManagedValueStoreCache::RunWithValueStoreForExtension,
80 base::Unretained(this),
81 callback,
82 extension));
83 }
84 }
85
86 void ManagedValueStoreCache::DeleteStorageSoon(
87 const std::string& extension_id) {
88 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
89 PolicyValueStore* store = GetStoreFor(extension_id);
90 if (!store) {
91 // It's possible that the store exists, but hasn't been loaded yet
92 // (because the extension is unloaded, for example). Open the database to
93 // clear it if it exists.
94 // TODO(joaodasilva): move this check to a ValueStore method.
95 if (file_util::DirectoryExists(base_path_.AppendASCII(extension_id))) {
96 CreateStoreFor(
97 extension_id,
98 false,
99 base::Bind(&ManagedValueStoreCache::DeleteStorageSoon,
100 base::Unretained(this),
101 extension_id));
102 }
103 } else {
104 store->DeleteStorage();
105 store_map_.erase(extension_id);
106 }
107 }
108
109 void ManagedValueStoreCache::OnPolicyUpdated(policy::PolicyDomain domain,
110 const std::string& component_id,
111 const policy::PolicyMap& previous,
112 const policy::PolicyMap& current) {
113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
114 BrowserThread::PostTask(
115 BrowserThread::FILE, FROM_HERE,
116 base::Bind(&ManagedValueStoreCache::UpdatePolicyOnFILE,
117 base::Unretained(this),
118 std::string(component_id),
119 base::Passed(current.DeepCopy())));
120 }
121
122 void ManagedValueStoreCache::UpdatePolicyOnFILE(
123 const std::string& extension_id,
124 scoped_ptr<policy::PolicyMap> current_policy) {
125 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
126 PolicyValueStore* store = GetStoreFor(extension_id);
127 if (!store) {
128 // The extension hasn't executed any storage.managed.* calls, and isn't
129 // listening for onChanged() either. Ignore this notification in that case.
130 return;
131 }
132 // Update the policy on the backing store, and fire notifications if it
133 // changed.
134 store->SetCurrentPolicy(*current_policy, true);
135 }
136
137 void ManagedValueStoreCache::OnListenerAdded(
138 const EventListenerInfo& details) {
139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
140 DCHECK_EQ(std::string(event_names::kOnSettingsChanged), details.event_name);
141 // This is invoked on several occasions:
142 //
143 // 1. when an extension first registers to observe storage.onChanged; in this
144 // case the backend doesn't have any previous data persisted, and it won't
145 // trigger a notification.
146 //
147 // 2. when the browser starts up and all existing extensions re-register for
148 // the onChanged event. In this case, if the current policy differs from
149 // the persisted version then a notification will be sent.
150 //
151 // 3. a policy update just occurred and sent a notification, and an extension
152 // with EventPages that is observing onChanged just woke up and registed
153 // again. In this case the policy update already persisted the current
154 // policy version, and |store| already exists.
155 BrowserThread::PostTask(
156 BrowserThread::FILE, FROM_HERE,
157 base::Bind(&ManagedValueStoreCache::CreateForExtensionOnFILE,
158 base::Unretained(this),
159 details.extension_id));
160 }
161
162 void ManagedValueStoreCache::CreateForExtensionOnFILE(
163 const std::string& extension_id) {
164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
165 PolicyValueStore* store = GetStoreFor(extension_id);
166 if (!store)
167 CreateStoreFor(extension_id, true, base::Closure());
168 }
169
170 PolicyValueStore* ManagedValueStoreCache::GetStoreFor(
171 const std::string& extension_id) {
172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
173 PolicyValueStoreMap::iterator it = store_map_.find(extension_id);
174 if (it == store_map_.end())
175 return NULL;
176 return it->second.get();
177 }
178
179 void ManagedValueStoreCache::CreateStoreFor(
180 const std::string& extension_id,
181 bool notify_if_changed,
182 const base::Closure& continuation) {
183 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
184 DCHECK(!GetStoreFor(extension_id));
185 // Creating or loading an existing database requires an immediate update
186 // with the current policy for the corresponding extension, which must be
187 // retrieved on UI.
188 BrowserThread::PostTask(
189 BrowserThread::UI, FROM_HERE,
190 base::Bind(&ManagedValueStoreCache::GetInitialPolicy,
191 weak_this_on_ui_,
192 extension_id,
193 notify_if_changed,
194 continuation));
195 }
196
197 void ManagedValueStoreCache::GetInitialPolicy(
198 const std::string& extension_id,
199 bool notify_if_changed,
200 const base::Closure& continuation) {
201 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
202 const policy::PolicyMap& policy = policy_service_->GetPolicies(
203 policy::POLICY_DOMAIN_EXTENSIONS, extension_id);
204 // Now post back to FILE to create the database.
205 BrowserThread::PostTask(
206 BrowserThread::FILE, FROM_HERE,
207 base::Bind(&ManagedValueStoreCache::CreateStoreWithInitialPolicy,
208 base::Unretained(this),
209 extension_id,
210 notify_if_changed,
211 base::Passed(policy.DeepCopy()),
212 continuation));
213 }
214
215 void ManagedValueStoreCache::CreateStoreWithInitialPolicy(
216 const std::string& extension_id,
217 bool notify_if_changed,
218 scoped_ptr<policy::PolicyMap> initial_policy,
219 const base::Closure& continuation) {
220 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
221 // If a 2nd call to CreateStoreFor() is issued before the 1st gets to execute
222 // its UI task, then the 2nd will enter this function but the store has
223 // already been created. Check for that.
224 PolicyValueStore* store = GetStoreFor(extension_id);
225
226 if (!store) {
227 // Create it now.
228
229 // If the database doesn't exist yet then this is the initial install,
230 // and no notifications should be issued in that case.
231 // TODO(joaodasilva): move this check to a ValueStore method.
232 if (!file_util::DirectoryExists(base_path_.AppendASCII(extension_id)))
233 notify_if_changed = false;
234
235 store = new PolicyValueStore(
236 extension_id,
237 observers_,
238 make_scoped_ptr(storage_factory_->Create(base_path_, extension_id)));
239 store_map_[extension_id] = make_linked_ptr(store);
240 }
241
242 // Send the latest policy to the store.
243 store->SetCurrentPolicy(*initial_policy, notify_if_changed);
244
245 // And finally resume from where this process started.
246 if (!continuation.is_null())
247 continuation.Run();
248 }
249
250 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698