1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/policy/core/common/policy_bundle.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace policy {
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PolicyBundle::PolicyBundle() {}
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PolicyBundle::~PolicyBundle() {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Clear();
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PolicyMap& PolicyBundle::Get(const PolicyNamespace& ns) {
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(ns.domain != POLICY_DOMAIN_CHROME || ns.component_id.empty());
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PolicyMap*& policy = policy_bundle_[ns];
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!policy)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    policy = new PolicyMap();
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *policy;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const PolicyMap& PolicyBundle::Get(const PolicyNamespace& ns) const {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(ns.domain != POLICY_DOMAIN_CHROME || ns.component_id.empty());
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const_iterator it = policy_bundle_.find(ns);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return it == end() ? kEmpty_ : *it->second;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PolicyBundle::Swap(PolicyBundle* other) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  policy_bundle_.swap(other->policy_bundle_);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PolicyBundle::CopyFrom(const PolicyBundle& other) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Clear();
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PolicyBundle::const_iterator it = other.begin();
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != other.end(); ++it) {
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    policy_bundle_[it->first] = it->second->DeepCopy().release();
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PolicyBundle::MergeFrom(const PolicyBundle& other) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Iterate over both |this| and |other| in order; skip what's extra in |this|,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // add what's missing, and merge the namespaces in common.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MapType::iterator it_this = policy_bundle_.begin();
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MapType::iterator end_this = policy_bundle_.end();
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const_iterator it_other = other.begin();
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const_iterator end_other = other.end();
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (it_this != end_this && it_other != end_other) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it_this->first == it_other->first) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Same namespace: merge existing PolicyMaps.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      it_this->second->MergeFrom(*it_other->second);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++it_this;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++it_other;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (it_this->first < it_other->first) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // |this| has a PolicyMap that |other| doesn't; skip it.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++it_this;
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (it_other->first < it_this->first) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // |other| has a PolicyMap that |this| doesn't; copy it.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PolicyMap*& policy = policy_bundle_[it_other->first];
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(!policy);
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      policy = it_other->second->DeepCopy().release();
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++it_other;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add extra PolicyMaps at the end.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (it_other != end_other) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PolicyMap*& policy = policy_bundle_[it_other->first];
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!policy);
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    policy = it_other->second->DeepCopy().release();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++it_other;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PolicyBundle::Equals(const PolicyBundle& other) const {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Equals() has the peculiarity that an entry with an empty PolicyMap equals
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // an non-existant entry. This handles usage of non-const Get() that doesn't
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // insert any policies.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const_iterator it_this = begin();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const_iterator it_other = other.begin();
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Skip empty PolicyMaps.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (it_this != end() && it_this->second->empty())
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++it_this;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (it_other != other.end() && it_other->second->empty())
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++it_other;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it_this == end() || it_other == other.end())
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it_this->first != it_other->first ||
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !it_this->second->Equals(*it_other->second)) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++it_this;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++it_other;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return it_this == end() && it_other == other.end();
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PolicyBundle::Clear() {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteValues(&policy_bundle_);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace policy
111