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
Entry()14 PolicyMap::Entry::Entry()
15 : level(POLICY_LEVEL_RECOMMENDED),
16 scope(POLICY_SCOPE_USER),
17 value(NULL),
18 external_data_fetcher(NULL) {}
19
DeleteOwnedMembers()20 void PolicyMap::Entry::DeleteOwnedMembers() {
21 delete value;
22 value = NULL;
23 delete external_data_fetcher;
24 external_data_fetcher = NULL;
25 }
26
DeepCopy() const27 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
has_higher_priority_than(const PolicyMap::Entry & other) const40 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
Equals(const PolicyMap::Entry & other) const48 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
PolicyMap()56 PolicyMap::PolicyMap() {
57 }
58
~PolicyMap()59 PolicyMap::~PolicyMap() {
60 Clear();
61 }
62
Get(const std::string & policy) const63 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
GetValue(const std::string & policy) const68 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
Set(const std::string & policy,PolicyLevel level,PolicyScope scope,base::Value * value,ExternalDataFetcher * external_data_fetcher)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
Erase(const std::string & policy)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
Swap(PolicyMap * other)94 void PolicyMap::Swap(PolicyMap* other) {
95 map_.swap(other->map_);
96 }
97
CopyFrom(const PolicyMap & other)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
DeepCopy() const108 scoped_ptr<PolicyMap> PolicyMap::DeepCopy() const {
109 PolicyMap* copy = new PolicyMap();
110 copy->CopyFrom(*this);
111 return make_scoped_ptr(copy);
112 }
113
MergeFrom(const PolicyMap & other)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
LoadFrom(const base::DictionaryValue * policies,PolicyLevel level,PolicyScope scope)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
GetDifferingKeys(const PolicyMap & other,std::set<std::string> * differing_keys) const136 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
FilterLevel(PolicyLevel level)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
Equals(const PolicyMap & other) const176 bool PolicyMap::Equals(const PolicyMap& other) const {
177 return other.size() == size() &&
178 std::equal(begin(), end(), other.begin(), MapEntryEquals);
179 }
180
empty() const181 bool PolicyMap::empty() const {
182 return map_.empty();
183 }
184
size() const185 size_t PolicyMap::size() const {
186 return map_.size();
187 }
188
begin() const189 PolicyMap::const_iterator PolicyMap::begin() const {
190 return map_.begin();
191 }
192
end() const193 PolicyMap::const_iterator PolicyMap::end() const {
194 return map_.end();
195 }
196
Clear()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
MapEntryEquals(const PolicyMap::PolicyMapType::value_type & a,const PolicyMap::PolicyMapType::value_type & b)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