summaryrefslogtreecommitdiffstats
path: root/chrome/browser/policy/cloud_policy_provider_impl.cc
blob: d1c3f3b7a21b50289370dc6f0524bcc5caeb9c40 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/policy/cloud_policy_provider_impl.h"

#include "chrome/browser/policy/configuration_policy_pref_store.h"

namespace policy {

CloudPolicyProviderImpl::CloudPolicyProviderImpl(
    const PolicyDefinitionList* policy_list,
    CloudPolicyCacheBase::PolicyLevel level)
    : CloudPolicyProvider(policy_list),
      level_(level),
      initialization_complete_(true) {}

CloudPolicyProviderImpl::~CloudPolicyProviderImpl() {
  for (ListType::iterator i = caches_.begin(); i != caches_.end(); ++i)
    (*i)->RemoveObserver(this);
}

bool CloudPolicyProviderImpl::ProvideInternal(PolicyMap* result) {
  result->CopyFrom(combined_);
  return true;
}

bool CloudPolicyProviderImpl::IsInitializationComplete() const {
  return initialization_complete_;
}

void CloudPolicyProviderImpl::OnCacheUpdate(CloudPolicyCacheBase* cache) {
  RecombineCachesAndTriggerUpdate();
}

void CloudPolicyProviderImpl::OnCacheGoingAway(CloudPolicyCacheBase* cache) {
  cache->RemoveObserver(this);
  for (ListType::iterator i = caches_.begin(); i != caches_.end(); ++i) {
    if (*i == cache) {
      caches_.erase(i);
      break;
    }
  }

  RecombineCachesAndTriggerUpdate();
}

void CloudPolicyProviderImpl::AppendCache(CloudPolicyCacheBase* cache) {
  initialization_complete_ &= cache->IsReady();
  cache->AddObserver(this);
  caches_.push_back(cache);
  RecombineCachesAndTriggerUpdate();
}

void CloudPolicyProviderImpl::PrependCache(CloudPolicyCacheBase* cache) {
  initialization_complete_ &= cache->IsReady();
  cache->AddObserver(this);
  caches_.insert(caches_.begin(), cache);
  RecombineCachesAndTriggerUpdate();
}

// static
void CloudPolicyProviderImpl::CombineTwoPolicyMaps(const PolicyMap& base,
                                                   const PolicyMap& overlay,
                                                   PolicyMap* out_map) {
  bool added_proxy_policy = false;
  out_map->Clear();

  for (PolicyMap::const_iterator i = base.begin(); i != base.end(); ++i) {
    out_map->Set(i->first, i->second->DeepCopy());
    added_proxy_policy = added_proxy_policy ||
                         ConfigurationPolicyPrefStore::IsProxyPolicy(i->first);
  }

  // Add every entry of |overlay| which has not been added by |base|. Only add
  // proxy policies if none of them was added by |base|.
  for (PolicyMap::const_iterator i = overlay.begin(); i != overlay.end(); ++i) {
    if (ConfigurationPolicyPrefStore::IsProxyPolicy(i->first)) {
      if (!added_proxy_policy) {
        out_map->Set(i->first, i->second->DeepCopy());
      }
    } else if (!out_map->Get(i->first)) {
      out_map->Set(i->first, i->second->DeepCopy());
    }
  }
}

void CloudPolicyProviderImpl::RecombineCachesAndTriggerUpdate() {
  // Re-check whether all caches are ready.
  if (!initialization_complete_) {
    bool all_caches_ready = true;
    for (ListType::const_iterator i = caches_.begin();
         i != caches_.end(); ++i) {
      if (!(*i)->IsReady()) {
        all_caches_ready = false;
        break;
      }
    }
    if (all_caches_ready)
      initialization_complete_ = true;
  }

  // Reconstruct the merged policy map.
  PolicyMap newly_combined;
  for (ListType::iterator i = caches_.begin(); i != caches_.end(); ++i) {
    if (!(*i)->IsReady())
      continue;
    PolicyMap tmp_map;
    CombineTwoPolicyMaps(newly_combined, *(*i)->policy(level_), &tmp_map);
    newly_combined.Swap(&tmp_map);
  }

  // Trigger a notification.
  combined_.Swap(&newly_combined);
  NotifyPolicyUpdated();
}

}  // namespace policy