summaryrefslogtreecommitdiff
path: root/components/policy/core/common/policy_map.cc
diff options
context:
space:
mode:
Diffstat (limited to 'components/policy/core/common/policy_map.cc')
-rw-r--r--components/policy/core/common/policy_map.cc234
1 files changed, 234 insertions, 0 deletions
diff --git a/components/policy/core/common/policy_map.cc b/components/policy/core/common/policy_map.cc
new file mode 100644
index 0000000000..50750bbd62
--- /dev/null
+++ b/components/policy/core/common/policy_map.cc
@@ -0,0 +1,234 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/policy/core/common/policy_map.h"
+
+#include <algorithm>
+
+#include "base/callback.h"
+#include "base/stl_util.h"
+
+namespace policy {
+
+PolicyMap::Entry::Entry() = default;
+
+PolicyMap::Entry::~Entry() = default;
+
+PolicyMap::Entry::Entry(Entry&&) noexcept = default;
+PolicyMap::Entry& PolicyMap::Entry::operator=(Entry&&) noexcept = default;
+
+PolicyMap::Entry PolicyMap::Entry::DeepCopy() const {
+ Entry copy;
+ copy.level = level;
+ copy.scope = scope;
+ copy.source = source;
+ if (value)
+ copy.value = value->CreateDeepCopy();
+ copy.error = error;
+ if (external_data_fetcher) {
+ copy.external_data_fetcher.reset(
+ new ExternalDataFetcher(*external_data_fetcher));
+ }
+ return copy;
+}
+
+bool PolicyMap::Entry::has_higher_priority_than(
+ const PolicyMap::Entry& other) const {
+ if (level != other.level)
+ return level > other.level;
+
+ if (scope != other.scope)
+ return scope > other.scope;
+
+ return source > other.source;
+}
+
+bool PolicyMap::Entry::Equals(const PolicyMap::Entry& other) const {
+ return level == other.level && scope == other.scope &&
+ source == other.source && // Necessary for PolicyUIHandler observers.
+ // They have to update when sources change.
+ error == other.error &&
+ ((!value && !other.value) ||
+ (value && other.value && *value == *other.value)) &&
+ ExternalDataFetcher::Equals(external_data_fetcher.get(),
+ other.external_data_fetcher.get());
+}
+
+PolicyMap::PolicyMap() {}
+
+PolicyMap::~PolicyMap() {
+ Clear();
+}
+
+const PolicyMap::Entry* PolicyMap::Get(const std::string& policy) const {
+ PolicyMapType::const_iterator entry = map_.find(policy);
+ return entry == map_.end() ? nullptr : &entry->second;
+}
+
+PolicyMap::Entry* PolicyMap::GetMutable(const std::string& policy) {
+ PolicyMapType::iterator entry = map_.find(policy);
+ return entry == map_.end() ? nullptr : &entry->second;
+}
+
+const base::Value* PolicyMap::GetValue(const std::string& policy) const {
+ PolicyMapType::const_iterator entry = map_.find(policy);
+ return entry == map_.end() ? nullptr : entry->second.value.get();
+}
+
+base::Value* PolicyMap::GetMutableValue(const std::string& policy) {
+ PolicyMapType::iterator entry = map_.find(policy);
+ return entry == map_.end() ? nullptr : entry->second.value.get();
+}
+
+void PolicyMap::Set(
+ const std::string& policy,
+ PolicyLevel level,
+ PolicyScope scope,
+ PolicySource source,
+ std::unique_ptr<base::Value> value,
+ std::unique_ptr<ExternalDataFetcher> external_data_fetcher) {
+ Entry entry;
+ entry.level = level;
+ entry.scope = scope;
+ entry.source = source;
+ entry.value = std::move(value);
+ entry.external_data_fetcher = std::move(external_data_fetcher);
+ Set(policy, std::move(entry));
+}
+
+void PolicyMap::Set(const std::string& policy, Entry entry) {
+ map_[policy] = std::move(entry);
+}
+
+void PolicyMap::SetError(const std::string& policy, const std::string& error) {
+ map_[policy].error = error;
+}
+
+void PolicyMap::SetSourceForAll(PolicySource source) {
+ for (auto& it : map_) {
+ it.second.source = source;
+ }
+}
+
+void PolicyMap::Erase(const std::string& policy) {
+ map_.erase(policy);
+}
+
+void PolicyMap::EraseMatching(
+ const base::Callback<bool(const const_iterator)>& filter) {
+ FilterErase(filter, true);
+}
+
+void PolicyMap::EraseNonmatching(
+ const base::Callback<bool(const const_iterator)>& filter) {
+ FilterErase(filter, false);
+}
+
+void PolicyMap::Swap(PolicyMap* other) {
+ map_.swap(other->map_);
+}
+
+void PolicyMap::CopyFrom(const PolicyMap& other) {
+ Clear();
+ for (const auto& it : other)
+ Set(it.first, it.second.DeepCopy());
+}
+
+std::unique_ptr<PolicyMap> PolicyMap::DeepCopy() const {
+ std::unique_ptr<PolicyMap> copy(new PolicyMap());
+ copy->CopyFrom(*this);
+ return copy;
+}
+
+void PolicyMap::MergeFrom(const PolicyMap& other) {
+ for (const auto& it : other) {
+ const Entry* entry = Get(it.first);
+ if (!entry || it.second.has_higher_priority_than(*entry))
+ Set(it.first, it.second.DeepCopy());
+ }
+}
+
+void PolicyMap::LoadFrom(const base::DictionaryValue* policies,
+ PolicyLevel level,
+ PolicyScope scope,
+ PolicySource source) {
+ for (base::DictionaryValue::Iterator it(*policies); !it.IsAtEnd();
+ it.Advance()) {
+ Set(it.key(), level, scope, source, it.value().CreateDeepCopy(), nullptr);
+ }
+}
+
+void PolicyMap::GetDifferingKeys(const PolicyMap& other,
+ std::set<std::string>* differing_keys) const {
+ // Walk over the maps in lockstep, adding everything that is different.
+ const_iterator iter_this(begin());
+ const_iterator iter_other(other.begin());
+ while (iter_this != end() && iter_other != other.end()) {
+ const int diff = iter_this->first.compare(iter_other->first);
+ if (diff == 0) {
+ if (!iter_this->second.Equals(iter_other->second))
+ differing_keys->insert(iter_this->first);
+ ++iter_this;
+ ++iter_other;
+ } else if (diff < 0) {
+ differing_keys->insert(iter_this->first);
+ ++iter_this;
+ } else {
+ differing_keys->insert(iter_other->first);
+ ++iter_other;
+ }
+ }
+
+ // Add the remaining entries.
+ for (; iter_this != end(); ++iter_this)
+ differing_keys->insert(iter_this->first);
+ for (; iter_other != other.end(); ++iter_other)
+ differing_keys->insert(iter_other->first);
+}
+
+bool PolicyMap::Equals(const PolicyMap& other) const {
+ return other.size() == size() &&
+ std::equal(begin(), end(), other.begin(), MapEntryEquals);
+}
+
+bool PolicyMap::empty() const {
+ return map_.empty();
+}
+
+size_t PolicyMap::size() const {
+ return map_.size();
+}
+
+PolicyMap::const_iterator PolicyMap::begin() const {
+ return map_.begin();
+}
+
+PolicyMap::const_iterator PolicyMap::end() const {
+ return map_.end();
+}
+
+void PolicyMap::Clear() {
+ map_.clear();
+}
+
+// static
+bool PolicyMap::MapEntryEquals(const PolicyMap::PolicyMapType::value_type& a,
+ const PolicyMap::PolicyMapType::value_type& b) {
+ return a.first == b.first && a.second.Equals(b.second);
+}
+
+void PolicyMap::FilterErase(
+ const base::Callback<bool(const const_iterator)>& filter,
+ bool deletion_value) {
+ PolicyMapType::iterator iter(map_.begin());
+ while (iter != map_.end()) {
+ if (filter.Run(iter) == deletion_value) {
+ map_.erase(iter++);
+ } else {
+ ++iter;
+ }
+ }
+}
+
+} // namespace policy