Chromium Code Reviews| 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" |
|
bartfab (slow)
2013/11/11 14:40:08
Nit: No longer used.
Joao da Silva
2013/11/12 15:26:33
It is, see lines 112 and 120
| |
| 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" |
| 22 #include "chrome/browser/policy/schema_registry.h" | 21 #include "chrome/browser/policy/schema_registry.h" |
| 23 #include "chrome/browser/policy/schema_registry_service.h" | 22 #include "chrome/browser/policy/schema_registry_service.h" |
| 24 #include "chrome/browser/policy/schema_registry_service_factory.h" | 23 #include "chrome/browser/policy/schema_registry_service_factory.h" |
| 25 #include "chrome/browser/profiles/profile.h" | 24 #include "chrome/browser/profiles/profile.h" |
| 26 #include "chrome/browser/value_store/value_store_change.h" | 25 #include "chrome/browser/value_store/value_store_change.h" |
| 27 #include "chrome/common/extensions/api/storage.h" | 26 #include "chrome/common/extensions/api/storage.h" |
| 28 #include "chrome/common/extensions/api/storage/storage_schema_manifest_handler.h " | 27 #include "chrome/common/extensions/api/storage/storage_schema_manifest_handler.h " |
| 29 #include "chrome/common/extensions/extension.h" | 28 #include "chrome/common/extensions/extension.h" |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 47 namespace storage = api::storage; | 46 namespace storage = api::storage; |
| 48 | 47 |
| 49 namespace { | 48 namespace { |
| 50 | 49 |
| 51 const char kLoadSchemasBackgroundTaskTokenName[] = | 50 const char kLoadSchemasBackgroundTaskTokenName[] = |
| 52 "load_managed_storage_schemas_token"; | 51 "load_managed_storage_schemas_token"; |
| 53 | 52 |
| 54 } // namespace | 53 } // namespace |
| 55 | 54 |
| 56 // This helper observes initialization of all the installed extensions and | 55 // This helper observes initialization of all the installed extensions and |
| 57 // subsequent loads and unloads, and keeps the PolicyService of the Profile | 56 // subsequent loads and unloads, and keeps the SchemaRegistry of the Profile |
| 58 // in sync with the current list of extensions. This allows the PolicyService | 57 // 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 | 58 // to fetch cloud policy for those extensions, and allows its providers to |
| 60 // selectively load only extension policy that has users. | 59 // selectively load only extension policy that has users. |
| 61 class ManagedValueStoreCache::ExtensionTracker | 60 class ManagedValueStoreCache::ExtensionTracker |
| 62 : public content::NotificationObserver { | 61 : public content::NotificationObserver { |
| 63 public: | 62 public: |
| 64 explicit ExtensionTracker(Profile* profile); | 63 explicit ExtensionTracker(Profile* profile); |
| 65 virtual ~ExtensionTracker() {} | 64 virtual ~ExtensionTracker() {} |
| 66 | 65 |
| 67 // NotificationObserver implementation: | 66 // NotificationObserver implementation: |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 142 ExtensionSet::const_iterator it = added->begin(); | 141 ExtensionSet::const_iterator it = added->begin(); |
| 143 while (it != added->end()) { | 142 while (it != added->end()) { |
| 144 std::string to_remove; | 143 std::string to_remove; |
| 145 if (!UsesManagedStorage(*it)) | 144 if (!UsesManagedStorage(*it)) |
| 146 to_remove = (*it)->id(); | 145 to_remove = (*it)->id(); |
| 147 ++it; | 146 ++it; |
| 148 if (!to_remove.empty()) | 147 if (!to_remove.empty()) |
| 149 added->Remove(to_remove); | 148 added->Remove(to_remove); |
| 150 } | 149 } |
| 151 | 150 |
| 152 if (added->is_empty()) | |
| 153 return; | |
| 154 | |
| 155 // Load the schema files in a background thread. | 151 // Load the schema files in a background thread. |
| 156 BrowserThread::PostBlockingPoolSequencedTask( | 152 BrowserThread::PostBlockingPoolSequencedTask( |
| 157 kLoadSchemasBackgroundTaskTokenName, FROM_HERE, | 153 kLoadSchemasBackgroundTaskTokenName, FROM_HERE, |
| 158 base::Bind(&ExtensionTracker::LoadSchemas, | 154 base::Bind(&ExtensionTracker::LoadSchemas, |
| 159 base::Passed(&added), | 155 base::Passed(&added), |
| 160 weak_factory_.GetWeakPtr())); | 156 weak_factory_.GetWeakPtr())); |
| 161 } | 157 } |
| 162 | 158 |
| 163 bool ManagedValueStoreCache::ExtensionTracker::UsesManagedStorage( | 159 bool ManagedValueStoreCache::ExtensionTracker::UsesManagedStorage( |
| 164 const Extension* extension) const { | 160 const Extension* extension) const { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 204 | 200 |
| 205 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 201 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 206 base::Bind(&ExtensionTracker::Register, self, | 202 base::Bind(&ExtensionTracker::Register, self, |
| 207 base::Owned(components.release()))); | 203 base::Owned(components.release()))); |
| 208 } | 204 } |
| 209 | 205 |
| 210 void ManagedValueStoreCache::ExtensionTracker::Register( | 206 void ManagedValueStoreCache::ExtensionTracker::Register( |
| 211 const policy::ComponentMap* components) { | 207 const policy::ComponentMap* components) { |
| 212 schema_registry_->RegisterComponents(policy::POLICY_DOMAIN_EXTENSIONS, | 208 schema_registry_->RegisterComponents(policy::POLICY_DOMAIN_EXTENSIONS, |
| 213 *components); | 209 *components); |
| 210 | |
| 211 // The first SetReady() call is performed after receiving | |
| 212 // NOTIFICATION_EXTENSIONS_READY, even if there are no managed extensions. | |
| 213 // It will trigger a loading of the initial policy for any managed | |
| 214 // extensions, and eventually the PolicyService will become ready for | |
| 215 // POLICY_DOMAIN_EXTENSIONS, and OnPolicyServiceInitialized() will be invoked. | |
|
bartfab (slow)
2013/11/11 14:40:08
Nit: Maybe add a sentence that explains any furthe
Joao da Silva
2013/11/12 15:26:33
Done.
| |
| 216 schema_registry_->SetReady(policy::POLICY_DOMAIN_EXTENSIONS); | |
| 214 } | 217 } |
| 215 | 218 |
| 216 ManagedValueStoreCache::ManagedValueStoreCache( | 219 ManagedValueStoreCache::ManagedValueStoreCache( |
| 217 Profile* profile, | 220 Profile* profile, |
| 218 const scoped_refptr<SettingsStorageFactory>& factory, | 221 const scoped_refptr<SettingsStorageFactory>& factory, |
| 219 const scoped_refptr<SettingsObserverList>& observers) | 222 const scoped_refptr<SettingsObserverList>& observers) |
| 220 : weak_factory_(this), | 223 : profile_(profile), |
| 221 weak_this_on_ui_(weak_factory_.GetWeakPtr()), | 224 policy_service_(policy::ProfilePolicyConnectorFactory::GetForProfile( |
| 222 profile_(profile), | 225 profile)->policy_service()), |
| 223 event_router_(ExtensionSystem::Get(profile)->event_router()), | |
| 224 storage_factory_(factory), | 226 storage_factory_(factory), |
| 225 observers_(observers), | 227 observers_(observers), |
| 226 base_path_(profile->GetPath().AppendASCII( | 228 base_path_(profile->GetPath().AppendASCII( |
| 227 extensions::kManagedSettingsDirectoryName)) { | 229 extensions::kManagedSettingsDirectoryName)) { |
| 228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 230 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 | 231 |
| 233 GetPolicyService()->AddObserver(policy::POLICY_DOMAIN_EXTENSIONS, this); | 232 policy_service_->AddObserver(policy::POLICY_DOMAIN_EXTENSIONS, this); |
| 234 | 233 |
| 235 extension_tracker_.reset(new ExtensionTracker(profile_)); | 234 extension_tracker_.reset(new ExtensionTracker(profile_)); |
| 235 | |
| 236 if (policy_service_->IsInitializationComplete( | |
| 237 policy::POLICY_DOMAIN_EXTENSIONS)) { | |
| 238 OnPolicyServiceInitialized(policy::POLICY_DOMAIN_EXTENSIONS); | |
| 239 } | |
| 236 } | 240 } |
| 237 | 241 |
| 238 ManagedValueStoreCache::~ManagedValueStoreCache() { | 242 ManagedValueStoreCache::~ManagedValueStoreCache() { |
| 239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 243 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 240 DCHECK(!event_router_); | |
| 241 // Delete the PolicyValueStores on FILE. | 244 // Delete the PolicyValueStores on FILE. |
| 242 store_map_.clear(); | 245 store_map_.clear(); |
| 243 } | 246 } |
| 244 | 247 |
| 245 void ManagedValueStoreCache::ShutdownOnUI() { | 248 void ManagedValueStoreCache::ShutdownOnUI() { |
| 246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 249 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 247 GetPolicyService()->RemoveObserver(policy::POLICY_DOMAIN_EXTENSIONS, this); | 250 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(); | 251 extension_tracker_.reset(); |
| 253 } | 252 } |
| 254 | 253 |
| 255 void ManagedValueStoreCache::RunWithValueStoreForExtension( | 254 void ManagedValueStoreCache::RunWithValueStoreForExtension( |
| 256 const StorageCallback& callback, | 255 const StorageCallback& callback, |
| 257 scoped_refptr<const Extension> extension) { | 256 scoped_refptr<const Extension> extension) { |
| 258 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 257 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 259 PolicyValueStore* store = GetStoreFor(extension->id()); | 258 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 } | 259 } |
| 275 | 260 |
| 276 void ManagedValueStoreCache::DeleteStorageSoon( | 261 void ManagedValueStoreCache::DeleteStorageSoon( |
| 277 const std::string& extension_id) { | 262 const std::string& extension_id) { |
| 278 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 263 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 279 PolicyValueStore* store = GetStoreFor(extension_id); | 264 // It's possible that the store exists, but hasn't been loaded yet |
| 280 if (!store) { | 265 // (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 | 266 // clear it if it exists. |
| 282 // (because the extension is unloaded, for example). Open the database to | 267 // TODO(joaodasilva): move this check to a ValueStore method. |
| 283 // clear it if it exists. | 268 if (!base::DirectoryExists(base_path_.AppendASCII(extension_id))) |
| 284 // TODO(joaodasilva): move this check to a ValueStore method. | 269 return; |
| 285 if (base::DirectoryExists(base_path_.AppendASCII(extension_id))) { | 270 GetStoreFor(extension_id)->DeleteStorage(); |
| 286 CreateStoreFor( | 271 store_map_.erase(extension_id); |
| 287 extension_id, | 272 } |
| 288 false, | 273 |
| 289 base::Bind(&ManagedValueStoreCache::DeleteStorageSoon, | 274 void ManagedValueStoreCache::OnPolicyServiceInitialized( |
| 290 base::Unretained(this), | 275 policy::PolicyDomain domain) { |
| 291 extension_id)); | 276 if (domain != policy::POLICY_DOMAIN_EXTENSIONS) |
| 292 } | 277 return; |
| 293 } else { | 278 |
| 294 store->DeleteStorage(); | 279 // The PolicyService now has all the initial policies ready. Send policy |
| 295 store_map_.erase(extension_id); | 280 // for all the managed extensions to their backing stores now. |
| 281 policy::SchemaRegistry* registry = | |
| 282 policy::SchemaRegistryServiceFactory::GetForContext(profile_); | |
| 283 const policy::ComponentMap* map = registry->schema_map()->GetComponents( | |
|
bartfab (slow)
2013/11/11 14:40:08
Nit: #include "chrome/browser/policy/schema_map.h"
Joao da Silva
2013/11/12 15:26:33
Done.
| |
| 284 policy::POLICY_DOMAIN_EXTENSIONS); | |
| 285 if (!map) | |
| 286 return; | |
| 287 | |
| 288 const policy::PolicyMap empty_map; | |
| 289 for (policy::ComponentMap::const_iterator it = map->begin(); | |
| 290 it != map->end(); ++it) { | |
| 291 policy::PolicyNamespace ns(policy::POLICY_DOMAIN_EXTENSIONS, it->first); | |
|
bartfab (slow)
2013/11/11 14:40:08
Nit: Const - or just create it inline.
Joao da Silva
2013/11/12 15:26:33
Done.
| |
| 292 // If there is no policy for |ns| then this will clear the previous store, | |
| 293 // if there is one. | |
| 294 OnPolicyUpdated(ns, empty_map, policy_service_->GetPolicies(ns)); | |
| 296 } | 295 } |
| 297 } | 296 } |
| 298 | 297 |
| 299 void ManagedValueStoreCache::OnPolicyUpdated(const policy::PolicyNamespace& ns, | 298 void ManagedValueStoreCache::OnPolicyUpdated(const policy::PolicyNamespace& ns, |
| 300 const policy::PolicyMap& previous, | 299 const policy::PolicyMap& previous, |
| 301 const policy::PolicyMap& current) { | 300 const policy::PolicyMap& current) { |
| 302 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 301 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 302 | |
| 303 if (!policy_service_->IsInitializationComplete( | |
| 304 policy::POLICY_DOMAIN_EXTENSIONS)) { | |
| 305 // OnPolicyUpdated is updated whenever a policy changes, but it doesn't | |
|
bartfab (slow)
2013/11/11 14:40:08
Nit: s/updated/called/
Joao da Silva
2013/11/12 15:26:33
Done.
| |
| 306 // mean that all the policy providers are ready; wait until we get the | |
| 307 // final policy values before passing them to the store. | |
| 308 return; | |
| 309 } | |
| 310 | |
| 303 BrowserThread::PostTask( | 311 BrowserThread::PostTask( |
| 304 BrowserThread::FILE, FROM_HERE, | 312 BrowserThread::FILE, FROM_HERE, |
| 305 base::Bind(&ManagedValueStoreCache::UpdatePolicyOnFILE, | 313 base::Bind(&ManagedValueStoreCache::UpdatePolicyOnFILE, |
| 306 base::Unretained(this), | 314 base::Unretained(this), |
| 307 ns.component_id, | 315 ns.component_id, |
| 308 base::Passed(current.DeepCopy()))); | 316 base::Passed(current.DeepCopy()))); |
| 309 } | 317 } |
| 310 | 318 |
| 311 void ManagedValueStoreCache::UpdatePolicyOnFILE( | 319 void ManagedValueStoreCache::UpdatePolicyOnFILE( |
| 312 const std::string& extension_id, | 320 const std::string& extension_id, |
| 313 scoped_ptr<policy::PolicyMap> current_policy) { | 321 scoped_ptr<policy::PolicyMap> current_policy) { |
| 314 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 322 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 315 PolicyValueStore* store = GetStoreFor(extension_id); | 323 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 } | 324 } |
| 358 | 325 |
| 359 PolicyValueStore* ManagedValueStoreCache::GetStoreFor( | 326 PolicyValueStore* ManagedValueStoreCache::GetStoreFor( |
| 360 const std::string& extension_id) { | 327 const std::string& extension_id) { |
| 361 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 328 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 329 | |
| 362 PolicyValueStoreMap::iterator it = store_map_.find(extension_id); | 330 PolicyValueStoreMap::iterator it = store_map_.find(extension_id); |
| 363 if (it == store_map_.end()) | 331 if (it != store_map_.end()) |
| 364 return NULL; | 332 return it->second.get(); |
| 365 return it->second.get(); | |
| 366 } | |
| 367 | 333 |
| 368 void ManagedValueStoreCache::CreateStoreFor( | 334 // Create the store now, and serve the cached policy until the PolicyService |
| 369 const std::string& extension_id, | 335 // sends updated values. |
| 370 bool notify_if_changed, | 336 PolicyValueStore* store = new PolicyValueStore( |
| 371 const base::Closure& continuation) { | 337 extension_id, |
| 372 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 338 observers_, |
| 373 DCHECK(!GetStoreFor(extension_id)); | 339 make_scoped_ptr(storage_factory_->Create(base_path_, extension_id))); |
| 374 // Creating or loading an existing database requires an immediate update | 340 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 | 341 |
| 386 void ManagedValueStoreCache::GetInitialPolicy( | 342 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 } | 343 } |
| 457 | 344 |
| 458 } // namespace extensions | 345 } // namespace extensions |
| OLD | NEW |