1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
|
// 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_UI_VIEWS_RELAUNCH_NOTIFICATION_RELAUNCH_NOTIFICATION_CONTROLLER_H_
#define CHROME_BROWSER_UI_VIEWS_RELAUNCH_NOTIFICATION_RELAUNCH_NOTIFICATION_CONTROLLER_H_
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "base/timer/wall_clock_timer.h"
#include "chrome/browser/upgrade_detector/upgrade_detector.h"
#include "chrome/browser/upgrade_detector/upgrade_observer.h"
#include "components/prefs/pref_change_registrar.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "chrome/browser/ui/views/relaunch_notification/relaunch_notification_controller_platform_impl_chromeos.h"
#else
#include "chrome/browser/ui/views/relaunch_notification/relaunch_notification_controller_platform_impl_desktop.h"
#endif // BUILDFLAG(IS_CHROMEOS)
namespace base {
class Clock;
class TickClock;
} // namespace base
// A class that observes changes to the browser.relaunch_notification
// preference (which is backed by the RelaunchNotification policy
// setting) and upgrade notifications from the UpgradeDetector. The two
// values for the RelaunchNotification policy setting are handled as follows:
//
// On Chrome desktop:
// - Recommended (1): The controller displays the relaunch recommended bubble on
// each change to the UpgradeDetector's upgrade_notification_stage (an
// "annoyance level" of low, elevated, grace or high). Once the high annoyance
// level is reached, the controller continually reshows a the bubble on a
// timer with a period equal to the time delta between the "elevated" and
// "high" showings.
//
// - Required (2): The controller displays the relaunch required dialog when the
// UpgradeDetector's upgrade_notification_stage changes to an "annoyance level"
// of low, elevated, and grace. The browser is relaunched when the "annoyance
// level" reaches "high".
//
// On Chrome OS both notifications (recommended and required, described above)
// are shown in the unified system tray, overwriting the default "update
// available" notification. It cannot be deferred, so it persists until reboot.
// In certain conditions, the preference value could be overridden by the
// UpgradeDetector which then takes priority over the original value and any
// further changes to the preference have no effect.
class RelaunchNotificationController : public UpgradeObserver {
public:
// |upgrade_detector| is expected to be the process-wide detector, and must
// outlive the controller.
explicit RelaunchNotificationController(UpgradeDetector* upgrade_detector);
RelaunchNotificationController(const RelaunchNotificationController&) =
delete;
RelaunchNotificationController& operator=(
const RelaunchNotificationController&) = delete;
~RelaunchNotificationController() override;
protected:
// The length of the final countdown given to the user before the browser is
// summarily relaunched on Chrome desktop, or the device is rebooted on
// Chrome OS.
static constexpr base::TimeDelta kRelaunchGracePeriod = base::Hours(1);
RelaunchNotificationController(UpgradeDetector* upgrade_detector,
const base::Clock* clock,
const base::TickClock* tick_clock);
// The deadline may be extended to ensure that the user has at least the full
// duration of the grace period to take action.
base::Time IncreaseRelaunchDeadlineOnShow();
// UpgradeObserver:
void OnUpgradeRecommended() override;
void OnRelaunchOverriddenToRequired(bool overridden) override;
private:
enum class NotificationStyle {
kNone, // No notifications are shown.
kRecommended, // Relaunches are recommended.
kRequired, // Relaunches are required.
};
// Adjusts to the current notification style as indicated by the
// browser.relaunch_notification Local State preference. If the notification
// style has been overridden, then that value is given priority over the
// preference value.
void HandleCurrentStyle();
// Bring the instance out of or back to dormant mode.
void StartObservingUpgrades();
void StopObservingUpgrades();
// Shows the proper notification based on the preference setting and starts
// the timer to either reshow the bubble or restart the browser/device as
// appropriate. |level| is the current annoyance level reported by the
// UpgradeDetector, and |high_deadline| is the time at which the
// UpgradeDetector will reach the high annoyance level; see the class comment
// for further details.
void ShowRelaunchNotification(
UpgradeDetector::UpgradeNotificationAnnoyanceLevel level,
base::Time high_deadline);
// Closes any previously-shown notifications. This is safe to call if no
// notifications have been shown. Notifications may be closed by other means
// (e.g., by the user), so there is no expectation that a previously-shown
// notification is still open when this is invoked. The timer to either
// repeatedly show the relaunch recommended notification or to force a
// relaunch once the deadline is reached is also stopped.
void CloseRelaunchNotification();
// Starts or reschedules a timer to periodically re-show the relaunch
// recommended bubble.
void StartReshowTimer();
// Run on a timer once high annoyance has been reached to re-show the relaunch
// recommended bubble.
void OnReshowRelaunchRecommended();
// Handles a new |level| and/or |high_deadline| by adjusting the runtime of
// the relaunch timer, updating the deadline displayed in the title of the
// relaunch required notification (if shown), and showing it if needed.
void HandleRelaunchRequiredState(
UpgradeDetector::UpgradeNotificationAnnoyanceLevel level,
base::Time high_deadline);
// Update |last_relaunch_notification_time_| before calling
// DoNotifyRelaunchRecommended. |past_deadline| reflects whether the
// Recommended deadline was already passed or not.
void NotifyRelaunchRecommended(bool past_deadline);
// Calls DoNotifyRelaunchRequired to show the notification.
void NotifyRelaunchRequired();
// The following methods, which are invoked by the controller to show or close
// notifications, are virtual for the sake of testing.
// Shows the relaunch recommended notification if it is not already open.
// |past_deadline| reflects whether the Recommended deadline was already
// passed or not.
virtual void DoNotifyRelaunchRecommended(bool past_deadline);
// Shows the relaunch required notification if it is not already open.
// |on_visible| is a callback to be run when the notification is potentially
// seen by the user to push back the relaunch deadline if the remaining time
// is less than the grace period.
virtual void DoNotifyRelaunchRequired(
base::Time relaunch_deadline,
base::OnceCallback<base::Time()> on_visible);
// Closes bubble or dialog if either is still open on desktop, or sets the
// default notification on Chrome OS.
virtual void Close();
// Run to restart the browser/device once the relaunch deadline is reached
// when relaunches are required by policy.
virtual void OnRelaunchDeadlineExpired();
// The process-wide upgrade detector.
const raw_ptr<UpgradeDetector> upgrade_detector_;
// A provider of Time to the controller and its timer for the sake of
// testability.
const raw_ptr<const base::Clock> clock_;
// The platform-specific implementation.
RelaunchNotificationControllerPlatformImpl platform_impl_;
// Observes changes to the browser.relaunch_notification Local State pref.
PrefChangeRegistrar pref_change_registrar_;
// The last observed notification style. When kNone, the controller is
// said to be "dormant" as there is no work for it to do aside from watch for
// changes to browser.relaunch_notification. When any other value, the
// controller is observing the UpgradeDetector to detect when to show a
// notification.
NotificationStyle last_notification_style_;
// The last observed annoyance level. This member is unconditionally
// UPGRADE_ANNOYANCE_NONE when the controller is dormant
// (browser.relaunch_notification is 0).
UpgradeDetector::UpgradeNotificationAnnoyanceLevel last_level_;
// The last observed high annoyance deadline.
base::Time last_high_deadline_;
// The last time recommended relaunch notification triggered
base::Time last_relaunch_notification_time_;
// A timer used either to repeatedly reshow the relaunch recommended bubble
// once the high annoyance level has been reached, or to trigger browser
// relaunch once the relaunch required dialog's deadline is reached.
base::WallClockTimer timer_;
// A flag to denote that the relaunch notification type policy value has been
// overridden to required. Changes to the policy value will not affect the
// notification type.
bool notification_type_required_overridden_ = false;
};
#endif // CHROME_BROWSER_UI_VIEWS_RELAUNCH_NOTIFICATION_RELAUNCH_NOTIFICATION_CONTROLLER_H_
|