Home | History | Annotate | Download | only in common
      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