policy_map.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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
12namespace policy {
13
14void PolicyMap::Entry::DeleteOwnedMembers() {
15  delete value;
16  value = NULL;
17  delete external_data_fetcher;
18  external_data_fetcher = NULL;
19}
20
21scoped_ptr<PolicyMap::Entry> PolicyMap::Entry::DeepCopy() const {
22  scoped_ptr<Entry> copy(new Entry);
23  copy->level = level;
24  copy->scope = scope;
25  if (value)
26    copy->value = value->DeepCopy();
27  if (external_data_fetcher) {
28    copy->external_data_fetcher =
29        new ExternalDataFetcher(*external_data_fetcher);
30  }
31  return copy.Pass();
32}
33
34bool PolicyMap::Entry::has_higher_priority_than(
35    const PolicyMap::Entry& other) const {
36  if (level == other.level)
37    return scope > other.scope;
38  else
39    return level > other.level;
40}
41
42bool PolicyMap::Entry::Equals(const PolicyMap::Entry& other) const {
43  return level == other.level &&
44         scope == other.scope &&
45         Value::Equals(value, other.value) &&
46         ExternalDataFetcher::Equals(external_data_fetcher,
47                                     other.external_data_fetcher);
48}
49
50PolicyMap::PolicyMap() {
51}
52
53PolicyMap::~PolicyMap() {
54  Clear();
55}
56
57const PolicyMap::Entry* PolicyMap::Get(const std::string& policy) const {
58  PolicyMapType::const_iterator entry = map_.find(policy);
59  return entry == map_.end() ? NULL : &entry->second;
60}
61
62const Value* PolicyMap::GetValue(const std::string& policy) const {
63  PolicyMapType::const_iterator entry = map_.find(policy);
64  return entry == map_.end() ? NULL : entry->second.value;
65}
66
67void PolicyMap::Set(const std::string& policy,
68                    PolicyLevel level,
69                    PolicyScope scope,
70                    Value* value,
71                    ExternalDataFetcher* external_data_fetcher) {
72  Entry& entry = map_[policy];
73  entry.DeleteOwnedMembers();
74  entry.level = level;
75  entry.scope = scope;
76  entry.value = value;
77  entry.external_data_fetcher = external_data_fetcher;
78}
79
80void PolicyMap::Erase(const std::string& policy) {
81  PolicyMapType::iterator it = map_.find(policy);
82  if (it != map_.end()) {
83    it->second.DeleteOwnedMembers();
84    map_.erase(it);
85  }
86}
87
88void PolicyMap::Swap(PolicyMap* other) {
89  map_.swap(other->map_);
90}
91
92void PolicyMap::CopyFrom(const PolicyMap& other) {
93  Clear();
94  for (const_iterator it = other.begin(); it != other.end(); ++it) {
95    const Entry& entry = it->second;
96    Set(it->first, entry.level, entry.scope,
97        entry.value->DeepCopy(), entry.external_data_fetcher ?
98            new ExternalDataFetcher(*entry.external_data_fetcher) : NULL);
99  }
100}
101
102scoped_ptr<PolicyMap> PolicyMap::DeepCopy() const {
103  PolicyMap* copy = new PolicyMap();
104  copy->CopyFrom(*this);
105  return make_scoped_ptr(copy);
106}
107
108void PolicyMap::MergeFrom(const PolicyMap& other) {
109  for (const_iterator it = other.begin(); it != other.end(); ++it) {
110    const Entry* entry = Get(it->first);
111    if (!entry || it->second.has_higher_priority_than(*entry)) {
112      Set(it->first, it->second.level, it->second.scope,
113          it->second.value->DeepCopy(), it->second.external_data_fetcher ?
114              new ExternalDataFetcher(*it->second.external_data_fetcher) :
115              NULL);
116    }
117  }
118}
119
120void PolicyMap::LoadFrom(
121    const DictionaryValue* policies,
122    PolicyLevel level,
123    PolicyScope scope) {
124  for (DictionaryValue::Iterator it(*policies); !it.IsAtEnd(); it.Advance())
125    Set(it.key(), level, scope, it.value().DeepCopy(), NULL);
126}
127
128void PolicyMap::GetDifferingKeys(const PolicyMap& other,
129                                 std::set<std::string>* differing_keys) const {
130  // Walk over the maps in lockstep, adding everything that is different.
131  const_iterator iter_this(begin());
132  const_iterator iter_other(other.begin());
133  while (iter_this != end() && iter_other != other.end()) {
134    const int diff = iter_this->first.compare(iter_other->first);
135    if (diff == 0) {
136      if (!iter_this->second.Equals(iter_other->second))
137        differing_keys->insert(iter_this->first);
138      ++iter_this;
139      ++iter_other;
140    } else if (diff < 0) {
141      differing_keys->insert(iter_this->first);
142      ++iter_this;
143    } else {
144      differing_keys->insert(iter_other->first);
145      ++iter_other;
146    }
147  }
148
149  // Add the remaining entries.
150  for ( ; iter_this != end(); ++iter_this)
151      differing_keys->insert(iter_this->first);
152  for ( ; iter_other != other.end(); ++iter_other)
153      differing_keys->insert(iter_other->first);
154}
155
156void PolicyMap::FilterLevel(PolicyLevel level) {
157  PolicyMapType::iterator iter(map_.begin());
158  while (iter != map_.end()) {
159    if (iter->second.level != level) {
160      iter->second.DeleteOwnedMembers();
161      map_.erase(iter++);
162    } else {
163      ++iter;
164    }
165  }
166}
167
168bool PolicyMap::Equals(const PolicyMap& other) const {
169  return other.size() == size() &&
170      std::equal(begin(), end(), other.begin(), MapEntryEquals);
171}
172
173bool PolicyMap::empty() const {
174  return map_.empty();
175}
176
177size_t PolicyMap::size() const {
178  return map_.size();
179}
180
181PolicyMap::const_iterator PolicyMap::begin() const {
182  return map_.begin();
183}
184
185PolicyMap::const_iterator PolicyMap::end() const {
186  return map_.end();
187}
188
189void PolicyMap::Clear() {
190  for (PolicyMapType::iterator it = map_.begin(); it != map_.end(); ++it)
191    it->second.DeleteOwnedMembers();
192  map_.clear();
193}
194
195// static
196bool PolicyMap::MapEntryEquals(const PolicyMap::PolicyMapType::value_type& a,
197                               const PolicyMap::PolicyMapType::value_type& b) {
198  return a.first == b.first && a.second.Equals(b.second);
199}
200
201}  // namespace policy
202