summaryrefslogtreecommitdiffstats
path: root/chrome/browser/policy/cloud_policy_provider_impl.cc
blob: 8d0509b32064474ed150657c0e36d0ebd2082a4b (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
119
120
121
122
123
124
125
// 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 <set>

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

namespace policy {

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

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

  FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer,
                    observer_list_, OnProviderGoingAway());
}

bool CloudPolicyProviderImpl::Provide(
    ConfigurationPolicyStoreInterface* store) {
  ApplyPolicyMap(&combined_, store);
  return true;
}

bool CloudPolicyProviderImpl::IsInitializationComplete() const {
  for (ListType::const_iterator i = caches_.begin(); i != caches_.end(); ++i) {
    if (!(*i)->IsReady()) {
      return false;
    }
  }
  return true;
}

void CloudPolicyProviderImpl::AddObserver(
    ConfigurationPolicyProvider::Observer* observer) {
  observer_list_.AddObserver(observer);
}

void CloudPolicyProviderImpl::RemoveObserver(
    ConfigurationPolicyProvider::Observer* observer) {
  observer_list_.RemoveObserver(observer);
}

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

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;
    }
  }

  RecombineCachesAndMaybeTriggerUpdate();
}

void CloudPolicyProviderImpl::AppendCache(CloudPolicyCacheBase* cache) {
  cache->AddObserver(this);
  caches_.push_back(cache);
  RecombineCachesAndMaybeTriggerUpdate();
}

void CloudPolicyProviderImpl::PrependCache(CloudPolicyCacheBase* cache) {
  cache->AddObserver(this);
  caches_.insert(caches_.begin(), cache);
  RecombineCachesAndMaybeTriggerUpdate();
}

// 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::RecombineCachesAndMaybeTriggerUpdate() {
  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);
  }
  if (newly_combined.Equals(combined_))
    return;

  // Trigger a notification if there was a change.
  combined_.Swap(&newly_combined);
  FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer,
                    observer_list_, OnUpdatePolicy());
}

}  // namespace policy