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

// Copyright 2021 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_DEVICE_SCHEDULED_REBOOT_HANDLER_H_
#define CHROME_BROWSER_ASH_POLICY_SCHEDULED_TASK_HANDLER_DEVICE_SCHEDULED_REBOOT_HANDLER_H_

#include <memory>
#include <optional>

#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "chrome/browser/ash/policy/scheduled_task_handler/reboot_notifications_scheduler.h"
#include "chrome/browser/ash/policy/scheduled_task_handler/scheduled_task_executor.h"
#include "chrome/browser/ash/policy/scheduled_task_handler/scoped_wake_lock.h"
#include "chromeos/ash/components/settings/cros_settings.h"
#include "chromeos/ash/components/settings/timezone_settings.h"
#include "chromeos/dbus/power/power_manager_client.h"
#include "services/device/public/mojom/wake_lock.mojom-forward.h"
#include "third_party/icu/source/i18n/unicode/timezone.h"

namespace policy {

// This class listens for changes in the scheduled reboot policy and then
// manages recurring reboots based on the policy.
class DeviceScheduledRebootHandler
    : public ash::system::TimezoneSettings::Observer,
      chromeos::PowerManagerClient::Observer {
 public:
  DeviceScheduledRebootHandler(
      ash::CrosSettings* cros_settings,
      std::unique_ptr<ScheduledTaskExecutor> scheduled_task_executor,
      RebootNotificationsScheduler* notifications_scheduler);
  DeviceScheduledRebootHandler(const DeviceScheduledRebootHandler&) = delete;
  DeviceScheduledRebootHandler& operator=(const DeviceScheduledRebootHandler&) =
      delete;
  ~DeviceScheduledRebootHandler() override;

  // TODO(https://crbug.com/1228718): Move Timezone observation to
  // ScheduledTaskExecutor. ash::system::TimezoneSettings::Observer
  // implementation.
  void TimezoneChanged(const icu::TimeZone& time_zone) override;

  // Called when the power manager service becomes available. Reboot timer can
  // only be started after this moment.
  // chromeos::PowerManagerClient::Observer overrides:
  void PowerManagerBecameAvailable(bool available) override;

  // The tag associated to register |scheduled_task_executor_|.
  static constexpr char kRebootTimerTag[] = "DeviceScheduledRebootHandler";

  // Sets reboot delay for testing.
  void SetRebootDelayForTest(const base::TimeDelta& reboot_delay);

  // Returns value of |scheduled_reboot_data_|.
  std::optional<ScheduledTaskExecutor::ScheduledTaskData>
  GetScheduledRebootDataForTest() const;

  // Returns value of |skip_reboot_|.
  bool IsRebootSkippedForTest() const;

 protected:
  using GetBootTimeCallback = base::RepeatingCallback<base::Time()>;

  // Extended constructor for testing purposes. `cros_settings` and
  // `notifications_scheduler` must outlive the handler.
  DeviceScheduledRebootHandler(
      ash::CrosSettings* cros_settings,
      std::unique_ptr<ScheduledTaskExecutor> scheduled_task_executor,
      RebootNotificationsScheduler* notifications_scheduler,
      GetBootTimeCallback get_boot_time_callback);

  // Called when scheduled timer fires. Triggers a reboot and
  // schedules the next reboot based on |scheduled_reboot_data_|.
  virtual void OnRebootTimerExpired();

  // Called on button click on the reboot notification or dialog. Executes
  // reboot instantly.
  virtual void OnRebootButtonClicked();

  // Callback triggered when scheduled reboot setting has changed.
  virtual void OnScheduledRebootDataChanged();

 private:
  // Calls |scheduled_task_executor_| to start the timer. Requires
  // |scheduled_update_check_data_| to be set.
  void StartRebootTimer();

  // Called upon starting reboot timer. Indicates whether or not the
  // timer was started successfully.
  void OnRebootTimerStartResult(ScopedWakeLock scoped_wake_lock, bool result);

  // Reset all state and cancel all pending tasks
  void ResetState();

  // Returns random delay between 0 and maximum reboot delay set by
  // ash::features::kDeviceForceScheduledRebootMaxDelay feature or
  // |reboot_delay_for_testing_| if set.
  const base::TimeDelta GetExternalDelay() const;

  void RebootDevice(const std::string& reboot_description) const;

  // Used to retrieve Chrome OS settings. Not owned.
  const raw_ptr<ash::CrosSettings> cros_settings_;

  // Subscription for callback when settings change.
  base::CallbackListSubscription cros_settings_subscription_;

  // Currently active scheduled reboot policy.
  std::optional<ScheduledTaskExecutor::ScheduledTaskData>
      scheduled_reboot_data_;

  // Timer that is scheduled to check for updates.
  std::unique_ptr<ScheduledTaskExecutor> scheduled_task_executor_;

  // Delay added to scheduled reboot time, used for testing.
  std::optional<base::TimeDelta> reboot_delay_for_testing_;

  // Scheduler for reboot notification and dialog. Unowned.
  raw_ptr<RebootNotificationsScheduler> notifications_scheduler_;

  // Indicating if the reboot should be skipped.
  bool skip_reboot_ = false;

  // Returns device's boot timestamp. The functor is used because the boot time
  // is not constant and can change at runtime, e.g. because of the time
  // sync.
  GetBootTimeCallback get_boot_time_callback_;

  // Observation of chromeos::PowerManagerClient.
  base::ScopedObservation<chromeos::PowerManagerClient,
                          chromeos::PowerManagerClient::Observer>
      observation_{this};
};

}  // namespace policy

#endif  // CHROME_BROWSER_ASH_POLICY_SCHEDULED_TASK_HANDLER_DEVICE_SCHEDULED_REBOOT_HANDLER_H_