|  | // Copyright 2017 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef CHROME_BROWSER_CHROMEOS_POLICY_MINIMUM_VERSION_POLICY_HANDLER_H_ | 
|  | #define CHROME_BROWSER_CHROMEOS_POLICY_MINIMUM_VERSION_POLICY_HANDLER_H_ | 
|  |  | 
|  | #include <memory> | 
|  |  | 
|  | #include "base/macros.h" | 
|  | #include "base/memory/weak_ptr.h" | 
|  | #include "base/observer_list.h" | 
|  | #include "base/time/time.h" | 
|  | #include "base/util/timer/wall_clock_timer.h" | 
|  | #include "base/version.h" | 
|  | #include "chrome/browser/ash/settings/cros_settings.h" | 
|  | #include "chrome/browser/upgrade_detector/build_state_observer.h" | 
|  | #include "chromeos/dbus/update_engine_client.h" | 
|  | #include "chromeos/network/network_state_handler_observer.h" | 
|  |  | 
|  | class PrefRegistrySimple; | 
|  |  | 
|  | namespace ash { | 
|  | class UpdateRequiredNotification; | 
|  | }  // namespace ash | 
|  |  | 
|  | namespace base { | 
|  | class Clock; | 
|  | class DictionaryValue; | 
|  | class Time; | 
|  | }  // namespace base | 
|  |  | 
|  | namespace policy { | 
|  |  | 
|  | // This class observes the device setting |kDeviceMinimumVersion|, and | 
|  | // checks if respective requirement is met. If an update is not required, all | 
|  | // running timers are reset. If an update is required, it calculates the | 
|  | // deadline using the warning period in the policy and restarts the timer. It | 
|  | // also calls UpdateRequiredNotification to show in-session notifications if an | 
|  | // update is required but it cannot be downloaded due to network limitations or | 
|  | // Auto Update Expiration. | 
|  | class MinimumVersionPolicyHandler | 
|  | : public BuildStateObserver, | 
|  | public chromeos::NetworkStateHandlerObserver, | 
|  | public chromeos::UpdateEngineClient::Observer { | 
|  | public: | 
|  | static const char kRequirements[]; | 
|  | static const char kChromeOsVersion[]; | 
|  | static const char kWarningPeriod[]; | 
|  | static const char kEolWarningPeriod[]; | 
|  | static const char kUnmanagedUserRestricted[]; | 
|  |  | 
|  | class Observer { | 
|  | public: | 
|  | virtual void OnMinimumVersionStateChanged() = 0; | 
|  | virtual ~Observer() = default; | 
|  | }; | 
|  |  | 
|  | // Delegate of MinimumVersionPolicyHandler to handle the external | 
|  | // dependencies. | 
|  | class Delegate { | 
|  | public: | 
|  | virtual ~Delegate() {} | 
|  |  | 
|  | // Checks if the user is logged in as any kiosk app. | 
|  | virtual bool IsKioskMode() const = 0; | 
|  |  | 
|  | // Checks if the device is enterprise managed. | 
|  | virtual bool IsEnterpriseManaged() const = 0; | 
|  |  | 
|  | // Checks if a user is logged in. | 
|  | virtual bool IsUserLoggedIn() const = 0; | 
|  |  | 
|  | // Checks if the user logged in is managed and not a child user. | 
|  | virtual bool IsUserEnterpriseManaged() const = 0; | 
|  |  | 
|  | // Checks if we are currently on the login screen. | 
|  | virtual bool IsLoginSessionState() const = 0; | 
|  |  | 
|  | // Checks if login is in progress before starting user session. | 
|  | virtual bool IsLoginInProgress() const = 0; | 
|  |  | 
|  | // Shows the update required screen. | 
|  | virtual void ShowUpdateRequiredScreen() = 0; | 
|  |  | 
|  | // Terminates the current session and restarts Chrome to show the login | 
|  | // screen. | 
|  | virtual void RestartToLoginScreen() = 0; | 
|  |  | 
|  | // Hides update required screen and shows the login screen. | 
|  | virtual void HideUpdateRequiredScreenIfShown() = 0; | 
|  |  | 
|  | virtual base::Version GetCurrentVersion() const = 0; | 
|  | }; | 
|  |  | 
|  | class MinimumVersionRequirement { | 
|  | public: | 
|  | MinimumVersionRequirement(const base::Version version, | 
|  | const base::TimeDelta warning, | 
|  | const base::TimeDelta eol_warning); | 
|  |  | 
|  | MinimumVersionRequirement(const MinimumVersionRequirement&) = delete; | 
|  |  | 
|  | // Method used to create an instance of MinimumVersionRequirement from | 
|  | // dictionary if it contains valid version string. | 
|  | static std::unique_ptr<MinimumVersionRequirement> CreateInstanceIfValid( | 
|  | const base::DictionaryValue* dict); | 
|  |  | 
|  | // This is used to compare two MinimumVersionRequirement objects | 
|  | // and returns 1 if the first object has version or warning time | 
|  | // or eol warning time greater than that the second, -1 if the | 
|  | // its version or warning time or eol warning time is less than the second, | 
|  | // else 0. | 
|  | int Compare(const MinimumVersionRequirement* other) const; | 
|  |  | 
|  | base::Version version() const { return minimum_version_; } | 
|  | base::TimeDelta warning() const { return warning_time_; } | 
|  | base::TimeDelta eol_warning() const { return eol_warning_time_; } | 
|  |  | 
|  | private: | 
|  | base::Version minimum_version_; | 
|  | base::TimeDelta warning_time_; | 
|  | base::TimeDelta eol_warning_time_; | 
|  | }; | 
|  |  | 
|  | enum class NetworkStatus { kAllowed, kMetered, kOffline }; | 
|  |  | 
|  | enum class NotificationType { | 
|  | kMeteredConnection, | 
|  | kNoConnection, | 
|  | kEolReached | 
|  | }; | 
|  |  | 
|  | explicit MinimumVersionPolicyHandler(Delegate* delegate, | 
|  | ash::CrosSettings* cros_settings); | 
|  | ~MinimumVersionPolicyHandler() override; | 
|  |  | 
|  | // BuildStateObserver: | 
|  | void OnUpdate(const BuildState* build_state) override; | 
|  |  | 
|  | // NetworkStateHandlerObserver: | 
|  | void DefaultNetworkChanged(const chromeos::NetworkState* network) override; | 
|  |  | 
|  | // UpdateEngineClient::Observer: | 
|  | void UpdateStatusChanged(const update_engine::StatusResult& status) override; | 
|  |  | 
|  | void AddObserver(Observer* observer); | 
|  | void RemoveObserver(Observer* observer); | 
|  | bool RequirementsAreSatisfied() const { return GetState() == nullptr; } | 
|  |  | 
|  | const MinimumVersionRequirement* GetState() const { return state_.get(); } | 
|  |  | 
|  | bool DeadlineReached() { return deadline_reached_; } | 
|  |  | 
|  | static void RegisterPrefs(PrefRegistrySimple* registry); | 
|  |  | 
|  | // Show notification on login if the user is managed or | 
|  | // |unmanaged_user_restricted_| is set to true if it is the last day to | 
|  | // deadline. | 
|  | void MaybeShowNotificationOnLogin(); | 
|  |  | 
|  | // Whether banner to return back the device should be visible in Settings. It | 
|  | // is true when an update is required on a device that has reached End Of Life | 
|  | // (Auto Update Expiration) and the currently signed in user is enterprise | 
|  | // managed or an unmanaged user restricted by DeviceMinimumVersion policy. | 
|  | bool ShouldShowUpdateRequiredEolBanner() const; | 
|  |  | 
|  | // Returns the number of days to deadline if update is required and deadline | 
|  | // has not been reached. Returns null if update is not required. | 
|  | base::Optional<int> GetTimeRemainingInDays(); | 
|  |  | 
|  | // Callback used in tests and invoked after end-of-life status has been | 
|  | // fetched from the update_engine. | 
|  | void set_fetch_eol_callback_for_testing(base::OnceClosure callback) { | 
|  | fetch_eol_callback_ = std::move(callback); | 
|  | } | 
|  |  | 
|  | base::Time update_required_deadline_for_testing() const { | 
|  | return update_required_deadline_; | 
|  | } | 
|  |  | 
|  | bool IsDeadlineTimerRunningForTesting() const; | 
|  |  | 
|  | private: | 
|  | // Returns |true| if the current version satisfies the given requirement. | 
|  | bool CurrentVersionSatisfies( | 
|  | const MinimumVersionRequirement& requirement) const; | 
|  |  | 
|  | // Whether the current user should receive update required notifications and | 
|  | // force signed out on reaching the deadline. Retuns true if the user is | 
|  | // enterprise managed or |unmanaged_user_restricted_| is true. | 
|  | bool IsPolicyRestrictionAppliedForUser() const; | 
|  |  | 
|  | void OnPolicyChanged(); | 
|  | bool IsPolicyApplicable(); | 
|  | void Reset(); | 
|  |  | 
|  | // Handles post update completed actions like reset timers, hide update | 
|  | // required notification and stop observing build state. | 
|  | void ResetOnUpdateCompleted(); | 
|  |  | 
|  | // Handles the state when update is required as per the policy. If on the | 
|  | // login screen, update required screen is shown, else the user is logged out | 
|  | // if the device is not updated within the given |warning_time|. The | 
|  | // |warning_time| is supplied by the policy. | 
|  | void HandleUpdateRequired(base::TimeDelta warning_time); | 
|  |  | 
|  | void HandleUpdateNotRequired(); | 
|  |  | 
|  | // Invokes update_engine_client to fetch the end-of-life status of the device. | 
|  | void FetchEolInfo(); | 
|  |  | 
|  | // Callback after fetching end-of-life info from the update_engine_client. | 
|  | void OnFetchEolInfo(chromeos::UpdateEngineClient::EolInfo info); | 
|  |  | 
|  | // Called when the warning time to apply updates has expired. If the user on | 
|  | // the login screen, the update required screen is shown else the current user | 
|  | // session is terminated to bring the user back to the login screen. | 
|  | void OnDeadlineReached(); | 
|  |  | 
|  | // Starts the timer to expire when |deadline| is reached. | 
|  | void StartDeadlineTimer(base::Time deadline); | 
|  |  | 
|  | // Starts observing the BuildState for any updates in Chrome OS and resets the | 
|  | // state if new version satisfies the minimum version requirement. | 
|  | void StartObservingUpdate(); | 
|  |  | 
|  | // Shows notification for a managed logged in user if update is required and | 
|  | // the device can not be updated due to end-of-life or network limitations. | 
|  | void MaybeShowNotification(base::TimeDelta warning); | 
|  |  | 
|  | // Shows notification if required and starts a timer to expire when the next | 
|  | // notification is to be shown. | 
|  | void ShowAndScheduleNotification(base::Time deadline); | 
|  |  | 
|  | void HideNotification() const; | 
|  |  | 
|  | void StopObservingNetwork(); | 
|  |  | 
|  | // Start updating over metered network as user has given consent through | 
|  | // notification click. | 
|  | void UpdateOverMeteredPermssionGranted(); | 
|  |  | 
|  | // Tells whether starting an update check succeeded or not. | 
|  | void OnUpdateCheckStarted( | 
|  | chromeos::UpdateEngineClient::UpdateCheckResult result); | 
|  |  | 
|  | // Callback from UpdateEngineClient::SetUpdateOverCellularOneTimePermission(). | 
|  | void OnSetUpdateOverCellularOneTimePermission(bool success); | 
|  |  | 
|  | // Updates pref |kUpdateRequiredWarningPeriod| in local state to | 
|  | // |warning_time|. If |kUpdateRequiredTimerStartTime| is not null, it means | 
|  | // update is already required and hence, the timer start time should not be | 
|  | // updated. | 
|  | void UpdateLocalState(base::TimeDelta warning_time); | 
|  |  | 
|  | // Resets the local state prefs to default values. | 
|  | void ResetLocalState(); | 
|  |  | 
|  | // This delegate instance is owned by the owner of | 
|  | // MinimumVersionPolicyHandler. The owner is responsible to make sure that the | 
|  | // delegate lives throughout the life of the policy handler. | 
|  | Delegate* delegate_; | 
|  |  | 
|  | // This represents the current minimum version requirement. | 
|  | // It is chosen as one of the configurations specified in the policy. It is | 
|  | // set to nullptr if the current version is higher than the minimum required | 
|  | // version in all the configurations. | 
|  | std::unique_ptr<MinimumVersionRequirement> state_; | 
|  |  | 
|  | // If this flag is true, unmanaged user sessions receive update required | 
|  | // notifications and are force logged out when deadline is reached. | 
|  | bool unmanaged_user_restricted_ = false; | 
|  |  | 
|  | bool eol_reached_ = false; | 
|  |  | 
|  | // If this flag is true, user should restricted to use the session by logging | 
|  | // out and/or showing update required screen. | 
|  | bool deadline_reached_ = false; | 
|  |  | 
|  | // Time when the policy is applied and with respect to which the deadline to | 
|  | // update the device is calculated. | 
|  | base::Time update_required_time_; | 
|  |  | 
|  | // Deadline for updating the device post which the user is restricted from | 
|  | // using the session by force log out if a session is active and then blocking | 
|  | // sign in at the login screen. | 
|  | base::Time update_required_deadline_; | 
|  |  | 
|  | // Fires when the deadline to update the device has reached or passed. | 
|  | util::WallClockTimer update_required_deadline_timer_; | 
|  |  | 
|  | // Fires when next update required notification is to be shown. | 
|  | util::WallClockTimer notification_timer_; | 
|  |  | 
|  | // Non-owning reference to CrosSettings. This class have shorter lifetime than | 
|  | // CrosSettings. | 
|  | ash::CrosSettings* cros_settings_; | 
|  |  | 
|  | base::Clock* const clock_; | 
|  |  | 
|  | base::OnceClosure fetch_eol_callback_; | 
|  |  | 
|  | base::CallbackListSubscription policy_subscription_; | 
|  |  | 
|  | // Handles showing in-session update required notifications on the basis of | 
|  | // current network and time to reach the deadline. | 
|  | std::unique_ptr<ash::UpdateRequiredNotification> notification_handler_; | 
|  |  | 
|  | // List of registered observers. | 
|  | base::ObserverList<Observer>::Unchecked observers_; | 
|  |  | 
|  | base::WeakPtrFactory<MinimumVersionPolicyHandler> weak_factory_{this}; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(MinimumVersionPolicyHandler); | 
|  | }; | 
|  |  | 
|  | }  // namespace policy | 
|  |  | 
|  | #endif  // CHROME_BROWSER_CHROMEOS_POLICY_MINIMUM_VERSION_POLICY_HANDLER_H_ |