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_bundle.h" 6 7 #include "base/logging.h" 8 9 namespace policy { 10 PolicyBundle()11PolicyBundle::PolicyBundle() {} 12 ~PolicyBundle()13PolicyBundle::~PolicyBundle() { 14 Clear(); 15 } 16 Get(const PolicyNamespace & ns)17PolicyMap& PolicyBundle::Get(const PolicyNamespace& ns) { 18 DCHECK(ns.domain != POLICY_DOMAIN_CHROME || ns.component_id.empty()); 19 std::unique_ptr<PolicyMap>& policy = policy_bundle_[ns]; 20 if (!policy) 21 policy = std::make_unique<PolicyMap>(); 22 return *policy; 23 } 24 Get(const PolicyNamespace & ns) const25const PolicyMap& PolicyBundle::Get(const PolicyNamespace& ns) const { 26 DCHECK(ns.domain != POLICY_DOMAIN_CHROME || ns.component_id.empty()); 27 const_iterator it = policy_bundle_.find(ns); 28 return it == end() ? kEmpty_ : *it->second; 29 } 30 Swap(PolicyBundle * other)31void PolicyBundle::Swap(PolicyBundle* other) { 32 policy_bundle_.swap(other->policy_bundle_); 33 } 34 CopyFrom(const PolicyBundle & other)35void PolicyBundle::CopyFrom(const PolicyBundle& other) { 36 Clear(); 37 for (auto it = other.begin(); it != other.end(); ++it) { 38 policy_bundle_[it->first] = it->second->DeepCopy(); 39 } 40 } 41 MergeFrom(const PolicyBundle & other)42void PolicyBundle::MergeFrom(const PolicyBundle& other) { 43 // Iterate over both |this| and |other| in order; skip what's extra in |this|, 44 // add what's missing, and merge the namespaces in common. 45 MapType::iterator it_this = policy_bundle_.begin(); 46 MapType::iterator end_this = policy_bundle_.end(); 47 const_iterator it_other = other.begin(); 48 const_iterator end_other = other.end(); 49 50 while (it_this != end_this && it_other != end_other) { 51 if (it_this->first == it_other->first) { 52 // Same namespace: merge existing PolicyMaps. 53 it_this->second->MergeFrom(*it_other->second); 54 ++it_this; 55 ++it_other; 56 } else if (it_this->first < it_other->first) { 57 // |this| has a PolicyMap that |other| doesn't; skip it. 58 ++it_this; 59 } else if (it_other->first < it_this->first) { 60 // |other| has a PolicyMap that |this| doesn't; copy it. 61 policy_bundle_[it_other->first] = it_other->second->DeepCopy(); 62 ++it_other; 63 } else { 64 NOTREACHED(); 65 } 66 } 67 68 // Add extra PolicyMaps at the end. 69 while (it_other != end_other) { 70 policy_bundle_[it_other->first] = it_other->second->DeepCopy(); 71 ++it_other; 72 } 73 } 74 Equals(const PolicyBundle & other) const75bool PolicyBundle::Equals(const PolicyBundle& other) const { 76 // Equals() has the peculiarity that an entry with an empty PolicyMap equals 77 // an non-existent entry. This handles usage of non-const Get() that doesn't 78 // insert any policies. 79 const_iterator it_this = begin(); 80 const_iterator it_other = other.begin(); 81 82 while (true) { 83 // Skip empty PolicyMaps. 84 while (it_this != end() && it_this->second->empty()) 85 ++it_this; 86 while (it_other != other.end() && it_other->second->empty()) 87 ++it_other; 88 if (it_this == end() || it_other == other.end()) 89 break; 90 if (it_this->first != it_other->first || 91 !it_this->second->Equals(*it_other->second)) { 92 return false; 93 } 94 ++it_this; 95 ++it_other; 96 } 97 return it_this == end() && it_other == other.end(); 98 } 99 Clear()100void PolicyBundle::Clear() { 101 policy_bundle_.clear(); 102 } 103 104 } // namespace policy 105