| // Copyright (c) 2012 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_LOGIN_WIZARD_CONTROLLER_H_ |
| #define CHROME_BROWSER_CHROMEOS_LOGIN_WIZARD_CONTROLLER_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <string> |
| |
| #include "base/compiler_specific.h" |
| #include "base/gtest_prod_util.h" |
| #include "base/macros.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/observer_list.h" |
| #include "base/optional.h" |
| #include "base/time/time.h" |
| #include "base/timer/timer.h" |
| #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" |
| #include "chrome/browser/chromeos/login/demo_mode/demo_session.h" |
| #include "chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h" |
| #include "chrome/browser/chromeos/login/enrollment/enrollment_screen.h" |
| #include "chrome/browser/chromeos/login/screen_manager.h" |
| #include "chrome/browser/chromeos/login/screens/active_directory_login_screen.h" |
| #include "chrome/browser/chromeos/login/screens/arc_terms_of_service_screen.h" |
| #include "chrome/browser/chromeos/login/screens/assistant_optin_flow_screen.h" |
| #include "chrome/browser/chromeos/login/screens/demo_preferences_screen.h" |
| #include "chrome/browser/chromeos/login/screens/demo_setup_screen.h" |
| #include "chrome/browser/chromeos/login/screens/edu_coexistence_login_screen.h" |
| #include "chrome/browser/chromeos/login/screens/enable_adb_sideloading_screen.h" |
| #include "chrome/browser/chromeos/login/screens/enable_debugging_screen.h" |
| #include "chrome/browser/chromeos/login/screens/eula_screen.h" |
| #include "chrome/browser/chromeos/login/screens/family_link_notice_screen.h" |
| #include "chrome/browser/chromeos/login/screens/fingerprint_setup_screen.h" |
| #include "chrome/browser/chromeos/login/screens/gaia_password_changed_screen.h" |
| #include "chrome/browser/chromeos/login/screens/gaia_screen.h" |
| #include "chrome/browser/chromeos/login/screens/gesture_navigation_screen.h" |
| #include "chrome/browser/chromeos/login/screens/hid_detection_screen.h" |
| #include "chrome/browser/chromeos/login/screens/kiosk_autolaunch_screen.h" |
| #include "chrome/browser/chromeos/login/screens/locale_switch_screen.h" |
| #include "chrome/browser/chromeos/login/screens/marketing_opt_in_screen.h" |
| #include "chrome/browser/chromeos/login/screens/multidevice_setup_screen.h" |
| #include "chrome/browser/chromeos/login/screens/network_screen.h" |
| #include "chrome/browser/chromeos/login/screens/offline_login_screen.h" |
| #include "chrome/browser/chromeos/login/screens/packaged_license_screen.h" |
| #include "chrome/browser/chromeos/login/screens/parental_handoff_screen.h" |
| #include "chrome/browser/chromeos/login/screens/pin_setup_screen.h" |
| #include "chrome/browser/chromeos/login/screens/recommend_apps_screen.h" |
| #include "chrome/browser/chromeos/login/screens/signin_fatal_error_screen.h" |
| #include "chrome/browser/chromeos/login/screens/sync_consent_screen.h" |
| #include "chrome/browser/chromeos/login/screens/terms_of_service_screen.h" |
| #include "chrome/browser/chromeos/login/screens/update_screen.h" |
| #include "chrome/browser/chromeos/login/screens/user_creation_screen.h" |
| #include "chrome/browser/chromeos/login/screens/welcome_screen.h" |
| #include "chrome/browser/chromeos/policy/enrollment_config.h" |
| #include "components/account_id/account_id.h" |
| |
| class PrefService; |
| |
| namespace chromeos { |
| |
| namespace login { |
| class NetworkStateHelper; |
| } // namespace login |
| |
| class DemoSetupController; |
| class ErrorScreen; |
| struct Geoposition; |
| enum class KioskAppType; |
| class LoginDisplayHost; |
| class SimpleGeolocationProvider; |
| class TimeZoneProvider; |
| struct TimeZoneResponseData; |
| |
| // Class that manages control flow between wizard screens. Wizard controller |
| // interacts with screen controllers to move the user between screens. |
| class WizardController { |
| public: |
| class ScreenObserver : public base::CheckedObserver { |
| public: |
| virtual void OnCurrentScreenChanged(BaseScreen* new_screen) = 0; |
| virtual void OnShutdown() = 0; |
| }; |
| |
| WizardController(); |
| ~WizardController(); |
| |
| // Returns the default wizard controller if it has been created. This is a |
| // helper for LoginDisplayHost::default_host()->GetWizardController(); |
| static WizardController* default_controller(); |
| |
| // Whether to skip any screens that may normally be shown after login |
| // (registration, Terms of Service, user image selection). |
| static bool skip_post_login_screens() { return skip_post_login_screens_; } |
| |
| // Whether to skip any prompts that may be normally shown during enrollment. |
| static bool skip_enrollment_prompts() { return skip_enrollment_prompts_; } |
| |
| // Sets delays to zero. MUST be used only for tests. |
| static void SetZeroDelays(); |
| |
| // If true zero delays have been enabled (for browser tests). |
| static bool IsZeroDelayEnabled(); |
| |
| // Skips any screens that may normally be shown after login (registration, |
| // Terms of Service, user image selection). |
| static void SkipPostLoginScreensForTesting(); |
| |
| // Skips any enrollment prompts that may be normally shown. |
| static void SkipEnrollmentPromptsForTesting(); |
| |
| // Forces screens that should only appear in chrome branded builds to show. |
| static std::unique_ptr<base::AutoReset<bool>> ForceBrandedBuildForTesting( |
| bool value); |
| |
| // Returns true if OOBE is operating under the |
| // Zero-Touch Hands-Off Enrollment Flow. |
| static bool UsingHandsOffEnrollment(); |
| |
| // Returns true if this is a branded build, value could be overwritten by |
| // `ForceBrandedBuildForTesting`. |
| static bool IsBrandedBuild() { return is_branded_build_; } |
| |
| bool is_initialized() { return is_initialized_; } |
| |
| // Shows the first screen defined by `first_screen` or by default if the |
| // parameter is empty. |
| void Init(OobeScreenId first_screen); |
| |
| // Advances to screen defined by `screen` and shows it. Might show HID |
| // detection screen in case HID connection is needed and screen_id == |
| // OobeScreen::SCREEN_UNKNOWN. |
| void AdvanceToScreen(OobeScreenId screen_id); |
| |
| // Advances to screen defined by `screen` and shows it. |
| void AdvanceToScreenAfterHIDDetection(OobeScreenId first_screen); |
| |
| // Returns `true` if accelerator `action` was handled by current screen |
| // or WizardController itself. |
| bool HandleAccelerator(ash::LoginAcceleratorAction action); |
| |
| // Starts Demo Mode setup flow. The flow starts from network screen and reuses |
| // some of regular OOBE screens. It consists of the following screens: |
| // chromeos::DemoPreferencesScreenView::kScreenId |
| // chromeos::NetworkScreenView::kScreenId |
| // chromeos::EulaView::kScreenId |
| // chromeos::ArcTermsOfServiceScreenView::kScreenId |
| // chromeos::UpdateView::kScreenId |
| // chromeos::DemoSetupScreenView::kScreenId |
| void StartDemoModeSetup(); |
| |
| // Simulates demo mode setup environment. If `demo_config` has a value, it |
| // is explicitly set on DemoSetupController and going through demo settings |
| // screens can be skipped. |
| void SimulateDemoModeSetupForTesting( |
| base::Optional<DemoSession::DemoModeConfig> demo_config = base::nullopt); |
| |
| // Advances to login/update screen. Should be used in for testing only. |
| void SkipToLoginForTesting(); |
| void SkipToUpdateForTesting(); |
| |
| // Skip update, go straight to enrollment after EULA is accepted. |
| void SkipUpdateEnrollAfterEula(); |
| |
| // Returns current DemoSetupController if demo setup flow is in progress or |
| // nullptr otherwise. |
| DemoSetupController* demo_setup_controller() const { |
| return demo_setup_controller_.get(); |
| } |
| |
| // Returns a pointer to the current screen or nullptr if there's no such |
| // screen. |
| BaseScreen* current_screen() const { return current_screen_; } |
| |
| // Returns true if the current wizard instance has reached the login screen. |
| bool login_screen_started() const { return login_screen_started_; } |
| |
| // Returns true if a given screen exists. |
| bool HasScreen(OobeScreenId screen_id); |
| |
| // Returns a given screen. Creates it lazily. |
| BaseScreen* GetScreen(OobeScreenId screen_id); |
| |
| // Returns the current ScreenManager instance. |
| ScreenManager* screen_manager() const { return screen_manager_.get(); } |
| |
| template <typename TScreen> |
| TScreen* GetScreen() const { |
| return static_cast<TScreen*>( |
| screen_manager()->GetScreen(TScreen::TView::kScreenId)); |
| } |
| |
| // Returns the current WizardContext instance. |
| WizardContext* get_wizard_context_for_testing() const { |
| return wizard_context_.get(); |
| } |
| |
| // Volume percent at which spoken feedback is still audible. |
| static const int kMinAudibleOutputVolumePercent; |
| |
| // Set the current screen. For Test use only. |
| void SetCurrentScreenForTesting(BaseScreen* screen); |
| |
| void SetSharedURLLoaderFactoryForTesting( |
| scoped_refptr<network::SharedURLLoaderFactory> factory); |
| |
| // Configure and show GAIA password changed screen. |
| void ShowGaiaPasswordChangedScreen(const AccountId& account_id, |
| bool has_error); |
| |
| // Configure and show active directory password change screen. |
| void ShowActiveDirectoryPasswordChangeScreen(const std::string& username); |
| |
| // Configure and show the signin fatal error screen. |
| void ShowSignInFatalErrorScreen(SignInFatalErrorScreen::Error error, |
| const base::Value* params); |
| |
| // Show Family Link notice screen. |
| void ShowFamilyLinkNoticeScreen(); |
| |
| // Set pref value for first run. |
| void PrepareFirstRunPrefs(); |
| |
| // Returns true if we are in user creation screen or gaia signin screen. |
| static bool IsSigninScreen(OobeScreenId screen_id); |
| |
| OobeScreenId first_screen_for_testing() const { |
| return first_screen_for_testing_; |
| } |
| |
| void AddObserver(ScreenObserver* obs); |
| void RemoveObserver(ScreenObserver* obs); |
| |
| private: |
| // Create BaseScreen instances. These are owned by `screen_manager_`. |
| std::vector<std::unique_ptr<BaseScreen>> CreateScreens(); |
| |
| // Show specific screen. |
| void ShowWelcomeScreen(); |
| void ShowNetworkScreen(); |
| void ShowEulaScreen(); |
| void ShowEnrollmentScreen(); |
| void ShowDemoModeSetupScreen(); |
| void ShowDemoModePreferencesScreen(); |
| void ShowResetScreen(); |
| void ShowKioskAutolaunchScreen(); |
| void ShowEnableAdbSideloadingScreen(); |
| void ShowEnableDebuggingScreen(); |
| void ShowKioskEnableScreen(); |
| void ShowTermsOfServiceScreen(); |
| void ShowSyncConsentScreen(); |
| void ShowFingerprintSetupScreen(); |
| void ShowArcTermsOfServiceScreen(); |
| void ShowRecommendAppsScreen(); |
| void ShowAppDownloadingScreen(); |
| void ShowWrongHWIDScreen(); |
| void ShowAutoEnrollmentCheckScreen(); |
| void ShowHIDDetectionScreen(); |
| void ShowDeviceDisabledScreen(); |
| void ShowEncryptionMigrationScreen(); |
| void ShowSupervisionTransitionScreen(); |
| void ShowUpdateRequiredScreen(); |
| void ShowAssistantOptInFlowScreen(); |
| void ShowMultiDeviceSetupScreen(); |
| void ShowGestureNavigationScreen(); |
| void ShowPinSetupScreen(); |
| void ShowMarketingOptInScreen(); |
| void ShowPackagedLicenseScreen(); |
| void ShowEduCoexistenceLoginScreen(); |
| void ShowParentalHandoffScreen(); |
| |
| // Shows images login screen. |
| void ShowLoginScreen(); |
| |
| // Check if advancing to `screen` is allowed using screen priorities. Return |
| // true if the priority of `screen` is higher or equal to current screen. |
| bool CanNavigateTo(OobeScreenId screen_id); |
| |
| // Shows default screen depending on device ownership. |
| void OnOwnershipStatusCheckDone( |
| DeviceSettingsService::OwnershipStatus status); |
| |
| // Shared actions to be performed on a screen exit. |
| // `exit_reason` is the screen specific exit reason reported by the screen. |
| void OnScreenExit(OobeScreenId screen, const std::string& exit_reason); |
| |
| // Exit handlers: |
| void OnWrongHWIDScreenExit(); |
| void OnHidDetectionScreenExit(HIDDetectionScreen::Result result); |
| void OnWelcomeScreenExit(WelcomeScreen::Result result); |
| void OnNetworkScreenExit(NetworkScreen::Result result); |
| bool ShowEulaOrArcTosAfterNetworkScreen(); |
| void OnEulaScreenExit(EulaScreen::Result result); |
| void OnEulaAccepted(bool usage_statistics_reporting_enabled); |
| void OnUpdateScreenExit(UpdateScreen::Result result); |
| void OnUpdateCompleted(); |
| void OnAutoEnrollmentCheckScreenExit(); |
| void OnEnrollmentScreenExit(EnrollmentScreen::Result result); |
| void OnEnrollmentDone(); |
| void OnEnableAdbSideloadingScreenExit(); |
| void OnEnableDebuggingScreenExit(); |
| void OnKioskEnableScreenExit(); |
| void OnKioskAutolaunchScreenExit(KioskAutolaunchScreen::Result result); |
| void OnDemoPreferencesScreenExit(DemoPreferencesScreen::Result result); |
| void OnDemoSetupScreenExit(DemoSetupScreen::Result result); |
| void OnLocaleSwitchScreenExit(LocaleSwitchScreen::Result result); |
| void OnTermsOfServiceScreenExit(TermsOfServiceScreen::Result result); |
| void OnFingerprintSetupScreenExit(FingerprintSetupScreen::Result result); |
| void OnSyncConsentScreenExit(SyncConsentScreen::Result result); |
| void OnPinSetupScreenExit(PinSetupScreen::Result result); |
| void OnArcTermsOfServiceScreenExit(ArcTermsOfServiceScreen::Result result); |
| void OnArcTermsOfServiceAccepted(); |
| void OnRecommendAppsScreenExit(RecommendAppsScreen::Result result); |
| void OnAppDownloadingScreenExit(); |
| void OnAssistantOptInFlowScreenExit(AssistantOptInFlowScreen::Result result); |
| void OnMultiDeviceSetupScreenExit(MultiDeviceSetupScreen::Result result); |
| void OnGestureNavigationScreenExit(GestureNavigationScreen::Result result); |
| void OnMarketingOptInScreenExit(MarketingOptInScreen::Result result); |
| void OnResetScreenExit(); |
| void OnDeviceModificationCanceled(); |
| void OnSupervisionTransitionScreenExit(); |
| void OnUpdateRequiredScreenExit(); |
| void OnOobeFlowFinished(); |
| void OnPackagedLicenseScreenExit(PackagedLicenseScreen::Result result); |
| void OnActiveDirectoryPasswordChangeScreenExit(); |
| void OnFamilyLinkNoticeScreenExit(FamilyLinkNoticeScreen::Result result); |
| void OnUserCreationScreenExit(UserCreationScreen::Result result); |
| void OnGaiaScreenExit(GaiaScreen::Result result); |
| void OnPasswordChangeScreenExit(GaiaPasswordChangedScreen::Result result); |
| void OnActiveDirectoryLoginScreenExit(); |
| void OnSignInFatalErrorScreenExit(); |
| void OnEduCoexistenceLoginScreenExit( |
| EduCoexistenceLoginScreen::Result result); |
| void OnParentalHandoffScreenExit(ParentalHandoffScreen::Result result); |
| void OnOfflineLoginScreenExit(OfflineLoginScreen::Result result); |
| |
| // Callback invoked once it has been determined whether the device is disabled |
| // or not. |
| void OnDeviceDisabledChecked(bool device_disabled); |
| |
| // Callback function after setting MetricsReporting. |
| void OnChangedMetricsReportingState(bool enabled); |
| |
| // Shows update screen and starts update process. |
| void InitiateOOBEUpdate(); |
| void StartOOBEUpdate(); |
| |
| // Retrieve filtered OOBE configuration and apply relevant values. |
| void UpdateOobeConfiguration(); |
| |
| // Actions that should be done right after EULA is accepted, |
| // before update check. |
| void PerformPostEulaActions(); |
| |
| // Actions that should be done right after update stage is finished. |
| void PerformOOBECompletedActions(); |
| |
| ErrorScreen* GetErrorScreen(); |
| void ShowErrorScreen(); |
| |
| void OnHIDScreenNecessityCheck(bool screen_needed); |
| |
| // Notification of a change in the state of an accessibility setting. |
| void OnAccessibilityStatusChanged( |
| const AccessibilityStatusEventDetails& details); |
| |
| // Switches from one screen to another. |
| void SetCurrentScreen(BaseScreen* screen); |
| |
| // Update the status area visibility for `screen`. |
| void UpdateStatusAreaVisibilityForScreen(OobeScreenId screen_id); |
| |
| // Launched kiosk app configured for auto-launch. |
| void AutoLaunchKioskApp(KioskAppType app_type); |
| |
| // Called when LocalState is initialized. |
| void OnLocalStateInitialized(bool /* succeeded */); |
| |
| // Returns local state. |
| PrefService* GetLocalState(); |
| |
| static void set_local_state_for_testing(PrefService* local_state) { |
| local_state_for_testing_ = local_state; |
| } |
| |
| // Starts a network request to resolve the timezone. Skips the request |
| // completely when the timezone is overridden through the command line. |
| void StartNetworkTimezoneResolve(); |
| void StartTimezoneResolve(); |
| |
| // Creates provider on demand. |
| TimeZoneProvider* GetTimezoneProvider(); |
| |
| // TimeZoneRequest::TimeZoneResponseCallback implementation. |
| void OnTimezoneResolved(std::unique_ptr<TimeZoneResponseData> timezone, |
| bool server_error); |
| |
| // Called from SimpleGeolocationProvider when location is resolved. |
| void OnLocationResolved(const Geoposition& position, |
| bool server_error, |
| const base::TimeDelta elapsed); |
| |
| // Returns true if callback has been installed. |
| // Returns false if timezone has already been resolved. |
| bool SetOnTimeZoneResolvedForTesting(const base::Closure& callback); |
| |
| // Start the enrollment screen using the config from |
| // `prescribed_enrollment_config_`. If `force_interactive` is true, |
| // the user will be presented with a manual enrollment screen requiring |
| // Gaia credentials. If it is false, the screen may return after trying |
| // attestation-based enrollment if appropriate. |
| void StartEnrollmentScreen(bool force_interactive); |
| void ShowEnrollmentScreenIfEligible(); |
| |
| void NotifyScreenChanged(); |
| |
| // Returns auto enrollment controller (lazily initializes one if it doesn't |
| // exist already). |
| AutoEnrollmentController* GetAutoEnrollmentController(); |
| |
| std::unique_ptr<AutoEnrollmentController> auto_enrollment_controller_; |
| std::unique_ptr<ScreenManager> screen_manager_; |
| std::unique_ptr<WizardContext> wizard_context_; |
| |
| // Whether to skip any screens that may normally be shown after login |
| // (registration, Terms of Service, user image selection). |
| static bool skip_post_login_screens_; |
| |
| static bool skip_enrollment_prompts_; |
| |
| // Screen that's currently active. |
| BaseScreen* current_screen_ = nullptr; |
| |
| // Screen that was active before, or nullptr for login screen. |
| BaseScreen* previous_screen_ = nullptr; |
| |
| // True if this is a branded build (i.e. Google Chrome). |
| static bool is_branded_build_; |
| |
| // True if full OOBE flow should be shown. |
| bool is_out_of_box_ = false; |
| |
| // Value of the screen name that WizardController was started with. |
| OobeScreenId first_screen_for_testing_ = OobeScreen::SCREEN_UNKNOWN; |
| |
| // The prescribed enrollment configuration for the device. |
| policy::EnrollmentConfig prescribed_enrollment_config_; |
| |
| // Whether the auto-enrollment check should be retried or the cached result |
| // returned if present. |
| bool retry_auto_enrollment_check_ = false; |
| |
| // Time when the EULA was accepted. Used to measure the duration from the EULA |
| // acceptance until the Sign-In screen is displayed. |
| base::TimeTicks time_eula_accepted_; |
| |
| // Whether OOBE has yet been marked as completed. |
| bool oobe_marked_completed_ = false; |
| |
| bool login_screen_started_ = false; |
| |
| // Non-owning pointer to local state used for testing. |
| static PrefService* local_state_for_testing_; |
| |
| FRIEND_TEST_ALL_PREFIXES(EnrollmentScreenTest, TestCancel); |
| FRIEND_TEST_ALL_PREFIXES(WizardControllerFlowTest, Accelerators); |
| FRIEND_TEST_ALL_PREFIXES(WizardControllerFlowTest, |
| ControlFlowSkipUpdateEnroll); |
| FRIEND_TEST_ALL_PREFIXES(WizardControllerDeviceStateTest, |
| ControlFlowNoForcedReEnrollmentOnFirstBoot); |
| |
| friend class AutoEnrollmentLocalPolicyServer; |
| friend class WizardControllerBrokenLocalStateTest; |
| friend class WizardControllerDeviceStateTest; |
| friend class WizardControllerFlowTest; |
| friend class WizardControllerOobeConfigurationTest; |
| friend class WizardControllerOobeResumeTest; |
| friend class WizardControllerScreenPriorityTest; |
| friend class WizardControllerSupervisionTransitionOobeTest; |
| |
| base::CallbackListSubscription accessibility_subscription_; |
| |
| std::unique_ptr<SimpleGeolocationProvider> geolocation_provider_; |
| std::unique_ptr<TimeZoneProvider> timezone_provider_; |
| |
| // Helper for network realted operations. |
| std::unique_ptr<login::NetworkStateHelper> network_state_helper_; |
| |
| // Controller of the demo mode setup. It has the lifetime of the single demo |
| // mode setup flow. |
| std::unique_ptr<DemoSetupController> demo_setup_controller_; |
| |
| // Maps screen names to last time of their shows. |
| std::map<OobeScreenId, base::TimeTicks> screen_show_times_; |
| |
| // Tests check result of timezone resolve. |
| bool timezone_resolved_ = false; |
| base::Closure on_timezone_resolved_for_testing_; |
| |
| bool is_initialized_ = false; |
| |
| base::ObserverList<ScreenObserver> screen_observers_; |
| |
| base::WeakPtrFactory<WizardController> weak_factory_{this}; |
| |
| DISALLOW_COPY_AND_ASSIGN(WizardController); |
| }; |
| |
| } // namespace chromeos |
| |
| #endif // CHROME_BROWSER_CHROMEOS_LOGIN_WIZARD_CONTROLLER_H_ |