Home | History | Annotate | Download | only in common
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "components/policy/core/common/schema_map.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/values.h"
      9 #include "components/policy/core/common/policy_bundle.h"
     10 #include "components/policy/core/common/policy_map.h"
     11 
     12 namespace policy {
     13 
     14 SchemaMap::SchemaMap() {}
     15 
     16 SchemaMap::SchemaMap(DomainMap& map) {
     17   map_.swap(map);
     18 }
     19 
     20 SchemaMap::~SchemaMap() {}
     21 
     22 const DomainMap& SchemaMap::GetDomains() const {
     23   return map_;
     24 }
     25 
     26 const ComponentMap* SchemaMap::GetComponents(PolicyDomain domain) const {
     27   DomainMap::const_iterator it = map_.find(domain);
     28   return it == map_.end() ? NULL : &it->second;
     29 }
     30 
     31 const Schema* SchemaMap::GetSchema(const PolicyNamespace& ns) const {
     32   const ComponentMap* map = GetComponents(ns.domain);
     33   if (!map)
     34     return NULL;
     35   ComponentMap::const_iterator it = map->find(ns.component_id);
     36   return it == map->end() ? NULL : &it->second;
     37 }
     38 
     39 void SchemaMap::FilterBundle(PolicyBundle* bundle) const {
     40   for (PolicyBundle::iterator it = bundle->begin(); it != bundle->end(); ++it) {
     41     // Chrome policies are not filtered, so that typos appear in about:policy.
     42     // Everything else gets filtered, so that components only see valid policy.
     43     if (it->first.domain == POLICY_DOMAIN_CHROME)
     44       continue;
     45 
     46     const Schema* schema = GetSchema(it->first);
     47 
     48     if (!schema) {
     49       it->second->Clear();
     50       continue;
     51     }
     52 
     53     // TODO(joaodasilva): if a component is registered but doesn't have a schema
     54     // then its policies aren't filtered. This behavior is enabled to allow a
     55     // graceful update of the Legacy Browser Support extension; it'll be removed
     56     // in a future release. http://crbug.com/240704
     57     static const char kLegacyBrowserSupportExtensionId[] =
     58         "heildphpnddilhkemkielfhnkaagiabh";
     59     if (it->first.domain == POLICY_DOMAIN_EXTENSIONS &&
     60         it->first.component_id == kLegacyBrowserSupportExtensionId) {
     61       continue;
     62     }
     63 
     64     if (!schema->valid()) {
     65       // Don't serve unknown policies.
     66       it->second->Clear();
     67       continue;
     68     }
     69 
     70     PolicyMap* map = it->second;
     71     for (PolicyMap::const_iterator it_map = map->begin();
     72          it_map != map->end();) {
     73       const std::string& policy_name = it_map->first;
     74       const base::Value* policy_value = it_map->second.value;
     75       Schema policy_schema = schema->GetProperty(policy_name);
     76       ++it_map;
     77       std::string error_path;
     78       std::string error;
     79       if (!policy_value ||
     80           !policy_schema.Validate(*policy_value,
     81                                   SCHEMA_STRICT,
     82                                   &error_path,
     83                                   &error)) {
     84         LOG(ERROR) << "Dropping policy " << policy_name << " for "
     85                    << it->first.component_id
     86                    << " because it's not valid: " << error
     87                    << " at " << error_path;
     88         map->Erase(policy_name);
     89       }
     90     }
     91   }
     92 }
     93 
     94 bool SchemaMap::HasComponents() const {
     95   for (DomainMap::const_iterator domain = map_.begin();
     96        domain != map_.end(); ++domain) {
     97     if (domain->first == POLICY_DOMAIN_CHROME)
     98       continue;
     99     if (!domain->second.empty())
    100       return true;
    101   }
    102   return false;
    103 }
    104 
    105 void SchemaMap::GetChanges(const scoped_refptr<SchemaMap>& older,
    106                            PolicyNamespaceList* removed,
    107                            PolicyNamespaceList* added) const {
    108   GetNamespacesNotInOther(older.get(), added);
    109   older->GetNamespacesNotInOther(this, removed);
    110 }
    111 
    112 void SchemaMap::GetNamespacesNotInOther(const SchemaMap* other,
    113                                         PolicyNamespaceList* list) const {
    114   list->clear();
    115   for (DomainMap::const_iterator domain = map_.begin();
    116        domain != map_.end(); ++domain) {
    117     const ComponentMap& components = domain->second;
    118     for (ComponentMap::const_iterator comp = components.begin();
    119          comp != components.end(); ++comp) {
    120       PolicyNamespace ns(domain->first, comp->first);
    121       if (!other->GetSchema(ns))
    122         list->push_back(ns);
    123     }
    124   }
    125 }
    126 
    127 }  // namespace policy
    128