This source file includes following definitions.
- ExtensionTracker
 
- weak_factory_
 
- Observe
 
- OnExtensionsReady
 
- LoadSchemas
 
- UsesManagedStorage
 
- LoadSchemasOnBlockingPool
 
- Register
 
- base_path_
 
- ShutdownOnUI
 
- RunWithValueStoreForExtension
 
- DeleteStorageSoon
 
- OnPolicyServiceInitialized
 
- OnPolicyUpdated
 
- UpdatePolicyOnFILE
 
- GetStoreFor
 
- HasStore
 
#include "chrome/browser/extensions/api/storage/managed_value_store_cache.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/api/storage/policy_value_store.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/policy/profile_policy_connector_factory.h"
#include "chrome/browser/policy/schema_registry_service.h"
#include "chrome/browser/policy/schema_registry_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/storage/storage_schema_manifest_handler.h"
#include "components/policy/core/common/policy_namespace.h"
#include "components/policy/core/common/schema.h"
#include "components/policy/core/common/schema_map.h"
#include "components/policy/core/common/schema_registry.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_source.h"
#include "extensions/browser/api/storage/settings_storage_factory.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/value_store/value_store_change.h"
#include "extensions/common/api/storage.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/manifest.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/one_shot_event.h"
using content::BrowserContext;
using content::BrowserThread;
namespace extensions {
namespace storage = core_api::storage;
namespace {
const char kLoadSchemasBackgroundTaskTokenName[] =
    "load_managed_storage_schemas_token";
const char kLegacyBrowserSupportExtensionId[] =
    "heildphpnddilhkemkielfhnkaagiabh";
}  
class ManagedValueStoreCache::ExtensionTracker
    : public content::NotificationObserver {
 public:
  explicit ExtensionTracker(Profile* profile);
  virtual ~ExtensionTracker() {}
  
  virtual void Observe(int type,
                       const content::NotificationSource& source,
                       const content::NotificationDetails& details) OVERRIDE;
 private:
  
  void OnExtensionsReady();
  
  void LoadSchemas(scoped_ptr<ExtensionSet> added);
  bool UsesManagedStorage(const Extension* extension) const;
  
  
  static void LoadSchemasOnBlockingPool(scoped_ptr<ExtensionSet> extensions,
                                        base::WeakPtr<ExtensionTracker> self);
  void Register(const policy::ComponentMap* components);
  Profile* profile_;
  content::NotificationRegistrar registrar_;
  policy::SchemaRegistry* schema_registry_;
  base::WeakPtrFactory<ExtensionTracker> weak_factory_;
  DISALLOW_COPY_AND_ASSIGN(ExtensionTracker);
};
ManagedValueStoreCache::ExtensionTracker::ExtensionTracker(Profile* profile)
    : profile_(profile),
      schema_registry_(
          policy::SchemaRegistryServiceFactory::GetForContext(profile)),
      weak_factory_(this) {
  registrar_.Add(this,
                 chrome::NOTIFICATION_EXTENSION_INSTALLED,
                 content::Source<Profile>(profile_));
  registrar_.Add(this,
                 chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
                 content::Source<Profile>(profile_));
  
  ExtensionSystem::Get(profile_)->ready().Post(
      FROM_HERE,
      base::Bind(&ExtensionTracker::OnExtensionsReady,
                 weak_factory_.GetWeakPtr()));
}
void ManagedValueStoreCache::ExtensionTracker::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  
  
  
  
  if (!ExtensionSystem::Get(profile_)->ready().is_signaled())
    return;
  switch (type) {
    case chrome::NOTIFICATION_EXTENSION_INSTALLED: {
      scoped_ptr<ExtensionSet> added(new ExtensionSet);
      added->Insert(
          content::Details<InstalledExtensionInfo>(details)->extension);
      LoadSchemas(added.Pass());
      break;
    }
    case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: {
      const Extension* removed =
          content::Details<const Extension>(details).ptr();
      if (removed && UsesManagedStorage(removed)) {
        schema_registry_->UnregisterComponent(policy::PolicyNamespace(
            policy::POLICY_DOMAIN_EXTENSIONS, removed->id()));
      }
      break;
    }
    default:
      NOTREACHED();
      return;
  }
}
void ManagedValueStoreCache::ExtensionTracker::OnExtensionsReady() {
  
  LoadSchemas(
      ExtensionRegistry::Get(profile_)->GenerateInstalledExtensionsSet());
}
void ManagedValueStoreCache::ExtensionTracker::LoadSchemas(
    scoped_ptr<ExtensionSet> added) {
  
  ExtensionSet::const_iterator it = added->begin();
  while (it != added->end()) {
    std::string to_remove;
    if (!UsesManagedStorage(*it))
      to_remove = (*it)->id();
    ++it;
    if (!to_remove.empty())
      added->Remove(to_remove);
  }
  
  BrowserThread::PostBlockingPoolSequencedTask(
      kLoadSchemasBackgroundTaskTokenName, FROM_HERE,
      base::Bind(&ExtensionTracker::LoadSchemasOnBlockingPool,
                 base::Passed(&added),
                 weak_factory_.GetWeakPtr()));
}
bool ManagedValueStoreCache::ExtensionTracker::UsesManagedStorage(
    const Extension* extension) const {
  if (extension->manifest()->HasPath(manifest_keys::kStorageManagedSchema))
    return true;
  
  return extension->id() == kLegacyBrowserSupportExtensionId;
}
void ManagedValueStoreCache::ExtensionTracker::LoadSchemasOnBlockingPool(
    scoped_ptr<ExtensionSet> extensions,
    base::WeakPtr<ExtensionTracker> self) {
  DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
  scoped_ptr<policy::ComponentMap> components(new policy::ComponentMap);
  for (ExtensionSet::const_iterator it = extensions->begin();
       it != extensions->end(); ++it) {
    std::string schema_file;
    if (!(*it)->manifest()->GetString(
            manifest_keys::kStorageManagedSchema, &schema_file)) {
      
      (*components)[(*it)->id()] = policy::Schema();
      continue;
    }
    
    
    std::string error;
    policy::Schema schema =
        StorageSchemaManifestHandler::GetSchema(it->get(), &error);
    CHECK(schema.valid()) << error;
    (*components)[(*it)->id()] = schema;
  }
  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                          base::Bind(&ExtensionTracker::Register, self,
                                     base::Owned(components.release())));
}
void ManagedValueStoreCache::ExtensionTracker::Register(
    const policy::ComponentMap* components) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  schema_registry_->RegisterComponents(policy::POLICY_DOMAIN_EXTENSIONS,
                                       *components);
  
  
  
  
  
  
  schema_registry_->SetReady(policy::POLICY_DOMAIN_EXTENSIONS);
}
ManagedValueStoreCache::ManagedValueStoreCache(
    BrowserContext* context,
    const scoped_refptr<SettingsStorageFactory>& factory,
    const scoped_refptr<SettingsObserverList>& observers)
    : profile_(Profile::FromBrowserContext(context)),
      policy_service_(policy::ProfilePolicyConnectorFactory::GetForProfile(
                          profile_)->policy_service()),
      storage_factory_(factory),
      observers_(observers),
      base_path_(profile_->GetPath().AppendASCII(
          extensions::kManagedSettingsDirectoryName)) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  policy_service_->AddObserver(policy::POLICY_DOMAIN_EXTENSIONS, this);
  extension_tracker_.reset(new ExtensionTracker(profile_));
  if (policy_service_->IsInitializationComplete(
          policy::POLICY_DOMAIN_EXTENSIONS)) {
    OnPolicyServiceInitialized(policy::POLICY_DOMAIN_EXTENSIONS);
  }
}
ManagedValueStoreCache::~ManagedValueStoreCache() {
  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
  
  store_map_.clear();
}
void ManagedValueStoreCache::ShutdownOnUI() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  policy_service_->RemoveObserver(policy::POLICY_DOMAIN_EXTENSIONS, this);
  extension_tracker_.reset();
}
void ManagedValueStoreCache::RunWithValueStoreForExtension(
    const StorageCallback& callback,
    scoped_refptr<const Extension> extension) {
  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
  callback.Run(GetStoreFor(extension->id()));
}
void ManagedValueStoreCache::DeleteStorageSoon(
    const std::string& extension_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
  
  
  
  if (!HasStore(extension_id))
    return;
  GetStoreFor(extension_id)->DeleteStorage();
  store_map_.erase(extension_id);
}
void ManagedValueStoreCache::OnPolicyServiceInitialized(
    policy::PolicyDomain domain) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (domain != policy::POLICY_DOMAIN_EXTENSIONS)
    return;
  
  
  policy::SchemaRegistry* registry =
      policy::SchemaRegistryServiceFactory::GetForContext(profile_);
  const policy::ComponentMap* map = registry->schema_map()->GetComponents(
      policy::POLICY_DOMAIN_EXTENSIONS);
  if (!map)
    return;
  const policy::PolicyMap empty_map;
  for (policy::ComponentMap::const_iterator it = map->begin();
       it != map->end(); ++it) {
    const policy::PolicyNamespace ns(policy::POLICY_DOMAIN_EXTENSIONS,
                                     it->first);
    
    
    OnPolicyUpdated(ns, empty_map, policy_service_->GetPolicies(ns));
  }
}
void ManagedValueStoreCache::OnPolicyUpdated(const policy::PolicyNamespace& ns,
                                             const policy::PolicyMap& previous,
                                             const policy::PolicyMap& current) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (!policy_service_->IsInitializationComplete(
           policy::POLICY_DOMAIN_EXTENSIONS)) {
    
    
    
    return;
  }
  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      base::Bind(&ManagedValueStoreCache::UpdatePolicyOnFILE,
                 base::Unretained(this),
                 ns.component_id,
                 base::Passed(current.DeepCopy())));
}
void ManagedValueStoreCache::UpdatePolicyOnFILE(
    const std::string& extension_id,
    scoped_ptr<policy::PolicyMap> current_policy) {
  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
  if (!HasStore(extension_id) && current_policy->empty()) {
    
    
    
    return;
  }
  GetStoreFor(extension_id)->SetCurrentPolicy(*current_policy);
}
PolicyValueStore* ManagedValueStoreCache::GetStoreFor(
    const std::string& extension_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
  PolicyValueStoreMap::iterator it = store_map_.find(extension_id);
  if (it != store_map_.end())
    return it->second.get();
  
  
  PolicyValueStore* store = new PolicyValueStore(
      extension_id,
      observers_,
      make_scoped_ptr(storage_factory_->Create(base_path_, extension_id)));
  store_map_[extension_id] = make_linked_ptr(store);
  return store;
}
bool ManagedValueStoreCache::HasStore(const std::string& extension_id) const {
  
  return base::DirectoryExists(base_path_.AppendASCII(extension_id));
}
}