chromium/chrome/browser/ash/child_accounts/screen_time_controller.h

// Copyright 2018 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_CHILD_ACCOUNTS_SCREEN_TIME_CONTROLLER_H_
#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_SCREEN_TIME_CONTROLLER_H_

#include <memory>
#include <optional>
#include <string>

#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/ash/child_accounts/parent_access_code/parent_access_service.h"
#include "chrome/browser/ash/child_accounts/time_limit_notifier.h"
#include "chrome/browser/ash/child_accounts/usage_time_limit_processor.h"
#include "chrome/browser/ash/child_accounts/usage_time_state_notifier.h"
#include "chromeos/ash/components/dbus/system_clock/system_clock_client.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/session_manager/core/session_manager_observer.h"

class PrefRegistrySimple;
class PrefService;

namespace base {
class Clock;
class TickClock;
class OneShotTimer;
class SequencedTaskRunner;
}  // namespace base

namespace content {
class BrowserContext;
}  // namespace content

namespace ash {
enum class ParentCodeValidationResult;

// The controller to track each user's screen time usage and inquiry time limit
// processor (a component to calculate state based on policy settings and time
// usage) when necessary to determine the current lock screen state.
// Schedule notifications and lock/unlock screen based on the processor output.
class ScreenTimeController
    : public KeyedService,
      public parent_access::ParentAccessService::Observer,
      public session_manager::SessionManagerObserver,
      public UsageTimeStateNotifier::Observer,
      public system::TimezoneSettings::Observer,
      public SystemClockClient::Observer {
 public:
  class Observer : public base::CheckedObserver {
   public:
    // Called when daily screen time limit is |kUsageTimeLimitWarningTime| or
    // less to finish.
    virtual void UsageTimeLimitWarning() = 0;
  };

  // Registers preferences.
  static void RegisterProfilePrefs(PrefRegistrySimple* registry);

  explicit ScreenTimeController(content::BrowserContext* context);

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

  ~ScreenTimeController() override;

  // Returns the child's screen time duration. This is how long the child has
  // used the device today (since the last reset).
  virtual base::TimeDelta GetScreenTimeDuration();

  // Method intended for testing purposes only.
  void SetClocksForTesting(
      const base::Clock* clock,
      const base::TickClock* tick_clock,
      scoped_refptr<base::SequencedTaskRunner> task_runner);

  // Call UsageTimeLimitWarning for each observer for testing.
  void NotifyUsageTimeLimitWarningForTesting();

  // Adds or removes an observer.
  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);

 private:
  // Call time limit processor for new state.
  void CheckTimeLimit(const std::string& source);

  // Request to lock the screen and show the time limits message when the screen
  // is locked.
  void ForceScreenLockByPolicy();

  // Enables the time limits message in the lock screen and performs tasks that
  // need to run after the screen is locked.
  // |active_policy|: Which policy is locking the device, only valid when
  //                  |visible| is true.
  // |next_unlock_time|: When user will be able to unlock the screen, only valid
  //                     when |visible| is true.
  void OnScreenLockByPolicy(usage_time_limit::PolicyType active_policy,
                            base::Time next_unlock_time);

  // Disables the time limits message in the lock screen.
  void OnScreenLockByPolicyEnd();

  // Called when the policy of time limits changes.
  void OnPolicyChanged();

  // Reset any currently running timers.
  void ResetStateTimers();
  void ResetInSessionTimers();
  void ResetWarningTimers();

  // Schedule a call for UsageTimeLimitWarning.
  void ScheduleUsageTimeLimitWarning(const usage_time_limit::State& state);

  // Save the |state| to |prefs::kScreenTimeLastState|.
  void SaveCurrentStateToPref(const usage_time_limit::State& state);

  // Get the last calculated |state| from |prefs::kScreenTimeLastState|, if it
  // exists.
  std::optional<usage_time_limit::State> GetLastStateFromPref();

  // Called when the usage time limit is |kUsageTimeLimitWarningTime| or less to
  // finish. It should call the method UsageTimeLimitWarning for each observer.
  void UsageTimeLimitWarning();

  // Converts a usage_time_limit::PolicyType to its TimeLimitNotifier::LimitType
  // equivalent.
  std::optional<TimeLimitNotifier::LimitType> ConvertPolicyType(
      usage_time_limit::PolicyType policy_type);

  // parent_access::ParentAccessService::Observer:
  void OnAccessCodeValidation(ParentCodeValidationResult result,
                              std::optional<AccountId> account_id) override;

  // session_manager::SessionManagerObserver:
  void OnSessionStateChanged() override;

  // UsageTimeStateNotifier::Observer:
  void OnUsageTimeStateChange(
      const UsageTimeStateNotifier::UsageTimeState state) override;

  // system::TimezoneSettings::Observer:
  void TimezoneChanged(const icu::TimeZone& timezone) override;

  // SystemClockClient::Observer:
  void SystemClockUpdated() override;

  raw_ptr<content::BrowserContext> context_;
  raw_ptr<PrefService> pref_service_;

  base::ObserverList<Observer> observers_;

  // Points to the base::DefaultClock by default.
  raw_ptr<const base::Clock> clock_;

  // Timer scheduled for when the next lock screen state change event is
  // expected to happen, e.g. when bedtime is over or the usage limit ends.
  std::unique_ptr<base::OneShotTimer> next_state_timer_;

  // Timer to schedule the usage time limit warning and call the
  // UsageTimeLimitWarning for each observer. This should happen
  // |kUsageTimeLimitWarningTime| minutes or less before the device is locked by
  // usage limit.
  std::unique_ptr<base::OneShotTimer> usage_time_limit_warning_timer_;

  // Contains the last time limit policy processed by this class. Used to
  // generate notifications when the policy changes.
  base::Value::Dict last_policy_;

  // Used to set up timers when a time limit is approaching.
  TimeLimitNotifier time_limit_notifier_;

  PrefChangeRegistrar pref_change_registrar_;
};

}  // namespace ash

#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_SCREEN_TIME_CONTROLLER_H_