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: 21 CloudPolicyProvider(const PolicyDefinitionList* policy_list, 22 CloudPolicyCacheBase* cache, 23 CloudPolicyCacheBase::PolicyLevel level) 24 : ConfigurationPolicyProvider(policy_list), 25 cache_(cache), 26 level_(level) {} 27 virtual ~CloudPolicyProvider() {} 28 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 37 virtual bool IsInitializationComplete() const { 38 return cache_->initialization_complete_; 39 } 40 41 virtual void AddObserver(ConfigurationPolicyProvider::Observer* observer) { 42 cache_->observer_list_.AddObserver(observer); 43 } 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 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 74 CloudPolicyCacheBase::~CloudPolicyCacheBase() { 75 FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, 76 observer_list_, OnProviderGoingAway()); 77 } 78 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 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 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 142 ConfigurationPolicyProvider* CloudPolicyCacheBase::GetManagedPolicyProvider() { 143 DCHECK(CalledOnValidThread()); 144 return managed_policy_provider_.get(); 145 } 146 147 ConfigurationPolicyProvider* 148 CloudPolicyCacheBase::GetRecommendedPolicyProvider() { 149 DCHECK(CalledOnValidThread()); 150 return recommended_policy_provider_.get(); 151 } 152 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 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