• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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()11 PolicyBundle::PolicyBundle() {}
12 
~PolicyBundle()13 PolicyBundle::~PolicyBundle() {
14   Clear();
15 }
16 
Get(const PolicyNamespace & ns)17 PolicyMap& 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) const25 const 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)31 void PolicyBundle::Swap(PolicyBundle* other) {
32   policy_bundle_.swap(other->policy_bundle_);
33 }
34 
CopyFrom(const PolicyBundle & other)35 void 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)42 void 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) const75 bool 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()100 void PolicyBundle::Clear() {
101   policy_bundle_.clear();
102 }
103 
104 }  // namespace policy
105