12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/storage/managed_value_store_cache.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind_helpers.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/callback.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/memory/weak_ptr.h" 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/scoped_observer.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/storage/policy_value_store.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/policy/profile_policy_connector.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/policy/profile_policy_connector_factory.h" 17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/policy/schema_registry_service.h" 18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/policy/schema_registry_service_factory.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/profiles/profile.h" 207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/common/extensions/api/storage/storage_schema_manifest_handler.h" 21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/policy/core/common/policy_namespace.h" 2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "components/policy/core/common/schema.h" 23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/policy/core/common/schema_map.h" 24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/policy/core/common/schema_registry.h" 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/api/storage/settings_storage_factory.h" 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_prefs.h" 2823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/browser/extension_registry.h" 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/browser/extension_registry_observer.h" 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h" 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/value_store/value_store_change.h" 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/common/api/storage.h" 3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "extensions/common/constants.h" 34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/common/extension_set.h" 363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/manifest.h" 373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/manifest_constants.h" 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/one_shot_event.h" 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using content::BrowserContext; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::BrowserThread; 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace extensions { 44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class ExtensionRegistry; 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace storage = core_api::storage; 473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace { 4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kLoadSchemasBackgroundTaskTokenName[] = 5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "load_managed_storage_schemas_token"; 5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// The Legacy Browser Support was the first user of the policy-for-extensions 54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// API, and relied on behavior that will be phased out. If this extension is 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// present then its policies will be loaded in a special way. 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// TODO(joaodasilva): remove this for M35. http://crbug.com/325349 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kLegacyBrowserSupportExtensionId[] = 58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "heildphpnddilhkemkielfhnkaagiabh"; 59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace 6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This helper observes initialization of all the installed extensions and 63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// subsequent loads and unloads, and keeps the SchemaRegistry of the Profile 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// in sync with the current list of extensions. This allows the PolicyService 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// to fetch cloud policy for those extensions, and allows its providers to 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// selectively load only extension policy that has users. 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ManagedValueStoreCache::ExtensionTracker 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : public ExtensionRegistryObserver { 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) explicit ExtensionTracker(Profile* profile); 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~ExtensionTracker() {} 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // ExtensionRegistryObserver implementation. 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual void OnExtensionWillBeInstalled( 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::BrowserContext* browser_context, 77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const Extension* extension, 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool is_update, 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool from_ephemeral, 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& old_name) OVERRIDE; 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual void OnExtensionUninstalled( 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) content::BrowserContext* browser_context, 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const Extension* extension, 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::UninstallReason reason) OVERRIDE; 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 8623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Handler for the signal from ExtensionSystem::ready(). 87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void OnExtensionsReady(); 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Starts a schema load for all extensions that use managed storage. 90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void LoadSchemas(scoped_ptr<ExtensionSet> added); 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool UsesManagedStorage(const Extension* extension) const; 93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Loads the schemas of the |extensions| and passes a ComponentMap to 95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Register(). 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static void LoadSchemasOnBlockingPool(scoped_ptr<ExtensionSet> extensions, 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::WeakPtr<ExtensionTracker> self); 98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) void Register(const policy::ComponentMap* components); 9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Profile* profile_; 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension_registry_observer_; 103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) policy::SchemaRegistry* schema_registry_; 10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::WeakPtrFactory<ExtensionTracker> weak_factory_; 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ExtensionTracker); 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ManagedValueStoreCache::ExtensionTracker::ExtensionTracker(Profile* profile) 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : profile_(profile), 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension_registry_observer_(this), 1126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) schema_registry_(policy::SchemaRegistryServiceFactory::GetForContext( 1136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) profile)->registry()), 11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) weak_factory_(this) { 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension_registry_observer_.Add(ExtensionRegistry::Get(profile_)); 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Load schemas when the extension system is ready. It might be ready now. 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ExtensionSystem::Get(profile_)->ready().Post( 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&ExtensionTracker::OnExtensionsReady, 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) weak_factory_.GetWeakPtr())); 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ManagedValueStoreCache::ExtensionTracker::OnExtensionWillBeInstalled( 124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::BrowserContext* browser_context, 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const Extension* extension, 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool is_update, 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool from_ephemeral, 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& old_name) { 12923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Some extensions are installed on the first run before the ExtensionSystem 130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // becomes ready. Wait until all of them are ready before registering the 131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // schemas of managed extensions, so that the policy loaders are reloaded at 132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // most once. 13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!ExtensionSystem::Get(profile_)->ready().is_signaled()) 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<ExtensionSet> added(new ExtensionSet); 136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) added->Insert(extension); 137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LoadSchemas(added.Pass()); 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ManagedValueStoreCache::ExtensionTracker::OnExtensionUninstalled( 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::BrowserContext* browser_context, 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const Extension* extension, 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::UninstallReason reason) { 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!ExtensionSystem::Get(profile_)->ready().is_signaled()) 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (extension && UsesManagedStorage(extension)) { 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) schema_registry_->UnregisterComponent(policy::PolicyNamespace( 148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) policy::POLICY_DOMAIN_EXTENSIONS, extension->id())); 149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ManagedValueStoreCache::ExtensionTracker::OnExtensionsReady() { 153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Load schemas for all installed extensions. 15423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) LoadSchemas( 15523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ExtensionRegistry::Get(profile_)->GenerateInstalledExtensionsSet()); 156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ManagedValueStoreCache::ExtensionTracker::LoadSchemas( 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<ExtensionSet> added) { 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Filter out extensions that don't use managed storage. 161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ExtensionSet::const_iterator it = added->begin(); 162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) while (it != added->end()) { 163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string to_remove; 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!UsesManagedStorage(it->get())) 165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) to_remove = (*it)->id(); 166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ++it; 167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!to_remove.empty()) 168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) added->Remove(to_remove); 16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Load the schema files in a background thread. 17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) BrowserThread::PostBlockingPoolSequencedTask( 17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kLoadSchemasBackgroundTaskTokenName, FROM_HERE, 174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&ExtensionTracker::LoadSchemasOnBlockingPool, 175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Passed(&added), 17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) weak_factory_.GetWeakPtr())); 17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool ManagedValueStoreCache::ExtensionTracker::UsesManagedStorage( 180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const Extension* extension) const { 181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (extension->manifest()->HasPath(manifest_keys::kStorageManagedSchema)) 182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // TODO(joaodasilva): remove this by M35. 185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return extension->id() == kLegacyBrowserSupportExtensionId; 186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static 189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ManagedValueStoreCache::ExtensionTracker::LoadSchemasOnBlockingPool( 19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<ExtensionSet> extensions, 19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::WeakPtr<ExtensionTracker> self) { 192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<policy::ComponentMap> components(new policy::ComponentMap); 19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (ExtensionSet::const_iterator it = extensions->begin(); 19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) it != extensions->end(); ++it) { 19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string schema_file; 19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!(*it)->manifest()->GetString( 1993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) manifest_keys::kStorageManagedSchema, &schema_file)) { 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(joaodasilva): Remove this. http://crbug.com/325349 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*components)[(*it)->id()] = policy::Schema(); 20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) continue; 20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // The extension should have been validated, so assume the schema exists 20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // and is valid. 20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string error; 207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) policy::Schema schema = 2087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) StorageSchemaManifestHandler::GetSchema(it->get(), &error); 2096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // If the schema is invalid then proceed with an empty schema. The extension 2106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // will be listed in chrome://policy but won't be able to load any policies. 2116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!schema.valid()) 2126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) schema = policy::Schema(); 213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) (*components)[(*it)->id()] = schema; 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Bind(&ExtensionTracker::Register, self, 218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Owned(components.release()))); 21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ManagedValueStoreCache::ExtensionTracker::Register( 222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const policy::ComponentMap* components) { 223effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) schema_registry_->RegisterComponents(policy::POLICY_DOMAIN_EXTENSIONS, 225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *components); 226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 22723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // The first SetReady() call is performed after the ExtensionSystem is ready, 22823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // even if there are no managed extensions. It will trigger a loading of the 22923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // initial policy for any managed extensions, and eventually the PolicyService 23023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // will become ready for POLICY_DOMAIN_EXTENSIONS, and 23123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // OnPolicyServiceInitialized() will be invoked. 232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Subsequent calls to SetReady() are ignored. 233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) schema_registry_->SetReady(policy::POLICY_DOMAIN_EXTENSIONS); 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ManagedValueStoreCache::ManagedValueStoreCache( 237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) BrowserContext* context, 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const scoped_refptr<SettingsStorageFactory>& factory, 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const scoped_refptr<SettingsObserverList>& observers) 240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : profile_(Profile::FromBrowserContext(context)), 241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) policy_service_(policy::ProfilePolicyConnectorFactory::GetForProfile( 242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) profile_)->policy_service()), 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) storage_factory_(factory), 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) observers_(observers), 245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base_path_(profile_->GetPath().AppendASCII( 24668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) extensions::kManagedSettingsDirectoryName)) { 247effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) policy_service_->AddObserver(policy::POLICY_DOMAIN_EXTENSIONS, this); 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension_tracker_.reset(new ExtensionTracker(profile_)); 252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (policy_service_->IsInitializationComplete( 254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) policy::POLICY_DOMAIN_EXTENSIONS)) { 255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) OnPolicyServiceInitialized(policy::POLICY_DOMAIN_EXTENSIONS); 256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ManagedValueStoreCache::~ManagedValueStoreCache() { 260effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::FILE); 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Delete the PolicyValueStores on FILE. 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) store_map_.clear(); 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ManagedValueStoreCache::ShutdownOnUI() { 266effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) policy_service_->RemoveObserver(policy::POLICY_DOMAIN_EXTENSIONS, this); 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension_tracker_.reset(); 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ManagedValueStoreCache::RunWithValueStoreForExtension( 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const StorageCallback& callback, 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<const Extension> extension) { 274effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::FILE); 275f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) callback.Run(GetStoreFor(extension->id())); 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ManagedValueStoreCache::DeleteStorageSoon( 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& extension_id) { 280effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::FILE); 281f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // It's possible that the store exists, but hasn't been loaded yet 282f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // (because the extension is unloaded, for example). Open the database to 283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // clear it if it exists. 284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!HasStore(extension_id)) 285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) GetStoreFor(extension_id)->DeleteStorage(); 287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) store_map_.erase(extension_id); 288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ManagedValueStoreCache::OnPolicyServiceInitialized( 291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) policy::PolicyDomain domain) { 292effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 293f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 294f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (domain != policy::POLICY_DOMAIN_EXTENSIONS) 295f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 296f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 297f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // The PolicyService now has all the initial policies ready. Send policy 298f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // for all the managed extensions to their backing stores now. 299f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) policy::SchemaRegistry* registry = 3006d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) policy::SchemaRegistryServiceFactory::GetForContext(profile_)->registry(); 301f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const policy::ComponentMap* map = registry->schema_map()->GetComponents( 302f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) policy::POLICY_DOMAIN_EXTENSIONS); 303f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!map) 304f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const policy::PolicyMap empty_map; 307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (policy::ComponentMap::const_iterator it = map->begin(); 308f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) it != map->end(); ++it) { 309f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const policy::PolicyNamespace ns(policy::POLICY_DOMAIN_EXTENSIONS, 310f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) it->first); 311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // If there is no policy for |ns| then this will clear the previous store, 312f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // if there is one. 313f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) OnPolicyUpdated(ns, empty_map, policy_service_->GetPolicies(ns)); 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ManagedValueStoreCache::OnPolicyUpdated(const policy::PolicyNamespace& ns, 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const policy::PolicyMap& previous, 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const policy::PolicyMap& current) { 320effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 321f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 322f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!policy_service_->IsInitializationComplete( 323f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) policy::POLICY_DOMAIN_EXTENSIONS)) { 324f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // OnPolicyUpdated is called whenever a policy changes, but it doesn't 325f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // mean that all the policy providers are ready; wait until we get the 326f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // final policy values before passing them to the store. 327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 329f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask( 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::FILE, FROM_HERE, 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&ManagedValueStoreCache::UpdatePolicyOnFILE, 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this), 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ns.component_id, 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Passed(current.DeepCopy()))); 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ManagedValueStoreCache::UpdatePolicyOnFILE( 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& extension_id, 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<policy::PolicyMap> current_policy) { 341effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::FILE); 342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!HasStore(extension_id) && current_policy->empty()) { 344f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Don't create the store now if there are no policies configured for this 345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // extension. If the extension uses the storage.managed API then the store 346f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // will be created at RunWithValueStoreForExtension(). 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 350f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) GetStoreFor(extension_id)->SetCurrentPolicy(*current_policy); 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PolicyValueStore* ManagedValueStoreCache::GetStoreFor( 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& extension_id) { 355effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::FILE); 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PolicyValueStoreMap::iterator it = store_map_.find(extension_id); 358f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (it != store_map_.end()) 359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return it->second.get(); 360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 361f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Create the store now, and serve the cached policy until the PolicyService 362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // sends updated values. 363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PolicyValueStore* store = new PolicyValueStore( 364f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extension_id, 365f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) observers_, 366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) make_scoped_ptr(storage_factory_->Create(base_path_, extension_id))); 367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) store_map_[extension_id] = make_linked_ptr(store); 368f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return store; 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool ManagedValueStoreCache::HasStore(const std::string& extension_id) const { 373f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // TODO(joaodasilva): move this check to a ValueStore method. 374f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return base::DirectoryExists(base_path_.AppendASCII(extension_id)); 375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace extensions 378