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/policy_map.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "base/callback.h"
     10 #include "base/stl_util.h"
     11 
     12 namespace policy {
     13 
     14 PolicyMap::Entry::Entry()
     15     : level(POLICY_LEVEL_RECOMMENDED),
     16       scope(POLICY_SCOPE_USER),
     17       value(NULL),
     18       external_data_fetcher(NULL) {}
     19 
     20 void PolicyMap::Entry::DeleteOwnedMembers() {
     21   delete value;
     22   value = NULL;
     23   delete external_data_fetcher;
     24   external_data_fetcher = NULL;
     25 }
     26 
     27 scoped_ptr<PolicyMap::Entry> PolicyMap::Entry::DeepCopy() const {
     28   scoped_ptr<Entry> copy(new Entry);
     29   copy->level = level;
     30   copy->scope = scope;
     31   if (value)
     32     copy->value = value->DeepCopy();
     33   if (external_data_fetcher) {
     34     copy->external_data_fetcher =
     35         new ExternalDataFetcher(*external_data_fetcher);
     36   }
     37   return copy.Pass();
     38 }
     39 
     40 bool PolicyMap::Entry::has_higher_priority_than(
     41     const PolicyMap::Entry& other) const {
     42   if (level == other.level)
     43     return scope > other.scope;
     44   else
     45     return level > other.level;
     46 }
     47 
     48 bool PolicyMap::Entry::Equals(const PolicyMap::Entry& other) const {
     49   return level == other.level &&
     50          scope == other.scope &&
     51          base::Value::Equals(value, other.value) &&
     52          ExternalDataFetcher::Equals(external_data_fetcher,
     53                                      other.external_data_fetcher);
     54 }
     55 
     56 PolicyMap::PolicyMap() {
     57 }
     58 
     59 PolicyMap::~PolicyMap() {
     60   Clear();
     61 }
     62 
     63 const PolicyMap::Entry* PolicyMap::Get(const std::string& policy) const {
     64   PolicyMapType::const_iterator entry = map_.find(policy);
     65   return entry == map_.end() ? NULL : &entry->second;
     66 }
     67 
     68 const base::Value* PolicyMap::GetValue(const std::string& policy) const {
     69   PolicyMapType::const_iterator entry = map_.find(policy);
     70   return entry == map_.end() ? NULL : entry->second.value;
     71 }
     72 
     73 void PolicyMap::Set(const std::string& policy,
     74                     PolicyLevel level,
     75                     PolicyScope scope,
     76                     base::Value* value,
     77                     ExternalDataFetcher* external_data_fetcher) {
     78   Entry& entry = map_[policy];
     79   entry.DeleteOwnedMembers();
     80   entry.level = level;
     81   entry.scope = scope;
     82   entry.value = value;
     83   entry.external_data_fetcher = external_data_fetcher;
     84 }
     85 
     86 void PolicyMap::Erase(const std::string& policy) {
     87   PolicyMapType::iterator it = map_.find(policy);
     88   if (it != map_.end()) {
     89     it->second.DeleteOwnedMembers();
     90     map_.erase(it);
     91   }
     92 }
     93 
     94 void PolicyMap::Swap(PolicyMap* other) {
     95   map_.swap(other->map_);
     96 }
     97 
     98 void PolicyMap::CopyFrom(const PolicyMap& other) {
     99   Clear();
    100   for (const_iterator it = other.begin(); it != other.end(); ++it) {
    101     const Entry& entry = it->second;
    102     Set(it->first, entry.level, entry.scope,
    103         entry.value->DeepCopy(), entry.external_data_fetcher ?
    104             new ExternalDataFetcher(*entry.external_data_fetcher) : NULL);
    105   }
    106 }
    107 
    108 scoped_ptr<PolicyMap> PolicyMap::DeepCopy() const {
    109   PolicyMap* copy = new PolicyMap();
    110   copy->CopyFrom(*this);
    111   return make_scoped_ptr(copy);
    112 }
    113 
    114 void PolicyMap::MergeFrom(const PolicyMap& other) {
    115   for (const_iterator it = other.begin(); it != other.end(); ++it) {
    116     const Entry* entry = Get(it->first);
    117     if (!entry || it->second.has_higher_priority_than(*entry)) {
    118       Set(it->first, it->second.level, it->second.scope,
    119           it->second.value->DeepCopy(), it->second.external_data_fetcher ?
    120               new ExternalDataFetcher(*it->second.external_data_fetcher) :
    121               NULL);
    122     }
    123   }
    124 }
    125 
    126 void PolicyMap::LoadFrom(
    127     const base::DictionaryValue* policies,
    128     PolicyLevel level,
    129     PolicyScope scope) {
    130   for (base::DictionaryValue::Iterator it(*policies);
    131        !it.IsAtEnd(); it.Advance()) {
    132     Set(it.key(), level, scope, it.value().DeepCopy(), NULL);
    133   }
    134 }
    135 
    136 void PolicyMap::GetDifferingKeys(const PolicyMap& other,
    137                                  std::set<std::string>* differing_keys) const {
    138   // Walk over the maps in lockstep, adding everything that is different.
    139   const_iterator iter_this(begin());
    140   const_iterator iter_other(other.begin());
    141   while (iter_this != end() && iter_other != other.end()) {
    142     const int diff = iter_this->first.compare(iter_other->first);
    143     if (diff == 0) {
    144       if (!iter_this->second.Equals(iter_other->second))
    145         differing_keys->insert(iter_this->first);
    146       ++iter_this;
    147       ++iter_other;
    148     } else if (diff < 0) {
    149       differing_keys->insert(iter_this->first);
    150       ++iter_this;
    151     } else {
    152       differing_keys->insert(iter_other->first);
    153       ++iter_other;
    154     }
    155   }
    156 
    157   // Add the remaining entries.
    158   for ( ; iter_this != end(); ++iter_this)
    159       differing_keys->insert(iter_this->first);
    160   for ( ; iter_other != other.end(); ++iter_other)
    161       differing_keys->insert(iter_other->first);
    162 }
    163 
    164 void PolicyMap::FilterLevel(PolicyLevel level) {
    165   PolicyMapType::iterator iter(map_.begin());
    166   while (iter != map_.end()) {
    167     if (iter->second.level != level) {
    168       iter->second.DeleteOwnedMembers();
    169       map_.erase(iter++);
    170     } else {
    171       ++iter;
    172     }
    173   }
    174 }
    175 
    176 bool PolicyMap::Equals(const PolicyMap& other) const {
    177   return other.size() == size() &&
    178       std::equal(begin(), end(), other.begin(), MapEntryEquals);
    179 }
    180 
    181 bool PolicyMap::empty() const {
    182   return map_.empty();
    183 }
    184 
    185 size_t PolicyMap::size() const {
    186   return map_.size();
    187 }
    188 
    189 PolicyMap::const_iterator PolicyMap::begin() const {
    190   return map_.begin();
    191 }
    192 
    193 PolicyMap::const_iterator PolicyMap::end() const {
    194   return map_.end();
    195 }
    196 
    197 void PolicyMap::Clear() {
    198   for (PolicyMapType::iterator it = map_.begin(); it != map_.end(); ++it)
    199     it->second.DeleteOwnedMembers();
    200   map_.clear();
    201 }
    202 
    203 // static
    204 bool PolicyMap::MapEntryEquals(const PolicyMap::PolicyMapType::value_type& a,
    205                                const PolicyMap::PolicyMapType::value_type& b) {
    206   return a.first == b.first && a.second.Equals(b.second);
    207 }
    208 
    209 }  // namespace policy
    210