blob: 5e5135fca842fc9a64fa72fded730120b3423afd [file] [log] [blame]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_POLICY_CLOUD_CLOUD_POLICY_INVALIDATOR_H_
#define CHROME_BROWSER_POLICY_CLOUD_CLOUD_POLICY_INVALIDATOR_H_
#include <stdint.h>
#include <memory>
#include <optional>
#include <string>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "components/invalidation/invalidation_listener.h"
#include "components/policy/core/common/cloud/cloud_policy_core.h"
#include "components/policy/core/common/cloud/cloud_policy_store.h"
#include "components/policy/core/common/cloud/policy_invalidation_scope.h"
namespace base {
class Clock;
class SequencedTaskRunner;
}
namespace policy {
// Listens for and provides policy invalidations.
// Listens to incoming invalidations only when `CloudPolicyCore` is connected
// and `CloudPolicyRefreshScheduler` is available, because otherwise there's
// no possibility to refresh policies.
class CloudPolicyInvalidator
: public invalidation::InvalidationListener::Observer,
public CloudPolicyCore::Observer,
public CloudPolicyStore::Observer {
public:
// The value for minimal delay of triggering a policy refresh after an
// received invalidation.
static constexpr base::TimeDelta kMinFetchDelay = base::Milliseconds(20);
// The default, min and max values for `max_fetch_delay_`.
static constexpr base::TimeDelta kMaxFetchDelayDefault =
base::Milliseconds(10000);
static constexpr base::TimeDelta kMaxFetchDelayMin = base::Milliseconds(1000);
static constexpr base::TimeDelta kMaxFetchDelayMax =
base::Milliseconds(300000);
// The grace period, to allow for invalidations to be received
// once the invalidation service starts up.
static constexpr base::TimeDelta kInvalidationGracePeriod = base::Seconds(10);
// Returns a name of a refresh metric associated with the given scope.
static const char* GetPolicyRefreshMetricName(PolicyInvalidationScope scope);
// Returns a name of an invalidation metric associated with the given scope.
static const char* GetPolicyInvalidationMetricName(
PolicyInvalidationScope scope);
// |scope| indicates the invalidation scope that this invalidator
// is responsible for.
// |invalidation_listener| provides invalidations and is observed during the
// whole invaldiator's lifetime. Must remain valid until the invalidator is
// destroyed.
// |core| is the cloud policy core which connects the various policy objects.
// It must remain valid until Shutdown is called.
// |task_runner| is used for scheduling delayed tasks. It must post tasks to
// the main policy thread.
// |clock| is used to get the current time.
// |highest_handled_invalidation_version| is the highest invalidation version
// that was handled already before this invalidator was created.
// |device_local_account_id| is a unique identity for invalidator with
// DeviceLocalAccount |scope| to have unique owner name. May be let empty
// if scope is not DeviceLocalAccount.
CloudPolicyInvalidator(
PolicyInvalidationScope scope,
invalidation::InvalidationListener* invalidation_listener,
CloudPolicyCore* core,
const scoped_refptr<base::SequencedTaskRunner>& task_runner,
const base::Clock* clock,
const std::string& device_local_account_id);
CloudPolicyInvalidator(
PolicyInvalidationScope scope,
invalidation::InvalidationListener* invalidation_listener,
CloudPolicyCore* core,
const scoped_refptr<base::SequencedTaskRunner>& task_runner,
const base::Clock* clock);
CloudPolicyInvalidator(const CloudPolicyInvalidator&) = delete;
CloudPolicyInvalidator& operator=(const CloudPolicyInvalidator&) = delete;
~CloudPolicyInvalidator() override;
// The highest invalidation version that was handled already.
int64_t highest_handled_invalidation_version() const;
// CloudPolicyCore::Observer:
void OnCoreConnected(CloudPolicyCore* core) override;
void OnRefreshSchedulerStarted(CloudPolicyCore* core) override;
void OnCoreDisconnecting(CloudPolicyCore* core) override;
// CloudPolicyStore::Observer:
void OnStoreLoaded(CloudPolicyStore* store) override;
void OnStoreError(CloudPolicyStore* store) override;
// InvalidationListener::Observer:
void OnExpectationChanged(
invalidation::InvalidationsExpected expected) override;
void OnInvalidationReceived(
const invalidation::DirectInvalidation& invalidation) override;
std::string GetType() const override;
private:
// Handles policy refresh depending on invalidations availability and incoming
// invalidations.
class PolicyInvalidationHandler {
public:
PolicyInvalidationHandler(
PolicyInvalidationScope scope,
CloudPolicyCore* core,
const base::Clock* clock,
scoped_refptr<base::SequencedTaskRunner> task_runner);
~PolicyInvalidationHandler();
// Handles an invalidation to the policy.
void HandleInvalidation(
const invalidation::DirectInvalidation& invalidation);
// Informs the core's refresh scheduler about whether invalidations are
// enabled.
void UpdateInvalidationsEnabled(bool invalidations_enabled);
// Update |max_fetch_delay_| based on the given policy map.
void UpdateMaxFetchDelay(const PolicyMap& policy_map);
void HandlePolicyRefresh(CloudPolicyStore* store);
void FinishInvalidationHandling();
int64_t highest_handled_invalidation_version() const {
return highest_handled_invalidation_version_;
}
bool IsCoreReady() const {
return core_->IsConnected() && core_->refresh_scheduler() &&
core_->store();
}
private:
void set_max_fetch_delay(base::TimeDelta delay);
// Performs the policy fetch.
void RefreshPolicy();
// Returns true if invalidations have been enabled for a while.
// This is a heuristic attempt to avoid counting initial policy fetches as
// invalidation-triggered.
// See https://codereview.chromium.org/213743014 for more details.
bool AreInvalidationsEnabledForAWhile() const;
// The invalidation scope this invalidator is responsible for.
const PolicyInvalidationScope scope_;
// The cloud policy core.
const raw_ptr<CloudPolicyCore> core_;
// The timestamp at which invalidations became enabled. If unset then
// invalidations are considered disabled.
std::optional<base::Time> invalidations_enabled_time_;
// If set, contains the currently handled invalidation, i.e. a
// policy refresh has been triggered due to it, but the policy refresh has
// not finished yet.
std::optional<invalidation::DirectInvalidation> in_progress_invalidation_;
// The highest invalidation version that was handled already.
int64_t highest_handled_invalidation_version_ = 0;
// The hash value of the current policy. This is used to determine if a new
// policy is different from the current one.
std::optional<size_t> policy_hash_value_;
// The maximum random delay, between receiving an invalidation and
// fetching the new policy.
base::TimeDelta max_fetch_delay_ = kMaxFetchDelayDefault;
// The clock.
const raw_ptr<const base::Clock> clock_;
// Schedules delayed tasks.
const scoped_refptr<base::SequencedTaskRunner> task_runner_;
// A thread checker to make sure that callbacks are invoked on the correct
// thread.
THREAD_CHECKER(thread_checker_);
// WeakPtrFactory used to create callbacks to this object.
base::WeakPtrFactory<PolicyInvalidationHandler> weak_factory_{this};
};
// Returns true if ready to receive invalidations.
bool IsRegistered() const;
// Returns true if ready to receive invalidations and invalidations are
// enabled.
bool AreInvalidationsEnabled() const;
PolicyInvalidationHandler policy_invalidation_handler_;
// The invalidation scope this invalidator is responsible for.
const PolicyInvalidationScope scope_;
// The cloud policy core.
raw_ptr<CloudPolicyCore> core_;
base::ScopedObservation<CloudPolicyCore, CloudPolicyInvalidator>
core_observation_{this};
base::ScopedObservation<CloudPolicyStore, CloudPolicyInvalidator>
store_observation_{this};
raw_ptr<invalidation::InvalidationListener> invalidation_listener_;
invalidation::InvalidationsExpected are_invalidations_expected_ =
invalidation::InvalidationsExpected::kMaybe;
base::ScopedObservation<invalidation::InvalidationListener,
CloudPolicyInvalidator>
invalidation_listener_observation_{this};
const std::string device_local_account_id_;
// A thread checker to make sure that callbacks are invoked on the correct
// thread.
THREAD_CHECKER(thread_checker_);
};
} // namespace policy
#endif // CHROME_BROWSER_POLICY_CLOUD_CLOUD_POLICY_INVALIDATOR_H_