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