OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/api/storage/managed_value_store_cache.h" | 5 #include "chrome/browser/extensions/api/storage/managed_value_store_cache.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/callback.h" | 9 #include "base/callback.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/memory/ref_counted.h" | 12 #include "base/memory/weak_ptr.h" |
13 #include "base/message_loop/message_loop_proxy.h" | |
14 #include "chrome/browser/chrome_notification_types.h" | 13 #include "chrome/browser/chrome_notification_types.h" |
15 #include "chrome/browser/extensions/api/storage/policy_value_store.h" | 14 #include "chrome/browser/extensions/api/storage/policy_value_store.h" |
16 #include "chrome/browser/extensions/api/storage/settings_storage_factory.h" | 15 #include "chrome/browser/extensions/api/storage/settings_storage_factory.h" |
17 #include "chrome/browser/extensions/extension_prefs.h" | 16 #include "chrome/browser/extensions/extension_prefs.h" |
18 #include "chrome/browser/extensions/extension_service.h" | 17 #include "chrome/browser/extensions/extension_service.h" |
19 #include "chrome/browser/extensions/extension_system.h" | 18 #include "chrome/browser/extensions/extension_system.h" |
20 #include "chrome/browser/policy/profile_policy_connector.h" | 19 #include "chrome/browser/policy/profile_policy_connector.h" |
21 #include "chrome/browser/policy/profile_policy_connector_factory.h" | 20 #include "chrome/browser/policy/profile_policy_connector_factory.h" |
| 21 #include "chrome/browser/policy/schema_map.h" |
22 #include "chrome/browser/policy/schema_registry.h" | 22 #include "chrome/browser/policy/schema_registry.h" |
23 #include "chrome/browser/policy/schema_registry_service.h" | 23 #include "chrome/browser/policy/schema_registry_service.h" |
24 #include "chrome/browser/policy/schema_registry_service_factory.h" | 24 #include "chrome/browser/policy/schema_registry_service_factory.h" |
25 #include "chrome/browser/profiles/profile.h" | 25 #include "chrome/browser/profiles/profile.h" |
26 #include "chrome/browser/value_store/value_store_change.h" | 26 #include "chrome/browser/value_store/value_store_change.h" |
27 #include "chrome/common/extensions/api/storage.h" | 27 #include "chrome/common/extensions/api/storage.h" |
28 #include "chrome/common/extensions/api/storage/storage_schema_manifest_handler.h
" | 28 #include "chrome/common/extensions/api/storage/storage_schema_manifest_handler.h
" |
29 #include "chrome/common/extensions/extension.h" | 29 #include "chrome/common/extensions/extension.h" |
30 #include "chrome/common/extensions/extension_set.h" | 30 #include "chrome/common/extensions/extension_set.h" |
31 #include "components/policy/core/common/policy_namespace.h" | 31 #include "components/policy/core/common/policy_namespace.h" |
(...skipping 15 matching lines...) Expand all Loading... |
47 namespace storage = api::storage; | 47 namespace storage = api::storage; |
48 | 48 |
49 namespace { | 49 namespace { |
50 | 50 |
51 const char kLoadSchemasBackgroundTaskTokenName[] = | 51 const char kLoadSchemasBackgroundTaskTokenName[] = |
52 "load_managed_storage_schemas_token"; | 52 "load_managed_storage_schemas_token"; |
53 | 53 |
54 } // namespace | 54 } // namespace |
55 | 55 |
56 // This helper observes initialization of all the installed extensions and | 56 // This helper observes initialization of all the installed extensions and |
57 // subsequent loads and unloads, and keeps the PolicyService of the Profile | 57 // subsequent loads and unloads, and keeps the SchemaRegistry of the Profile |
58 // in sync with the current list of extensions. This allows the PolicyService | 58 // in sync with the current list of extensions. This allows the PolicyService |
59 // to fetch cloud policy for those extensions, and allows its providers to | 59 // to fetch cloud policy for those extensions, and allows its providers to |
60 // selectively load only extension policy that has users. | 60 // selectively load only extension policy that has users. |
61 class ManagedValueStoreCache::ExtensionTracker | 61 class ManagedValueStoreCache::ExtensionTracker |
62 : public content::NotificationObserver { | 62 : public content::NotificationObserver { |
63 public: | 63 public: |
64 explicit ExtensionTracker(Profile* profile); | 64 explicit ExtensionTracker(Profile* profile); |
65 virtual ~ExtensionTracker() {} | 65 virtual ~ExtensionTracker() {} |
66 | 66 |
67 // NotificationObserver implementation: | 67 // NotificationObserver implementation: |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 ExtensionSet::const_iterator it = added->begin(); | 142 ExtensionSet::const_iterator it = added->begin(); |
143 while (it != added->end()) { | 143 while (it != added->end()) { |
144 std::string to_remove; | 144 std::string to_remove; |
145 if (!UsesManagedStorage(*it)) | 145 if (!UsesManagedStorage(*it)) |
146 to_remove = (*it)->id(); | 146 to_remove = (*it)->id(); |
147 ++it; | 147 ++it; |
148 if (!to_remove.empty()) | 148 if (!to_remove.empty()) |
149 added->Remove(to_remove); | 149 added->Remove(to_remove); |
150 } | 150 } |
151 | 151 |
152 if (added->is_empty()) | |
153 return; | |
154 | |
155 // Load the schema files in a background thread. | 152 // Load the schema files in a background thread. |
156 BrowserThread::PostBlockingPoolSequencedTask( | 153 BrowserThread::PostBlockingPoolSequencedTask( |
157 kLoadSchemasBackgroundTaskTokenName, FROM_HERE, | 154 kLoadSchemasBackgroundTaskTokenName, FROM_HERE, |
158 base::Bind(&ExtensionTracker::LoadSchemas, | 155 base::Bind(&ExtensionTracker::LoadSchemas, |
159 base::Passed(&added), | 156 base::Passed(&added), |
160 weak_factory_.GetWeakPtr())); | 157 weak_factory_.GetWeakPtr())); |
161 } | 158 } |
162 | 159 |
163 bool ManagedValueStoreCache::ExtensionTracker::UsesManagedStorage( | 160 bool ManagedValueStoreCache::ExtensionTracker::UsesManagedStorage( |
164 const Extension* extension) const { | 161 const Extension* extension) const { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 | 201 |
205 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 202 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
206 base::Bind(&ExtensionTracker::Register, self, | 203 base::Bind(&ExtensionTracker::Register, self, |
207 base::Owned(components.release()))); | 204 base::Owned(components.release()))); |
208 } | 205 } |
209 | 206 |
210 void ManagedValueStoreCache::ExtensionTracker::Register( | 207 void ManagedValueStoreCache::ExtensionTracker::Register( |
211 const policy::ComponentMap* components) { | 208 const policy::ComponentMap* components) { |
212 schema_registry_->RegisterComponents(policy::POLICY_DOMAIN_EXTENSIONS, | 209 schema_registry_->RegisterComponents(policy::POLICY_DOMAIN_EXTENSIONS, |
213 *components); | 210 *components); |
| 211 |
| 212 // The first SetReady() call is performed after receiving |
| 213 // NOTIFICATION_EXTENSIONS_READY, even if there are no managed extensions. |
| 214 // It will trigger a loading of the initial policy for any managed |
| 215 // extensions, and eventually the PolicyService will become ready for |
| 216 // POLICY_DOMAIN_EXTENSIONS, and OnPolicyServiceInitialized() will be invoked. |
| 217 // Subsequent calls to SetReady() are ignored. |
| 218 schema_registry_->SetReady(policy::POLICY_DOMAIN_EXTENSIONS); |
214 } | 219 } |
215 | 220 |
216 ManagedValueStoreCache::ManagedValueStoreCache( | 221 ManagedValueStoreCache::ManagedValueStoreCache( |
217 Profile* profile, | 222 Profile* profile, |
218 const scoped_refptr<SettingsStorageFactory>& factory, | 223 const scoped_refptr<SettingsStorageFactory>& factory, |
219 const scoped_refptr<SettingsObserverList>& observers) | 224 const scoped_refptr<SettingsObserverList>& observers) |
220 : weak_factory_(this), | 225 : profile_(profile), |
221 weak_this_on_ui_(weak_factory_.GetWeakPtr()), | 226 policy_service_(policy::ProfilePolicyConnectorFactory::GetForProfile( |
222 profile_(profile), | 227 profile)->policy_service()), |
223 event_router_(ExtensionSystem::Get(profile)->event_router()), | |
224 storage_factory_(factory), | 228 storage_factory_(factory), |
225 observers_(observers), | 229 observers_(observers), |
226 base_path_(profile->GetPath().AppendASCII( | 230 base_path_(profile->GetPath().AppendASCII( |
227 extensions::kManagedSettingsDirectoryName)) { | 231 extensions::kManagedSettingsDirectoryName)) { |
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
229 // |event_router_| can be NULL on unit_tests. | |
230 if (event_router_) | |
231 event_router_->RegisterObserver(this, storage::OnChanged::kEventName); | |
232 | 233 |
233 GetPolicyService()->AddObserver(policy::POLICY_DOMAIN_EXTENSIONS, this); | 234 policy_service_->AddObserver(policy::POLICY_DOMAIN_EXTENSIONS, this); |
234 | 235 |
235 extension_tracker_.reset(new ExtensionTracker(profile_)); | 236 extension_tracker_.reset(new ExtensionTracker(profile_)); |
| 237 |
| 238 if (policy_service_->IsInitializationComplete( |
| 239 policy::POLICY_DOMAIN_EXTENSIONS)) { |
| 240 OnPolicyServiceInitialized(policy::POLICY_DOMAIN_EXTENSIONS); |
| 241 } |
236 } | 242 } |
237 | 243 |
238 ManagedValueStoreCache::~ManagedValueStoreCache() { | 244 ManagedValueStoreCache::~ManagedValueStoreCache() { |
239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 245 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
240 DCHECK(!event_router_); | |
241 // Delete the PolicyValueStores on FILE. | 246 // Delete the PolicyValueStores on FILE. |
242 store_map_.clear(); | 247 store_map_.clear(); |
243 } | 248 } |
244 | 249 |
245 void ManagedValueStoreCache::ShutdownOnUI() { | 250 void ManagedValueStoreCache::ShutdownOnUI() { |
246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 251 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
247 GetPolicyService()->RemoveObserver(policy::POLICY_DOMAIN_EXTENSIONS, this); | 252 policy_service_->RemoveObserver(policy::POLICY_DOMAIN_EXTENSIONS, this); |
248 if (event_router_) | |
249 event_router_->UnregisterObserver(this); | |
250 event_router_ = NULL; | |
251 weak_factory_.InvalidateWeakPtrs(); | |
252 extension_tracker_.reset(); | 253 extension_tracker_.reset(); |
253 } | 254 } |
254 | 255 |
255 void ManagedValueStoreCache::RunWithValueStoreForExtension( | 256 void ManagedValueStoreCache::RunWithValueStoreForExtension( |
256 const StorageCallback& callback, | 257 const StorageCallback& callback, |
257 scoped_refptr<const Extension> extension) { | 258 scoped_refptr<const Extension> extension) { |
258 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 259 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
259 PolicyValueStore* store = GetStoreFor(extension->id()); | 260 callback.Run(GetStoreFor(extension->id())); |
260 if (store) { | |
261 callback.Run(store); | |
262 } else { | |
263 // First time that an extension calls storage.managed.get(). Create the | |
264 // store and load it with the current policy, and don't send event | |
265 // notifications. | |
266 CreateStoreFor( | |
267 extension->id(), | |
268 false, | |
269 base::Bind(&ManagedValueStoreCache::RunWithValueStoreForExtension, | |
270 base::Unretained(this), | |
271 callback, | |
272 extension)); | |
273 } | |
274 } | 261 } |
275 | 262 |
276 void ManagedValueStoreCache::DeleteStorageSoon( | 263 void ManagedValueStoreCache::DeleteStorageSoon( |
277 const std::string& extension_id) { | 264 const std::string& extension_id) { |
278 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
279 PolicyValueStore* store = GetStoreFor(extension_id); | 266 // It's possible that the store exists, but hasn't been loaded yet |
280 if (!store) { | 267 // (because the extension is unloaded, for example). Open the database to |
281 // It's possible that the store exists, but hasn't been loaded yet | 268 // clear it if it exists. |
282 // (because the extension is unloaded, for example). Open the database to | 269 // TODO(joaodasilva): move this check to a ValueStore method. |
283 // clear it if it exists. | 270 if (!base::DirectoryExists(base_path_.AppendASCII(extension_id))) |
284 // TODO(joaodasilva): move this check to a ValueStore method. | 271 return; |
285 if (base::DirectoryExists(base_path_.AppendASCII(extension_id))) { | 272 GetStoreFor(extension_id)->DeleteStorage(); |
286 CreateStoreFor( | 273 store_map_.erase(extension_id); |
287 extension_id, | 274 } |
288 false, | 275 |
289 base::Bind(&ManagedValueStoreCache::DeleteStorageSoon, | 276 void ManagedValueStoreCache::OnPolicyServiceInitialized( |
290 base::Unretained(this), | 277 policy::PolicyDomain domain) { |
291 extension_id)); | 278 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
292 } | 279 |
293 } else { | 280 if (domain != policy::POLICY_DOMAIN_EXTENSIONS) |
294 store->DeleteStorage(); | 281 return; |
295 store_map_.erase(extension_id); | 282 |
| 283 // The PolicyService now has all the initial policies ready. Send policy |
| 284 // for all the managed extensions to their backing stores now. |
| 285 policy::SchemaRegistry* registry = |
| 286 policy::SchemaRegistryServiceFactory::GetForContext(profile_); |
| 287 const policy::ComponentMap* map = registry->schema_map()->GetComponents( |
| 288 policy::POLICY_DOMAIN_EXTENSIONS); |
| 289 if (!map) |
| 290 return; |
| 291 |
| 292 const policy::PolicyMap empty_map; |
| 293 for (policy::ComponentMap::const_iterator it = map->begin(); |
| 294 it != map->end(); ++it) { |
| 295 const policy::PolicyNamespace ns(policy::POLICY_DOMAIN_EXTENSIONS, |
| 296 it->first); |
| 297 // If there is no policy for |ns| then this will clear the previous store, |
| 298 // if there is one. |
| 299 OnPolicyUpdated(ns, empty_map, policy_service_->GetPolicies(ns)); |
296 } | 300 } |
297 } | 301 } |
298 | 302 |
299 void ManagedValueStoreCache::OnPolicyUpdated(const policy::PolicyNamespace& ns, | 303 void ManagedValueStoreCache::OnPolicyUpdated(const policy::PolicyNamespace& ns, |
300 const policy::PolicyMap& previous, | 304 const policy::PolicyMap& previous, |
301 const policy::PolicyMap& current) { | 305 const policy::PolicyMap& current) { |
302 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 306 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 307 |
| 308 if (!policy_service_->IsInitializationComplete( |
| 309 policy::POLICY_DOMAIN_EXTENSIONS)) { |
| 310 // OnPolicyUpdated is called whenever a policy changes, but it doesn't |
| 311 // mean that all the policy providers are ready; wait until we get the |
| 312 // final policy values before passing them to the store. |
| 313 return; |
| 314 } |
| 315 |
303 BrowserThread::PostTask( | 316 BrowserThread::PostTask( |
304 BrowserThread::FILE, FROM_HERE, | 317 BrowserThread::FILE, FROM_HERE, |
305 base::Bind(&ManagedValueStoreCache::UpdatePolicyOnFILE, | 318 base::Bind(&ManagedValueStoreCache::UpdatePolicyOnFILE, |
306 base::Unretained(this), | 319 base::Unretained(this), |
307 ns.component_id, | 320 ns.component_id, |
308 base::Passed(current.DeepCopy()))); | 321 base::Passed(current.DeepCopy()))); |
309 } | 322 } |
310 | 323 |
311 void ManagedValueStoreCache::UpdatePolicyOnFILE( | 324 void ManagedValueStoreCache::UpdatePolicyOnFILE( |
312 const std::string& extension_id, | 325 const std::string& extension_id, |
313 scoped_ptr<policy::PolicyMap> current_policy) { | 326 scoped_ptr<policy::PolicyMap> current_policy) { |
314 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 327 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
315 PolicyValueStore* store = GetStoreFor(extension_id); | 328 GetStoreFor(extension_id)->SetCurrentPolicy(*current_policy); |
316 if (!store) { | |
317 // The extension hasn't executed any storage.managed.* calls, and isn't | |
318 // listening for onChanged() either. Ignore this notification in that case. | |
319 return; | |
320 } | |
321 // Update the policy on the backing store, and fire notifications if it | |
322 // changed. | |
323 store->SetCurrentPolicy(*current_policy, true); | |
324 } | |
325 | |
326 void ManagedValueStoreCache::OnListenerAdded( | |
327 const EventListenerInfo& details) { | |
328 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
329 DCHECK_EQ(std::string(storage::OnChanged::kEventName), details.event_name); | |
330 // This is invoked on several occasions: | |
331 // | |
332 // 1. when an extension first registers to observe storage.onChanged; in this | |
333 // case the backend doesn't have any previous data persisted, and it won't | |
334 // trigger a notification. | |
335 // | |
336 // 2. when the browser starts up and all existing extensions re-register for | |
337 // the onChanged event. In this case, if the current policy differs from | |
338 // the persisted version then a notification will be sent. | |
339 // | |
340 // 3. a policy update just occurred and sent a notification, and an extension | |
341 // with EventPages that is observing onChanged just woke up and registed | |
342 // again. In this case the policy update already persisted the current | |
343 // policy version, and |store| already exists. | |
344 BrowserThread::PostTask( | |
345 BrowserThread::FILE, FROM_HERE, | |
346 base::Bind(&ManagedValueStoreCache::CreateForExtensionOnFILE, | |
347 base::Unretained(this), | |
348 details.extension_id)); | |
349 } | |
350 | |
351 void ManagedValueStoreCache::CreateForExtensionOnFILE( | |
352 const std::string& extension_id) { | |
353 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
354 PolicyValueStore* store = GetStoreFor(extension_id); | |
355 if (!store) | |
356 CreateStoreFor(extension_id, true, base::Closure()); | |
357 } | 329 } |
358 | 330 |
359 PolicyValueStore* ManagedValueStoreCache::GetStoreFor( | 331 PolicyValueStore* ManagedValueStoreCache::GetStoreFor( |
360 const std::string& extension_id) { | 332 const std::string& extension_id) { |
361 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 333 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 334 |
362 PolicyValueStoreMap::iterator it = store_map_.find(extension_id); | 335 PolicyValueStoreMap::iterator it = store_map_.find(extension_id); |
363 if (it == store_map_.end()) | 336 if (it != store_map_.end()) |
364 return NULL; | 337 return it->second.get(); |
365 return it->second.get(); | |
366 } | |
367 | 338 |
368 void ManagedValueStoreCache::CreateStoreFor( | 339 // Create the store now, and serve the cached policy until the PolicyService |
369 const std::string& extension_id, | 340 // sends updated values. |
370 bool notify_if_changed, | 341 PolicyValueStore* store = new PolicyValueStore( |
371 const base::Closure& continuation) { | 342 extension_id, |
372 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 343 observers_, |
373 DCHECK(!GetStoreFor(extension_id)); | 344 make_scoped_ptr(storage_factory_->Create(base_path_, extension_id))); |
374 // Creating or loading an existing database requires an immediate update | 345 store_map_[extension_id] = make_linked_ptr(store); |
375 // with the current policy for the corresponding extension, which must be | |
376 // retrieved on UI. | |
377 BrowserThread::PostTask( | |
378 BrowserThread::UI, FROM_HERE, | |
379 base::Bind(&ManagedValueStoreCache::GetInitialPolicy, | |
380 weak_this_on_ui_, | |
381 extension_id, | |
382 notify_if_changed, | |
383 continuation)); | |
384 } | |
385 | 346 |
386 void ManagedValueStoreCache::GetInitialPolicy( | 347 return store; |
387 const std::string& extension_id, | |
388 bool notify_if_changed, | |
389 const base::Closure& continuation) { | |
390 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
391 | |
392 policy::PolicyService* policy_service = GetPolicyService(); | |
393 | |
394 // If initialization of POLICY_DOMAIN_EXTENSIONS isn't complete then all the | |
395 // policies served are empty; let the extension see what's cached in LevelDB | |
396 // in that case. The PolicyService will issue notifications once new policies | |
397 // are ready. | |
398 scoped_ptr<policy::PolicyMap> policy; | |
399 if (policy_service->IsInitializationComplete( | |
400 policy::POLICY_DOMAIN_EXTENSIONS)) { | |
401 policy::PolicyNamespace ns(policy::POLICY_DOMAIN_EXTENSIONS, extension_id); | |
402 policy = policy_service->GetPolicies(ns).DeepCopy(); | |
403 } | |
404 | |
405 // Now post back to FILE to create the database. | |
406 BrowserThread::PostTask( | |
407 BrowserThread::FILE, FROM_HERE, | |
408 base::Bind(&ManagedValueStoreCache::CreateStoreWithInitialPolicy, | |
409 base::Unretained(this), | |
410 extension_id, | |
411 notify_if_changed, | |
412 base::Passed(&policy), | |
413 continuation)); | |
414 } | |
415 | |
416 void ManagedValueStoreCache::CreateStoreWithInitialPolicy( | |
417 const std::string& extension_id, | |
418 bool notify_if_changed, | |
419 scoped_ptr<policy::PolicyMap> initial_policy, | |
420 const base::Closure& continuation) { | |
421 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
422 // If a 2nd call to CreateStoreFor() is issued before the 1st gets to execute | |
423 // its UI task, then the 2nd will enter this function but the store has | |
424 // already been created. Check for that. | |
425 PolicyValueStore* store = GetStoreFor(extension_id); | |
426 | |
427 if (!store) { | |
428 // Create it now. | |
429 | |
430 // If the database doesn't exist yet then this is the initial install, | |
431 // and no notifications should be issued in that case. | |
432 // TODO(joaodasilva): move this check to a ValueStore method. | |
433 if (!base::DirectoryExists(base_path_.AppendASCII(extension_id))) | |
434 notify_if_changed = false; | |
435 | |
436 store = new PolicyValueStore( | |
437 extension_id, | |
438 observers_, | |
439 make_scoped_ptr(storage_factory_->Create(base_path_, extension_id))); | |
440 store_map_[extension_id] = make_linked_ptr(store); | |
441 } | |
442 | |
443 // Send the latest policy to the store, if it's already available. | |
444 if (initial_policy) | |
445 store->SetCurrentPolicy(*initial_policy, notify_if_changed); | |
446 | |
447 // And finally resume from where this process started. | |
448 if (!continuation.is_null()) | |
449 continuation.Run(); | |
450 } | |
451 | |
452 policy::PolicyService* ManagedValueStoreCache::GetPolicyService() { | |
453 policy::ProfilePolicyConnector* connector = | |
454 policy::ProfilePolicyConnectorFactory::GetForProfile(profile_); | |
455 return connector->policy_service(); | |
456 } | 348 } |
457 | 349 |
458 } // namespace extensions | 350 } // namespace extensions |
OLD | NEW |