// Copyright 2013 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/cloud_policy_invalidator.h"

#include "base/bind.h"
#include "base/hash.h"
#include "base/location.h"
#include "base/metrics/histogram.h"
#include "base/rand_util.h"
#include "base/sequenced_task_runner.h"
#include "base/time/clock.h"
#include "base/time/time.h"
#include "base/values.h"
#include "components/invalidation/invalidation_service.h"
#include "components/invalidation/object_id_invalidation_map.h"
#include "components/policy/core/common/cloud/cloud_policy_client.h"
#include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h"
#include "components/policy/core/common/cloud/enterprise_metrics.h"
#include "policy/policy_constants.h"

namespace policy {

const int CloudPolicyInvalidator::kMissingPayloadDelay = 5;
const int CloudPolicyInvalidator::kMaxFetchDelayDefault = 10000;
const int CloudPolicyInvalidator::kMaxFetchDelayMin = 1000;
const int CloudPolicyInvalidator::kMaxFetchDelayMax = 300000;
const int CloudPolicyInvalidator::kInvalidationGracePeriod = 10;
const int CloudPolicyInvalidator::kUnknownVersionIgnorePeriod = 30;
const int CloudPolicyInvalidator::kMaxInvalidationTimeDelta = 300;

CloudPolicyInvalidator::CloudPolicyInvalidator(
    CloudPolicyCore* core,
    const scoped_refptr<base::SequencedTaskRunner>& task_runner,
    scoped_ptr<base::Clock> clock)
    : state_(UNINITIALIZED),
      core_(core),
      task_runner_(task_runner),
      clock_(clock.Pass()),
      invalidation_service_(NULL),
      invalidations_enabled_(false),
      invalidation_service_enabled_(false),
      is_registered_(false),
      invalid_(false),
      invalidation_version_(0),
      unknown_version_invalidation_count_(0),
      weak_factory_(this),
      max_fetch_delay_(kMaxFetchDelayDefault),
      policy_hash_value_(0) {
  DCHECK(core);
  DCHECK(task_runner.get());
}

CloudPolicyInvalidator::~CloudPolicyInvalidator() {
  DCHECK(state_ == SHUT_DOWN);
}

void CloudPolicyInvalidator::Initialize(
    invalidation::InvalidationService* invalidation_service) {
  DCHECK(state_ == UNINITIALIZED);
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(invalidation_service);
  invalidation_service_ = invalidation_service;
  state_ = STOPPED;
  core_->AddObserver(this);
  if (core_->refresh_scheduler())
    OnRefreshSchedulerStarted(core_);
}

void CloudPolicyInvalidator::Shutdown() {
  DCHECK(state_ != SHUT_DOWN);
  DCHECK(thread_checker_.CalledOnValidThread());
  if (state_ == STARTED) {
    if (is_registered_)
      invalidation_service_->UnregisterInvalidationHandler(this);
    core_->store()->RemoveObserver(this);
    weak_factory_.InvalidateWeakPtrs();
  }
  if (state_ != UNINITIALIZED)
    core_->RemoveObserver(this);
  state_ = SHUT_DOWN;
}

void CloudPolicyInvalidator::OnInvalidatorStateChange(
    syncer::InvalidatorState state) {
  DCHECK(state_ == STARTED);
  DCHECK(thread_checker_.CalledOnValidThread());
  invalidation_service_enabled_ = state == syncer::INVALIDATIONS_ENABLED;
  UpdateInvalidationsEnabled();
}

void CloudPolicyInvalidator::OnIncomingInvalidation(
    const syncer::ObjectIdInvalidationMap& invalidation_map) {
  DCHECK(state_ == STARTED);
  DCHECK(thread_checker_.CalledOnValidThread());
  const syncer::SingleObjectInvalidationSet& list =
      invalidation_map.ForObject(object_id_);
  if (list.IsEmpty()) {
    NOTREACHED();
    return;
  }

  // Acknowledge all except the invalidation with the highest version.
  syncer::SingleObjectInvalidationSet::const_reverse_iterator it =
      list.rbegin();
  ++it;
  for ( ; it != list.rend(); ++it) {
    it->Acknowledge();
  }

  // Handle the highest version invalidation.
  HandleInvalidation(list.back());
}

std::string CloudPolicyInvalidator::GetOwnerName() const { return "Cloud"; }

void CloudPolicyInvalidator::OnCoreConnected(CloudPolicyCore* core) {}

void CloudPolicyInvalidator::OnRefreshSchedulerStarted(CloudPolicyCore* core) {
  DCHECK(state_ == STOPPED);
  DCHECK(thread_checker_.CalledOnValidThread());
  state_ = STARTED;
  OnStoreLoaded(core_->store());
  core_->store()->AddObserver(this);
}

void CloudPolicyInvalidator::OnCoreDisconnecting(CloudPolicyCore* core) {
  DCHECK(state_ == STARTED || state_ == STOPPED);
  DCHECK(thread_checker_.CalledOnValidThread());
  if (state_ == STARTED) {
    Unregister();
    core_->store()->RemoveObserver(this);
    state_ = STOPPED;
  }
}

void CloudPolicyInvalidator::OnStoreLoaded(CloudPolicyStore* store) {
  DCHECK(state_ == STARTED);
  DCHECK(thread_checker_.CalledOnValidThread());
  bool policy_changed = IsPolicyChanged(store->policy());

  if (is_registered_) {
    // Update the kMetricPolicyRefresh histogram.
    UMA_HISTOGRAM_ENUMERATION(
        kMetricPolicyRefresh,
        GetPolicyRefreshMetric(policy_changed),
        METRIC_POLICY_REFRESH_SIZE);

    // If the policy was invalid and the version stored matches the latest
    // invalidation version, acknowledge the latest invalidation.
    if (invalid_ && store->invalidation_version() == invalidation_version_)
      AcknowledgeInvalidation();
  }

  UpdateRegistration(store->policy());
  UpdateMaxFetchDelay(store->policy_map());
}

void CloudPolicyInvalidator::OnStoreError(CloudPolicyStore* store) {}

void CloudPolicyInvalidator::HandleInvalidation(
    const syncer::Invalidation& invalidation) {
  // Ignore old invalidations.
  if (invalid_ &&
      !invalidation.is_unknown_version() &&
      invalidation.version() <= invalidation_version_) {
    return;
  }

  // If there is still a pending invalidation, acknowledge it, since we only
  // care about the latest invalidation.
  if (invalid_)
    AcknowledgeInvalidation();

  // Get the version and payload from the invalidation.
  // When an invalidation with unknown version is received, use negative
  // numbers based on the number of such invalidations received. This
  // ensures that the version numbers do not collide with "real" versions
  // (which are positive) or previous invalidations with unknown version.
  int64 version;
  std::string payload;
  if (invalidation.is_unknown_version()) {
    version = -(++unknown_version_invalidation_count_);
  } else {
    version = invalidation.version();
    payload = invalidation.payload();
  }

  // Ignore the invalidation if it is expired.
  bool is_expired = IsInvalidationExpired(version);
  UMA_HISTOGRAM_ENUMERATION(
      kMetricPolicyInvalidations,
      GetInvalidationMetric(payload.empty(), is_expired),
      POLICY_INVALIDATION_TYPE_SIZE);
  if (is_expired) {
    invalidation.Acknowledge();
    return;
  }

  // Update invalidation state.
  invalid_ = true;
  invalidation_.reset(new syncer::Invalidation(invalidation));
  invalidation_version_ = version;

  // In order to prevent the cloud policy server from becoming overwhelmed when
  // a policy with many users is modified, delay for a random period of time
  // before fetching the policy. Delay for at least 20ms so that if multiple
  // invalidations are received in quick succession, only one fetch will be
  // performed.
  base::TimeDelta delay = base::TimeDelta::FromMilliseconds(
      base::RandInt(20, max_fetch_delay_));

  // If there is a payload, the policy can be refreshed at any time, so set
  // the version and payload on the client immediately. Otherwise, the refresh
  // must only run after at least kMissingPayloadDelay minutes.
  if (!payload.empty())
    core_->client()->SetInvalidationInfo(version, payload);
  else
    delay += base::TimeDelta::FromMinutes(kMissingPayloadDelay);

  // Schedule the policy to be refreshed.
  task_runner_->PostDelayedTask(
      FROM_HERE,
      base::Bind(
          &CloudPolicyInvalidator::RefreshPolicy,
          weak_factory_.GetWeakPtr(),
          payload.empty() /* is_missing_payload */),
      delay);
}

void CloudPolicyInvalidator::UpdateRegistration(
    const enterprise_management::PolicyData* policy) {
  // Create the ObjectId based on the policy data.
  // If the policy does not specify an the ObjectId, then unregister.
  if (!policy ||
      !policy->has_invalidation_source() ||
      !policy->has_invalidation_name()) {
    Unregister();
    return;
  }
  invalidation::ObjectId object_id(
      policy->invalidation_source(),
      policy->invalidation_name());

  // If the policy object id in the policy data is different from the currently
  // registered object id, update the object registration.
  if (!is_registered_ || !(object_id == object_id_))
    Register(object_id);
}

void CloudPolicyInvalidator::Register(const invalidation::ObjectId& object_id) {
  // Register this handler with the invalidation service if needed.
  if (!is_registered_) {
    OnInvalidatorStateChange(invalidation_service_->GetInvalidatorState());
    invalidation_service_->RegisterInvalidationHandler(this);
  }

  // Update internal state.
  if (invalid_)
    AcknowledgeInvalidation();
  is_registered_ = true;
  object_id_ = object_id;
  UpdateInvalidationsEnabled();

  // Update registration with the invalidation service.
  syncer::ObjectIdSet ids;
  ids.insert(object_id);
  invalidation_service_->UpdateRegisteredInvalidationIds(this, ids);
}

void CloudPolicyInvalidator::Unregister() {
  if (is_registered_) {
    if (invalid_)
      AcknowledgeInvalidation();
    invalidation_service_->UpdateRegisteredInvalidationIds(
        this,
        syncer::ObjectIdSet());
    invalidation_service_->UnregisterInvalidationHandler(this);
    is_registered_ = false;
    UpdateInvalidationsEnabled();
  }
}

void CloudPolicyInvalidator::UpdateMaxFetchDelay(const PolicyMap& policy_map) {
  int delay;

  // Try reading the delay from the policy.
  const base::Value* delay_policy_value =
      policy_map.GetValue(key::kMaxInvalidationFetchDelay);
  if (delay_policy_value && delay_policy_value->GetAsInteger(&delay)) {
    set_max_fetch_delay(delay);
    return;
  }

  set_max_fetch_delay(kMaxFetchDelayDefault);
}

void CloudPolicyInvalidator::set_max_fetch_delay(int delay) {
  if (delay < kMaxFetchDelayMin)
    max_fetch_delay_ = kMaxFetchDelayMin;
  else if (delay > kMaxFetchDelayMax)
    max_fetch_delay_ = kMaxFetchDelayMax;
  else
    max_fetch_delay_ = delay;
}

void CloudPolicyInvalidator::UpdateInvalidationsEnabled() {
  bool invalidations_enabled = invalidation_service_enabled_ && is_registered_;
  if (invalidations_enabled_ != invalidations_enabled) {
    invalidations_enabled_ = invalidations_enabled;
    if (invalidations_enabled)
      invalidations_enabled_time_ = clock_->Now();
    core_->refresh_scheduler()->SetInvalidationServiceAvailability(
        invalidations_enabled);
  }
}

void CloudPolicyInvalidator::RefreshPolicy(bool is_missing_payload) {
  DCHECK(thread_checker_.CalledOnValidThread());
  // In the missing payload case, the invalidation version has not been set on
  // the client yet, so set it now that the required time has elapsed.
  if (is_missing_payload)
    core_->client()->SetInvalidationInfo(invalidation_version_, std::string());
  core_->refresh_scheduler()->RefreshSoon();
}

void CloudPolicyInvalidator::AcknowledgeInvalidation() {
  DCHECK(invalid_);
  invalid_ = false;
  core_->client()->SetInvalidationInfo(0, std::string());
  invalidation_->Acknowledge();
  invalidation_.reset();
  // Cancel any scheduled policy refreshes.
  weak_factory_.InvalidateWeakPtrs();
}

bool CloudPolicyInvalidator::IsPolicyChanged(
    const enterprise_management::PolicyData* policy) {
  // Determine if the policy changed by comparing its hash value to the
  // previous policy's hash value.
  uint32 new_hash_value = 0;
  if (policy && policy->has_policy_value())
    new_hash_value = base::Hash(policy->policy_value());
  bool changed = new_hash_value != policy_hash_value_;
  policy_hash_value_ = new_hash_value;
  return changed;
}

bool CloudPolicyInvalidator::IsInvalidationExpired(int64 version) {
  base::Time last_fetch_time = base::Time::UnixEpoch() +
      base::TimeDelta::FromMilliseconds(core_->store()->policy()->timestamp());

  // If the version is unknown, consider the invalidation invalid if the
  // policy was fetched very recently.
  if (version < 0) {
    base::TimeDelta elapsed = clock_->Now() - last_fetch_time;
    return elapsed.InSeconds() < kUnknownVersionIgnorePeriod;
  }

  // The invalidation version is the timestamp in microseconds. If the
  // invalidation occurred before the last policy fetch, then the invalidation
  // is expired. Time is added to the invalidation to err on the side of not
  // expired.
  base::Time invalidation_time = base::Time::UnixEpoch() +
      base::TimeDelta::FromMicroseconds(version) +
      base::TimeDelta::FromSeconds(kMaxInvalidationTimeDelta);
  return invalidation_time < last_fetch_time;
}

int CloudPolicyInvalidator::GetPolicyRefreshMetric(bool policy_changed) {
  if (policy_changed) {
    if (invalid_)
      return METRIC_POLICY_REFRESH_INVALIDATED_CHANGED;
    if (GetInvalidationsEnabled())
      return METRIC_POLICY_REFRESH_CHANGED;
    return METRIC_POLICY_REFRESH_CHANGED_NO_INVALIDATIONS;
  }
  if (invalid_)
    return METRIC_POLICY_REFRESH_INVALIDATED_UNCHANGED;
  return METRIC_POLICY_REFRESH_UNCHANGED;
}

int CloudPolicyInvalidator::GetInvalidationMetric(bool is_missing_payload,
                                                  bool is_expired) {
  if (is_expired) {
    if (is_missing_payload)
      return POLICY_INVALIDATION_TYPE_NO_PAYLOAD_EXPIRED;
    return POLICY_INVALIDATION_TYPE_EXPIRED;
  }
  if (is_missing_payload)
    return POLICY_INVALIDATION_TYPE_NO_PAYLOAD;
  return POLICY_INVALIDATION_TYPE_NORMAL;
}

bool CloudPolicyInvalidator::GetInvalidationsEnabled() {
  if (!invalidations_enabled_)
    return false;
  // If invalidations have been enabled for less than the grace period, then
  // consider invalidations to be disabled for metrics reporting.
  base::TimeDelta elapsed = clock_->Now() - invalidations_enabled_time_;
  return elapsed.InSeconds() >= kInvalidationGracePeriod;
}

}  // namespace policy
