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