• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 "chrome/browser/policy/cloud_policy_cache_base.h"
6 
7 #include <string>
8 
9 #include "base/logging.h"
10 #include "base/values.h"
11 #include "chrome/browser/policy/configuration_policy_pref_store.h"
12 #include "chrome/browser/policy/policy_notifier.h"
13 
14 namespace policy {
15 
16 // A thin ConfigurationPolicyProvider implementation sitting on top of
17 // CloudPolicyCacheBase for hooking up with ConfigurationPolicyPrefStore.
18 class CloudPolicyCacheBase::CloudPolicyProvider
19     : public ConfigurationPolicyProvider {
20  public:
CloudPolicyProvider(const PolicyDefinitionList * policy_list,CloudPolicyCacheBase * cache,CloudPolicyCacheBase::PolicyLevel level)21   CloudPolicyProvider(const PolicyDefinitionList* policy_list,
22                       CloudPolicyCacheBase* cache,
23                       CloudPolicyCacheBase::PolicyLevel level)
24       : ConfigurationPolicyProvider(policy_list),
25         cache_(cache),
26         level_(level) {}
~CloudPolicyProvider()27   virtual ~CloudPolicyProvider() {}
28 
Provide(ConfigurationPolicyStoreInterface * store)29   virtual bool Provide(ConfigurationPolicyStoreInterface* store) {
30     if (level_ == POLICY_LEVEL_MANDATORY)
31       ApplyPolicyMap(&cache_->mandatory_policy_, store);
32     else if (level_ == POLICY_LEVEL_RECOMMENDED)
33       ApplyPolicyMap(&cache_->recommended_policy_, store);
34     return true;
35   }
36 
IsInitializationComplete() const37   virtual bool IsInitializationComplete() const {
38     return cache_->initialization_complete_;
39   }
40 
AddObserver(ConfigurationPolicyProvider::Observer * observer)41   virtual void AddObserver(ConfigurationPolicyProvider::Observer* observer) {
42     cache_->observer_list_.AddObserver(observer);
43   }
RemoveObserver(ConfigurationPolicyProvider::Observer * observer)44   virtual void RemoveObserver(ConfigurationPolicyProvider::Observer* observer) {
45     cache_->observer_list_.RemoveObserver(observer);
46   }
47 
48  private:
49   // The underlying policy cache.
50   CloudPolicyCacheBase* cache_;
51   // Policy level this provider will handle.
52   CloudPolicyCacheBase::PolicyLevel level_;
53 
54   DISALLOW_COPY_AND_ASSIGN(CloudPolicyProvider);
55 };
56 
CloudPolicyCacheBase()57 CloudPolicyCacheBase::CloudPolicyCacheBase()
58     : notifier_(NULL),
59       initialization_complete_(false),
60       is_unmanaged_(false) {
61   public_key_version_.valid = false;
62   managed_policy_provider_.reset(
63       new CloudPolicyProvider(
64           ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(),
65           this,
66           POLICY_LEVEL_MANDATORY));
67   recommended_policy_provider_.reset(
68       new CloudPolicyProvider(
69           ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(),
70           this,
71           POLICY_LEVEL_RECOMMENDED));
72 }
73 
~CloudPolicyCacheBase()74 CloudPolicyCacheBase::~CloudPolicyCacheBase() {
75   FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer,
76                     observer_list_, OnProviderGoingAway());
77 }
78 
GetPublicKeyVersion(int * version)79 bool CloudPolicyCacheBase::GetPublicKeyVersion(int* version) {
80   if (public_key_version_.valid)
81     *version = public_key_version_.version;
82 
83   return public_key_version_.valid;
84 }
85 
SetPolicyInternal(const em::PolicyFetchResponse & policy,base::Time * timestamp,bool check_for_timestamp_validity)86 bool CloudPolicyCacheBase::SetPolicyInternal(
87     const em::PolicyFetchResponse& policy,
88     base::Time* timestamp,
89     bool check_for_timestamp_validity) {
90   DCHECK(CalledOnValidThread());
91   bool initialization_was_not_complete = !initialization_complete_;
92   is_unmanaged_ = false;
93   PolicyMap mandatory_policy;
94   PolicyMap recommended_policy;
95   base::Time temp_timestamp;
96   PublicKeyVersion temp_public_key_version;
97   bool ok = DecodePolicyResponse(policy, &mandatory_policy, &recommended_policy,
98                                  &temp_timestamp, &temp_public_key_version);
99   if (!ok) {
100     LOG(WARNING) << "Decoding policy data failed.";
101     return false;
102   }
103   if (timestamp) {
104     *timestamp = temp_timestamp;
105   }
106   if (check_for_timestamp_validity &&
107       temp_timestamp > base::Time::NowFromSystemTime()) {
108     LOG(WARNING) << "Rejected policy data, file is from the future.";
109     return false;
110   }
111   public_key_version_.version = temp_public_key_version.version;
112   public_key_version_.valid = temp_public_key_version.valid;
113 
114   const bool new_policy_differs =
115       !mandatory_policy_.Equals(mandatory_policy) ||
116       !recommended_policy_.Equals(recommended_policy);
117   mandatory_policy_.Swap(&mandatory_policy);
118   recommended_policy_.Swap(&recommended_policy);
119   initialization_complete_ = true;
120 
121   if (new_policy_differs || initialization_was_not_complete) {
122     FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer,
123                       observer_list_, OnUpdatePolicy());
124   }
125   InformNotifier(CloudPolicySubsystem::SUCCESS,
126                  CloudPolicySubsystem::NO_DETAILS);
127   return true;
128 }
129 
SetUnmanagedInternal(const base::Time & timestamp)130 void CloudPolicyCacheBase::SetUnmanagedInternal(const base::Time& timestamp) {
131   is_unmanaged_ = true;
132   initialization_complete_ = true;
133   public_key_version_.valid = false;
134   mandatory_policy_.Clear();
135   recommended_policy_.Clear();
136   last_policy_refresh_time_ = timestamp;
137 
138   FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer,
139                     observer_list_, OnUpdatePolicy());
140 }
141 
GetManagedPolicyProvider()142 ConfigurationPolicyProvider* CloudPolicyCacheBase::GetManagedPolicyProvider() {
143   DCHECK(CalledOnValidThread());
144   return managed_policy_provider_.get();
145 }
146 
147 ConfigurationPolicyProvider*
GetRecommendedPolicyProvider()148     CloudPolicyCacheBase::GetRecommendedPolicyProvider() {
149   DCHECK(CalledOnValidThread());
150   return recommended_policy_provider_.get();
151 }
152 
DecodePolicyResponse(const em::PolicyFetchResponse & policy_response,PolicyMap * mandatory,PolicyMap * recommended,base::Time * timestamp,PublicKeyVersion * public_key_version)153 bool CloudPolicyCacheBase::DecodePolicyResponse(
154     const em::PolicyFetchResponse& policy_response,
155     PolicyMap* mandatory,
156     PolicyMap* recommended,
157     base::Time* timestamp,
158     PublicKeyVersion* public_key_version) {
159   std::string data = policy_response.policy_data();
160   em::PolicyData policy_data;
161   if (!policy_data.ParseFromString(data)) {
162     LOG(WARNING) << "Failed to parse PolicyData protobuf.";
163     return false;
164   }
165   if (timestamp) {
166     *timestamp = base::Time::UnixEpoch() +
167                  base::TimeDelta::FromMilliseconds(policy_data.timestamp());
168   }
169   if (public_key_version) {
170     public_key_version->valid = policy_data.has_public_key_version();
171     if (public_key_version->valid)
172       public_key_version->version = policy_data.public_key_version();
173   }
174 
175   return DecodePolicyData(policy_data, mandatory, recommended);
176 }
177 
InformNotifier(CloudPolicySubsystem::PolicySubsystemState state,CloudPolicySubsystem::ErrorDetails error_details)178 void CloudPolicyCacheBase::InformNotifier(
179     CloudPolicySubsystem::PolicySubsystemState state,
180     CloudPolicySubsystem::ErrorDetails error_details) {
181   // TODO(jkummerow): To obsolete this NULL-check, make all uses of
182   // UserPolicyCache explicitly set a notifier using |set_policy_notifier()|.
183   if (notifier_)
184     notifier_->Inform(state, error_details, PolicyNotifier::POLICY_CACHE);
185 }
186 
187 }  // namespace policy
188