blob: f217c03f6bd768ef6e31fba53e0a00025414ccba [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ash/login/wizard_controller.h"
#include <signal.h>
#include <stddef.h>
#include <stdlib.h>
#include <sys/types.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "ash/components/arc/arc_features.h"
#include "ash/components/arc/arc_prefs.h"
#include "ash/components/arc/arc_util.h"
#include "ash/components/arc/session/arc_bridge_service.h"
#include "ash/constants/ash_features.h"
#include "ash/constants/ash_switches.h"
#include "ash/public/cpp/login_types.h"
#include "base/check.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/json/json_string_value_serializer.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
#include "base/strings/utf_string_conversions.h"
#include "base/system/sys_info.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "chrome/browser/ash/accessibility/accessibility_manager.h"
#include "chrome/browser/ash/app_mode/kiosk_app_types.h"
#include "chrome/browser/ash/app_mode/kiosk_controller.h"
#include "chrome/browser/ash/arc/arc_util.h"
#include "chrome/browser/ash/customization/customization_document.h"
#include "chrome/browser/ash/drive/file_system_util.h"
#include "chrome/browser/ash/login/choobe_flow_controller.h"
#include "chrome/browser/ash/login/configuration_keys.h"
#include "chrome/browser/ash/login/demo_mode/demo_session.h"
#include "chrome/browser/ash/login/demo_mode/demo_setup_controller.h"
#include "chrome/browser/ash/login/enrollment/auto_enrollment_check_screen.h"
#include "chrome/browser/ash/login/enrollment/enrollment_screen.h"
#include "chrome/browser/ash/login/existing_user_controller.h"
#include "chrome/browser/ash/login/hwid_checker.h"
#include "chrome/browser/ash/login/login_pref_names.h"
#include "chrome/browser/ash/login/login_wizard.h"
#include "chrome/browser/ash/login/oobe_screen.h"
#include "chrome/browser/ash/login/quick_unlock/quick_unlock_utils.h"
#include "chrome/browser/ash/login/quickstart_controller.h"
// Make sure to include new screen to all relevant metric enums.
// LINT.IfChange(UsageMetrics)
#include "chrome/browser/ash/login/screens/account_selection_screen.h"
#include "chrome/browser/ash/login/screens/add_child_screen.h"
#include "chrome/browser/ash/login/screens/ai_intro_screen.h"
#include "chrome/browser/ash/login/screens/app_downloading_screen.h"
#include "chrome/browser/ash/login/screens/app_launch_splash_screen.h"
#include "chrome/browser/ash/login/screens/arc_vm_data_migration_screen.h"
#include "chrome/browser/ash/login/screens/assistant_optin_flow_screen.h"
#include "chrome/browser/ash/login/screens/base_screen.h"
#include "chrome/browser/ash/login/screens/categories_selection_screen.h"
#include "chrome/browser/ash/login/screens/choobe_screen.h"
#include "chrome/browser/ash/login/screens/consolidated_consent_screen.h"
#include "chrome/browser/ash/login/screens/consumer_update_screen.h"
#include "chrome/browser/ash/login/screens/demo_preferences_screen.h"
#include "chrome/browser/ash/login/screens/demo_setup_screen.h"
#include "chrome/browser/ash/login/screens/device_disabled_screen.h"
#include "chrome/browser/ash/login/screens/display_size_screen.h"
#include "chrome/browser/ash/login/screens/drive_pinning_screen.h"
#include "chrome/browser/ash/login/screens/edu_coexistence_login_screen.h"
#include "chrome/browser/ash/login/screens/enable_adb_sideloading_screen.h"
#include "chrome/browser/ash/login/screens/enable_debugging_screen.h"
#include "chrome/browser/ash/login/screens/encryption_migration_screen.h"
#include "chrome/browser/ash/login/screens/error_screen.h"
#include "chrome/browser/ash/login/screens/family_link_notice_screen.h"
#include "chrome/browser/ash/login/screens/fingerprint_setup_screen.h"
#include "chrome/browser/ash/login/screens/gaia_info_screen.h"
#include "chrome/browser/ash/login/screens/gaia_screen.h"
#include "chrome/browser/ash/login/screens/gemini_intro_screen.h"
#include "chrome/browser/ash/login/screens/gesture_navigation_screen.h"
#include "chrome/browser/ash/login/screens/hardware_data_collection_screen.h"
#include "chrome/browser/ash/login/screens/hid_detection_screen.h"
#include "chrome/browser/ash/login/screens/install_attributes_error_screen.h"
#include "chrome/browser/ash/login/screens/local_state_error_screen.h"
#include "chrome/browser/ash/login/screens/locale_switch_screen.h"
#include "chrome/browser/ash/login/screens/management_transition_screen.h"
#include "chrome/browser/ash/login/screens/marketing_opt_in_screen.h"
#include "chrome/browser/ash/login/screens/multidevice_setup_screen.h"
#include "chrome/browser/ash/login/screens/network_error.h"
#include "chrome/browser/ash/login/screens/network_screen.h"
#include "chrome/browser/ash/login/screens/offline_login_screen.h"
#include "chrome/browser/ash/login/screens/online_authentication_screen.h"
#include "chrome/browser/ash/login/screens/osauth/apply_online_password_screen.h"
#include "chrome/browser/ash/login/screens/osauth/cryptohome_recovery_screen.h"
#include "chrome/browser/ash/login/screens/osauth/cryptohome_recovery_setup_screen.h"
#include "chrome/browser/ash/login/screens/osauth/enter_old_password_screen.h"
#include "chrome/browser/ash/login/screens/osauth/factor_setup_success_screen.h"
#include "chrome/browser/ash/login/screens/osauth/local_data_loss_warning_screen.h"
#include "chrome/browser/ash/login/screens/osauth/local_password_setup_screen.h"
#include "chrome/browser/ash/login/screens/osauth/osauth_error_screen.h"
#include "chrome/browser/ash/login/screens/osauth/password_selection_screen.h"
#include "chrome/browser/ash/login/screens/osauth/recovery_eligibility_screen.h"
#include "chrome/browser/ash/login/screens/packaged_license_screen.h"
#include "chrome/browser/ash/login/screens/perks_discovery_screen.h"
#include "chrome/browser/ash/login/screens/personalized_recommend_apps_screen.h"
#include "chrome/browser/ash/login/screens/pin_setup_screen.h"
#include "chrome/browser/ash/login/screens/quick_start_screen.h"
#include "chrome/browser/ash/login/screens/recommend_apps_screen.h"
#include "chrome/browser/ash/login/screens/remote_activity_notification_screen.h"
#include "chrome/browser/ash/login/screens/reset_screen.h"
#include "chrome/browser/ash/login/screens/saml_confirm_password_screen.h"
#include "chrome/browser/ash/login/screens/signin_fatal_error_screen.h"
#include "chrome/browser/ash/login/screens/smart_privacy_protection_screen.h"
#include "chrome/browser/ash/login/screens/split_modifier_keyboard_info_screen.h"
#include "chrome/browser/ash/login/screens/sync_consent_screen.h"
#include "chrome/browser/ash/login/screens/theme_selection_screen.h"
#include "chrome/browser/ash/login/screens/touchpad_scroll_screen.h"
#include "chrome/browser/ash/login/screens/tpm_error_screen.h"
#include "chrome/browser/ash/login/screens/update_required_screen.h"
#include "chrome/browser/ash/login/screens/update_screen.h"
#include "chrome/browser/ash/login/screens/user_allowlist_check_screen.h"
#include "chrome/browser/ash/login/screens/user_creation_screen.h"
#include "chrome/browser/ash/login/screens/welcome_screen.h"
#include "chrome/browser/ash/login/screens/wrong_hwid_screen.h"
// Add new screens before this block. Add screens and exit reasons to
// OOBE histograms.
// LINT.ThenChange(//tools/metrics/histograms/metadata/oobe/histograms.xml)
#include "chrome/browser/ash/login/session/user_session_manager.h"
#include "chrome/browser/ash/login/startup_utils.h"
#include "chrome/browser/ash/login/wizard_context.h"
#include "chrome/browser/ash/multidevice_setup/multidevice_setup_client_factory.h"
#include "chrome/browser/ash/net/delay_network_call.h"
#include "chrome/browser/ash/net/rollback_network_config/rollback_network_config_service.h"
#include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h"
#include "chrome/browser/ash/policy/core/device_cloud_policy_manager_ash.h"
#include "chrome/browser/ash/policy/enrollment/auto_enrollment_controller.h"
#include "chrome/browser/ash/policy/enrollment/enrollment_requisition_manager.h"
#include "chrome/browser/ash/settings/stats_reporting_controller.h"
#include "chrome/browser/ash/system/device_disabling_manager.h"
#include "chrome/browser/ash/system/timezone_resolver_manager.h"
#include "chrome/browser/ash/system/timezone_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/metrics/metrics_reporting_state.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/ash/login/login_display_host.h"
#include "chrome/browser/ui/ash/system/system_tray_client_impl.h"
#include "chrome/browser/ui/webui/ash/login/account_selection_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/add_child_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/ai_intro_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/app_downloading_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/app_launch_splash_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/arc_vm_data_migration_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/assistant_optin_flow_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/auto_enrollment_check_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/categories_selection_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/choobe_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/consolidated_consent_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/consumer_update_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/cryptohome_recovery_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/cryptohome_recovery_setup_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/demo_preferences_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/demo_setup_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/device_disabled_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/display_size_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/drive_pinning_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/enable_adb_sideloading_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/enable_debugging_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/encryption_migration_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/enrollment_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/enter_old_password_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/error_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/family_link_notice_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/fingerprint_setup_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/gaia_info_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/gaia_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/gemini_intro_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/gesture_navigation_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/guest_tos_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/hardware_data_collection_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/hid_detection_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/install_attributes_error_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/local_password_setup_handler.h"
#include "chrome/browser/ui/webui/ash/login/local_state_error_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/locale_switch_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/management_transition_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/marketing_opt_in_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/multidevice_setup_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/network_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/offline_login_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/online_authentication_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/oobe_ui.h"
#include "chrome/browser/ui/webui/ash/login/os_install_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/os_trial_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/osauth/apply_online_password_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/osauth/factor_setup_success_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/osauth/local_data_loss_warning_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/osauth/osauth_error_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/packaged_license_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/parental_handoff_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/password_selection_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/perks_discovery_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/personalized_recommend_apps_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/pin_setup_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/quick_start_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/recommend_apps_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/recovery_eligibility_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/remote_activity_notification_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/reset_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/saml_confirm_password_handler.h"
#include "chrome/browser/ui/webui/ash/login/signin_fatal_error_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/smart_privacy_protection_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/split_modifier_keyboard_info_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/sync_consent_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/terms_of_service_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/theme_selection_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/touchpad_scroll_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/tpm_error_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/update_required_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/update_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/user_allowlist_check_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/user_creation_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/welcome_screen_handler.h"
#include "chrome/browser/ui/webui/ash/login/wrong_hwid_screen_handler.h"
#include "chrome/browser/ui/webui/help/help_utils_chromeos.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/pref_names.h"
#include "chromeos/ash/components/audio/cras_audio_handler.h"
#include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
#include "chromeos/ash/components/dbus/update_engine/update_engine_client.h"
#include "chromeos/ash/components/geolocation/simple_geolocation_provider.h"
#include "chromeos/ash/components/install_attributes/install_attributes.h"
#include "chromeos/ash/components/language_packs/language_pack_manager.h"
#include "chromeos/ash/components/network/network_state.h"
#include "chromeos/ash/components/network/network_state_handler.h"
#include "chromeos/ash/components/osauth/public/auth_session_storage.h"
#include "chromeos/ash/components/settings/cros_settings.h"
#include "chromeos/ash/components/settings/cros_settings_names.h"
#include "chromeos/ash/components/settings/cros_settings_provider.h"
#include "chromeos/ash/components/settings/timezone_settings.h"
#include "chromeos/ash/components/timezone/timezone_provider.h"
#include "chromeos/ash/components/timezone/timezone_request.h"
#include "chromeos/ash/services/cros_healthd/private/cpp/dlc_utils.h"
#include "chromeos/ash/services/rollback_network_config/public/mojom/rollback_network_config.mojom.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/session_manager/core/session_manager.h"
#include "components/user_manager/known_user.h"
#include "components/user_manager/user_manager.h"
#include "components/user_manager/user_names.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "remoting/host/chromeos/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/service_manager/public/cpp/connector.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
#include "ui/base/accelerators/accelerator.h"
// Enable VLOG level 1.
#undef ENABLED_VLOG_LEVEL
#define ENABLED_VLOG_LEVEL 1
namespace ash {
namespace {
using ::content::BrowserThread;
bool g_using_zero_delays = false;
// Total timezone resolving process timeout.
const unsigned int kResolveTimeZoneTimeoutSeconds = 60;
constexpr const char kDefaultExitReason[] = "Next";
constexpr const char kResetScreenExitReason[] = "Cancel";
// TODO(crbug.com/40738890) Remove after stepping stone is set after M87.
constexpr char kLegacyUpdateScreenName[] = "update";
// Stores the list of all screens that should be shown when resuming OOBE.
const StaticOobeScreenId kResumableOobeScreens[] = {
WelcomeView::kScreenId,
NetworkScreenView::kScreenId,
UpdateView::kScreenId,
EnrollmentScreenView::kScreenId,
AutoEnrollmentCheckScreenView::kScreenId,
UserCreationView::kScreenId,
AddChildScreenView::kScreenId,
ConsumerUpdateScreenView::kScreenId,
};
const StaticOobeScreenId kResumablePostLoginScreens[] = {
TermsOfServiceScreenView::kScreenId,
SyncConsentScreenView::kScreenId,
HWDataCollectionView::kScreenId,
FingerprintSetupScreenView::kScreenId,
GestureNavigationScreenView::kScreenId,
RecommendAppsScreenView::kScreenId,
AiIntroScreenView::kScreenId,
GeminiIntroScreenView::kScreenId,
PinSetupScreenView::kScreenId,
MarketingOptInScreenView::kScreenId,
MultiDeviceSetupScreenView::kScreenId,
ConsolidatedConsentScreenView::kScreenId,
ThemeSelectionScreenView::kScreenId,
ChoobeScreenView::kScreenId,
DisplaySizeScreenView::kScreenId,
TouchpadScrollScreenView::kScreenId,
CategoriesSelectionScreenView::kScreenId,
PerksDiscoveryScreenView::kScreenId,
SplitModifierKeyboardInfoScreenView::kScreenId,
};
const StaticOobeScreenId kScreensWithHiddenStatusArea[] = {
EnableAdbSideloadingScreenView::kScreenId,
EnableDebuggingScreenView::kScreenId,
ManagementTransitionScreenView::kScreenId,
TpmErrorView::kScreenId,
InstallAttributesErrorView::kScreenId,
WrongHWIDScreenView::kScreenId,
LocalStateErrorScreenView::kScreenId,
};
std::string GetApplicationLocale() {
return g_browser_process->GetApplicationLocale();
}
bool IsResumableOobeScreen(OobeScreenId screen_id) {
for (const auto& resumable_screen : kResumableOobeScreens) {
if (screen_id == resumable_screen) {
return true;
}
}
return false;
}
bool ShouldHideStatusArea(OobeScreenId screen_id) {
for (const auto& s : kScreensWithHiddenStatusArea) {
if (screen_id == s) {
return true;
}
}
return false;
}
LoginDisplayHost* GetLoginDisplayHost() {
return LoginDisplayHost::default_host();
}
OobeUI* GetOobeUI() {
auto* host = LoginDisplayHost::default_host();
return host ? host->GetOobeUI() : nullptr;
}
OobeScreenId PrefToScreenId(const std::string& pref_value) {
if (pref_value == kLegacyUpdateScreenName) {
return UpdateView::kScreenId;
}
return OobeScreenId(pref_value);
}
bool IsGaiaPageDefaultsToSAML() {
int authentication_behavior = 0;
bool authentication_behavior_set = CrosSettings::Get()->GetInteger(
kLoginAuthenticationBehavior, &authentication_behavior);
return authentication_behavior_set && authentication_behavior;
}
bool IsContextNeededForScreen(OobeScreenId screen_id) {
return screen_id == SamlConfirmPasswordView::kScreenId ||
screen_id == CryptohomeRecoveryScreenView::kScreenId ||
screen_id == LocalDataLossWarningScreenView::kScreenId;
}
std::string SetupTypeToString(WizardContext::AuthChangeFlow flow_type) {
switch (flow_type) {
case WizardContext::AuthChangeFlow::kInitialSetup:
return "Initial Setup";
case WizardContext::AuthChangeFlow::kReauthentication:
return "ReAuth";
case WizardContext::AuthChangeFlow::kRecovery:
return "Recovery";
}
}
} // namespace
// static
const int WizardController::kMinAudibleOutputVolumePercent = 10;
// static
bool WizardController::skip_enrollment_prompts_for_testing_ = false;
// static
WizardController* WizardController::default_controller() {
auto* host = LoginDisplayHost::default_host();
return (host && host->IsWizardControllerCreated())
? host->GetWizardController()
: nullptr;
}
///////////////////////////////////////////////////////////////////////////////
// WizardController, public:
PrefService* WizardController::local_state_for_testing_ = nullptr;
WizardController::WizardController(WizardContext* wizard_context)
: quickstart_controller_(
std::make_unique<quick_start::QuickStartController>()),
screen_manager_(std::make_unique<ScreenManager>()),
wizard_context_(wizard_context),
shared_url_loader_factory_(
g_browser_process->shared_url_loader_factory()) {
const auto has_been_skipped =
wizard_context_->skip_post_login_screens_for_tests;
wizard_context_->skip_post_login_screens_for_tests =
has_been_skipped || switches::ShouldSkipOobePostLogin();
AccessibilityManager* accessibility_manager = AccessibilityManager::Get();
if (accessibility_manager) {
// accessibility_manager could be null in Tests.
accessibility_subscription_ = accessibility_manager->RegisterCallback(
base::BindRepeating(&WizardController::OnAccessibilityStatusChanged,
weak_factory_.GetWeakPtr()));
}
if (GetOobeUI()) {
// could be null in unit tests.
screen_manager_->Init(CreateScreens());
// If the frontend element is constructed and OobeScreensHandlerFactory is
// created with a pending receiver, bind the receiver when the
// WizardController is created.
if (GetOobeUI()->GetOobeScreensHandlerFactory()) {
GetOobeUI()->GetOobeScreensHandlerFactory()->BindScreensHandlerFactory();
}
// OOBE UI can be recreated in case of CrossOriginOpenerPolicyByDefault.
// TODO(crbug.com/40138102): Remove this logic after WebUI split is done,
// as screens should work with late binding/early unbinding in that case.
oobe_ui_observation_.Observe(GetOobeUI());
}
}
WizardController::~WizardController() {
for (ScreenObserver& obs : screen_observers_) {
obs.OnShutdown();
}
// Use `OobeUI` reference in `oobe_ui_observation_` because the destructor
// could be called after `LoginDisplayHost` resets its reference to OobeUI.
// As a result,`GetOobeUI()` would return nullptr but the actual OobeUI
// instance might still be alive and could call us.
// See http://crbug.com/384745864.
OobeUI* oobe_ui = oobe_ui_observation_.GetSource();
if (oobe_ui && oobe_ui->GetOobeScreensHandlerFactory()) {
oobe_ui->GetOobeScreensHandlerFactory()->UnbindScreensHandlerFactory();
}
previous_screens_.clear();
screen_manager_.reset();
}
void WizardController::Init(OobeScreenId first_screen) {
DCHECK(!is_initialized());
is_initialized_ = true;
prescribed_enrollment_config_ =
policy::EnrollmentConfig::GetPrescribedEnrollmentConfig();
VLOG(1) << "Starting OOBE wizard with screen: " << first_screen;
bool oobe_complete = StartupUtils::IsOobeCompleted();
if (!oobe_complete) {
UpdateOobeConfiguration();
is_out_of_box_ = true;
}
wizard_context_->is_add_person_flow =
oobe_complete && StartupUtils::IsDeviceOwned();
// This is a hacky way to check for local state corruption, because
// it depends on the fact that the local state is loaded
// synchronously and at the first demand.
// ash::InstallAttributes::IsEnterpriseManaged() check is required
// because currently powerwash is disabled for enterprise-enrolled devices.
//
// TODO (ygorshenin@): implement handling of the local state
// corruption in the case of asynchronous loading.
bool is_enterprise_managed =
ash::InstallAttributes::Get()->IsEnterpriseManaged();
if (!is_enterprise_managed) {
const PrefService::PrefInitializationStatus status =
GetLocalState()->GetInitializationStatus();
if (status == PrefService::INITIALIZATION_STATUS_ERROR) {
OnLocalStateInitialized(false);
return;
}
if (status == PrefService::INITIALIZATION_STATUS_WAITING) {
GetLocalState()->AddPrefInitObserver(
base::BindOnce(&WizardController::OnLocalStateInitialized,
weak_factory_.GetWeakPtr()));
}
}
if (!oobe_complete) {
bool updated =
GetLocalState()->GetBoolean(prefs::kOobeConsumerUpdateCompleted) ||
GetLocalState()->GetBoolean(prefs::kOobeCriticalUpdateCompleted);
if (!updated) {
GetLoginDisplayHost()->GetOobeMetricsHelper()->RecordChromeVersion();
}
}
const bool device_is_owned =
is_enterprise_managed ||
!user_manager::UserManager::Get()->GetUsers().empty();
// Do not show the HID Detection screen if device is owned.
if (!device_is_owned && HIDDetectionScreen::CanShowScreen() &&
first_screen == ash::OOBE_SCREEN_UNKNOWN) {
// TODO(https://crbug.com/1275960): Move logic into
// HIDDetectionScreen::MaybeSkip.
GetScreen<HIDDetectionScreen>()->CheckIsScreenRequired(
base::BindOnce(&WizardController::OnHIDScreenNecessityCheck,
weak_factory_.GetWeakPtr()));
return;
}
AdvanceToScreenAfterHIDDetection(first_screen);
}
void WizardController::OnDestroyingOobeUI() {
previous_screens_.clear();
// Reset `current_screen_` to prevent its usage after OobeUI is gone.
ResetCurrentScreen();
// Reset screens, they should not access handlers anymore.
// TODO(https://crbug.com/1309022): This should probably be removed when all
// the screen/handlers migrated to the new patterns.
screen_manager_->Shutdown();
oobe_ui_observation_.Reset();
}
void WizardController::HideCurrentScreen() {
SetCurrentScreen(nullptr);
}
void WizardController::ContinueOobeFlow() {
// Use the saved screen preference from Local State if exist.
const std::string screen_pref =
GetLocalState()->GetString(prefs::kOobeScreenPending);
const OobeScreenId screen_id = PrefToScreenId(screen_pref);
GetLoginDisplayHost()->GetOobeMetricsHelper()->RecordPreLoginOobeResume(
screen_id);
if (!screen_pref.empty() && HasScreen(screen_id)) {
AdvanceToScreen(screen_id);
} else {
ShowPackagedLicenseScreen();
}
}
void WizardController::AdvanceToScreenAfterHIDDetection(
OobeScreenId first_screen) {
OobeScreenId actual_first_screen = first_screen;
if (actual_first_screen == ash::OOBE_SCREEN_UNKNOWN) {
if (!is_out_of_box_) {
DeviceSettingsService::Get()->GetOwnershipStatusAsync(
base::BindOnce(&WizardController::OnOwnershipStatusCheckDone,
weak_factory_.GetWeakPtr()));
return;
}
// Use the saved screen preference from Local State.
const std::string screen_pref =
GetLocalState()->GetString(prefs::kOobeScreenPending);
if (!screen_pref.empty() && HasScreen(PrefToScreenId(screen_pref))) {
actual_first_screen = PrefToScreenId(screen_pref);
} else {
actual_first_screen = WelcomeView::kScreenId;
}
}
first_screen_for_testing_ = actual_first_screen;
if (!IsMachineHWIDCorrect() && !StartupUtils::IsDeviceRegistered() &&
first_screen == ash::OOBE_SCREEN_UNKNOWN) {
ShowWrongHWIDScreen();
} else {
AdvanceToScreen(actual_first_screen);
}
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kOobeSkipToLogin)) {
SkipToLoginForTesting();
}
}
ErrorScreen* WizardController::GetErrorScreen() {
return GetOobeUI()->GetErrorScreen();
}
bool WizardController::HasScreen(OobeScreenId screen_id) {
return screen_manager_->HasScreen(screen_id);
}
// static
bool WizardController::IsErrorScreen(OobeScreenId screen_id) {
return screen_id == ErrorScreenView::kScreenId;
}
BaseScreen* WizardController::GetScreen(OobeScreenId screen_id) {
if (WizardController::IsErrorScreen(screen_id)) {
return GetErrorScreen();
}
return screen_manager_->GetScreen(screen_id);
}
OobeScreenId WizardController::GetScreenByName(const std::string& screen_name) {
if (screen_name == ErrorScreenView::kScreenId.name) {
return ErrorScreenView::kScreenId;
}
return screen_manager_->GetScreenByName(screen_name);
}
void WizardController::SetCurrentScreenForTesting(BaseScreen* screen) {
current_screen_ = screen;
}
void WizardController::SetSharedURLLoaderFactoryForTesting(
scoped_refptr<network::SharedURLLoaderFactory> factory) {
shared_url_loader_factory_ = factory;
}
std::vector<std::pair<OobeScreenId, std::unique_ptr<BaseScreen>>>
WizardController::CreateScreens() {
OobeUI* oobe_ui = GetOobeUI();
std::vector<std::pair<OobeScreenId, std::unique_ptr<BaseScreen>>> result;
auto append = [&](std::unique_ptr<BaseScreen> screen) {
result.emplace_back(screen->screen_id(), std::move(screen));
};
if (oobe_ui->display_type() == OobeUI::kOobeDisplay) {
append(std::make_unique<WelcomeScreen>(
oobe_ui->GetView<WelcomeScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnWelcomeScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<DemoPreferencesScreen>(
oobe_ui->GetView<DemoPreferencesScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnDemoPreferencesScreenExit,
weak_factory_.GetWeakPtr())));
}
append(std::make_unique<QuickStartScreen>(
oobe_ui->GetView<QuickStartScreenHandler>()->AsWeakPtr(),
quick_start_controller(),
base::BindRepeating(&WizardController::OnQuickStartScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<NetworkScreen>(
oobe_ui->GetView<NetworkScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnNetworkScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<UpdateScreen>(
oobe_ui->GetView<UpdateScreenHandler>()->AsWeakPtr(),
oobe_ui->GetErrorScreen(),
base::BindRepeating(&WizardController::OnUpdateScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<EnrollmentScreen>(
oobe_ui->GetView<EnrollmentScreenHandler>()->AsWeakPtr(),
oobe_ui->GetErrorScreen(),
base::BindRepeating(&WizardController::OnEnrollmentScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<ResetScreen>(
oobe_ui->GetView<ResetScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnResetScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<DemoSetupScreen>(
oobe_ui->GetView<DemoSetupScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnDemoSetupScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<EnableAdbSideloadingScreen>(
oobe_ui->GetView<EnableAdbSideloadingScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnEnableAdbSideloadingScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<EnableDebuggingScreen>(
oobe_ui->GetView<EnableDebuggingScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnEnableDebuggingScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<LocaleSwitchScreen>(
oobe_ui->GetView<LocaleSwitchScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnLocaleSwitchScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<RecoveryEligibilityScreen>(
base::BindRepeating(&WizardController::OnRecoveryEligibilityScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<CryptohomeRecoverySetupScreen>(
oobe_ui->GetView<CryptohomeRecoverySetupScreenHandler>()->AsWeakPtr(),
base::BindRepeating(
&WizardController::OnCryptohomeRecoverySetupScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<TermsOfServiceScreen>(
oobe_ui->GetView<TermsOfServiceScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnTermsOfServiceScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<SyncConsentScreen>(
oobe_ui->GetView<SyncConsentScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnSyncConsentScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<RecommendAppsScreen>(
oobe_ui->GetView<RecommendAppsScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnRecommendAppsScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<AppDownloadingScreen>(
oobe_ui->GetView<AppDownloadingScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnAppDownloadingScreenExit,
weak_factory_.GetWeakPtr())));
if (features::IsOobeAiIntroEnabled()) {
append(std::make_unique<AiIntroScreen>(
oobe_ui->GetView<AiIntroScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnAiIntroScreenExit,
weak_factory_.GetWeakPtr())));
}
append(std::make_unique<GeminiIntroScreen>(
oobe_ui->GetView<GeminiIntroScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnGeminiIntroScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<WrongHWIDScreen>(
oobe_ui->GetView<WrongHWIDScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnWrongHWIDScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<LocalStateErrorScreen>(
oobe_ui->GetView<LocalStateErrorScreenHandler>()->AsWeakPtr()));
if (base::FeatureList::IsEnabled(arc::kEnableArcVmDataMigration)) {
append(std::make_unique<ArcVmDataMigrationScreen>(
oobe_ui->GetView<ArcVmDataMigrationScreenHandler>()->AsWeakPtr()));
}
if (HIDDetectionScreen::CanShowScreen()) {
append(std::make_unique<HIDDetectionScreen>(
oobe_ui->GetView<HIDDetectionScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnHidDetectionScreenExit,
weak_factory_.GetWeakPtr())));
}
append(std::make_unique<AutoEnrollmentCheckScreen>(
oobe_ui->GetView<AutoEnrollmentCheckScreenHandler>()->AsWeakPtr(),
oobe_ui->GetErrorScreen(),
base::BindRepeating(&WizardController::OnAutoEnrollmentCheckScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<DeviceDisabledScreen>(
oobe_ui->GetView<DeviceDisabledScreenHandler>()->AsWeakPtr()));
append(std::make_unique<EncryptionMigrationScreen>(
oobe_ui->GetView<EncryptionMigrationScreenHandler>()->AsWeakPtr()));
append(std::make_unique<ManagementTransitionScreen>(
oobe_ui->GetView<ManagementTransitionScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnManagementTransitionScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<UpdateRequiredScreen>(
oobe_ui->GetView<UpdateRequiredScreenHandler>()->AsWeakPtr(),
oobe_ui->GetErrorScreen(),
base::BindRepeating(&WizardController::OnUpdateRequiredScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<AssistantOptInFlowScreen>(
oobe_ui->GetView<AssistantOptInFlowScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnAssistantOptInFlowScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<MultiDeviceSetupScreen>(
oobe_ui->GetView<MultiDeviceSetupScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnMultiDeviceSetupScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<PinSetupScreen>(
oobe_ui->GetView<PinSetupScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnPinSetupScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<FingerprintSetupScreen>(
oobe_ui->GetView<FingerprintSetupScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnFingerprintSetupScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<GestureNavigationScreen>(
oobe_ui->GetView<GestureNavigationScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnGestureNavigationScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<MarketingOptInScreen>(
oobe_ui->GetView<MarketingOptInScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnMarketingOptInScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<PackagedLicenseScreen>(
oobe_ui->GetView<PackagedLicenseScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnPackagedLicenseScreenExit,
weak_factory_.GetWeakPtr())));
if (features::IsOobeGaiaInfoScreenEnabled()) {
append(std::make_unique<GaiaInfoScreen>(
oobe_ui->GetView<GaiaInfoScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnGaiaInfoScreenExit,
weak_factory_.GetWeakPtr())));
}
append(std::make_unique<GaiaScreen>(
oobe_ui->GetView<GaiaScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnGaiaScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<OnlineAuthenticationScreen>(
oobe_ui->GetView<OnlineAuthenticationScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnOnlineAuthenticationScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<UserAllowlistCheckScreen>(
oobe_ui->GetView<UserAllowlistCheckScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnUserAllowlistCheckScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<SamlConfirmPasswordScreen>(
oobe_ui->GetView<SamlConfirmPasswordHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnSamlConfirmPasswordScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<OfflineLoginScreen>(
oobe_ui->GetView<OfflineLoginScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnOfflineLoginScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<TpmErrorScreen>(
oobe_ui->GetView<TpmErrorScreenHandler>()->AsWeakPtr()));
append(std::make_unique<InstallAttributesErrorScreen>(
oobe_ui->GetView<InstallAttributesErrorScreenHandler>()->AsWeakPtr()));
append(std::make_unique<FamilyLinkNoticeScreen>(
oobe_ui->GetView<FamilyLinkNoticeScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnFamilyLinkNoticeScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<UserCreationScreen>(
oobe_ui->GetView<UserCreationScreenHandler>()->AsWeakPtr(),
oobe_ui->GetErrorScreen(),
base::BindRepeating(&WizardController::OnUserCreationScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<AddChildScreen>(
oobe_ui->GetView<AddChildScreenHandler>()->AsWeakPtr(),
oobe_ui->GetErrorScreen(),
base::BindRepeating(&WizardController::OnAddChildScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<EduCoexistenceLoginScreen>(
base::BindRepeating(&WizardController::OnEduCoexistenceLoginScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<SignInFatalErrorScreen>(
oobe_ui->GetView<SignInFatalErrorScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnSignInFatalErrorScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<ParentalHandoffScreen>(
oobe_ui->GetView<ParentalHandoffScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnParentalHandoffScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<ConsolidatedConsentScreen>(
oobe_ui->GetView<ConsolidatedConsentScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnConsolidatedConsentScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<GuestTosScreen>(
oobe_ui->GetView<GuestTosScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnGuestTosScreenExit,
weak_factory_.GetWeakPtr())));
if (switches::IsOsInstallAllowed()) {
append(std::make_unique<OsInstallScreen>(
oobe_ui->GetView<OsInstallScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnOsInstallScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<OsTrialScreen>(
oobe_ui->GetView<OsTrialScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnOsTrialScreenExit,
weak_factory_.GetWeakPtr())));
}
if (switches::IsRevenBranding()) {
append(std::make_unique<HWDataCollectionScreen>(
oobe_ui->GetView<HWDataCollectionScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnHWDataCollectionScreenExit,
weak_factory_.GetWeakPtr())));
}
append(std::make_unique<SmartPrivacyProtectionScreen>(
oobe_ui->GetView<SmartPrivacyProtectionScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnSmartPrivacyProtectionScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<ThemeSelectionScreen>(
oobe_ui->GetView<ThemeSelectionScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnThemeSelectionScreenExit,
weak_factory_.GetWeakPtr())));
if (base::FeatureList::IsEnabled(
remoting::features::kEnableCrdAdminRemoteAccessV2)) {
append(std::make_unique<RemoteActivityNotificationScreen>(
oobe_ui->GetView<RemoteActivityNotificationScreenHandler>()
->AsWeakPtr(),
base::BindRepeating(
&WizardController::OnRemoteActivityNotificationScreenExit,
weak_factory_.GetWeakPtr())));
}
append(std::make_unique<CryptohomeRecoveryScreen>(
oobe_ui->GetView<CryptohomeRecoveryScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnCryptohomeRecoveryScreenExit,
weak_factory_.GetWeakPtr())));
if (features::IsOobeChoobeEnabled()) {
append(std::make_unique<ChoobeScreen>(
oobe_ui->GetView<ChoobeScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnChoobeScreenExit,
weak_factory_.GetWeakPtr())));
}
if (features::IsOobeTouchpadScrollEnabled()) {
append(std::make_unique<TouchpadScrollScreen>(
oobe_ui->GetView<TouchpadScrollScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnTouchpadScreenExit,
weak_factory_.GetWeakPtr())));
}
if (features::IsOobeDisplaySizeEnabled()) {
append(std::make_unique<DisplaySizeScreen>(
oobe_ui->GetView<DisplaySizeScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnDisplaySizeScreenExit,
weak_factory_.GetWeakPtr())));
}
if (drive::util::IsOobeDrivePinningScreenEnabled()) {
append(std::make_unique<DrivePinningScreen>(
oobe_ui->GetView<DrivePinningScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnDrivePinningScreenExit,
weak_factory_.GetWeakPtr())));
}
if (features::IsOobeSoftwareUpdateEnabled()) {
append(std::make_unique<ConsumerUpdateScreen>(
oobe_ui->GetView<ConsumerUpdateScreenHandler>()->AsWeakPtr(),
oobe_ui->GetErrorScreen(),
base::BindRepeating(&WizardController::OnConsumerUpdateScreenExit,
weak_factory_.GetWeakPtr())));
}
// We don't guard creation of those screens via feature flag to prevent cases
// when we didn't apply Finch config, but user restarted their device
// and our screen being marked as resumable is expected to be shown, but Finch
// decided that feature should be turned off.
// Instead, we will check for feature flag inside each screen's `MaybeSkip()`.
append(std::make_unique<CategoriesSelectionScreen>(
oobe_ui->GetView<CategoriesSelectionScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnCategoriesSelectionScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<PersonalizedRecommendAppsScreen>(
oobe_ui->GetView<PersonalizedRecommendAppsScreenHandler>()->AsWeakPtr(),
base::BindRepeating(
&WizardController::OnPersonalizedRecomendAppsScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<SplitModifierKeyboardInfoScreen>(
oobe_ui->GetView<SplitModifierKeyboardInfoScreenHandler>()->AsWeakPtr(),
base::BindRepeating(
&WizardController::OnSplitModifierKeyboardInfoScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<PasswordSelectionScreen>(
oobe_ui->GetView<PasswordSelectionScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnPasswordSelectionScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<ApplyOnlinePasswordScreen>(
oobe_ui->GetView<ApplyOnlinePasswordScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnApplyOnlinePasswordScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<LocalPasswordSetupScreen>(
oobe_ui->GetView<LocalPasswordSetupHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnLocalPasswordSetupScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<LocalDataLossWarningScreen>(
oobe_ui->GetView<LocalDataLossWarningScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnLocalDataLossWarningScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<EnterOldPasswordScreen>(
oobe_ui->GetView<EnterOldPasswordScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnEnterOldPasswordScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<PerksDiscoveryScreen>(
oobe_ui->GetView<PerksDiscoveryScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnPerksDiscoveryScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<OSAuthErrorScreen>(
oobe_ui->GetView<OSAuthErrorScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnOSAuthErrorScreenExit,
weak_factory_.GetWeakPtr())));
append(std::make_unique<FactorSetupSuccessScreen>(
oobe_ui->GetView<FactorSetupSuccessScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnFactorSetupSuccessScreenExit,
weak_factory_.GetWeakPtr())));
if (features::IsOobeAddUserDuringEnrollmentEnabled()) {
append(std::make_unique<AccountSelectionScreen>(
oobe_ui->GetView<AccountSelectionScreenHandler>()->AsWeakPtr(),
base::BindRepeating(&WizardController::OnAccountSelectionScreenExit,
weak_factory_.GetWeakPtr())));
}
append(std::make_unique<AppLaunchSplashScreen>(
oobe_ui->GetView<AppLaunchSplashScreenHandler>()->AsWeakPtr(),
oobe_ui->GetErrorScreen(),
base::BindRepeating(&WizardController::OnAppLaunchSplashScreenExit,
weak_factory_.GetWeakPtr())));
return result;
}
void WizardController::ShowWelcomeScreen() {
SetCurrentScreen(GetScreen(WelcomeView::kScreenId));
}
void WizardController::ShowQuickStartScreen() {
CHECK(wizard_context_->quick_start_enabled);
SetCurrentScreen(GetScreen(QuickStartView::kScreenId));
}
void WizardController::ShowNetworkScreen() {
SetCurrentScreen(GetScreen(NetworkScreenView::kScreenId));
}
void WizardController::OnOwnershipStatusCheckDone(
DeviceSettingsService::OwnershipStatus status) {
if (status == DeviceSettingsService::OwnershipStatus::kOwnershipNone) {
ContinueOobeFlow();
} else {
ShowLoginScreen();
}
}
void WizardController::ShowSignInFatalErrorScreen(
SignInFatalErrorScreen::Error error,
base::Value::Dict params) {
GetScreen<SignInFatalErrorScreen>()->SetErrorState(error, std::move(params));
AdvanceToScreen(SignInFatalErrorView::kScreenId);
}
void WizardController::OnSignInFatalErrorScreenExit() {
OnScreenExit(SignInFatalErrorView::kScreenId, kDefaultExitReason);
if (base::Contains(previous_screens_, current_screen_) &&
IsContextNeededForScreen(
previous_screens_[current_screen_]->screen_id())) {
// If the last screen user have visited before reaching SignInFatalError
// screen was a screen that needs user context, we should not go back there
// because the context is lost at this point. We should go to the Gaia
// screen instead.
previous_screens_[current_screen_] = GetScreen(GaiaView::kScreenId);
}
// It's possible to get on the SignInFatalError screen both from the user pods
// and from the Gaia sign-in screen. The screen exits when user presses
// "try again". Go to the previous screen if it is set. Otherwise go to the
// login screen with pods.
if (MaybeSetToPreviousScreen()) {
return;
}
ShowLoginScreen();
}
void WizardController::ShowLoginScreen() {
VLOG(1) << "Showing login screen.";
UpdateStatusAreaVisibilityForScreen(GaiaView::kScreenId);
GetLoginDisplayHost()->StartSignInScreen();
}
void WizardController::ShowGaiaInfoScreen() {
SetCurrentScreen(GetScreen(GaiaInfoScreenView::kScreenId));
}
void WizardController::ShowAddChildScreen() {
SetCurrentScreen(GetScreen(AddChildScreenView::kScreenId));
}
void WizardController::ShowConsumerUpdateScreen() {
SetCurrentScreen(GetScreen(ConsumerUpdateScreenView::kScreenId));
}
void WizardController::ShowLocalPasswordSetupScreen() {
SetCurrentScreen(GetScreen(LocalPasswordSetupView::kScreenId));
}
void WizardController::ShowApplyOnlinePasswordScreen() {
SetCurrentScreen(GetScreen(ApplyOnlinePasswordScreenView::kScreenId));
}
void WizardController::ShowLocalDataLossWarningScreen() {
SetCurrentScreen(GetScreen(LocalDataLossWarningScreenView::kScreenId));
}
void WizardController::ShowEnterOldPasswordScreen() {
SetCurrentScreen(GetScreen(EnterOldPasswordScreenView::kScreenId));
}
void WizardController::ShowEnrollmentScreen() {
MaybeAbortQuickStartFlow(quick_start::QuickStartController::AbortFlowReason::
ENTERPRISE_ENROLLMENT);
// Update the enrollment configuration and start the screen.
GetLoginDisplayHost()->GetOobeMetricsHelper()->RecordEnrollingUserType();
prescribed_enrollment_config_ =
policy::EnrollmentConfig::GetPrescribedEnrollmentConfig();
StartEnrollmentScreen();
}
void WizardController::ShowDemoModePreferencesScreen() {
SetCurrentScreen(GetScreen(DemoPreferencesScreenView::kScreenId));
}
void WizardController::ShowDemoModeSetupScreen() {
SetCurrentScreen(GetScreen(DemoSetupScreenView::kScreenId));
}
void WizardController::ShowDrivePinningScreen() {
if (drive::util::IsOobeDrivePinningAvailable()) {
SetCurrentScreen(GetScreen(DrivePinningScreenView::kScreenId));
} else {
OnDrivePinningScreenExit(DrivePinningScreen::Result::NOT_APPLICABLE);
}
}
void WizardController::ShowResetScreen() {
SetCurrentScreen(GetScreen(ResetView::kScreenId));
}
void WizardController::ShowEnableAdbSideloadingScreen() {
SetCurrentScreen(GetScreen(EnableAdbSideloadingScreenView::kScreenId));
}
void WizardController::ShowEnableDebuggingScreen() {
SetCurrentScreen(GetScreen(EnableDebuggingScreenView::kScreenId));
}
void WizardController::ShowTermsOfServiceScreen() {
SetCurrentScreen(GetScreen(TermsOfServiceScreenView::kScreenId));
}
void WizardController::ShowFamilyLinkNoticeScreen() {
AdvanceToScreen(FamilyLinkNoticeView::kScreenId);
}
void WizardController::ShowSyncConsentScreen() {
// First screen after login. Perform a timezone request so that any screens
// relying on geolocation can tailor their contents according to the user's
// region. Currently used on the MarketingOptInScreen.
StartNetworkTimezoneResolve();
SetCurrentScreen(GetScreen(SyncConsentScreenView::kScreenId));
}
void WizardController::StartAuthFactorsSetup() {
ShowCryptohomeRecoverySetupScreen();
}
void WizardController::ShowCryptohomeRecoverySetupScreen() {
SetCurrentScreen(GetScreen(CryptohomeRecoverySetupScreenView::kScreenId));
}
void WizardController::ShowPasswordSelectionScreen() {
SetCurrentScreen(GetScreen(PasswordSelectionScreenView::kScreenId));
}
void WizardController::ShowOSAuthErrorScreen() {
CHECK(wizard_context_->osauth_error.has_value());
SetCurrentScreen(GetScreen(OSAuthErrorScreenView::kScreenId));
}
void WizardController::ShowFactorSetupSuccessScreen() {
SetCurrentScreen(GetScreen(FactorSetupSuccessScreenView::kScreenId));
}
void WizardController::ShowFingerprintSetupScreen() {
SetCurrentScreen(GetScreen(FingerprintSetupScreenView::kScreenId));
}
void WizardController::ShowPinSetupScreenAsSecondaryFactor() {
wizard_context_->knowledge_factor_setup.pin_setup_mode =
WizardContext::PinSetupMode::kSetupAsSecondaryFactor;
SetCurrentScreen(GetScreen(PinSetupScreenView::kScreenId));
}
void WizardController::ShowPinSetupScreenAsMainFactor() {
wizard_context_->knowledge_factor_setup.pin_setup_mode =
WizardContext::PinSetupMode::kSetupAsPrimaryFactor;
SetCurrentScreen(GetScreen(PinSetupScreenView::kScreenId));
}
void WizardController::ShowPinSetupScreenForRecovery() {
wizard_context_->knowledge_factor_setup.pin_setup_mode =
WizardContext::PinSetupMode::kRecovery;
SetCurrentScreen(GetScreen(PinSetupScreenView::kScreenId));
}
void WizardController::ShowThemeSelectionScreen() {
SetCurrentScreen(GetScreen(ThemeSelectionScreenView::kScreenId));
}
void WizardController::ShowMarketingOptInScreen() {
SetCurrentScreen(GetScreen(MarketingOptInScreenView::kScreenId));
}
void WizardController::ShowRecommendAppsScreen() {
SetCurrentScreen(GetScreen(RecommendAppsScreenView::kScreenId));
}
void WizardController::ShowRemoteActivityNotificationScreen() {
SetCurrentScreen(GetScreen(RemoteActivityNotificationView::kScreenId));
}
void WizardController::ShowAppDownloadingScreen() {
SetCurrentScreen(GetScreen(AppDownloadingScreenView::kScreenId));
}
void WizardController::ShowAiIntroScreen() {
SetCurrentScreen(GetScreen(AiIntroScreenView::kScreenId));
}
void WizardController::ShowGeminiIntroScreen() {
SetCurrentScreen(GetScreen(GeminiIntroScreenView::kScreenId));
}
void WizardController::ShowWrongHWIDScreen() {
SetCurrentScreen(GetScreen(WrongHWIDScreenView::kScreenId));
}
void WizardController::ShowAutoEnrollmentCheckScreen() {
AutoEnrollmentCheckScreen* screen = GetScreen<AutoEnrollmentCheckScreen>();
screen->set_auto_enrollment_controller(GetAutoEnrollmentController());
SetCurrentScreen(screen);
}
void WizardController::ShowHIDDetectionScreen() {
SetCurrentScreen(GetScreen(HIDDetectionView::kScreenId));
}
void WizardController::ShowDeviceDisabledScreen() {
SetCurrentScreen(GetScreen(DeviceDisabledScreenView::kScreenId));
}
void WizardController::ShowEncryptionMigrationScreen() {
SetCurrentScreen(GetScreen(EncryptionMigrationScreenView::kScreenId));
}
void WizardController::ShowManagementTransitionScreen() {
SetCurrentScreen(GetScreen(ManagementTransitionScreenView::kScreenId));
}
void WizardController::ShowUpdateRequiredScreen() {
SetCurrentScreen(GetScreen(UpdateRequiredView::kScreenId));
}
void WizardController::ShowAssistantOptInFlowScreen() {
SetCurrentScreen(GetScreen(AssistantOptInFlowScreenView::kScreenId));
}
void WizardController::ShowMultiDeviceSetupScreen() {
SetCurrentScreen(GetScreen(MultiDeviceSetupScreenView::kScreenId));
}
void WizardController::ShowGestureNavigationScreen() {
SetCurrentScreen(GetScreen(GestureNavigationScreenView::kScreenId));
}
void WizardController::ShowPackagedLicenseScreen() {
SetCurrentScreen(GetScreen(PackagedLicenseView::kScreenId));
}
void WizardController::ShowEduCoexistenceLoginScreen() {
SetCurrentScreen(GetScreen(EduCoexistenceLoginScreen::kScreenId));
}
void WizardController::ShowParentalHandoffScreen() {
SetCurrentScreen(GetScreen(ParentalHandoffScreenView::kScreenId));
}
void WizardController::ShowOsInstallScreen() {
SetCurrentScreen(GetScreen(OsInstallScreenView::kScreenId));
}
void WizardController::ShowOsTrialScreen() {
SetCurrentScreen(GetScreen(OsTrialScreenView::kScreenId));
}
void WizardController::ShowConsolidatedConsentScreen() {
SetCurrentScreen(GetScreen(ConsolidatedConsentScreenView::kScreenId));
}
void WizardController::ShowChoobeScreen() {
DCHECK(features::IsOobeChoobeEnabled());
SetCurrentScreen(GetScreen(ChoobeScreenView::kScreenId));
}
void WizardController::ShowCategoriesSelectionScreen() {
SetCurrentScreen(GetScreen(CategoriesSelectionScreenView::kScreenId));
}
void WizardController::ShowPersonalizedRecomendAppsScreen() {
SetCurrentScreen(GetScreen(PersonalizedRecommendAppsScreenView::kScreenId));
}
void WizardController::ShowPerksDiscoveryScreen() {
SetCurrentScreen(GetScreen(PerksDiscoveryScreenView::kScreenId));
}
void WizardController::ShowSplitModifierKeyboardInfoScreen() {
SetCurrentScreen(GetScreen(SplitModifierKeyboardInfoScreenView::kScreenId));
}
void WizardController::ShowTouchpadScrollScreen() {
// If the `OobeChoobe` or `OobeDisplaySize` feature is disabled, the
// DisplaySizeScreen object will not be created. In this case,
// `OnTouchpadScreenExit()` function is called with the exit result
// `kNotApplicable` to proceed to the next screen.
if (features::IsOobeTouchpadScrollEnabled()) {
SetCurrentScreen(GetScreen(TouchpadScrollScreenView::kScreenId));
} else {
OnTouchpadScreenExit(TouchpadScrollScreen::Result::kNotApplicable);
}
}
void WizardController::ShowDisplaySizeScreen() {
if (features::IsOobeDisplaySizeEnabled()) {
SetCurrentScreen(GetScreen(DisplaySizeScreenView::kScreenId));
} else {
OnDisplaySizeScreenExit(DisplaySizeScreen::Result::kNotApplicable);
}
}
void WizardController::ShowGuestTosScreen() {
SetCurrentScreen(GetScreen(GuestTosScreenView::kScreenId));
}
void WizardController::ShowArcVmDataMigrationScreen() {
SetCurrentScreen(GetScreen(ArcVmDataMigrationScreenView::kScreenId));
}
void WizardController::ShowCryptohomeRecoveryScreen(
std::unique_ptr<UserContext> user_context) {
wizard_context_->user_context = std::move(user_context);
SetCurrentScreen(GetScreen(CryptohomeRecoveryScreenView::kScreenId));
}
void WizardController::ShowAccountSelectionScreen() {
SetCurrentScreen(GetScreen(AccountSelectionScreenView::kScreenId));
}
void WizardController::ShowAppLaunchSplashScreen() {
SetCurrentScreen(GetScreen(AppLaunchSplashScreenView::kScreenId));
}
void WizardController::OnUserCreationScreenExit(
UserCreationScreen::Result result) {
OnScreenExit(UserCreationView::kScreenId,
UserCreationScreen::GetResultString(result));
switch (result) {
case UserCreationScreen::Result::SIGNIN_SCHOOL:
MaybeAbortQuickStartFlow(
quick_start::QuickStartController::AbortFlowReason::SIGNIN_SCHOOL);
[[fallthrough]];
case UserCreationScreen::Result::SIGNIN_TRIAGE:
GetLocalState()->SetBoolean(prefs::kOobeIsConsumerSegment, true);
StartupUtils::SaveScreenAfterConsumerUpdate(GaiaView::kScreenId.name);
ShowConsumerUpdateScreen();
break;
case UserCreationScreen::Result::SIGNIN:
if (features::IsOobeSoftwareUpdateEnabled()) {
if (features::IsOobeGaiaInfoScreenEnabled()) {
GetLocalState()->SetBoolean(prefs::kOobeIsConsumerSegment, true);
StartupUtils::SaveScreenAfterConsumerUpdate(
GaiaInfoScreenView::kScreenId.name);
ShowConsumerUpdateScreen();
} else {
GetLocalState()->SetBoolean(prefs::kOobeIsConsumerSegment, true);
StartupUtils::SaveScreenAfterConsumerUpdate(GaiaView::kScreenId.name);
ShowConsumerUpdateScreen();
}
} else {
if (features::IsOobeGaiaInfoScreenEnabled()) {
ShowGaiaInfoScreen();
} else {
AdvanceToScreen(GaiaView::kScreenId);
}
}
break;
case UserCreationScreen::Result::SKIPPED:
if (features::IsOobeAddUserDuringEnrollmentEnabled() &&
wizard_context_->timebound_user_context_holder) {
ShowAccountSelectionScreen();
} else {
AdvanceToScreen(GaiaView::kScreenId);
}
break;
case UserCreationScreen::Result::ADD_CHILD:
MaybeAbortQuickStartFlow(
quick_start::QuickStartController::AbortFlowReason::ADD_CHILD);
if (features::IsOobeSoftwareUpdateEnabled()) {
StartupUtils::SaveScreenAfterConsumerUpdate(
AddChildScreenView::kScreenId.name);
ShowConsumerUpdateScreen();
} else {
ShowAddChildScreen();
}
break;
case UserCreationScreen::Result::ENTERPRISE_ENROLL_TRIAGE:
case UserCreationScreen::Result::ENTERPRISE_ENROLL_SHORTCUT:
ShowEnrollmentScreenIfEligible();
break;
case UserCreationScreen::Result::KIOSK_ENTERPRISE_ENROLL:
wizard_context_->enrollment_preference_ =
WizardContext::EnrollmentPreference::kKiosk;
ShowEnrollmentScreenIfEligible();
break;
case UserCreationScreen::Result::CANCEL:
LoginDisplayHost::default_host()->HideOobeDialog();
break;
}
}
void WizardController::OnConsumerUpdateScreenExit(
ConsumerUpdateScreen::Result result) {
OnScreenExit(ConsumerUpdateScreenView::kScreenId,
ConsumerUpdateScreen::GetResultString(result));
if (result == ConsumerUpdateScreen::Result::BACK) {
AdvanceToScreen(UserCreationView::kScreenId);
return;
}
const std::string screen_name =
GetLocalState()->GetString(prefs::kOobeScreenAfterConsumerUpdate);
if (screen_name == GaiaInfoScreenView::kScreenId.name) {
if (features::IsOobeGaiaInfoScreenEnabled() &&
HasScreen(PrefToScreenId(screen_name))) {
AdvanceToScreen(PrefToScreenId(screen_name));
} else {
AdvanceToScreen(GaiaView::kScreenId);
}
} else if (HasScreen(PrefToScreenId(screen_name))) {
AdvanceToScreen(PrefToScreenId(screen_name));
} else {
// Fallback for resuming consumer update screen from local state. This
// handles cases where screen names/structure changed between versions.
// 'OnUserCreationScreenExit' would update the state for compatibility.
AdvanceToScreen(UserCreationView::kScreenId);
}
}
void WizardController::OnGaiaScreenExit(GaiaScreen::Result result) {
OnScreenExit(GaiaView::kScreenId, GaiaScreen::GetResultString(result));
switch (result) {
case GaiaScreen::Result::BACK_CHILD:
ShowAddChildScreen();
break;
case GaiaScreen::Result::BACK:
case GaiaScreen::Result::CANCEL: {
if (features::IsOobeSoftwareUpdateEnabled()) {
// When `OobeSoftwareUpdate` is enabled, clicking the back button should
// return the user to the user creation screen if it is enabled or the
// user is still in the oobe flow.
if ((wizard_context_->is_user_creation_enabled ||
!wizard_context_->is_add_person_flow) &&
result == GaiaScreen::Result::BACK) {
AdvanceToScreen(UserCreationView::kScreenId);
break;
}
}
if (features::IsOobeGaiaInfoScreenEnabled()) {
if (wizard_context_->is_user_creation_enabled) {
// `Result::BACK` and `Result::BACK_CHILD` are only triggered when
// pressing back button. It goes back to GaiaInfoScreenView if user
// creation is enabled; otherwise, it behaves the same as
// `Result::CANCEL` which is triggered by pressing ESC key.
if (result == GaiaScreen::Result::BACK) {
if (wizard_context_->is_add_person_flow) {
AdvanceToScreen(UserCreationView::kScreenId);
} else {
AdvanceToScreen(GaiaInfoScreenView::kScreenId);
}
break;
}
}
} else {
// TODO: delete this part after removing the feature flag (b:282728089)
if (result == GaiaScreen::Result::BACK &&
wizard_context_->is_user_creation_enabled) {
// `Result::BACK` is only triggered when pressing back button. It goes
// back to UserCreationScreen if screen is enabled; otherwise, it
// behaves the same as `Result::CANCEL` which is triggered by pressing
// ESC key.
AdvanceToScreen(UserCreationView::kScreenId);
break;
}
}
// If a default redirection to third party IdP is set we can hide the
// dialog.
const bool gaia_page_defaults_to_saml = IsGaiaPageDefaultsToSAML();
if ((LoginDisplayHost::default_host()->HasUserPods() &&
!wizard_context_->is_user_creation_enabled) ||
(!LoginDisplayHost::default_host()->HasUserPods() &&
gaia_page_defaults_to_saml)) {
GetScreen<GaiaScreen>()->Reset();
LoginDisplayHost::default_host()->HideOobeDialog(
gaia_page_defaults_to_saml);
} else {
GetScreen<GaiaScreen>()->LoadOnlineGaia();
}
break;
}
case GaiaScreen::Result::ENTERPRISE_ENROLL:
ShowEnrollmentScreenIfEligible();
break;
case GaiaScreen::Result::ENTER_QUICK_START:
[[fallthrough]];
case GaiaScreen::Result::QUICK_START_ONGOING:
ShowQuickStartScreen();
break;
}
}
void WizardController::OnUserAllowlistCheckScreenExit(
UserAllowlistCheckScreen::Result result) {
CHECK(result == UserAllowlistCheckScreen::Result::RETRY);
OnScreenExit(UserAllowlistCheckScreenView::kScreenId,
UserAllowlistCheckScreen::GetResultString(result));
GetScreen<GaiaScreen>()->Reset();
AdvanceToScreen(GaiaView::kScreenId);
}
void WizardController::OnOnlineAuthenticationScreenExit(
OnlineAuthenticationScreen::Result result) {}
void WizardController::OnGaiaInfoScreenExit(GaiaInfoScreen::Result result) {
OnScreenExit(GaiaInfoScreenView::kScreenId,
GaiaInfoScreen::GetResultString(result));
switch (result) {
case GaiaInfoScreen::Result::kBack:
AdvanceToScreen(UserCreationView::kScreenId);
break;
case GaiaInfoScreen::Result::kManual:
[[fallthrough]];
case GaiaInfoScreen::Result::kNotApplicable:
AdvanceToScreen(GaiaView::kScreenId);
break;
case GaiaInfoScreen::Result::kEnterQuickStart:
[[fallthrough]];
case GaiaInfoScreen::Result::kQuickStartOngoing:
ShowQuickStartScreen();
break;
}
}
void WizardController::OnAddChildScreenExit(AddChildScreen::Result result) {
OnScreenExit(AddChildScreenView::kScreenId,
AddChildScreen::GetResultString(result));
switch (result) {
case AddChildScreen::Result::CHILD_SIGNIN:
wizard_context_->gaia_config.gaia_path =
WizardContext::GaiaPath::kChildSignin;
AdvanceToScreen(GaiaView::kScreenId);
break;
case AddChildScreen::Result::CHILD_ACCOUNT_CREATE:
wizard_context_->gaia_config.gaia_path =
WizardContext::GaiaPath::kChildSignup;
AdvanceToScreen(GaiaView::kScreenId);
break;
case AddChildScreen::Result::ENTERPRISE_ENROLL:
ShowEnrollmentScreenIfEligible();
break;
case AddChildScreen::Result::KIOSK_ENTERPRISE_ENROLL:
wizard_context_->enrollment_preference_ =
WizardContext::EnrollmentPreference::kKiosk;
ShowEnrollmentScreenIfEligible();
break;
case AddChildScreen::Result::SKIPPED:
AdvanceToScreen(GaiaView::kScreenId);
break;
case AddChildScreen::Result::BACK:
AdvanceToScreen(UserCreationView::kScreenId);
if (features::IsOobeSoftwareUpdateEnabled()) {
GetScreen<UserCreationScreen>()->SetChildSetupStep();
}
break;
}
}
void WizardController::OnSamlConfirmPasswordScreenExit(
SamlConfirmPasswordScreen::Result result) {
OnScreenExit(SamlConfirmPasswordView::kScreenId,
SamlConfirmPasswordScreen::GetResultString(result));
switch (result) {
case SamlConfirmPasswordScreen::Result::kCancel:
LoginDisplayHost::default_host()->StartSignInScreen();
return;
case SamlConfirmPasswordScreen::Result::kTooManyAttempts:
ShowSignInFatalErrorScreen(
SignInFatalErrorScreen::Error::kScrapedPasswordVerificationFailure,
base::Value::Dict());
}
}
void WizardController::OnEduCoexistenceLoginScreenExit(
EduCoexistenceLoginScreen::Result result) {
OnScreenExit(EduCoexistenceLoginScreen::kScreenId,
EduCoexistenceLoginScreen::GetResultString(result));
ShowConsolidatedConsentScreen();
}
void WizardController::OnParentalHandoffScreenExit(
ParentalHandoffScreen::Result result) {
OnScreenExit(ParentalHandoffScreenView::kScreenId,
ParentalHandoffScreen::GetResultString(result));
ShowMultiDeviceSetupScreen();
}
void WizardController::OnConsolidatedConsentScreenExit(
ConsolidatedConsentScreen::Result result) {
OnScreenExit(ConsolidatedConsentScreenView::kScreenId,
ConsolidatedConsentScreen::GetResultString(result));
if (drive::util::IsOobeDrivePinningAvailable()) {
GetScreen<DrivePinningScreen>()->StartCalculatingRequiredSpace();
}
if (wizard_context_->is_cloud_ready_update_flow) {
AdvanceToScreen(HWDataCollectionView::kScreenId);
return;
}
switch (result) {
case ConsolidatedConsentScreen::Result::ACCEPTED:
case ConsolidatedConsentScreen::Result::NOT_APPLICABLE:
ShowSyncConsentScreen();
break;
case ConsolidatedConsentScreen::Result::ACCEPTED_DEMO_ONLINE:
DCHECK(demo_setup_controller_);
ShowAutoEnrollmentCheckScreen();
break;
case ConsolidatedConsentScreen::Result::BACK_DEMO:
DCHECK(demo_setup_controller_);
ShowDemoModePreferencesScreen();
break;
}
}
void WizardController::OnOfflineLoginScreenExit(
OfflineLoginScreen::Result result) {
OnScreenExit(OfflineLoginView::kScreenId,
OfflineLoginScreen::GetResultString(result));
switch (result) {
case OfflineLoginScreen::Result::BACK:
// Go back to online login, if still no connection it will trigger
// ErrorScreen with fix options. If UserCreationScreen isn't available
// it will exit with Result::SKIPPED and open GaiaScreen instead.
AdvanceToScreen(UserCreationView::kScreenId);
break;
case OfflineLoginScreen::Result::RELOAD_ONLINE_LOGIN:
AdvanceToScreen(GaiaView::kScreenId);
break;
}
}
void WizardController::OnOsInstallScreenExit() {
OnScreenExit(OsInstallScreenView::kScreenId, kDefaultExitReason);
// The screen exits when user goes back. There could be a previous_screen_ or
// we could get to OsInstallScreen directly from the login screen.
// (When installation is finished or error occurs - user can only shut down)
if (LoginDisplayHost::default_host()->HasUserPods()) {
LoginDisplayHost::default_host()->HideOobeDialog();
return;
}
const bool did_advance = MaybeSetToPreviousScreen();
DCHECK(did_advance);
}
void WizardController::OnOsTrialScreenExit(OsTrialScreen::Result result) {
OnScreenExit(OsTrialScreenView::kScreenId,
OsTrialScreen::GetResultString(result));
switch (result) {
case OsTrialScreen::Result::kBack:
// The OS Trial screen is only shown when OS Installation is started from
// the welcome screen, so if the back button was clicked we go back to
// the welcome screen.
ShowWelcomeScreen();
break;
case OsTrialScreen::Result::kNextTry:
ShowNetworkScreen();
break;
case OsTrialScreen::Result::kNextInstall:
ShowOsInstallScreen();
break;
}
}
void WizardController::OnHWDataCollectionScreenExit(
HWDataCollectionScreen::Result result) {
OnScreenExit(HWDataCollectionView::kScreenId,
HWDataCollectionScreen::GetResultString(result));
if (wizard_context_->is_cloud_ready_update_flow) {
OnOobeFlowFinished();
return;
}
StartAuthFactorsSetup();
}
void WizardController::OnSmartPrivacyProtectionScreenExit(
SmartPrivacyProtectionScreen::Result result) {
OnScreenExit(SmartPrivacyProtectionView::kScreenId,
SmartPrivacyProtectionScreen::GetResultString(result));
ShowParentalHandoffScreen();
}
void WizardController::OnGuestTosScreenExit(GuestTosScreen::Result result) {
OnScreenExit(GuestTosScreenView::kScreenId,
GuestTosScreen::GetResultString(result));
switch (result) {
case GuestTosScreen::Result::ACCEPT:
ash::LoginDisplayHost::default_host()->GetExistingUserController()->Login(
UserContext(user_manager::UserType::kGuest,
user_manager::GuestAccountId()),
SigninSpecifics());
break;
case GuestTosScreen::Result::BACK:
if (MaybeSetToPreviousScreen()) {
break;
}
if (LoginDisplayHost::default_host()->HasUserPods()) {
LoginDisplayHost::default_host()->HideOobeDialog();
}
break;
case GuestTosScreen::Result::CANCEL:
if (LoginDisplayHost::default_host()->HasUserPods()) {
LoginDisplayHost::default_host()->HideOobeDialog();
}
}
}
void WizardController::OnThemeSelectionScreenExit(
ThemeSelectionScreen::Result result) {
OnScreenExit(ThemeSelectionScreenView::kScreenId,
ThemeSelectionScreen::GetResultString(result));
switch (result) {
case ThemeSelectionScreen::Result::kProceed:
case ThemeSelectionScreen::Result::kNotApplicable:
if (wizard_context_->return_to_choobe_screen) {
wizard_context_->return_to_choobe_screen = false;
ShowChoobeScreen();
} else {
if (choobe_flow_controller_) {
choobe_flow_controller_->OnChoobeFlowExit();
choobe_flow_controller_.reset();
}
ShowMarketingOptInScreen();
}
break;
}
}
void WizardController::OnCryptohomeRecoveryScreenExit(
CryptohomeRecoveryScreen::Result result) {
OnScreenExit(CryptohomeRecoveryScreenView::kScreenId,
CryptohomeRecoveryScreen::GetResultString(result));
switch (result) {
case CryptohomeRecoveryScreen::Result::kAuthenticated: {
switch (wizard_context_->knowledge_factor_setup.auth_setup_flow) {
case WizardContext::AuthChangeFlow::kInitialSetup:
NOTREACHED() << "Recovery can not be used during initial setup.";
case WizardContext::AuthChangeFlow::kRecovery:
ShowPasswordSelectionScreen();
return;
case WizardContext::AuthChangeFlow::kReauthentication:
// Proceed with login
ObtainContextAndLoginAuthenticated();
return;
}
}
case CryptohomeRecoveryScreen::Result::kGaiaLogin:
// TODO(b/257073746): We probably want to differentiate between retry with
// or without login.
wizard_context_->gaia_config.prefilled_account =
wizard_context_->user_context->GetAccountId();
AdvanceToScreen(GaiaView::kScreenId);
break;
case CryptohomeRecoveryScreen::Result::kFallbackOnline:
ShowEnterOldPasswordScreen();
break;
case CryptohomeRecoveryScreen::Result::kFallbackLocal: {
switch (wizard_context_->knowledge_factor_setup.auth_setup_flow) {
case WizardContext::AuthChangeFlow::kInitialSetup:
NOTREACHED() << "Recovery is not used during initial setup";
case WizardContext::AuthChangeFlow::kReauthentication:
AttemptLocalAuthenticationWithContext(
std::move(wizard_context_->user_context));
return;
case WizardContext::AuthChangeFlow::kRecovery:
// Recovery flow indicates that user does not remember
// their local password, so there is no step to retry.
wizard_context_->knowledge_factor_setup.data_loss_back_option =
WizardContext::DataLossBackOptions::kNone;
ShowLocalDataLossWarningScreen();
return;
}
}
case CryptohomeRecoveryScreen::Result::kError:
ShowOSAuthErrorScreen();
break;
}
}
void WizardController::OnLocalDataLossWarningScreenExit(
LocalDataLossWarningScreen::Result result) {
OnScreenExit(LocalDataLossWarningScreenView::kScreenId,
LocalDataLossWarningScreen::GetResultString(result));
switch (result) {
case LocalDataLossWarningScreen::Result::kRemoveUser: {
std::unique_ptr<UserContext> context =
std::move(wizard_context_->user_context);
ash::LoginDisplayHost::default_host()->CompleteLogin(*context);
break;
}
case LocalDataLossWarningScreen::Result::kCryptohomeError:
ShowOSAuthErrorScreen();
break;
case LocalDataLossWarningScreen::Result::kCancel:
LoginDisplayHost::default_host()->CancelPasswordChangedFlow();
break;
case LocalDataLossWarningScreen::Result::kBackToOnlineAuth:
ShowEnterOldPasswordScreen();
break;
case LocalDataLossWarningScreen::Result::kBackToLocalAuth:
AttemptLocalAuthenticationWithContext(
std::move(wizard_context_->user_context));
break;
}
}
void WizardController::OnEnterOldPasswordScreenExit(
EnterOldPasswordScreen::Result result) {
OnScreenExit(EnterOldPasswordScreenView::kScreenId,
EnterOldPasswordScreen::GetResultString(result));
switch (result) {
case EnterOldPasswordScreen::Result::kForgotOldPassword:
wizard_context_->knowledge_factor_setup.data_loss_back_option =
WizardContext::DataLossBackOptions::kBackToOnlineAuth;
ShowLocalDataLossWarningScreen();
break;
case EnterOldPasswordScreen::Result::kCryptohomeError:
ShowOSAuthErrorScreen();
break;
case EnterOldPasswordScreen::Result::kAuthenticated: {
switch (wizard_context_->knowledge_factor_setup.auth_setup_flow) {
case WizardContext::AuthChangeFlow::kInitialSetup:
NOTREACHED() << "Old password is not used during initial setup";
case WizardContext::AuthChangeFlow::kRecovery:
case WizardContext::AuthChangeFlow::kReauthentication:
ShowApplyOnlinePasswordScreen();
return;
}
break;
}
}
}
void WizardController::OnChoobeScreenExit(ChoobeScreen::Result result) {
OnScreenExit(ChoobeScreenView::kScreenId,
ChoobeScreen::GetResultString(result));
switch (result) {
case ChoobeScreen::Result::SELECTED:
case ChoobeScreen::Result::NOT_APPLICABLE:
ShowTouchpadScrollScreen();
break;
case ChoobeScreen::Result::SKIPPED:
choobe_flow_controller_->OnChoobeFlowExit();
choobe_flow_controller_.reset();
ShowMarketingOptInScreen();
break;
}
}
void WizardController::OnTouchpadScreenExit(
TouchpadScrollScreen::Result result) {
OnScreenExit(TouchpadScrollScreenView::kScreenId,
TouchpadScrollScreen::GetResultString(result));
ShowDrivePinningScreen();
}
void WizardController::OnCategoriesSelectionScreenExit(
CategoriesSelectionScreen::Result result) {
OnScreenExit(CategoriesSelectionScreenView::kScreenId,
CategoriesSelectionScreen::GetResultString(result));
switch (result) {
case CategoriesSelectionScreen::Result::kError:
case CategoriesSelectionScreen::Result::kNotApplicable:
case CategoriesSelectionScreen::Result::kDataMalformed:
case CategoriesSelectionScreen::Result::kTimeout:
ShowRecommendAppsScreen();
break;
case CategoriesSelectionScreen::Result::kNext:
case CategoriesSelectionScreen::Result::kSkip:
ShowPersonalizedRecomendAppsScreen();
break;
}
}
void WizardController::OnPerksDiscoveryScreenExit(
PerksDiscoveryScreen::Result result) {
OnScreenExit(PerksDiscoveryScreenView::kScreenId,
PerksDiscoveryScreen::GetResultString(result));
if (features::IsOobeAiIntroEnabled()) {
ShowAiIntroScreen();
} else {
ShowGeminiIntroScreen();
}
}
void WizardController::OnPersonalizedRecomendAppsScreenExit(
PersonalizedRecommendAppsScreen::Result result) {
OnScreenExit(PersonalizedRecommendAppsScreenView::kScreenId,
PersonalizedRecommendAppsScreen::GetResultString(result));
switch (result) {
case PersonalizedRecommendAppsScreen::Result::kBack:
ShowCategoriesSelectionScreen();
break;
case PersonalizedRecommendAppsScreen::Result::kNext:
case PersonalizedRecommendAppsScreen::Result::kNotApplicable:
case PersonalizedRecommendAppsScreen::Result::kSkip:
case PersonalizedRecommendAppsScreen::Result::kDataMalformed:
case PersonalizedRecommendAppsScreen::Result::kError:
case PersonalizedRecommendAppsScreen::Result::kTimeout:
ShowPerksDiscoveryScreen();
break;
}
}
void WizardController::OnSplitModifierKeyboardInfoScreenExit(
SplitModifierKeyboardInfoScreen::Result result) {
OnScreenExit(SplitModifierKeyboardInfoScreenView::kScreenId,
SplitModifierKeyboardInfoScreen::GetResultString(result));
ShowGestureNavigationScreen();
}
void WizardController::OnDrivePinningScreenExit(
DrivePinningScreen::Result result) {
OnScreenExit(DrivePinningScreenView::kScreenId,
DrivePinningScreen::GetResultString(result));
if (features::IsOobeDisplaySizeEnabled()) {
ShowDisplaySizeScreen();
} else {
OnDisplaySizeScreenExit(DisplaySizeScreen::Result::kNotApplicable);
}
}
void WizardController::OnDisplaySizeScreenExit(
DisplaySizeScreen::Result result) {
OnScreenExit(DisplaySizeScreenView::kScreenId,
DisplaySizeScreen::GetResultString(result));
switch (result) {
case DisplaySizeScreen::Result::kNotApplicable:
case DisplaySizeScreen::Result::kNext:
ShowThemeSelectionScreen();
}
}
void WizardController::OnAccountSelectionScreenExit(
AccountSelectionScreen::Result result) {
OnScreenExit(AccountSelectionScreenView::kScreenId,
AccountSelectionScreen::GetResultString(result));
switch (result) {
case AccountSelectionScreen::Result::kNotApplicable:
case AccountSelectionScreen::Result::kGaiaFallback:
AdvanceToScreen(GaiaView::kScreenId);
}
}
void WizardController::SkipToLoginForTesting() {
VLOG(1) << "WizardController::SkipToLoginForTesting()";
// This method should only be used on test images.
base::SysInfo::CrashIfChromeOSNonTestImage();
if (current_screen_ && current_screen_->screen_id() == GaiaView::kScreenId) {
return;
}
wizard_context_->skip_to_login_for_tests = true;
StartNetworkTimezoneResolve();
DelayNetworkCall(ServicesCustomizationDocument::GetInstance()
->EnsureCustomizationAppliedClosure());
OnDeviceDisabledChecked(/*device_disabled=*/false);
}
void WizardController::OnScreenExit(OobeScreenId screen,
const std::string& exit_reason) {
VLOG(1) << "Wizard screen " << screen
<< " exited with reason: " << exit_reason << " during setup type: "
<< SetupTypeToString(
wizard_context_->knowledge_factor_setup.auth_setup_flow);
// Do not perform checks and record stats for the skipped screen.
if (exit_reason == BaseScreen::kNotApplicable) {
return;
}
DCHECK(current_screen_->screen_id() == screen);
GetLoginDisplayHost()->GetOobeMetricsHelper()->RecordScreenExit(screen,
exit_reason);
}
///////////////////////////////////////////////////////////////////////////////
// WizardController, ExitHandlers:
void WizardController::OnWrongHWIDScreenExit() {
OnScreenExit(WrongHWIDScreenView::kScreenId, kDefaultExitReason);
OnDeviceModificationCanceled();
}
void WizardController::OnHidDetectionScreenExit(
HIDDetectionScreen::Result result) {
OnScreenExit(HIDDetectionView::kScreenId,
HIDDetectionScreen::GetResultString(result));
if (result == HIDDetectionScreen::Result::SKIPPED_FOR_TESTS &&
current_screen_) {
return;
}
AdvanceToScreenAfterHIDDetection(ash::OOBE_SCREEN_UNKNOWN);
}
void WizardController::OnWelcomeScreenExit(WelcomeScreen::Result result) {
OnScreenExit(WelcomeView::kScreenId, WelcomeScreen::GetResultString(result));
switch (result) {
case WelcomeScreen::Result::kSetupDemo:
StartDemoModeSetup();
return;
case WelcomeScreen::Result::kEnableDebugging:
ShowEnableDebuggingScreen();
return;
case WelcomeScreen::Result::kNextOSInstall:
ShowOsTrialScreen();
return;
case WelcomeScreen::Result::kNext:
ShowNetworkScreen();
return;
case WelcomeScreen::Result::kQuickStart:
ShowQuickStartScreen();
return;
}
}
void WizardController::OnQuickStartScreenExit(QuickStartScreen::Result result) {
OnScreenExit(QuickStartView::kScreenId,
QuickStartScreen::GetResultString(result));
switch (result) {
case QuickStartScreen::Result::CANCEL_AND_RETURN_TO_WELCOME:
ShowWelcomeScreen();
return;
case QuickStartScreen::Result::WIFI_CREDENTIALS_RECEIVED:
case QuickStartScreen::Result::CANCEL_AND_RETURN_TO_NETWORK:
ShowNetworkScreen();
return;
case QuickStartScreen::Result::CANCEL_AND_RETURN_TO_GAIA_INFO:
AdvanceToScreen(GaiaInfoScreenView::kScreenId);
return;
case ash::QuickStartScreen::Result::FALLBACK_URL_ON_GAIA:
wizard_context_->gaia_config.gaia_path =
WizardContext::GaiaPath::kQuickStartFallback;
wizard_context_->gaia_config.quick_start_fallback_path_contents =
quickstart_controller_->GetFallbackUrl();
AdvanceToScreen(GaiaView::kScreenId);
return;
case QuickStartScreen::Result::CANCEL_AND_RETURN_TO_SIGNIN:
AdvanceToScreen(GaiaView::kScreenId);
return;
// Last step of the QuickStart flow. This is triggered immediately
// after the 'RecoveryEligibility' screen and continues OOBE into
// the TermsOfServiceScreen
case QuickStartScreen::Result::SETUP_COMPLETE_NEXT_BUTTON:
quickstart_controller_->RecordFlowFinished();
AdvanceToScreen(TermsOfServiceScreenView::kScreenId);
}
}
// The network screen is part of 3 different flows:
// * Regular Flow: Welcome Screen -> Network Screen -> Update Screen.
// * Demo Flow: Welcome Screen -> Network Screen -> Demo Preferences Screen.
// * OS Install Flow: OS Trial Screen -> Network Screen -> Update Screen.
void WizardController::OnNetworkScreenExit(NetworkScreen::Result result) {
OnScreenExit(NetworkScreenView::kScreenId,
NetworkScreen::GetResultString(result));
// Demo mode flow.
if (DemoSetupController::IsOobeDemoSetupFlowInProgress()) {
switch (result) {
case NetworkScreen::Result::CONNECTED:
case NetworkScreen::Result::NOT_APPLICABLE:
demo_setup_controller_->set_demo_config(
DemoSession::DemoModeConfig::kOnline);
ShowDemoModePreferencesScreen();
break;
case NetworkScreen::Result::BACK:
demo_setup_controller_.reset();
ShowWelcomeScreen();
break;
case NetworkScreen::Result::QUICK_START:
NOTREACHED();
}
return;
}
// OS Install flow.
if (switches::IsOsInstallAllowed()) {
switch (result) {
case NetworkScreen::Result::CONNECTED:
case NetworkScreen::Result::NOT_APPLICABLE:
MaybeTakeTPMOwnership();
PerformPostNetworkScreenActions();
InitiateOOBEUpdate();
break;
case NetworkScreen::Result::BACK:
ShowOsTrialScreen();
break;
case NetworkScreen::Result::QUICK_START:
NOTREACHED();
}
return;
}
// Regular flow.
switch (result) {
case NetworkScreen::Result::CONNECTED:
case NetworkScreen::Result::NOT_APPLICABLE:
MaybeTakeTPMOwnership();
PerformPostNetworkScreenActions();
InitiateOOBEUpdate();
break;
case NetworkScreen::Result::BACK:
ShowWelcomeScreen();
break;
case NetworkScreen::Result::QUICK_START:
ShowQuickStartScreen();
break;
}
}
void WizardController::OnUpdateScreenExit(UpdateScreen::Result result) {
OnScreenExit(UpdateView::kScreenId, UpdateScreen::GetResultString(result));
switch (result) {
case UpdateScreen::Result::UPDATE_NOT_REQUIRED:
case UpdateScreen::Result::UPDATE_CHECK_TIMEOUT:
case UpdateScreen::Result::UPDATE_SKIPPED:
case UpdateScreen::Result::UPDATE_OPT_OUT_INFO_SHOWN:
OnUpdateCompleted();
break;
case UpdateScreen::Result::UPDATE_ERROR:
// Ignore update errors if the OOBE flow has already completed - this
// prevents the user getting blocked from getting to the login screen.
if (is_out_of_box_) {
ShowNetworkScreen();
} else {
OnUpdateCompleted();
}
break;
}
}
void WizardController::OnUpdateCompleted() {
// Install language packs based on the user selected language.
if (ash::features::IsLanguagePacksInOobeEnabled()) {
const std::string locale = GetApplicationLocale();
language_packs::LanguagePackManager::UpdatePacksForOobe(locale,
base::DoNothing());
}
if (demo_setup_controller_) {
ShowConsolidatedConsentScreen();
return;
}
ShowAutoEnrollmentCheckScreen();
}
void WizardController::OnAutoEnrollmentCheckScreenExit(
AutoEnrollmentCheckScreen::Result result) {
OnScreenExit(AutoEnrollmentCheckScreenView::kScreenId,
AutoEnrollmentCheckScreen::GetResultString(result));
VLOG(1) << "WizardController::OnAutoEnrollmentCheckScreenExit()";
// Check whether the device is disabled. OnDeviceDisabledChecked() will be
// invoked when the result of this check is known. Until then, the current
// screen will remain visible and will continue showing a spinner.
g_browser_process->platform_part()
->device_disabling_manager()
->CheckWhetherDeviceDisabledDuringOOBE(
base::BindRepeating(&WizardController::OnDeviceDisabledChecked,
weak_factory_.GetWeakPtr()));
}
void WizardController::OnEnrollmentScreenExit(EnrollmentScreen::Result result) {
OnScreenExit(EnrollmentScreenView::kScreenId,
EnrollmentScreen::GetResultString(result));
VLOG(1) << "WizardController::OnEnrollmentScreenExit(result= "
<< EnrollmentScreen::GetResultString(result) << ").";
switch (result) {
case EnrollmentScreen::Result::COMPLETED:
OnEnrollmentDone();
break;
case EnrollmentScreen::Result::BACK:
case EnrollmentScreen::Result::SKIPPED_FOR_TESTS:
// The following `PerformOOBECompletedAction()` call will occur in both
// manual and auto enrollment. However, in the manual enrollment case,
// `PerformOOBECompletedAction()` method would be already called before
// with `CompletedPreLoginOobeFlowType::kRegular` argument.
// OOBECompletedActions are only performed in the first call.
PerformOOBECompletedActions(
OobeMetricsHelper::CompletedPreLoginOobeFlowType::kAutoEnrollment);
DCHECK(!prescribed_enrollment_config_.is_forced());
// set the userCreationScreen with the default step creation and
// pre-select 'For personal use'.
GetScreen<UserCreationScreen>()->SetDefaultStep();
ShowLoginScreen();
break;
case EnrollmentScreen::Result::TPM_ERROR:
DCHECK(switches::IsTpmDynamic());
wizard_context_->tpm_owned_error = true;
AdvanceToScreen(TpmErrorView::kScreenId);
break;
case EnrollmentScreen::Result::TPM_DBUS_ERROR:
DCHECK(switches::IsTpmDynamic());
wizard_context_->tpm_dbus_error = true;
AdvanceToScreen(TpmErrorView::kScreenId);
break;
case EnrollmentScreen::Result::BACK_TO_AUTO_ENROLLMENT_CHECK:
ShowAutoEnrollmentCheckScreen();
break;
}
}
void WizardController::OnEnrollmentDone() {
// The following `PerformOOBECompletedAction()` call will occur in both
// manual and auto enrollment. However, in the manual enrollment case,
// `PerformOOBECompletedAction()` method would be already called before
// with `CompletedPreLoginOobeFlowType::kRegular` argument.
// OOBECompletedActions are only performed in the first call.
PerformOOBECompletedActions(
OobeMetricsHelper::CompletedPreLoginOobeFlowType::kAutoEnrollment);
// Restart to make the login page pick up the policy changes resulting from
// enrollment recovery. (Not pretty, but this codepath is rarely
// exercised.)
if (prescribed_enrollment_config_.mode ==
policy::EnrollmentConfig::MODE_RECOVERY) {
LOG(WARNING) << "Restart Chrome to pick up the policy changes";
EnrollmentScreen* screen = EnrollmentScreen::Get(screen_manager());
screen->OnBrowserRestart();
chrome::AttemptRestart();
return;
}
// We need a log to understand when the device finished enrollment.
VLOG(1) << "Enrollment done";
if (auto app = KioskController::Get().GetAutoLaunchApp(); app.has_value()) {
AutoLaunchKioskApp(app.value());
} else if (ash::InstallAttributes::Get()->IsEnterpriseManaged()) {
// Could be not managed in tests.
DCHECK_EQ(LoginDisplayHost::default_host()->GetOobeUI()->display_type(),
OobeUI::kOobeDisplay);
SwitchWebUItoMojo();
} else {
ShowLoginScreen();
}
}
void WizardController::OnEnableAdbSideloadingScreenExit() {
OnScreenExit(EnableAdbSideloadingScreenView::kScreenId, kDefaultExitReason);
OnDeviceModificationCanceled();
}
void WizardController::OnEnableDebuggingScreenExit() {
OnScreenExit(EnableDebuggingScreenView::kScreenId, kDefaultExitReason);
OnDeviceModificationCanceled();
}
void WizardController::OnDemoPreferencesScreenExit(
DemoPreferencesScreen::Result result) {
OnScreenExit(DemoPreferencesScreenView::kScreenId,
DemoPreferencesScreen::GetResultString(result));
DCHECK(demo_setup_controller_);
switch (result) {
case DemoPreferencesScreen::Result::COMPLETED:
demo_setup_controller_->set_demo_config(
DemoSession::DemoModeConfig::kOnline);
MaybeTakeTPMOwnership();
PerformPostNetworkScreenActions();
InitiateOOBEUpdate();
break;
case DemoPreferencesScreen::Result::CANCELED:
ShowNetworkScreen();
break;
}
}
void WizardController::OnDemoSetupScreenExit(DemoSetupScreen::Result result) {
OnScreenExit(DemoSetupScreenView::kScreenId,
DemoSetupScreen::GetResultString(result));
DCHECK(demo_setup_controller_);
demo_setup_controller_.reset();
switch (result) {
case DemoSetupScreen::Result::kCompleted:
PerformOOBECompletedActions(
OobeMetricsHelper::CompletedPreLoginOobeFlowType::kDemo);
SwitchWebUItoMojo();
break;
case DemoSetupScreen::Result::kCanceled:
ShowWelcomeScreen();
break;
}
}
void WizardController::OnLocaleSwitchScreenExit(
LocaleSwitchScreen::Result result) {
OnScreenExit(LocaleSwitchView::kScreenId,
LocaleSwitchScreen::GetResultString(result));
AdvanceToScreen(RecoveryEligibilityView::kScreenId);
}
void WizardController::OnRecoveryEligibilityScreenExit(
RecoveryEligibilityScreen::Result result) {
OnScreenExit(RecoveryEligibilityView::kScreenId,
RecoveryEligibilityScreen::GetResultString(result));
// QuickStart's 'Setup Complete' screen step is the first screen
// that a user sees after logging in. It just shows a 'Next' button
// which exits the screen into the TermsOfServiceScreen
if (wizard_context_->quick_start_enabled &&
wizard_context_->quick_start_setup_ongoing) {
AdvanceToScreen(QuickStartView::kScreenId);
} else {
AdvanceToScreen(TermsOfServiceScreenView::kScreenId);
}
}
void WizardController::OnTermsOfServiceScreenExit(
TermsOfServiceScreen::Result result) {
OnScreenExit(TermsOfServiceScreenView::kScreenId,
TermsOfServiceScreen::GetResultString(result));
switch (result) {
case TermsOfServiceScreen::Result::ACCEPTED:
case TermsOfServiceScreen::Result::NOT_APPLICABLE:
if (wizard_context_->screen_after_managed_tos ==
ash::OOBE_SCREEN_UNKNOWN) {
OnOobeFlowFinished();
return;
}
AdvanceToScreen(wizard_context_->screen_after_managed_tos);
break;
case TermsOfServiceScreen::Result::DECLINED:
// End the session and return to the login screen.
SessionManagerClient::Get()->StopSession(
login_manager::SessionStopReason::TERMS_DECLINED);
break;
}
}
void WizardController::OnFamilyLinkNoticeScreenExit(
FamilyLinkNoticeScreen::Result result) {
OnScreenExit(FamilyLinkNoticeView::kScreenId,
FamilyLinkNoticeScreen::GetResultString(result));
ShowEduCoexistenceLoginScreen();
}
void WizardController::OnSyncConsentScreenExit(
SyncConsentScreen::Result result) {
OnScreenExit(SyncConsentScreenView::kScreenId,
SyncConsentScreen::GetResultString(result));
if (switches::IsRevenBranding()) {
AdvanceToScreen(HWDataCollectionView::kScreenId);
return;
}
StartAuthFactorsSetup();
}
// Start of local authentication setup screen exit handlers.
void WizardController::OnCryptohomeRecoverySetupScreenExit(
CryptohomeRecoverySetupScreen::Result result) {
OnScreenExit(CryptohomeRecoverySetupScreenView::kScreenId,
CryptohomeRecoverySetupScreen::GetResultString(result));
if (features::IsAllowPasswordlessSetupEnabled()) {
// First step of the AuthFactor setup flow. Offer PIN as a main factor. If
// there isn't hardware support, the screen exits gracefully.
ShowPinSetupScreenAsMainFactor();
} else {
ShowPasswordSelectionScreen();
}
}
void WizardController::OnPasswordSelectionScreenExit(
PasswordSelectionScreen::Result result) {
OnScreenExit(PasswordSelectionScreenView::kScreenId,
PasswordSelectionScreen::GetResultString(result));
switch (result) {
// TODO(b/291808449): add an edge case for Enterprise users
// without GAIA/SAML password.
case PasswordSelectionScreen::Result::NOT_APPLICABLE:
ShowFingerprintSetupScreen();
return;
case PasswordSelectionScreen::Result::BACK: {
// The back button is only shown for going back to main PIN setup.
CHECK_EQ(wizard_context_->knowledge_factor_setup.pin_setup_mode,
WizardContext::PinSetupMode::kUserChosePasswordInstead);
ShowPinSetupScreenAsMainFactor();
return;
}
case PasswordSelectionScreen::Result::PIN_RESET: {
// User has PIN-only. This can only happen during the recovery path.
CHECK_EQ(wizard_context_->knowledge_factor_setup.auth_setup_flow,
WizardContext::AuthChangeFlow::kRecovery)
<< "PasswordSelection exited with PIN_RESET result outside recovery.";
CHECK(features::IsAllowPasswordlessRecoveryEnabled());
ShowPinSetupScreenForRecovery();
return;
}
case PasswordSelectionScreen::Result::LOCAL_PASSWORD_CHOICE:
case PasswordSelectionScreen::Result::LOCAL_PASSWORD_FORCED:
ShowLocalPasswordSetupScreen();
return;
case PasswordSelectionScreen::Result::GAIA_PASSWORD_CHOICE:
case PasswordSelectionScreen::Result::GAIA_PASSWORD_FALLBACK:
case PasswordSelectionScreen::Result::GAIA_PASSWORD_ENTERPRISE:
ShowApplyOnlinePasswordScreen();
return;
}
}
void WizardController::OnLocalPasswordSetupScreenExit(
LocalPasswordSetupScreen::Result result) {
OnScreenExit(LocalPasswordSetupView::kScreenId,
LocalPasswordSetupScreen::GetResultString(result));
switch (result) {
case LocalPasswordSetupScreen::Result::kBack:
// Go back to the PasswordSelectionScreen if the user had a choice between
// local vs. online password.
if (!wizard_context_->knowledge_factor_setup.local_password_forced) {
ShowPasswordSelectionScreen();
return;
}
// The user could not choose between an online vs. local password because
// they went through a passwordless signin. In that case, going back is
// only possible for returning to the PinSetupScreen as a main factor.
CHECK_EQ(wizard_context_->knowledge_factor_setup.pin_setup_mode,
WizardContext::PinSetupMode::kUserChosePasswordInstead);
ShowPinSetupScreenAsMainFactor();
return;
case LocalPasswordSetupScreen::Result::kDone:
case LocalPasswordSetupScreen::Result::kNotApplicable:
ShowFactorSetupSuccessScreen();
return;
}
}
void WizardController::OnApplyOnlinePasswordScreenExit(
ApplyOnlinePasswordScreen::Result result) {
OnScreenExit(ApplyOnlinePasswordScreenView::kScreenId,
ApplyOnlinePasswordScreen::GetResultString(result));
switch (result) {
case ApplyOnlinePasswordScreen::Result::kError:
ShowOSAuthErrorScreen();
return;
case ApplyOnlinePasswordScreen::Result::kSuccess:
case ApplyOnlinePasswordScreen::Result::kNotApplicable: {
switch (wizard_context_->knowledge_factor_setup.auth_setup_flow) {
case WizardContext::AuthChangeFlow::kInitialSetup:
ShowFingerprintSetupScreen();
return;
case WizardContext::AuthChangeFlow::kRecovery:
ShowFactorSetupSuccessScreen();
return;
case WizardContext::AuthChangeFlow::kReauthentication:
NOTREACHED() << "Reauthentication should have been switched to "
"Recovery if there was password update";
}
}
return;
}
}
void WizardController::OnOSAuthErrorScreenExit(
OSAuthErrorScreen::Result result) {
OnScreenExit(OSAuthErrorScreenView::kScreenId,
OSAuthErrorScreen::GetResultString(result));
switch (result) {
case OSAuthErrorScreen::Result::kFallbackOnline:
ShowEnterOldPasswordScreen();
break;
case OSAuthErrorScreen::Result::kFallbackLocal: {
switch (wizard_context_->knowledge_factor_setup.auth_setup_flow) {
case WizardContext::AuthChangeFlow::kInitialSetup:
NOTREACHED() << "Recovery is not used during initial setup";
case WizardContext::AuthChangeFlow::kReauthentication:
AttemptLocalAuthenticationWithContext(
std::move(wizard_context_->user_context));
return;
case WizardContext::AuthChangeFlow::kRecovery:
// Recovery flow means that the user forgot their
// local password. It does not make sense to ask for it.
ShowLocalDataLossWarningScreen();
return;
}
}
case OSAuthErrorScreen::Result::kProceedAuthenticated: {
switch (wizard_context_->knowledge_factor_setup.auth_setup_flow) {
case WizardContext::AuthChangeFlow::kInitialSetup:
case WizardContext::AuthChangeFlow::kRecovery:
ShowPasswordSelectionScreen();
return;
case WizardContext::AuthChangeFlow::kReauthentication:
// Proceed with login
ObtainContextAndLoginAuthenticated();
return;
}
}
return;
case OSAuthErrorScreen::Result::kAbortSignin:
ShowLoginScreen();
return;
}
}
void WizardController::OnFactorSetupSuccessScreenExit(
FactorSetupSuccessScreen::Result result) {
OnScreenExit(FactorSetupSuccessScreenView::kScreenId,
FactorSetupSuccessScreen::GetResultString(result));
switch (result) {
case FactorSetupSuccessScreen::Result::kNotApplicable:
case FactorSetupSuccessScreen::Result::kProceed: {
switch (wizard_context_->knowledge_factor_setup.auth_setup_flow) {
case WizardContext::AuthChangeFlow::kInitialSetup:
ShowFingerprintSetupScreen();
return;
case WizardContext::AuthChangeFlow::kRecovery:
case WizardContext::AuthChangeFlow::kReauthentication:
// Proceed with login
ObtainContextAndLoginAuthenticated();
return;
}
}
case FactorSetupSuccessScreen::Result::kTimedOut:
ShowLoginScreen();
return;
}
}
// After FingerprintSetup, PIN is offered as an additional factor, unless:
// - The user has already set a PIN as their main factor.
// - The user chose 'Use Password instead' when offered a PIN.
void WizardController::OnFingerprintSetupScreenExit(
FingerprintSetupScreen::Result result) {
OnScreenExit(FingerprintSetupScreenView::kScreenId,
FingerprintSetupScreen::GetResultString(result));
const bool pin_was_already_set =
wizard_context_->knowledge_factor_setup.pin_setup_mode ==
WizardContext::PinSetupMode::kAlreadyPerformed;
const bool user_chose_password_instead =
wizard_context_->knowledge_factor_setup.pin_setup_mode ==
WizardContext::PinSetupMode::kUserChosePasswordInstead;
if (pin_was_already_set || user_chose_password_instead) {
FinishAuthFactorsSetup();
} else {
ShowPinSetupScreenAsSecondaryFactor();
}
}
void WizardController::OnPinSetupScreenExit(PinSetupScreen::Result result) {
OnScreenExit(PinSetupScreenView::kScreenId,
PinSetupScreen::GetResultString(result));
if (features::IsAllowPasswordlessSetupEnabled()) {
switch (result) {
// PIN as a main factor is not supported or not wanted. In both cases,
// proceed to the PasswordSelectionScreen.
case PinSetupScreen::Result::kUserChosePassword:
// The user does not wish to have a PIN as their main authentication
// factor. Setting this setup mode ensures that the screen is not
// resurfaced later in the flow a second time, and that a back button
// will be shown on PasswordSelectionScreen for the user to go back.
wizard_context_->knowledge_factor_setup.pin_setup_mode =
WizardContext::PinSetupMode::kUserChosePasswordInstead;
[[fallthrough]];
case PinSetupScreen::Result::kNotApplicableAsPrimaryFactor:
ShowPasswordSelectionScreen();
return;
case PinSetupScreen::Result::kDoneAsMainFactor:
wizard_context_->knowledge_factor_setup.pin_setup_mode =
WizardContext::PinSetupMode::kAlreadyPerformed;
ShowFingerprintSetupScreen();
return;
// These are emitted when the screen is surfaced at the end of the flow,
// offering PIN as an additional factor.
case PinSetupScreen::Result::kDoneAsSecondaryFactor:
case PinSetupScreen::Result::kUserSkip:
case PinSetupScreen::Result::kNotApplicable:
case PinSetupScreen::Result::kTimedOut:
FinishAuthFactorsSetup();
return;
// Proceed into session when PIN is reset via recovery.
case PinSetupScreen::Result::kDoneRecoveryReset:
CHECK_EQ(wizard_context_->knowledge_factor_setup.auth_setup_flow,
WizardContext::AuthChangeFlow::kRecovery);
CHECK(features::IsAllowPasswordlessRecoveryEnabled());
ObtainContextAndLoginAuthenticated();
return;
}
} else {
FinishAuthFactorsSetup();
}
}
void WizardController::ObtainContextAndLoginAuthenticated() {
CHECK(wizard_context_->extra_factors_token);
auto token = std::move(wizard_context_->extra_factors_token);
wizard_context_->extra_factors_token = std::nullopt;
ash::AuthSessionStorage::Get()->Withdraw(
*token, base::BindOnce(&WizardController::LoginAuthenticatedWithContext,
weak_factory_.GetWeakPtr()));
}
void WizardController::ObtainContextAndAttemptLocalAuthentication() {
CHECK(wizard_context_->extra_factors_token);
auto token = std::move(wizard_context_->extra_factors_token);
wizard_context_->extra_factors_token = std::nullopt;
ash::AuthSessionStorage::Get()->Withdraw(
*token,
base::BindOnce(&WizardController::AttemptLocalAuthenticationWithContext,
weak_factory_.GetWeakPtr()));
}
void WizardController::LoginAuthenticatedWithContext(
std::unique_ptr<UserContext> context) {
if (!context) {
// Session has expired.
LOG(ERROR) << "Session expired before login could proceed.";
wizard_context_->osauth_error = WizardContext::OSAuthErrorKind::kFatal;
ShowOSAuthErrorScreen();
return;
}
ash::LoginDisplayHost::default_host()
->GetExistingUserController()
->LoginAuthenticated(std::move(context));
}
void WizardController::AttemptLocalAuthenticationWithContext(
std::unique_ptr<UserContext> context) {
ash::LoginDisplayHost::default_host()->GetSigninUI()->RunLocalAuthentication(
std::move(context));
}
void WizardController::FinishAuthFactorsSetup() {
// TODO(crbug.com/372213353): Ensure that AuthSession is terminated after this
// step.
if (wizard_context_->extra_factors_token.has_value()) {
ash::AuthSessionStorage::Get()->Invalidate(
wizard_context_->extra_factors_token.value(), base::DoNothing());
wizard_context_->extra_factors_token = std::nullopt;
}
if (features::IsOobePersonalizedOnboardingEnabled()) {
ShowCategoriesSelectionScreen();
} else {
ShowRecommendAppsScreen();
}
}
// End of local authentication setup screen exit handlers.
void WizardController::OnRecommendAppsScreenExit(
RecommendAppsScreen::Result result) {
OnScreenExit(RecommendAppsScreenView::kScreenId,
RecommendAppsScreen::GetResultString(result));
switch (result) {
case RecommendAppsScreen::Result::kSelected:
ShowAppDownloadingScreen();
break;
case RecommendAppsScreen::Result::kSkipped:
case RecommendAppsScreen::Result::kNotApplicable:
case RecommendAppsScreen::Result::kLoadError:
ShowPerksDiscoveryScreen();
break;
}
}
void WizardController::OnRemoteActivityNotificationScreenExit() {
// Remember the user acknowledged the message.
GetLocalState()->SetBoolean(::prefs::kRemoteAdminWasPresent, false);
// Check if there are any local accounts present for the lock screen which
// suggest that the OOBE flow was completed and the dialog should be hidden.
if (LoginDisplayHost::default_host()->HasUserPods()) {
LoginDisplayHost::default_host()->HideOobeDialog();
return;
}
// When, there is no local accounts present and the OOBE flow must be
// continued. Hence, we go back to the previous screen present in the flow.
bool switched_screen = MaybeSetToPreviousScreen();
CHECK(switched_screen);
}
void WizardController::OnAppDownloadingScreenExit() {
OnScreenExit(AppDownloadingScreenView::kScreenId, kDefaultExitReason);
ShowPerksDiscoveryScreen();
}
void WizardController::OnAiIntroScreenExit(AiIntroScreen::Result result) {
OnScreenExit(AiIntroScreenView::kScreenId,
AiIntroScreen::GetResultString(result));
ShowGeminiIntroScreen();
}
void WizardController::OnGeminiIntroScreenExit(
GeminiIntroScreen::Result result) {
OnScreenExit(GeminiIntroScreenView::kScreenId,
GeminiIntroScreen::GetResultString(result));
if (result == GeminiIntroScreen::Result::kBack) {
CHECK(!AiIntroScreen::ShouldBeSkipped());
ShowAiIntroScreen();
return;
}
ShowAssistantOptInFlowScreen();
}
void WizardController::OnAssistantOptInFlowScreenExit(
AssistantOptInFlowScreen::Result result) {
OnScreenExit(AssistantOptInFlowScreenView::kScreenId,
AssistantOptInFlowScreen::GetResultString(result));
AdvanceToScreen(SmartPrivacyProtectionView::kScreenId);
}
void WizardController::OnMultiDeviceSetupScreenExit(
MultiDeviceSetupScreen::Result result) {
OnScreenExit(MultiDeviceSetupScreenView::kScreenId,
MultiDeviceSetupScreen::GetResultString(result));
ShowSplitModifierKeyboardInfoScreen();
}
void WizardController::OnGestureNavigationScreenExit(
GestureNavigationScreen::Result result) {
OnScreenExit(GestureNavigationScreenView::kScreenId,
GestureNavigationScreen::GetResultString(result));
if (features::IsOobeChoobeEnabled()) {
ShowChoobeScreen();
} else {
ShowThemeSelectionScreen();
}
}
void WizardController::OnMarketingOptInScreenExit(
MarketingOptInScreen::Result result) {
OnScreenExit(MarketingOptInScreenView::kScreenId,
MarketingOptInScreen::GetResultString(result));
OnOobeFlowFinished();
}
void WizardController::OnResetScreenExit() {
OnScreenExit(ResetView::kScreenId, kResetScreenExitReason);
OnDeviceModificationCanceled();
}
void WizardController::OnDeviceModificationCanceled() {
BaseScreen* previous_screen = nullptr;
if (base::Contains(previous_screens_, current_screen_)) {
previous_screen = previous_screens_[current_screen_];
}
ResetCurrentScreen();
if (previous_screen) {
if (IsSigninScreen(previous_screen->screen_id())) {
ShowLoginScreen();
} else {
SetCurrentScreen(previous_screen);
}
return;
}
// No previous screen found. Most likely the device is owned,
// in which case the login screen is the default.
if (ash::InstallAttributes::Get()->IsDeviceLocked()) {
ShowLoginScreen();
return;
}
LOG(WARNING) << "No previous screen on unowned device";
if (prescribed_enrollment_config_.should_enroll()) {
ShowPackagedLicenseScreen();
} else {
ShowLoginScreen();
}
}
void WizardController::OnManagementTransitionScreenExit() {
OnScreenExit(ManagementTransitionScreenView::kScreenId, kDefaultExitReason);
OnOobeFlowFinished();
}
void WizardController::OnUpdateRequiredScreenExit() {
ResetCurrentScreen();
ShowLoginScreen();
}
void WizardController::OnPackagedLicenseScreenExit(
PackagedLicenseScreen::Result result) {
OnScreenExit(PackagedLicenseView::kScreenId,
PackagedLicenseScreen::GetResultString(result));
switch (result) {
case PackagedLicenseScreen::Result::DONT_ENROLL:
case PackagedLicenseScreen::Result::NOT_APPLICABLE:
ShowLoginScreen();
break;
case PackagedLicenseScreen::Result::ENROLL:
case PackagedLicenseScreen::Result::NOT_APPLICABLE_SKIP_TO_ENROLL:
ShowEnrollmentScreen();
break;
}
}
void WizardController::OnAppLaunchSplashScreenExit() {
// TODO(b/343483938): Exit AppLaunchSplashScreen before launching the app.
NOTIMPLEMENTED();
}
void WizardController::OnOobeFlowFinished() {
if (GetLoginDisplayHost()
->GetWizardContext()
->defer_oobe_flow_finished_for_tests) {
return;
}
SetCurrentScreen(nullptr);
user_manager::KnownUser known_user(GetLocalState());
const AccountId account_id =
user_manager::UserManager::Get()->GetActiveUser()->GetAccountId();
known_user.SetOnboardingCompletedVersion(account_id,
version_info::GetVersion());
known_user.RemovePendingOnboardingScreen(account_id);
PrefService* active_user_prefs =
ProfileManager::GetActiveUserProfile()->GetPrefs();
if (features::IsOobeChoobeEnabled()) {
// Additional cleanup of CHOOBE prefs in case it was not already cleared.
active_user_prefs->ClearPref(prefs::kChoobeSelectedScreens);
active_user_prefs->ClearPref(prefs::kChoobeCompletedScreens);
}
GetLoginDisplayHost()->GetOobeMetricsHelper()->RecordOnboadingComplete(
GetLocalState()->GetTime(prefs::kOobeStartTime),
active_user_prefs->GetTime(prefs::kOobeOnboardingTime));
GetLocalState()->ClearPref(prefs::kOobeStartTime);
GetLocalState()->ClearPref(prefs::kOobeMetricsClientIdAtOobeStart);
GetLocalState()->ClearPref(prefs::kOobeMetricsReportedAsEnabled);
GetLocalState()->ClearPref(prefs::kOobeStatsReportingControllerReportedReset);
// Launch browser and delete login host controller.
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(
&UserSessionManager::DoBrowserLaunch,
UserSessionManager::GetInstance()->GetUserSessionManagerAsWeakPtr(),
ProfileManager::GetActiveUserProfile()));
}
void WizardController::OnDeviceDisabledChecked(bool device_disabled) {
prescribed_enrollment_config_ =
policy::EnrollmentConfig::GetPrescribedEnrollmentConfig();
if (device_disabled) {
demo_setup_controller_.reset();
ShowDeviceDisabledScreen();
} else if (demo_setup_controller_) {
ShowDemoModeSetupScreen();
} else if (wizard_context_->enrollment_triggered_early ||
prescribed_enrollment_config_.should_enroll()) {
VLOG(1) << "StartEnrollment from OnDeviceDisabledChecked("
<< "device_disabled=" << device_disabled << ") "
<< "skip_update_enroll_after_eula_="
<< wizard_context_->enrollment_triggered_early
<< ", prescribed_enrollment_config_.should_enroll()="
<< prescribed_enrollment_config_.should_enroll();
StartEnrollmentScreen();
} else {
PerformOOBECompletedActions(
OobeMetricsHelper::CompletedPreLoginOobeFlowType::kRegular);
ShowPackagedLicenseScreen();
}
}
void WizardController::InitiateOOBEUpdate() {
// If this is a Cellular First device, instruct UpdateEngine to allow
// updates over cellular data connections.
if (switches::IsCellularFirstDevice()) {
UpdateEngineClient::Get()->SetUpdateOverCellularPermission(
true, base::BindOnce(&WizardController::StartOOBEUpdate,
weak_factory_.GetWeakPtr()));
} else {
StartOOBEUpdate();
}
}
void WizardController::StartOOBEUpdate() {
SetCurrentScreen(GetScreen(UpdateView::kScreenId));
}
void WizardController::StartNetworkTimezoneResolve() {
// Bypass the network requests for the geolocation and the timezone if the
// timezone is being overridden through the command line.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kOobeTimezoneOverrideForTests)) {
auto timezone = std::make_unique<TimeZoneResponseData>();
timezone->status = TimeZoneResponseData::OK;
timezone->timeZoneId =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kOobeTimezoneOverrideForTests);
VLOG(1) << "Timezone is being overridden with : " << timezone->timeZoneId;
OnTimezoneResolved(std::move(timezone), /*server_error*/ false);
return;
}
DelayNetworkCall(base::BindOnce(&WizardController::StartTimezoneResolve,
weak_factory_.GetWeakPtr()));
}
// Resolving the timezone consists of first determining the location,
// and then determining the timezone.
void WizardController::StartTimezoneResolve() {
if (!g_browser_process->platform_part()
->GetTimezoneResolverManager()
->TimeZoneResolverShouldBeRunning()) {
return;
}
SimpleGeolocationProvider::GetInstance()->RequestGeolocation(
base::Seconds(kResolveTimeZoneTimeoutSeconds),
false /* send_wifi_geolocation_data */,
false /* send_cellular_geolocation_data */,
base::BindOnce(&WizardController::OnLocationResolved,
weak_factory_.GetWeakPtr()),
SimpleGeolocationProvider::ClientId::kWizardController);
}
void WizardController::PerformPostNetworkScreenActions() {
StartNetworkTimezoneResolve();
DelayNetworkCall(ServicesCustomizationDocument::GetInstance()
->EnsureCustomizationAppliedClosure());
GetAutoEnrollmentController()->Start();
}
void WizardController::PerformOOBECompletedActions(
OobeMetricsHelper::CompletedPreLoginOobeFlowType flow_type) {
// Avoid marking OOBE as completed multiple times if going from login screen
// to enrollment screen (and back).
if (StartupUtils::IsOobeCompleted()) {
return;
}
StartupUtils::MarkOobeCompleted();
GetLoginDisplayHost()->GetOobeMetricsHelper()->RecordPreLoginOobeComplete(
flow_type);
// Triggers DLC installation once OOBE is complete.
cros_healthd::internal::TriggerDlcInstall();
}
void WizardController::SetCurrentScreen(BaseScreen* new_current) {
VLOG(1) << "SetCurrentScreen: "
<< (new_current ? new_current->screen_id().name : "null");
if (new_current && new_current->MaybeSkip(*wizard_context_)) {
// choobe_flow_controller_ lives only while CHOOBE flow is active, metrics
// regarding screens shown while CHOOBE is active is handled by
// choobe_flow_controller_.
if (features::IsOobeChoobeEnabled()) {
if (ChoobeFlowController::IsOptionalScreen(new_current->screen_id()) &&
choobe_flow_controller_) {
return;
}
}
GetLoginDisplayHost()->GetOobeMetricsHelper()->RecordScreenShownStatus(
new_current->screen_id(),
OobeMetricsHelper::ScreenShownStatus::kSkipped);
return;
}
if (current_screen_ == new_current || GetOobeUI() == nullptr) {
return;
}
// Check if we didn't come here via the previous screen logic.
if (current_screen_ && new_current &&
(!base::Contains(previous_screens_, current_screen_) ||
previous_screens_[current_screen_] != new_current)) {
previous_screens_[new_current] = current_screen_;
}
ResetCurrentScreen();
current_screen_ = new_current;
if (!current_screen_) {
NotifyScreenChanged();
return;
}
// WizardController should not save the pending screen during demo mode, nor
// should it save it while exercising the recovery path.
const bool isEligibleForSavingPendingScreen =
!demo_setup_controller_ &&
wizard_context_->knowledge_factor_setup.auth_setup_flow !=
WizardContext::AuthChangeFlow::kRecovery;
// First remember how far have we reached so that we can resume if needed.
if (isEligibleForSavingPendingScreen) {
if (!wizard_context_->is_add_person_flow &&
IsResumableOobeScreen(current_screen_->screen_id())) {
StartupUtils::SaveOobePendingScreen(current_screen_->screen_id().name);
} else if (IsResumablePostLoginScreen(current_screen_->screen_id()) &&
!wizard_context_->is_cloud_ready_update_flow &&
wizard_context_->screen_after_managed_tos !=
ash::OOBE_SCREEN_UNKNOWN) {
// If screen_after_managed_tos == SCREEN_UNKNOWN means that the
// onboarding has already been finished by the user and we don't need to
// save the state here.
user_manager::KnownUser(GetLocalState())
.SetPendingOnboardingScreen(
user_manager::UserManager::Get()->GetActiveUser()->GetAccountId(),
current_screen_->screen_id().name);
}
}
UpdateStatusAreaVisibilityForScreen(current_screen_->screen_id());
GetLoginDisplayHost()->GetOobeMetricsHelper()->RecordScreenShownStatus(
current_screen_->screen_id(),
OobeMetricsHelper::ScreenShownStatus::kShown);
current_screen_->Show(wizard_context_);
NotifyScreenChanged();
}
void WizardController::UpdateStatusAreaVisibilityForScreen(
OobeScreenId screen_id) {
// SystemTrayClientImpl::Get() can be nullptr in unit tests.
if (SystemTrayClientImpl::Get()) {
SystemTrayClientImpl::Get()->SetPrimaryTrayVisible(
!ShouldHideStatusArea(screen_id));
}
}
void WizardController::OnHIDScreenNecessityCheck(bool screen_needed) {
if (!GetOobeUI()) {
return;
}
// Check for tests configurations.
if (wizard_context_->skip_to_update_for_tests ||
wizard_context_->skip_to_login_for_tests || current_screen_) {
return;
}
if (screen_needed) {
ShowHIDDetectionScreen();
} else {
AdvanceToScreenAfterHIDDetection(ash::OOBE_SCREEN_UNKNOWN);
}
}
void WizardController::UpdateOobeConfiguration() {
wizard_context_->configuration = configuration::FilterConfiguration(
OobeConfiguration::Get()->configuration(),
configuration::ConfigurationHandlerSide::HANDLER_CPP);
auto* requisition_value = wizard_context_->configuration.FindString(
configuration::kDeviceRequisition);
if (requisition_value) {
VLOG(1) << "Using Device Requisition from configuration"
<< *requisition_value;
policy::EnrollmentRequisitionManager::SetDeviceRequisition(
*requisition_value);
} else if (policy::EnrollmentRequisitionManager::IsCuttlefishDevice()) {
VLOG(1) << "Using default Device Requisition value for Cuttlefish build "
"configuration"
<< policy::EnrollmentRequisitionManager::kCuttlefishRequisition;
policy::EnrollmentRequisitionManager::SetDeviceRequisition(
policy::EnrollmentRequisitionManager::kCuttlefishRequisition);
} else if (policy::EnrollmentRequisitionManager::IsMeetDevice()) {
VLOG(1) << "Using default Device Requisition value for CFM build "
"configuration"
<< policy::EnrollmentRequisitionManager::kRemoraRequisition;
policy::EnrollmentRequisitionManager::SetDeviceRequisition(
policy::EnrollmentRequisitionManager::kRemoraRequisition);
}
auto* network_config =
wizard_context_->configuration.FindString(configuration::kNetworkConfig);
if (network_config) {
auto rollback_network_config = std::make_unique<
mojo::Remote<rollback_network_config::mojom::RollbackNetworkConfig>>();
rollback_network_config::BindToInProcessInstance(
rollback_network_config->BindNewPipeAndPassReceiver());
rollback_network_config->get()->RollbackConfigImport(*network_config,
base::DoNothing());
}
}
bool WizardController::CanNavigateTo(OobeScreenId screen_id) {
if (!current_screen_) {
return true;
}
if (wizard_context_->skip_to_login_for_tests) {
VLOG(1) << "CanNavigateTo to screen " << screen_id
<< " returns true because skip_to_login_for_tests is set to true";
return true;
}
BaseScreen* next_screen = GetScreen(screen_id);
return next_screen->screen_priority() <= current_screen_->screen_priority();
}
void WizardController::AdvanceToScreen(OobeScreenId screen_id) {
VLOG(1) << "AdvanceToScreen " << screen_id;
if (!CanNavigateTo(screen_id)) {
LOG(WARNING) << "Cannot advance to screen : " << screen_id
<< " as it's priority is less than the current screen : "
<< current_screen_->screen_id();
return;
}
if (screen_id == WelcomeView::kScreenId) {
ShowWelcomeScreen();
} else if (screen_id == NetworkScreenView::kScreenId) {
ShowNetworkScreen();
} else if (screen_id == PackagedLicenseView::kScreenId) {
ShowPackagedLicenseScreen();
} else if (screen_id == UpdateView::kScreenId) {
InitiateOOBEUpdate();
} else if (screen_id == ResetView::kScreenId) {
ShowResetScreen();
} else if (screen_id == EnableAdbSideloadingScreenView::kScreenId) {
ShowEnableAdbSideloadingScreen();
} else if (screen_id == EnableDebuggingScreenView::kScreenId) {
ShowEnableDebuggingScreen();
} else if (screen_id == EnrollmentScreenView::kScreenId) {
ShowEnrollmentScreen();
} else if (screen_id == DemoSetupScreenView::kScreenId) {
ShowDemoModeSetupScreen();
} else if (screen_id == DemoPreferencesScreenView::kScreenId) {
ShowDemoModePreferencesScreen();
} else if (screen_id == TermsOfServiceScreenView::kScreenId) {
ShowTermsOfServiceScreen();
} else if (screen_id == SyncConsentScreenView::kScreenId) {
ShowSyncConsentScreen();
} else if (screen_id == RecommendAppsScreenView::kScreenId) {
ShowRecommendAppsScreen();
} else if (screen_id == RemoteActivityNotificationView::kScreenId) {
ShowRemoteActivityNotificationScreen();
} else if (screen_id == AppDownloadingScreenView::kScreenId) {
ShowAppDownloadingScreen();
} else if (screen_id == AiIntroScreenView::kScreenId) {
ShowAiIntroScreen();
} else if (screen_id == GeminiIntroScreenView::kScreenId) {
ShowGeminiIntroScreen();
} else if (screen_id == WrongHWIDScreenView::kScreenId) {
ShowWrongHWIDScreen();
} else if (screen_id == AutoEnrollmentCheckScreenView::kScreenId) {
ShowAutoEnrollmentCheckScreen();
} else if (screen_id == AppLaunchSplashScreenView::kScreenId) {
ShowAppLaunchSplashScreen();
} else if (screen_id == HIDDetectionView::kScreenId) {
ShowHIDDetectionScreen();
} else if (screen_id == DeviceDisabledScreenView::kScreenId) {
ShowDeviceDisabledScreen();
} else if (screen_id == EncryptionMigrationScreenView::kScreenId) {
ShowEncryptionMigrationScreen();
} else if (screen_id == UpdateRequiredView::kScreenId) {
ShowUpdateRequiredScreen();
} else if (screen_id == AssistantOptInFlowScreenView::kScreenId) {
ShowAssistantOptInFlowScreen();
} else if (screen_id == MultiDeviceSetupScreenView::kScreenId) {
ShowMultiDeviceSetupScreen();
} else if (screen_id == GestureNavigationScreenView::kScreenId) {
ShowGestureNavigationScreen();
} else if (screen_id == PinSetupScreenView::kScreenId) {
ShowPinSetupScreenAsSecondaryFactor();
} else if (screen_id == FingerprintSetupScreenView::kScreenId) {
ShowFingerprintSetupScreen();
} else if (screen_id == MarketingOptInScreenView::kScreenId) {
ShowMarketingOptInScreen();
} else if (screen_id == ManagementTransitionScreenView::kScreenId) {
ShowManagementTransitionScreen();
} else if (screen_id == GuestTosScreenView::kScreenId) {
ShowGuestTosScreen();
} else if (screen_id == ConsolidatedConsentScreenView::kScreenId) {
ShowConsolidatedConsentScreen();
} else if (screen_id == CryptohomeRecoverySetupScreenView::kScreenId) {
ShowCryptohomeRecoverySetupScreen();
} else if (screen_id == ArcVmDataMigrationScreenView::kScreenId) {
ShowArcVmDataMigrationScreen();
} else if (screen_id == TouchpadScrollScreenView::kScreenId) {
ShowTouchpadScrollScreen();
} else if (screen_id == GaiaInfoScreenView::kScreenId) {
ShowGaiaInfoScreen();
} else if (screen_id == DrivePinningScreenView::kScreenId) {
ShowDrivePinningScreen();
} else if (screen_id == DisplaySizeScreenView::kScreenId) {
ShowDisplaySizeScreen();
} else if (screen_id == ChoobeScreenView::kScreenId) {
ShowChoobeScreen();
} else if (screen_id == AddChildScreenView::kScreenId) {
ShowAddChildScreen();
} else if (screen_id == ConsumerUpdateScreenView::kScreenId) {
ShowConsumerUpdateScreen();
} else if (screen_id == PasswordSelectionScreenView::kScreenId) {
ShowPasswordSelectionScreen();
} else if (screen_id == ApplyOnlinePasswordScreenView::kScreenId) {
ShowApplyOnlinePasswordScreen();
} else if (screen_id == OSAuthErrorScreenView::kScreenId) {
ShowOSAuthErrorScreen();
} else if (screen_id == FactorSetupSuccessScreenView::kScreenId) {
ShowFactorSetupSuccessScreen();
} else if (screen_id == LocalPasswordSetupView::kScreenId) {
ShowLocalPasswordSetupScreen();
} else if (screen_id == CategoriesSelectionScreenView::kScreenId) {
ShowCategoriesSelectionScreen();
} else if (screen_id == PersonalizedRecommendAppsScreenView::kScreenId) {
ShowPersonalizedRecomendAppsScreen();
} else if (screen_id == PerksDiscoveryScreenView::kScreenId) {
ShowPerksDiscoveryScreen();
} else if (screen_id == SplitModifierKeyboardInfoScreenView::kScreenId) {
ShowSplitModifierKeyboardInfoScreen();
} else if (screen_id == TpmErrorView::kScreenId ||
screen_id == InstallAttributesErrorView::kScreenId ||
screen_id == FamilyLinkNoticeView::kScreenId ||
screen_id == GaiaView::kScreenId ||
screen_id == UserCreationView::kScreenId ||
screen_id == SignInFatalErrorView::kScreenId ||
screen_id == UserAllowlistCheckScreenView::kScreenId ||
screen_id == LocaleSwitchView::kScreenId ||
screen_id == RecoveryEligibilityView::kScreenId ||
screen_id == OfflineLoginView::kScreenId ||
screen_id == OsInstallScreenView::kScreenId ||
screen_id == OsTrialScreenView::kScreenId ||
screen_id == ParentalHandoffScreenView::kScreenId ||
screen_id == HWDataCollectionView::kScreenId ||
screen_id == SmartPrivacyProtectionView::kScreenId ||
screen_id == ThemeSelectionScreenView::kScreenId ||
screen_id == SamlConfirmPasswordView::kScreenId ||
screen_id == LocalStateErrorScreenView::kScreenId ||
screen_id == QuickStartView::kScreenId) {
SetCurrentScreen(GetScreen(screen_id));
} else {
NOTREACHED();
}
}
bool WizardController::HandleAccelerator(LoginAcceleratorAction action) {
return current_screen_ && current_screen_->HandleAccelerator(action);
}
void WizardController::StartDemoModeSetup() {
// Start Demo Mode by initiate demo set up controller and showing the first
// network screen in demo mode setup flow.
demo_setup_controller_ = std::make_unique<DemoSetupController>();
ShowNetworkScreen();
}
void WizardController::CreateChoobeFlowController() {
choobe_flow_controller_ = std::make_unique<ChoobeFlowController>();
}
void WizardController::SimulateDemoModeSetupForTesting(
std::optional<DemoSession::DemoModeConfig> demo_config) {
if (!demo_setup_controller_) {
demo_setup_controller_ = std::make_unique<DemoSetupController>();
}
if (demo_config.has_value()) {
demo_setup_controller_->set_demo_config(*demo_config);
}
}
void WizardController::OnAccessibilityStatusChanged(
const AccessibilityStatusEventDetails& details) {
enum AccessibilityNotificationType type = details.notification_type;
if (type == AccessibilityNotificationType::kManagerShutdown) {
accessibility_subscription_ = {};
return;
} else if (type != AccessibilityNotificationType::kToggleSpokenFeedback ||
!details.enabled) {
return;
}
CrasAudioHandler* cras = CrasAudioHandler::Get();
if (cras->IsOutputMuted()) {
cras->SetOutputMute(false);
cras->SetOutputVolumePercent(kMinAudibleOutputVolumePercent);
} else if (cras->GetOutputVolumePercent() < kMinAudibleOutputVolumePercent) {
cras->SetOutputVolumePercent(kMinAudibleOutputVolumePercent);
}
}
void WizardController::AutoLaunchKioskApp(const KioskApp& app) {
// Wait until `CrosSettings` is either trusted or permanently untrusted.
const CrosSettingsProvider::TrustedStatus status =
CrosSettings::Get()->PrepareTrustedValues(
base::BindOnce(&WizardController::AutoLaunchKioskApp,
weak_factory_.GetWeakPtr(), app));
if (status == CrosSettingsProvider::TEMPORARILY_UNTRUSTED) {
return;
}
if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
// If the `cros_settings_` are permanently untrusted, show an error
// message and refuse to auto-launch the kiosk app.
AdvanceToScreen(LocalStateErrorScreenView::kScreenId);
return;
}
if (system::DeviceDisablingManager::IsDeviceDisabledDuringNormalOperation()) {
// If the device is disabled, bail out. A device disabled screen will be
// shown by the DeviceDisablingManager.
return;
}
constexpr bool auto_launch = true;
GetLoginDisplayHost()->StartKiosk(app.id(), auto_launch);
}
// static
void WizardController::SetZeroDelays() {
g_using_zero_delays = true;
}
// static
bool WizardController::IsZeroDelayEnabled() {
return g_using_zero_delays;
}
void WizardController::SkipPostLoginScreensForTesting() {
wizard_context_->skip_post_login_screens_for_tests = true;
auto* current_screen = default_controller()->current_screen();
if (current_screen && !current_screen->MaybeSkip(*wizard_context_)) {
LOG(WARNING) << __func__ << ": Ignore screen "
<< current_screen->screen_id().name;
}
}
// statis
bool WizardController::IsResumablePostLoginScreen(OobeScreenId screen_id) {
for (const auto& resumable_screen : kResumablePostLoginScreens) {
if (screen_id == resumable_screen) {
return true;
}
}
return false;
}
// static
void WizardController::SkipEnrollmentPromptsForTesting() {
skip_enrollment_prompts_for_testing_ = true;
}
// static
bool WizardController::IsSigninScreen(OobeScreenId screen_id) {
return screen_id == UserCreationView::kScreenId ||
screen_id == GaiaView::kScreenId ||
screen_id == SignInFatalErrorView::kScreenId;
}
void WizardController::AddObserver(ScreenObserver* obs) {
screen_observers_.AddObserver(obs);
}
void WizardController::RemoveObserver(ScreenObserver* obs) {
screen_observers_.RemoveObserver(obs);
}
void WizardController::OnLocalStateInitialized(bool /* succeeded */) {
if (GetLocalState()->GetInitializationStatus() !=
PrefService::INITIALIZATION_STATUS_ERROR) {
return;
}
AdvanceToScreen(LocalStateErrorScreenView::kScreenId);
}
void WizardController::PrepareFirstRunPrefs() {
// Showoff starts in parallel to OOBE onboarding. We need to store the prefs
// early to make sure showoff has the correct data when launched.
Profile* profile = ProfileManager::GetActiveUserProfile();
bool shouldShowParentalControl =
wizard_context_->sign_in_as_child && !profile->IsChild() &&
!profile->GetProfilePolicyConnector()->IsManaged();
profile->GetPrefs()->SetBoolean(::prefs::kHelpAppShouldShowParentalControl,
shouldShowParentalControl);
}
PrefService* WizardController::GetLocalState() {
if (local_state_for_testing_) {
return local_state_for_testing_;
}
return g_browser_process->local_state();
}
void WizardController::OnTimezoneResolved(
std::unique_ptr<TimeZoneResponseData> timezone,
bool server_error) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(timezone);
timezone_resolved_ = true;
base::ScopedClosureRunner inform_test(
std::move(on_timezone_resolved_for_testing_));
VLOG(1) << "Resolved local timezone={" << timezone->ToStringForDebug()
<< "}.";
if (timezone->status != TimeZoneResponseData::OK) {
LOG(WARNING) << "Resolve TimeZone: failed to resolve timezone.";
return;
}
if (ash::InstallAttributes::Get()->IsEnterpriseManaged()) {
std::string policy_timezone;
if (CrosSettings::Get()->GetString(kSystemTimezonePolicy,
&policy_timezone) &&
!policy_timezone.empty()) {
VLOG(1) << "Resolve TimeZone: TimeZone settings are overridden"
<< " by DevicePolicy.";
return;
}
}
if (!timezone->timeZoneId.empty()) {
VLOG(1) << "Resolve TimeZone: setting timezone to '" << timezone->timeZoneId
<< "'";
system::SetSystemAndSigninScreenTimezone(timezone->timeZoneId);
}
}
TimeZoneProvider* WizardController::GetTimezoneProvider() {
if (!timezone_provider_) {
timezone_provider_ = std::make_unique<TimeZoneProvider>(
shared_url_loader_factory_, DefaultTimezoneProviderURL());
}
return timezone_provider_.get();
}
void WizardController::OnLocationResolved(const Geoposition& position,
bool server_error,
const base::TimeDelta elapsed) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
const base::TimeDelta timeout = base::Seconds(kResolveTimeZoneTimeoutSeconds);
// Ignore invalid position.
if (!position.Valid()) {
return;
}
if (elapsed >= timeout) {
LOG(WARNING) << "Resolve TimeZone: got location after timeout ("
<< elapsed.InSecondsF() << " seconds elapsed). Ignored.";
return;
}
if (!g_browser_process->platform_part()
->GetTimezoneResolverManager()
->TimeZoneResolverShouldBeRunning()) {
return;
}
// WizardController owns TimezoneProvider, so timezone request is silently
// cancelled on destruction.
GetTimezoneProvider()->RequestTimezone(
position, timeout - elapsed,
base::BindOnce(&WizardController::OnTimezoneResolved,
weak_factory_.GetWeakPtr()));
}
bool WizardController::SetOnTimeZoneResolvedForTesting(
base::OnceClosure callback) {
if (timezone_resolved_) {
return false;
}
on_timezone_resolved_for_testing_ = std::move(callback);
return true;
}
void WizardController::StartEnrollmentScreen() {
VLOG(1) << "Showing enrollment screen.";
// Determine the effective enrollment configuration. If OOBE Configuration
// exits, it might also affect enrollment configuration.
policy::EnrollmentConfig effective_config =
prescribed_enrollment_config_.GetEffectiveConfig();
effective_config.enrollment_nudge_email =
GetScreen<GaiaScreen>()->EnrollmentNudgeEmail();
EnrollmentScreen* screen = EnrollmentScreen::Get(screen_manager());
screen->SetEnrollmentConfig(std::move(effective_config));
UpdateStatusAreaVisibilityForScreen(EnrollmentScreenView::kScreenId);
SetCurrentScreen(screen);
}
void WizardController::ShowEnrollmentScreenIfEligible() {
const bool enterprise_managed =
ash::InstallAttributes::Get()->IsEnterpriseManaged();
const bool has_users = !user_manager::UserManager::Get()->GetUsers().empty();
if (!has_users && !enterprise_managed) {
AdvanceToScreen(EnrollmentScreenView::kScreenId);
}
}
bool WizardController::MaybeSetToPreviousScreen() {
DCHECK(current_screen_);
if (!base::Contains(previous_screens_, current_screen_)) {
return false;
}
auto* old_current_screen = current_screen_.get();
auto* previous_screen = previous_screens_[current_screen_].get();
if (previous_screen->screen_id() == GaiaView::kScreenId) {
wizard_context_->gaia_config.gaia_path =
wizard_context_->gaia_config.last_gaia_path_shown;
}
SetCurrentScreen(previous_screen);
return old_current_screen != current_screen_;
}
void WizardController::NotifyScreenChanged() {
for (ScreenObserver& obs : screen_observers_) {
obs.OnCurrentScreenChanged(current_screen_);
}
}
policy::AutoEnrollmentController*
WizardController::GetAutoEnrollmentController() {
if (!auto_enrollment_controller_) {
auto_enrollment_controller_ =
std::make_unique<policy::AutoEnrollmentController>(
shared_url_loader_factory_);
}
return auto_enrollment_controller_.get();
}
void WizardController::MaybeTakeTPMOwnership() {
if (wizard_context_->is_branded_build || switches::IsTpmDynamic()) {
return;
}
chromeos::TpmManagerClient::Get()->TakeOwnership(
::tpm_manager::TakeOwnershipRequest(), base::DoNothing());
}
void WizardController::ResetCurrentScreen() {
if (current_screen_) {
current_screen_->Hide();
current_screen_ = nullptr;
}
}
void WizardController::MaybeAbortQuickStartFlow(
quick_start::QuickStartController::AbortFlowReason reason) {
if (wizard_context_->quick_start_setup_ongoing) {
quickstart_controller_->AbortFlow(reason);
}
}
} // namespace ash