chromium/chrome/browser/ash/policy/scheduled_task_handler/os_and_policies_update_checker.h

// Copyright 2019 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_ASH_POLICY_SCHEDULED_TASK_HANDLER_OS_AND_POLICIES_UPDATE_CHECKER_H_
#define CHROME_BROWSER_ASH_POLICY_SCHEDULED_TASK_HANDLER_OS_AND_POLICIES_UPDATE_CHECKER_H_

#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chrome/browser/ash/policy/scheduled_task_handler/task_executor_with_retries.h"
#include "chromeos/ash/components/dbus/update_engine/update_engine_client.h"
#include "chromeos/ash/components/network/network_state_handler_observer.h"

namespace ash {
class NetworkStateHandler;
}  // namespace ash

namespace policy {

namespace update_checker_internal {

// The maximum iterations allowed to check for and download an update if the
// operation fails. Used with |os_and_policies_update_checker_|.
constexpr int kMaxOsAndPoliciesUpdateCheckerRetryIterations = 2;

// Interval at which |os_and_policies_update_checker_| retries checking for and
// downloading updates.
constexpr base::TimeDelta kOsAndPoliciesUpdateCheckerRetryTime =
    base::Minutes(10);

// Time for which |OsAndPoliciesUpdateChecker| will wait for a valid network
// before querying the update server for updates. After this time it will return
// a failure. During testing it was noted that on average 1 minute seemed to be
// the delay after which a network would be detected by Chrome.
constexpr base::TimeDelta kWaitForNetworkTimeout = base::Minutes(5);

}  // namespace update_checker_internal

// This class is used by the scheduled update check policy to perform the actual
// device update check.
class OsAndPoliciesUpdateChecker : public ash::UpdateEngineClient::Observer,
                                   public ash::NetworkStateHandlerObserver {
 public:
  explicit OsAndPoliciesUpdateChecker(
      ash::NetworkStateHandler* network_state_handler);

  OsAndPoliciesUpdateChecker(const OsAndPoliciesUpdateChecker&) = delete;
  OsAndPoliciesUpdateChecker& operator=(const OsAndPoliciesUpdateChecker&) =
      delete;

  ~OsAndPoliciesUpdateChecker() override;

  using UpdateCheckCompletionCallback = base::OnceCallback<void(bool result)>;

  // Starts an update check and possible download. Once the update check is
  // finished it refreshes policies and finally calls |cb| to indicate success
  // or failure when the process is complete. Calls |cb| with false if |timeout|
  // passed without the operation completing. Overrides any previous calls to
  // |Start|.
  void Start(UpdateCheckCompletionCallback cb, base::TimeDelta timeout);

  // Stops any pending update checks or policy refreshes. Calls
  // |update_check_completion_cb_| with false. It is safe to call |Start| after
  // this.
  void Stop();

  // Returns true if |Start| has been called and not been |Stop|ped.
  bool IsRunning() const;

  // ash::NetworkStateHandlerObserver overrides.
  void DefaultNetworkChanged(const ash::NetworkState* network) override;

 private:
  // Schedules update check by using |update_check_task_executor_|.
  void ScheduleUpdateCheck();

  // Runs |update_check_completion_cb_| with |update_check_result| and runs
  // |ResetState|.
  void RunCompletionCallbackAndResetState(bool update_check_result);

  // Runs when |wait_for_network_timer_| expires i.e. a network hasn't been
  // detected after the maximum time out.
  void OnNetworkWaitTimeout();

  // Runs when |update_check_task_executor_::Start| has failed after retries.
  void OnUpdateCheckFailure();

  // Requests update engine to do an update check.
  void StartUpdateCheck();

  // UpdateEngineClient::Observer overrides.
  void UpdateStatusChanged(const update_engine::StatusResult& status) override;

  // Tells whether starting an update check succeeded or not.
  void OnUpdateCheckStarted(ash::UpdateEngineClient::UpdateCheckResult result);

  // Refreshes policies. |update_check_result| represents the status of the
  // previous stage i.e. an OS update check and download.
  void RefreshPolicies(bool update_check_result);

  // Called when the API call to refresh policies is completed.
  // |update_check_result| represents the result of the update check which
  // triggered this policy refresh.
  void OnRefreshPoliciesCompletion(bool update_check_result);

  // Resets all state and cancels any pending update checks.
  void ResetState();

  // Ignore fist IDLE status that is sent when the update check is initiated.
  bool ignore_idle_status_ = true;

  // Set to true when |Start| is called and false when |Stop| is called.
  bool is_running_ = false;

  // Callback passed to |Start|. Called if |StartUpdateCheck| is unsuccessful
  // after retries or when an update check finishes successfully.
  UpdateCheckCompletionCallback update_check_completion_cb_;

  // Not owned.
  const raw_ptr<ash::NetworkStateHandler> network_state_handler_;
  base::ScopedObservation<ash::NetworkStateHandler,
                          ash::NetworkStateHandlerObserver>
      network_state_handler_observer_{this};

  // Scheduled and retries |StartUpdateCheck|.
  TaskExecutorWithRetries update_check_task_executor_;

  // Timer to wait for a valid network after |Start| is called.
  base::OneShotTimer wait_for_network_timer_;

  // Timer to abort any pending operations and call
  // |update_check_completion_cb_| with false.
  base::OneShotTimer timeout_timer_;

  // Not owned.
  const raw_ptr<ash::UpdateEngineClient> update_engine_client_;

  base::WeakPtrFactory<OsAndPoliciesUpdateChecker> weak_factory_{this};
};

}  // namespace policy

#endif  // CHROME_BROWSER_ASH_POLICY_SCHEDULED_TASK_HANDLER_OS_AND_POLICIES_UPDATE_CHECKER_H_