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