| // Copyright (c) 2012 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_cache_base.h" |
| |
| #include <string> |
| |
| #include "base/logging.h" |
| #include "base/metrics/histogram.h" |
| #include "chrome/browser/policy/enterprise_metrics.h" |
| #include "chrome/browser/policy/policy_notifier.h" |
| |
| namespace em = enterprise_management; |
| |
| namespace policy { |
| |
| CloudPolicyCacheBase::CloudPolicyCacheBase() |
| : notifier_(NULL), |
| initialization_complete_(false), |
| is_unmanaged_(false), |
| machine_id_missing_(false) { |
| public_key_version_.version = 0; |
| public_key_version_.valid = false; |
| } |
| |
| CloudPolicyCacheBase::~CloudPolicyCacheBase() { |
| FOR_EACH_OBSERVER(Observer, observer_list_, OnCacheGoingAway(this)); |
| } |
| |
| void CloudPolicyCacheBase::SetFetchingDone() { |
| // NotifyObservers only fires notifications if the cache is ready. |
| NotifyObservers(); |
| } |
| |
| void CloudPolicyCacheBase::AddObserver(Observer* observer) { |
| observer_list_.AddObserver(observer); |
| } |
| |
| void CloudPolicyCacheBase::RemoveObserver(Observer* observer) { |
| observer_list_.RemoveObserver(observer); |
| } |
| |
| void CloudPolicyCacheBase::Reset() { |
| last_policy_refresh_time_ = base::Time(); |
| is_unmanaged_ = false; |
| policies_.Clear(); |
| public_key_version_.version = 0; |
| public_key_version_.valid = false; |
| InformNotifier(CloudPolicySubsystem::UNENROLLED, |
| CloudPolicySubsystem::NO_DETAILS); |
| } |
| |
| bool CloudPolicyCacheBase::IsReady() { |
| return initialization_complete_; |
| } |
| |
| bool CloudPolicyCacheBase::GetPublicKeyVersion(int* version) { |
| if (public_key_version_.valid) |
| *version = public_key_version_.version; |
| |
| return public_key_version_.valid; |
| } |
| |
| bool CloudPolicyCacheBase::SetPolicyInternal( |
| const em::PolicyFetchResponse& policy, |
| base::Time* timestamp, |
| bool check_for_timestamp_validity) { |
| DCHECK(CalledOnValidThread()); |
| is_unmanaged_ = false; |
| PolicyMap policies; |
| base::Time temp_timestamp; |
| PublicKeyVersion temp_public_key_version; |
| bool ok = DecodePolicyResponse(policy, &policies, |
| &temp_timestamp, &temp_public_key_version); |
| if (!ok) { |
| LOG(WARNING) << "Decoding policy data failed."; |
| UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchInvalidPolicy, |
| kMetricPolicySize); |
| return false; |
| } |
| if (timestamp) { |
| *timestamp = temp_timestamp; |
| } |
| if (check_for_timestamp_validity && |
| temp_timestamp > base::Time::NowFromSystemTime()) { |
| LOG(WARNING) << "Rejected policy data, file is from the future."; |
| UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, |
| kMetricPolicyFetchTimestampInFuture, |
| kMetricPolicySize); |
| return false; |
| } |
| public_key_version_.version = temp_public_key_version.version; |
| public_key_version_.valid = temp_public_key_version.valid; |
| |
| if (policies_.Equals(policies)) { |
| UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchNotModified, |
| kMetricPolicySize); |
| } |
| |
| policies_.Swap(&policies); |
| |
| InformNotifier(CloudPolicySubsystem::SUCCESS, |
| CloudPolicySubsystem::NO_DETAILS); |
| return true; |
| } |
| |
| void CloudPolicyCacheBase::SetUnmanagedInternal(const base::Time& timestamp) { |
| is_unmanaged_ = true; |
| public_key_version_.valid = false; |
| policies_.Clear(); |
| last_policy_refresh_time_ = timestamp; |
| } |
| |
| void CloudPolicyCacheBase::SetReady() { |
| initialization_complete_ = true; |
| NotifyObservers(); |
| } |
| |
| bool CloudPolicyCacheBase::DecodePolicyResponse( |
| const em::PolicyFetchResponse& policy_response, |
| PolicyMap* policies, |
| base::Time* timestamp, |
| PublicKeyVersion* public_key_version) { |
| std::string data = policy_response.policy_data(); |
| em::PolicyData policy_data; |
| if (!policy_data.ParseFromString(data)) { |
| LOG(WARNING) << "Failed to parse PolicyData protobuf."; |
| return false; |
| } |
| if (timestamp) { |
| *timestamp = base::Time::UnixEpoch() + |
| base::TimeDelta::FromMilliseconds(policy_data.timestamp()); |
| } |
| if (public_key_version) { |
| public_key_version->valid = policy_data.has_public_key_version(); |
| if (public_key_version->valid) |
| public_key_version->version = policy_data.public_key_version(); |
| } |
| machine_id_missing_ = policy_data.valid_serial_number_missing(); |
| |
| return DecodePolicyData(policy_data, policies); |
| } |
| |
| void CloudPolicyCacheBase::NotifyObservers() { |
| if (IsReady()) |
| FOR_EACH_OBSERVER(Observer, observer_list_, OnCacheUpdate(this)); |
| } |
| |
| void CloudPolicyCacheBase::InformNotifier( |
| CloudPolicySubsystem::PolicySubsystemState state, |
| CloudPolicySubsystem::ErrorDetails error_details) { |
| // TODO(jkummerow): To obsolete this NULL-check, make all uses of |
| // UserPolicyCache explicitly set a notifier using |set_policy_notifier()|. |
| if (notifier_) |
| notifier_->Inform(state, error_details, PolicyNotifier::POLICY_CACHE); |
| } |
| |
| } // namespace policy |