Home | History | Annotate | Download | only in policy
      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