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