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 12namespace policy { 13 14bool 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 22bool 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 30PolicyMap::PolicyMap() { 31} 32 33PolicyMap::~PolicyMap() { 34 Clear(); 35} 36 37const 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 42const 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 47void 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 61void 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 70void PolicyMap::Swap(PolicyMap* other) { 71 map_.swap(other->map_); 72} 73 74void 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 84scoped_ptr<PolicyMap> PolicyMap::DeepCopy() const { 85 PolicyMap* copy = new PolicyMap(); 86 copy->CopyFrom(*this); 87 return make_scoped_ptr(copy); 88} 89 90void 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 102void 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 110void 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 138void 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 151bool PolicyMap::Equals(const PolicyMap& other) const { 152 return other.size() == size() && 153 std::equal(begin(), end(), other.begin(), MapEntryEquals); 154} 155 156bool PolicyMap::empty() const { 157 return map_.empty(); 158} 159 160size_t PolicyMap::size() const { 161 return map_.size(); 162} 163 164PolicyMap::const_iterator PolicyMap::begin() const { 165 return map_.begin(); 166} 167 168PolicyMap::const_iterator PolicyMap::end() const { 169 return map_.end(); 170} 171 172void 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 181bool 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