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() = default;
15
16 PolicyMap::Entry::~Entry() = default;
17
18 PolicyMap::Entry::Entry(Entry&&) noexcept = default;
19 PolicyMap::Entry& PolicyMap::Entry::operator=(Entry&&) noexcept = default;
20
DeepCopy() const21 PolicyMap::Entry PolicyMap::Entry::DeepCopy() const {
22 Entry copy;
23 copy.level = level;
24 copy.scope = scope;
25 copy.source = source;
26 if (value)
27 copy.value = value->CreateDeepCopy();
28 copy.error = error;
29 if (external_data_fetcher) {
30 copy.external_data_fetcher.reset(
31 new ExternalDataFetcher(*external_data_fetcher));
32 }
33 return copy;
34 }
35
has_higher_priority_than(const PolicyMap::Entry & other) const36 bool PolicyMap::Entry::has_higher_priority_than(
37 const PolicyMap::Entry& other) const {
38 if (level != other.level)
39 return level > other.level;
40
41 if (scope != other.scope)
42 return scope > other.scope;
43
44 return source > other.source;
45 }
46
Equals(const PolicyMap::Entry & other) const47 bool PolicyMap::Entry::Equals(const PolicyMap::Entry& other) const {
48 return level == other.level && scope == other.scope &&
49 source == other.source && // Necessary for PolicyUIHandler observers.
50 // They have to update when sources change.
51 error == other.error &&
52 ((!value && !other.value) ||
53 (value && other.value && *value == *other.value)) &&
54 ExternalDataFetcher::Equals(external_data_fetcher.get(),
55 other.external_data_fetcher.get());
56 }
57
PolicyMap()58 PolicyMap::PolicyMap() {}
59
~PolicyMap()60 PolicyMap::~PolicyMap() {
61 Clear();
62 }
63
Get(const std::string & policy) const64 const PolicyMap::Entry* PolicyMap::Get(const std::string& policy) const {
65 PolicyMapType::const_iterator entry = map_.find(policy);
66 return entry == map_.end() ? nullptr : &entry->second;
67 }
68
GetMutable(const std::string & policy)69 PolicyMap::Entry* PolicyMap::GetMutable(const std::string& policy) {
70 PolicyMapType::iterator entry = map_.find(policy);
71 return entry == map_.end() ? nullptr : &entry->second;
72 }
73
GetValue(const std::string & policy) const74 const base::Value* PolicyMap::GetValue(const std::string& policy) const {
75 PolicyMapType::const_iterator entry = map_.find(policy);
76 return entry == map_.end() ? nullptr : entry->second.value.get();
77 }
78
GetMutableValue(const std::string & policy)79 base::Value* PolicyMap::GetMutableValue(const std::string& policy) {
80 PolicyMapType::iterator entry = map_.find(policy);
81 return entry == map_.end() ? nullptr : entry->second.value.get();
82 }
83
Set(const std::string & policy,PolicyLevel level,PolicyScope scope,PolicySource source,std::unique_ptr<base::Value> value,std::unique_ptr<ExternalDataFetcher> external_data_fetcher)84 void PolicyMap::Set(
85 const std::string& policy,
86 PolicyLevel level,
87 PolicyScope scope,
88 PolicySource source,
89 std::unique_ptr<base::Value> value,
90 std::unique_ptr<ExternalDataFetcher> external_data_fetcher) {
91 Entry entry;
92 entry.level = level;
93 entry.scope = scope;
94 entry.source = source;
95 entry.value = std::move(value);
96 entry.external_data_fetcher = std::move(external_data_fetcher);
97 Set(policy, std::move(entry));
98 }
99
Set(const std::string & policy,Entry entry)100 void PolicyMap::Set(const std::string& policy, Entry entry) {
101 map_[policy] = std::move(entry);
102 }
103
SetError(const std::string & policy,const std::string & error)104 void PolicyMap::SetError(const std::string& policy, const std::string& error) {
105 map_[policy].error = error;
106 }
107
SetSourceForAll(PolicySource source)108 void PolicyMap::SetSourceForAll(PolicySource source) {
109 for (auto& it : map_) {
110 it.second.source = source;
111 }
112 }
113
Erase(const std::string & policy)114 void PolicyMap::Erase(const std::string& policy) {
115 map_.erase(policy);
116 }
117
EraseMatching(const base::Callback<bool (const const_iterator)> & filter)118 void PolicyMap::EraseMatching(
119 const base::Callback<bool(const const_iterator)>& filter) {
120 FilterErase(filter, true);
121 }
122
EraseNonmatching(const base::Callback<bool (const const_iterator)> & filter)123 void PolicyMap::EraseNonmatching(
124 const base::Callback<bool(const const_iterator)>& filter) {
125 FilterErase(filter, false);
126 }
127
Swap(PolicyMap * other)128 void PolicyMap::Swap(PolicyMap* other) {
129 map_.swap(other->map_);
130 }
131
CopyFrom(const PolicyMap & other)132 void PolicyMap::CopyFrom(const PolicyMap& other) {
133 Clear();
134 for (const auto& it : other)
135 Set(it.first, it.second.DeepCopy());
136 }
137
DeepCopy() const138 std::unique_ptr<PolicyMap> PolicyMap::DeepCopy() const {
139 std::unique_ptr<PolicyMap> copy(new PolicyMap());
140 copy->CopyFrom(*this);
141 return copy;
142 }
143
MergeFrom(const PolicyMap & other)144 void PolicyMap::MergeFrom(const PolicyMap& other) {
145 for (const auto& it : other) {
146 const Entry* entry = Get(it.first);
147 if (!entry || it.second.has_higher_priority_than(*entry))
148 Set(it.first, it.second.DeepCopy());
149 }
150 }
151
LoadFrom(const base::DictionaryValue * policies,PolicyLevel level,PolicyScope scope,PolicySource source)152 void PolicyMap::LoadFrom(const base::DictionaryValue* policies,
153 PolicyLevel level,
154 PolicyScope scope,
155 PolicySource source) {
156 for (base::DictionaryValue::Iterator it(*policies); !it.IsAtEnd();
157 it.Advance()) {
158 Set(it.key(), level, scope, source, it.value().CreateDeepCopy(), nullptr);
159 }
160 }
161
GetDifferingKeys(const PolicyMap & other,std::set<std::string> * differing_keys) const162 void PolicyMap::GetDifferingKeys(const PolicyMap& other,
163 std::set<std::string>* differing_keys) const {
164 // Walk over the maps in lockstep, adding everything that is different.
165 const_iterator iter_this(begin());
166 const_iterator iter_other(other.begin());
167 while (iter_this != end() && iter_other != other.end()) {
168 const int diff = iter_this->first.compare(iter_other->first);
169 if (diff == 0) {
170 if (!iter_this->second.Equals(iter_other->second))
171 differing_keys->insert(iter_this->first);
172 ++iter_this;
173 ++iter_other;
174 } else if (diff < 0) {
175 differing_keys->insert(iter_this->first);
176 ++iter_this;
177 } else {
178 differing_keys->insert(iter_other->first);
179 ++iter_other;
180 }
181 }
182
183 // Add the remaining entries.
184 for (; iter_this != end(); ++iter_this)
185 differing_keys->insert(iter_this->first);
186 for (; iter_other != other.end(); ++iter_other)
187 differing_keys->insert(iter_other->first);
188 }
189
Equals(const PolicyMap & other) const190 bool PolicyMap::Equals(const PolicyMap& other) const {
191 return other.size() == size() &&
192 std::equal(begin(), end(), other.begin(), MapEntryEquals);
193 }
194
empty() const195 bool PolicyMap::empty() const {
196 return map_.empty();
197 }
198
size() const199 size_t PolicyMap::size() const {
200 return map_.size();
201 }
202
begin() const203 PolicyMap::const_iterator PolicyMap::begin() const {
204 return map_.begin();
205 }
206
end() const207 PolicyMap::const_iterator PolicyMap::end() const {
208 return map_.end();
209 }
210
Clear()211 void PolicyMap::Clear() {
212 map_.clear();
213 }
214
215 // static
MapEntryEquals(const PolicyMap::PolicyMapType::value_type & a,const PolicyMap::PolicyMapType::value_type & b)216 bool PolicyMap::MapEntryEquals(const PolicyMap::PolicyMapType::value_type& a,
217 const PolicyMap::PolicyMapType::value_type& b) {
218 return a.first == b.first && a.second.Equals(b.second);
219 }
220
FilterErase(const base::Callback<bool (const const_iterator)> & filter,bool deletion_value)221 void PolicyMap::FilterErase(
222 const base::Callback<bool(const const_iterator)>& filter,
223 bool deletion_value) {
224 PolicyMapType::iterator iter(map_.begin());
225 while (iter != map_.end()) {
226 if (filter.Run(iter) == deletion_value) {
227 map_.erase(iter++);
228 } else {
229 ++iter;
230 }
231 }
232 }
233
234 } // namespace policy
235