| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/chromeos/login/wizard_controller.h" |
| |
| #include <signal.h> |
| #include <stddef.h> |
| #include <stdlib.h> |
| #include <sys/types.h> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/bind.h" |
| #include "base/callback_helpers.h" |
| #include "base/command_line.h" |
| #include "base/json/json_string_value_serializer.h" |
| #include "base/location.h" |
| #include "base/logging.h" |
| #include "base/macros.h" |
| #include "base/metrics/histogram_macros.h" |
| #include "base/single_thread_task_runner.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/task_scheduler/post_task.h" |
| #include "base/threading/sequenced_worker_pool.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/browser_process_platform_part.h" |
| #include "chrome/browser/chrome_notification_types.h" |
| #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" |
| #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" |
| #include "chrome/browser/chromeos/arc/arc_util.h" |
| #include "chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.h" |
| #include "chrome/browser/chromeos/customization/customization_document.h" |
| #include "chrome/browser/chromeos/device/input_service_proxy.h" |
| #include "chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.h" |
| #include "chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h" |
| #include "chrome/browser/chromeos/login/enrollment/enrollment_screen.h" |
| #include "chrome/browser/chromeos/login/existing_user_controller.h" |
| #include "chrome/browser/chromeos/login/helper.h" |
| #include "chrome/browser/chromeos/login/hwid_checker.h" |
| #include "chrome/browser/chromeos/login/screens/arc_terms_of_service_screen.h" |
| #include "chrome/browser/chromeos/login/screens/device_disabled_screen.h" |
| #include "chrome/browser/chromeos/login/screens/enable_debugging_screen.h" |
| #include "chrome/browser/chromeos/login/screens/encryption_migration_screen.h" |
| #include "chrome/browser/chromeos/login/screens/error_screen.h" |
| #include "chrome/browser/chromeos/login/screens/eula_screen.h" |
| #include "chrome/browser/chromeos/login/screens/hid_detection_view.h" |
| #include "chrome/browser/chromeos/login/screens/kiosk_autolaunch_screen.h" |
| #include "chrome/browser/chromeos/login/screens/kiosk_enable_screen.h" |
| #include "chrome/browser/chromeos/login/screens/network_error.h" |
| #include "chrome/browser/chromeos/login/screens/network_view.h" |
| #include "chrome/browser/chromeos/login/screens/reset_screen.h" |
| #include "chrome/browser/chromeos/login/screens/terms_of_service_screen.h" |
| #include "chrome/browser/chromeos/login/screens/update_screen.h" |
| #include "chrome/browser/chromeos/login/screens/user_image_screen.h" |
| #include "chrome/browser/chromeos/login/screens/voice_interaction_value_prop_screen.h" |
| #include "chrome/browser/chromeos/login/screens/wait_for_container_ready_screen.h" |
| #include "chrome/browser/chromeos/login/screens/wrong_hwid_screen.h" |
| #include "chrome/browser/chromeos/login/session/user_session_manager.h" |
| #include "chrome/browser/chromeos/login/startup_utils.h" |
| #include "chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.h" |
| #include "chrome/browser/chromeos/login/ui/login_display_host.h" |
| #include "chrome/browser/chromeos/net/delay_network_call.h" |
| #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" |
| #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h" |
| #include "chrome/browser/chromeos/settings/cros_settings.h" |
| #include "chrome/browser/chromeos/system/device_disabling_manager.h" |
| #include "chrome/browser/chromeos/system/timezone_resolver_manager.h" |
| #include "chrome/browser/chromeos/system/timezone_util.h" |
| #include "chrome/browser/lifetime/application_lifetime.h" |
| #include "chrome/browser/metrics/metrics_reporting_state.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/profiles/profile_manager.h" |
| #include "chrome/browser/ui/ash/ash_util.h" |
| #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" |
| #include "chrome/browser/ui/webui/chromeos/login/signin_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/audio/cras_audio_handler.h" |
| #include "chromeos/chromeos_constants.h" |
| #include "chromeos/chromeos_switches.h" |
| #include "chromeos/dbus/dbus_thread_manager.h" |
| #include "chromeos/dbus/session_manager_client.h" |
| #include "chromeos/geolocation/simple_geolocation_provider.h" |
| #include "chromeos/network/network_state.h" |
| #include "chromeos/network/network_state_handler.h" |
| #include "chromeos/network/portal_detector/network_portal_detector.h" |
| #include "chromeos/settings/cros_settings_names.h" |
| #include "chromeos/settings/cros_settings_provider.h" |
| #include "chromeos/settings/timezone_settings.h" |
| #include "chromeos/timezone/timezone_provider.h" |
| #include "components/arc/arc_bridge_service.h" |
| #include "components/arc/arc_prefs.h" |
| #include "components/crash/content/app/breakpad_linux.h" |
| #include "components/pairing/bluetooth_controller_pairing_controller.h" |
| #include "components/pairing/bluetooth_host_pairing_controller.h" |
| #include "components/pairing/shark_connection_listener.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/user_manager.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/notification_types.h" |
| #include "third_party/cros_system_api/dbus/service_constants.h" |
| #include "ui/base/accelerators/accelerator.h" |
| |
| using content::BrowserThread; |
| |
| namespace { |
| // Interval in ms which is used for smooth screen showing. |
| static int kShowDelayMs = 400; |
| |
| // Total timezone resolving process timeout. |
| const unsigned int kResolveTimeZoneTimeoutSeconds = 60; |
| |
| // Stores the list of all screens that should be shown when resuming OOBE. |
| const chromeos::OobeScreen kResumableScreens[] = { |
| chromeos::OobeScreen::SCREEN_OOBE_NETWORK, |
| chromeos::OobeScreen::SCREEN_OOBE_UPDATE, |
| chromeos::OobeScreen::SCREEN_OOBE_EULA, |
| chromeos::OobeScreen::SCREEN_OOBE_ENROLLMENT, |
| chromeos::OobeScreen::SCREEN_TERMS_OF_SERVICE, |
| chromeos::OobeScreen::SCREEN_ARC_TERMS_OF_SERVICE, |
| chromeos::OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK}; |
| |
| // Checks flag for HID-detection screen show. |
| bool CanShowHIDDetectionScreen() { |
| return !base::CommandLine::ForCurrentProcess()->HasSwitch( |
| chromeos::switches::kDisableHIDDetectionOnOOBE); |
| } |
| |
| bool IsResumableScreen(chromeos::OobeScreen screen) { |
| for (size_t i = 0; i < arraysize(kResumableScreens); ++i) { |
| if (screen == kResumableScreens[i]) |
| return true; |
| } |
| return false; |
| } |
| |
| struct Entry { |
| chromeos::OobeScreen screen; |
| const char* uma_name; |
| }; |
| |
| // Some screens had multiple different names in the past (they have since been |
| // unified). We need to always use the same name for UMA stats, though. |
| constexpr const Entry kLegacyUmaOobeScreenNames[] = { |
| {chromeos::OobeScreen::SCREEN_ARC_TERMS_OF_SERVICE, "arc_tos"}, |
| {chromeos::OobeScreen::SCREEN_OOBE_ENROLLMENT, "enroll"}, |
| {chromeos::OobeScreen::SCREEN_OOBE_NETWORK, "network"}, |
| {chromeos::OobeScreen::SCREEN_CREATE_SUPERVISED_USER_FLOW, |
| "supervised-user-creation-flow"}, |
| {chromeos::OobeScreen::SCREEN_TERMS_OF_SERVICE, "tos"}, |
| {chromeos::OobeScreen::SCREEN_USER_IMAGE_PICKER, "image"}}; |
| |
| void RecordUMAHistogramForOOBEStepCompletionTime(chromeos::OobeScreen screen, |
| base::TimeDelta step_time) { |
| // Fetch screen name; make sure to use initial UMA name if the name has |
| // changed. |
| std::string screen_name = chromeos::GetOobeScreenName(screen); |
| for (const auto& entry : kLegacyUmaOobeScreenNames) { |
| if (entry.screen == screen) { |
| screen_name = entry.uma_name; |
| break; |
| } |
| } |
| |
| screen_name[0] = std::toupper(screen_name[0]); |
| std::string histogram_name = "OOBE.StepCompletionTime." + screen_name; |
| // Equivalent to using UMA_HISTOGRAM_MEDIUM_TIMES. UMA_HISTOGRAM_MEDIUM_TIMES |
| // can not be used here, because |histogram_name| is calculated dynamically |
| // and changes from call to call. |
| base::HistogramBase* histogram = base::Histogram::FactoryTimeGet( |
| histogram_name, |
| base::TimeDelta::FromMilliseconds(10), |
| base::TimeDelta::FromMinutes(3), |
| 50, |
| base::HistogramBase::kUmaTargetedHistogramFlag); |
| histogram->AddTime(step_time); |
| } |
| |
| bool IsRemoraRequisition() { |
| policy::DeviceCloudPolicyManagerChromeOS* policy_manager = |
| g_browser_process->platform_part() |
| ->browser_policy_connector_chromeos() |
| ->GetDeviceCloudPolicyManager(); |
| return policy_manager && policy_manager->IsRemoraRequisition(); |
| } |
| |
| bool IsSharkRequisition() { |
| policy::DeviceCloudPolicyManagerChromeOS* policy_manager = |
| g_browser_process->platform_part() |
| ->browser_policy_connector_chromeos() |
| ->GetDeviceCloudPolicyManager(); |
| return policy_manager && policy_manager->IsSharkRequisition(); |
| } |
| |
| // Checks if a controller device ("Master") is detected during the bootstrapping |
| // or shark/remora setup process. |
| bool IsControllerDetected() { |
| return g_browser_process->local_state()->GetBoolean( |
| prefs::kOobeControllerDetected); |
| } |
| |
| void SetControllerDetectedPref(bool value) { |
| PrefService* prefs = g_browser_process->local_state(); |
| prefs->SetBoolean(prefs::kOobeControllerDetected, value); |
| prefs->CommitPendingWrite(); |
| } |
| |
| // Checks if the device is a "slave" device in the bootstrapping process. |
| bool IsBootstrappingSlave() { |
| return g_browser_process->local_state()->GetBoolean( |
| prefs::kIsBootstrappingSlave); |
| } |
| |
| // Checks if the device is a "Master" device in the bootstrapping process. |
| bool IsBootstrappingMaster() { |
| return base::CommandLine::ForCurrentProcess()->HasSwitch( |
| chromeos::switches::kOobeBootstrappingMaster); |
| } |
| |
| bool NetworkAllowUpdate(const chromeos::NetworkState* network) { |
| if (!network || !network->IsConnectedState()) |
| return false; |
| if (network->type() == shill::kTypeBluetooth || |
| (network->type() == shill::kTypeCellular && |
| !help_utils_chromeos::IsUpdateOverCellularAllowed( |
| false /* interactive */))) { |
| return false; |
| } |
| return true; |
| } |
| |
| } // namespace |
| |
| namespace chromeos { |
| |
| // static |
| const int WizardController::kMinAudibleOutputVolumePercent = 10; |
| |
| // Initialize default controller. |
| // static |
| WizardController* WizardController::default_controller_ = nullptr; |
| |
| // static |
| bool WizardController::skip_post_login_screens_ = false; |
| |
| // static |
| bool WizardController::zero_delay_enabled_ = false; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // WizardController, public: |
| |
| PrefService* WizardController::local_state_for_testing_ = nullptr; |
| |
| WizardController::WizardController(LoginDisplayHost* host, OobeUI* oobe_ui) |
| : host_(host), oobe_ui_(oobe_ui), weak_factory_(this) { |
| DCHECK(default_controller_ == nullptr); |
| default_controller_ = this; |
| screen_manager_ = base::MakeUnique<ScreenManager>(this); |
| // In session OOBE was initiated from voice interaction keyboard shortcuts. |
| is_in_session_oobe_ = |
| session_manager::SessionManager::Get()->IsSessionStarted(); |
| if (!ash_util::IsRunningInMash()) { |
| AccessibilityManager* accessibility_manager = AccessibilityManager::Get(); |
| CHECK(accessibility_manager); |
| accessibility_subscription_ = accessibility_manager->RegisterCallback( |
| base::Bind(&WizardController::OnAccessibilityStatusChanged, |
| base::Unretained(this))); |
| } else { |
| NOTIMPLEMENTED(); |
| } |
| } |
| |
| WizardController::~WizardController() { |
| screen_manager_.reset(); |
| // |remora_controller| has to be reset after |screen_manager_| is reset. |
| remora_controller_.reset(); |
| if (shark_connection_listener_.get()) { |
| base::ThreadTaskRunnerHandle::Get()->DeleteSoon( |
| FROM_HERE, shark_connection_listener_.release()); |
| } |
| if (default_controller_ == this) { |
| default_controller_ = nullptr; |
| } else { |
| NOTREACHED() << "More than one controller are alive."; |
| } |
| } |
| |
| void WizardController::Init(OobeScreen first_screen) { |
| VLOG(1) << "Starting OOBE wizard with screen: " |
| << GetOobeScreenName(first_screen); |
| first_screen_ = first_screen; |
| |
| bool oobe_complete = StartupUtils::IsOobeCompleted(); |
| if (!oobe_complete || first_screen == OobeScreen::SCREEN_SPECIAL_OOBE) |
| is_out_of_box_ = true; |
| |
| // 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. 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 asynchronious loading. |
| policy::BrowserPolicyConnectorChromeOS* connector = |
| g_browser_process->platform_part()->browser_policy_connector_chromeos(); |
| if (!connector->IsEnterpriseManaged()) { |
| const PrefService::PrefInitializationStatus status = |
| GetLocalState()->GetInitializationStatus(); |
| if (status == PrefService::INITIALIZATION_STATUS_ERROR) { |
| OnLocalStateInitialized(false); |
| return; |
| } else if (status == PrefService::INITIALIZATION_STATUS_WAITING) { |
| GetLocalState()->AddPrefInitObserver( |
| base::Bind(&WizardController::OnLocalStateInitialized, |
| weak_factory_.GetWeakPtr())); |
| } |
| } |
| |
| // If the device is a Master device in bootstrapping process (mostly for demo |
| // and test purpose), start the enrollment OOBE flow. |
| if (IsBootstrappingMaster()) |
| connector->GetDeviceCloudPolicyManager()->SetDeviceEnrollmentAutoStart(); |
| |
| // Use the saved screen preference from Local State. |
| const std::string screen_pref = |
| GetLocalState()->GetString(prefs::kOobeScreenPending); |
| if (is_out_of_box_ && !screen_pref.empty() && !IsRemoraPairingOobe() && |
| !IsControllerDetected() && |
| (first_screen == OobeScreen::SCREEN_UNKNOWN || |
| first_screen == OobeScreen::SCREEN_TEST_NO_WINDOW)) { |
| first_screen_ = GetOobeScreenFromName(screen_pref); |
| } |
| // We need to reset the kOobeControllerDetected pref to allow the user to have |
| // the choice to setup the device manually. The pref will be set properly if |
| // an eligible controller is detected later. |
| SetControllerDetectedPref(false); |
| |
| // Show Material Design unless explicitly disabled or for an untested UX, |
| // or when resuming an OOBE that had it disabled or unset. We use an if/else |
| // here to try and not set state when it is the default value so it can |
| // change and affect the OOBE again. |
| if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| chromeos::switches::kDisableMdOobe)) |
| SetShowMdOobe(false); |
| else if ((screen_pref.empty() || |
| GetLocalState()->HasPrefPath(prefs::kOobeMdMode)) || |
| GetLocalState()->GetBoolean(prefs::kOobeMdMode)) |
| SetShowMdOobe(true); |
| |
| // TODO(drcrash): Remove this after testing (http://crbug.com/647411). |
| if (IsRemoraPairingOobe() || IsSharkRequisition()) { |
| SetShowMdOobe(false); |
| } |
| |
| AdvanceToScreen(first_screen_); |
| if (!IsMachineHWIDCorrect() && !StartupUtils::IsDeviceRegistered() && |
| first_screen_ == OobeScreen::SCREEN_UNKNOWN) |
| ShowWrongHWIDScreen(); |
| } |
| |
| ErrorScreen* WizardController::GetErrorScreen() { |
| return oobe_ui_->GetErrorScreen(); |
| } |
| |
| BaseScreen* WizardController::GetScreen(OobeScreen screen) { |
| if (screen == OobeScreen::SCREEN_ERROR_MESSAGE) |
| return GetErrorScreen(); |
| return screen_manager_->GetScreen(screen); |
| } |
| |
| BaseScreen* WizardController::CreateScreen(OobeScreen screen) { |
| if (screen == OobeScreen::SCREEN_OOBE_NETWORK) { |
| return new NetworkScreen(this, this, oobe_ui_->GetNetworkView()); |
| } else if (screen == OobeScreen::SCREEN_OOBE_UPDATE) { |
| return new UpdateScreen(this, oobe_ui_->GetUpdateView(), |
| remora_controller_.get()); |
| } else if (screen == OobeScreen::SCREEN_USER_IMAGE_PICKER) { |
| return new UserImageScreen(this, oobe_ui_->GetUserImageView()); |
| } else if (screen == OobeScreen::SCREEN_OOBE_EULA) { |
| return new EulaScreen(this, this, oobe_ui_->GetEulaView()); |
| } else if (screen == OobeScreen::SCREEN_OOBE_ENROLLMENT) { |
| return new EnrollmentScreen(this, oobe_ui_->GetEnrollmentScreenView()); |
| } else if (screen == OobeScreen::SCREEN_OOBE_RESET) { |
| return new chromeos::ResetScreen(this, oobe_ui_->GetResetView()); |
| } else if (screen == OobeScreen::SCREEN_OOBE_ENABLE_DEBUGGING) { |
| return new EnableDebuggingScreen(this, |
| oobe_ui_->GetEnableDebuggingScreenView()); |
| } else if (screen == OobeScreen::SCREEN_KIOSK_ENABLE) { |
| return new KioskEnableScreen(this, oobe_ui_->GetKioskEnableScreenView()); |
| } else if (screen == OobeScreen::SCREEN_KIOSK_AUTOLAUNCH) { |
| return new KioskAutolaunchScreen(this, |
| oobe_ui_->GetKioskAutolaunchScreenView()); |
| } else if (screen == OobeScreen::SCREEN_TERMS_OF_SERVICE) { |
| return new TermsOfServiceScreen(this, |
| oobe_ui_->GetTermsOfServiceScreenView()); |
| } else if (screen == OobeScreen::SCREEN_ARC_TERMS_OF_SERVICE) { |
| return new ArcTermsOfServiceScreen( |
| this, oobe_ui_->GetArcTermsOfServiceScreenView()); |
| } else if (screen == OobeScreen::SCREEN_WRONG_HWID) { |
| return new WrongHWIDScreen(this, oobe_ui_->GetWrongHWIDScreenView()); |
| } else if (screen == OobeScreen::SCREEN_CREATE_SUPERVISED_USER_FLOW) { |
| return new SupervisedUserCreationScreen( |
| this, oobe_ui_->GetSupervisedUserCreationScreenView()); |
| } else if (screen == OobeScreen::SCREEN_OOBE_HID_DETECTION) { |
| return new chromeos::HIDDetectionScreen(this, |
| oobe_ui_->GetHIDDetectionView()); |
| } else if (screen == OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK) { |
| return new AutoEnrollmentCheckScreen( |
| this, oobe_ui_->GetAutoEnrollmentCheckScreenView()); |
| } else if (screen == OobeScreen::SCREEN_OOBE_CONTROLLER_PAIRING) { |
| if (!shark_controller_) { |
| shark_controller_.reset( |
| new pairing_chromeos::BluetoothControllerPairingController()); |
| } |
| return new ControllerPairingScreen( |
| this, this, oobe_ui_->GetControllerPairingScreenView(), |
| shark_controller_.get()); |
| } else if (screen == OobeScreen::SCREEN_OOBE_HOST_PAIRING) { |
| if (!remora_controller_) { |
| remora_controller_.reset( |
| new pairing_chromeos::BluetoothHostPairingController( |
| InputServiceProxy::GetInputServiceTaskRunner())); |
| remora_controller_->StartPairing(); |
| } |
| return new HostPairingScreen(this, this, |
| oobe_ui_->GetHostPairingScreenView(), |
| remora_controller_.get()); |
| } else if (screen == OobeScreen::SCREEN_DEVICE_DISABLED) { |
| return new DeviceDisabledScreen(this, |
| oobe_ui_->GetDeviceDisabledScreenView()); |
| } else if (screen == OobeScreen::SCREEN_ENCRYPTION_MIGRATION) { |
| return new EncryptionMigrationScreen( |
| this, oobe_ui_->GetEncryptionMigrationScreenView()); |
| } else if (screen == OobeScreen::SCREEN_VOICE_INTERACTION_VALUE_PROP) { |
| return new VoiceInteractionValuePropScreen( |
| this, oobe_ui_->GetVoiceInteractionValuePropScreenView()); |
| } else if (screen == OobeScreen::SCREEN_WAIT_FOR_CONTAINER_READY) { |
| return new WaitForContainerReadyScreen( |
| this, oobe_ui_->GetWaitForContainerReadyScreenView()); |
| } |
| |
| return nullptr; |
| } |
| |
| void WizardController::ShowNetworkScreen() { |
| VLOG(1) << "Showing network screen."; |
| UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_OOBE_NETWORK); |
| SetCurrentScreen(GetScreen(OobeScreen::SCREEN_OOBE_NETWORK)); |
| |
| // There are two possible screens where we listen to the incoming Bluetooth |
| // connection request: the first one is the HID detection screen, which will |
| // show up when there is no sufficient input devices. In this case, we just |
| // keep the logic as it is today: always put the Bluetooth is discoverable |
| // mode. The other place is the Network screen (here), which will show up when |
| // there are input devices detected. In this case, we disable the Bluetooth by |
| // default until the user explicitly enable it by pressing a key combo (Ctrl+ |
| // Alt+Shift+S). |
| if (IsBootstrappingSlave()) |
| MaybeStartListeningForSharkConnection(); |
| } |
| |
| void WizardController::ShowLoginScreen(const LoginScreenContext& context) { |
| // This may be triggered by multiply asynchronous events from the JS side. |
| if (login_screen_started_) |
| return; |
| |
| if (!time_eula_accepted_.is_null()) { |
| base::TimeDelta delta = base::Time::Now() - time_eula_accepted_; |
| UMA_HISTOGRAM_MEDIUM_TIMES("OOBE.EULAToSignInTime", delta); |
| } |
| VLOG(1) << "Showing login screen."; |
| UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_SPECIAL_LOGIN); |
| host_->StartSignInScreen(context); |
| smooth_show_timer_.Stop(); |
| login_screen_started_ = true; |
| } |
| |
| void WizardController::ShowUserImageScreen() { |
| const user_manager::UserManager* user_manager = |
| user_manager::UserManager::Get(); |
| // Skip user image selection for public sessions and ephemeral non-regual user |
| // logins. |
| if (user_manager->IsLoggedInAsPublicAccount() || |
| (user_manager->IsCurrentUserNonCryptohomeDataEphemeral() && |
| user_manager->GetActiveUser()->GetType() != |
| user_manager::USER_TYPE_REGULAR)) { |
| OnUserImageSkipped(); |
| return; |
| } |
| VLOG(1) << "Showing user image screen."; |
| |
| // Status area has been already shown at sign in screen so it |
| // doesn't make sense to hide it here and then show again at user session as |
| // this produces undesired UX transitions. |
| UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_USER_IMAGE_PICKER); |
| |
| SetCurrentScreen(GetScreen(OobeScreen::SCREEN_USER_IMAGE_PICKER)); |
| } |
| |
| void WizardController::ShowEulaScreen() { |
| VLOG(1) << "Showing EULA screen."; |
| UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_OOBE_EULA); |
| SetCurrentScreen(GetScreen(OobeScreen::SCREEN_OOBE_EULA)); |
| } |
| |
| void WizardController::ShowEnrollmentScreen() { |
| // Update the enrollment configuration and start the screen. |
| prescribed_enrollment_config_ = g_browser_process->platform_part() |
| ->browser_policy_connector_chromeos() |
| ->GetPrescribedEnrollmentConfig(); |
| StartEnrollmentScreen(false); |
| } |
| |
| void WizardController::ShowResetScreen() { |
| VLOG(1) << "Showing reset screen."; |
| UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_OOBE_RESET); |
| SetCurrentScreen(GetScreen(OobeScreen::SCREEN_OOBE_RESET)); |
| } |
| |
| void WizardController::ShowKioskEnableScreen() { |
| VLOG(1) << "Showing kiosk enable screen."; |
| UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_KIOSK_ENABLE); |
| SetCurrentScreen(GetScreen(OobeScreen::SCREEN_KIOSK_ENABLE)); |
| } |
| |
| void WizardController::ShowKioskAutolaunchScreen() { |
| VLOG(1) << "Showing kiosk autolaunch screen."; |
| UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_KIOSK_AUTOLAUNCH); |
| SetCurrentScreen(GetScreen(OobeScreen::SCREEN_KIOSK_AUTOLAUNCH)); |
| } |
| |
| void WizardController::ShowEnableDebuggingScreen() { |
| VLOG(1) << "Showing enable developer features screen."; |
| UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_OOBE_ENABLE_DEBUGGING); |
| SetCurrentScreen(GetScreen(OobeScreen::SCREEN_OOBE_ENABLE_DEBUGGING)); |
| } |
| |
| void WizardController::ShowTermsOfServiceScreen() { |
| // Only show the Terms of Service when logging into a public account and Terms |
| // of Service have been specified through policy. In all other cases, advance |
| // to the ARC opt-in screen immediately. |
| if (!user_manager::UserManager::Get()->IsLoggedInAsPublicAccount() || |
| !ProfileManager::GetActiveUserProfile()->GetPrefs()->IsManagedPreference( |
| prefs::kTermsOfServiceURL)) { |
| ShowArcTermsOfServiceScreen(); |
| return; |
| } |
| |
| VLOG(1) << "Showing Terms of Service screen."; |
| UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_TERMS_OF_SERVICE); |
| SetCurrentScreen(GetScreen(OobeScreen::SCREEN_TERMS_OF_SERVICE)); |
| } |
| |
| void WizardController::ShowArcTermsOfServiceScreen() { |
| if (ShouldShowArcTerms()) { |
| VLOG(1) << "Showing ARC Terms of Service screen."; |
| UpdateStatusAreaVisibilityForScreen( |
| OobeScreen::SCREEN_ARC_TERMS_OF_SERVICE); |
| SetCurrentScreen(GetScreen(OobeScreen::SCREEN_ARC_TERMS_OF_SERVICE)); |
| } else { |
| ShowUserImageScreen(); |
| } |
| } |
| |
| void WizardController::ShowWrongHWIDScreen() { |
| VLOG(1) << "Showing wrong HWID screen."; |
| UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_WRONG_HWID); |
| SetCurrentScreen(GetScreen(OobeScreen::SCREEN_WRONG_HWID)); |
| } |
| |
| void WizardController::ShowAutoEnrollmentCheckScreen() { |
| VLOG(1) << "Showing Auto-enrollment check screen."; |
| UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK); |
| AutoEnrollmentCheckScreen* screen = |
| AutoEnrollmentCheckScreen::Get(screen_manager()); |
| if (retry_auto_enrollment_check_) |
| screen->ClearState(); |
| screen->set_auto_enrollment_controller(GetAutoEnrollmentController()); |
| SetCurrentScreen(screen); |
| } |
| |
| void WizardController::ShowSupervisedUserCreationScreen() { |
| VLOG(1) << "Showing Locally managed user creation screen screen."; |
| UpdateStatusAreaVisibilityForScreen( |
| OobeScreen::SCREEN_CREATE_SUPERVISED_USER_FLOW); |
| SetCurrentScreen(GetScreen(OobeScreen::SCREEN_CREATE_SUPERVISED_USER_FLOW)); |
| } |
| |
| void WizardController::ShowArcKioskSplashScreen() { |
| VLOG(1) << "Showing ARC kiosk splash screen."; |
| UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_ARC_KIOSK_SPLASH); |
| SetCurrentScreen(GetScreen(OobeScreen::SCREEN_ARC_KIOSK_SPLASH)); |
| } |
| |
| void WizardController::ShowHIDDetectionScreen() { |
| VLOG(1) << "Showing HID discovery screen."; |
| UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_OOBE_HID_DETECTION); |
| SetCurrentScreen(GetScreen(OobeScreen::SCREEN_OOBE_HID_DETECTION)); |
| // In HID detection screen, puts the Bluetooth in discoverable mode and waits |
| // for the incoming Bluetooth connection request. See the comments in |
| // WizardController::ShowNetworkScreen() for more details. |
| MaybeStartListeningForSharkConnection(); |
| } |
| |
| void WizardController::ShowControllerPairingScreen() { |
| VLOG(1) << "Showing controller pairing screen."; |
| UpdateStatusAreaVisibilityForScreen( |
| OobeScreen::SCREEN_OOBE_CONTROLLER_PAIRING); |
| SetCurrentScreen(GetScreen(OobeScreen::SCREEN_OOBE_CONTROLLER_PAIRING)); |
| } |
| |
| void WizardController::ShowHostPairingScreen() { |
| VLOG(1) << "Showing host pairing screen."; |
| UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_OOBE_HOST_PAIRING); |
| SetCurrentScreen(GetScreen(OobeScreen::SCREEN_OOBE_HOST_PAIRING)); |
| } |
| |
| void WizardController::ShowDeviceDisabledScreen() { |
| VLOG(1) << "Showing device disabled screen."; |
| UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_DEVICE_DISABLED); |
| SetCurrentScreen(GetScreen(OobeScreen::SCREEN_DEVICE_DISABLED)); |
| } |
| |
| void WizardController::ShowEncryptionMigrationScreen() { |
| VLOG(1) << "Showing encryption migration screen."; |
| UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_ENCRYPTION_MIGRATION); |
| SetCurrentScreen(GetScreen(OobeScreen::SCREEN_ENCRYPTION_MIGRATION)); |
| } |
| |
| void WizardController::ShowVoiceInteractionValuePropScreen() { |
| if (ShouldShowVoiceInteractionValueProp()) { |
| VLOG(1) << "Showing voice interaction value prop screen."; |
| UpdateStatusAreaVisibilityForScreen( |
| OobeScreen::SCREEN_VOICE_INTERACTION_VALUE_PROP); |
| SetCurrentScreen( |
| GetScreen(OobeScreen::SCREEN_VOICE_INTERACTION_VALUE_PROP)); |
| } else { |
| OnOobeFlowFinished(); |
| } |
| } |
| |
| void WizardController::ShowWaitForContainerReadyScreen() { |
| DCHECK(is_in_session_oobe_); |
| // At this point we could make sure the value prop flow has been accepted. |
| // Set the value prop pref as accepted in framework service. |
| auto* service = |
| arc::ArcVoiceInteractionFrameworkService::GetForBrowserContext( |
| ProfileManager::GetActiveUserProfile()); |
| if (service) |
| service->SetVoiceInteractionSetupCompleted(); |
| |
| UpdateStatusAreaVisibilityForScreen( |
| OobeScreen::SCREEN_WAIT_FOR_CONTAINER_READY); |
| SetCurrentScreen(GetScreen(OobeScreen::SCREEN_WAIT_FOR_CONTAINER_READY)); |
| } |
| |
| void WizardController::SkipToLoginForTesting( |
| const LoginScreenContext& context) { |
| VLOG(1) << "SkipToLoginForTesting."; |
| StartupUtils::MarkEulaAccepted(); |
| PerformPostEulaActions(); |
| OnDeviceDisabledChecked(false /* device_disabled */); |
| } |
| |
| pairing_chromeos::SharkConnectionListener* |
| WizardController::GetSharkConnectionListenerForTesting() { |
| return shark_connection_listener_.get(); |
| } |
| |
| void WizardController::SkipUpdateEnrollAfterEula() { |
| skip_update_enroll_after_eula_ = true; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // WizardController, ExitHandlers: |
| void WizardController::OnHIDDetectionCompleted() { |
| // Check for tests configuration. |
| if (!StartupUtils::IsOobeCompleted()) |
| ShowNetworkScreen(); |
| } |
| |
| void WizardController::OnNetworkConnected() { |
| if (is_official_build_) { |
| if (!StartupUtils::IsEulaAccepted()) { |
| ShowEulaScreen(); |
| } else { |
| // Possible cases: |
| // 1. EULA was accepted, forced shutdown/reboot during update. |
| // 2. EULA was accepted, planned reboot after update. |
| // Make sure that device is up to date. |
| InitiateOOBEUpdate(); |
| } |
| } else { |
| InitiateOOBEUpdate(); |
| } |
| } |
| |
| void WizardController::OnConnectionFailed() { |
| // TODO(dpolukhin): show error message after login screen is displayed. |
| ShowLoginScreen(LoginScreenContext()); |
| } |
| |
| void WizardController::OnUpdateCompleted() { |
| if (IsSharkRequisition() || IsBootstrappingMaster()) { |
| ShowControllerPairingScreen(); |
| } else if (IsControllerDetected()) { |
| ShowHostPairingScreen(); |
| } else { |
| ShowAutoEnrollmentCheckScreen(); |
| } |
| } |
| |
| void WizardController::OnEulaAccepted() { |
| time_eula_accepted_ = base::Time::Now(); |
| StartupUtils::MarkEulaAccepted(); |
| ChangeMetricsReportingStateWithReply( |
| usage_statistics_reporting_, |
| base::Bind(&WizardController::OnChangedMetricsReportingState, |
| weak_factory_.GetWeakPtr())); |
| PerformPostEulaActions(); |
| |
| if (skip_update_enroll_after_eula_) { |
| ShowAutoEnrollmentCheckScreen(); |
| } else { |
| InitiateOOBEUpdate(); |
| } |
| } |
| |
| void WizardController::OnChangedMetricsReportingState(bool enabled) { |
| CrosSettings::Get()->SetBoolean(kStatsReportingPref, enabled); |
| if (!enabled) |
| return; |
| #if defined(GOOGLE_CHROME_BUILD) |
| base::PostTaskWithTraits( |
| FROM_HERE, {base::MayBlock()}, |
| base::Bind(&breakpad::InitCrashReporter, std::string())); |
| #endif |
| } |
| |
| void WizardController::OnUpdateErrorCheckingForUpdate() { |
| // TODO(nkostylev): Update should be required during OOBE. |
| // We do not want to block users from being able to proceed to the login |
| // screen if there is any error checking for an update. |
| // They could use "browse without sign-in" feature to set up the network to be |
| // able to perform the update later. |
| OnUpdateCompleted(); |
| } |
| |
| void WizardController::OnUpdateErrorUpdating(bool is_critical_update) { |
| // If there was an error while getting or applying the update, return to |
| // network selection screen if the OOBE isn't complete and the update is |
| // deemed critical. Otherwise, similar to OnUpdateErrorCheckingForUpdate(), |
| // we do not want to block users from being able to proceed to the login |
| // screen. |
| if (is_out_of_box_ && is_critical_update) |
| ShowNetworkScreen(); |
| else |
| OnUpdateCompleted(); |
| } |
| |
| void WizardController::EnableUserImageScreenReturnToPreviousHack() { |
| user_image_screen_return_to_previous_hack_ = true; |
| } |
| |
| void WizardController::OnUserImageSelected() { |
| if (user_image_screen_return_to_previous_hack_) { |
| user_image_screen_return_to_previous_hack_ = false; |
| DCHECK(previous_screen_); |
| if (previous_screen_) { |
| SetCurrentScreen(previous_screen_); |
| return; |
| } |
| } |
| OnOobeFlowFinished(); |
| } |
| |
| void WizardController::OnUserImageSkipped() { |
| OnUserImageSelected(); |
| } |
| |
| void WizardController::OnEnrollmentDone() { |
| PerformOOBECompletedActions(); |
| |
| // 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) { |
| chrome::AttemptRestart(); |
| } |
| |
| // TODO(mnissler): Unify the logic for auto-login for Public Sessions and |
| // Kiosk Apps and make this code cover both cases: http://crbug.com/234694. |
| if (KioskAppManager::Get()->IsAutoLaunchEnabled()) |
| AutoLaunchKioskApp(); |
| else |
| ShowLoginScreen(LoginScreenContext()); |
| } |
| |
| void WizardController::OnDeviceModificationCanceled() { |
| if (previous_screen_) { |
| SetCurrentScreen(previous_screen_); |
| } else { |
| ShowLoginScreen(LoginScreenContext()); |
| } |
| } |
| |
| void WizardController::OnKioskAutolaunchCanceled() { |
| ShowLoginScreen(LoginScreenContext()); |
| } |
| |
| void WizardController::OnKioskAutolaunchConfirmed() { |
| DCHECK(KioskAppManager::Get()->IsAutoLaunchEnabled()); |
| AutoLaunchKioskApp(); |
| } |
| |
| void WizardController::OnKioskEnableCompleted() { |
| ShowLoginScreen(LoginScreenContext()); |
| } |
| |
| void WizardController::OnWrongHWIDWarningSkipped() { |
| if (previous_screen_) |
| SetCurrentScreen(previous_screen_); |
| else |
| ShowLoginScreen(LoginScreenContext()); |
| } |
| |
| void WizardController::OnTermsOfServiceDeclined() { |
| // If the user declines the Terms of Service, end the session and return to |
| // the login screen. |
| DBusThreadManager::Get()->GetSessionManagerClient()->StopSession(); |
| } |
| |
| void WizardController::OnTermsOfServiceAccepted() { |
| // If the user accepts the Terms of Service, advance to the PlayStore terms |
| // of serice. |
| ShowArcTermsOfServiceScreen(); |
| } |
| |
| void WizardController::OnArcTermsOfServiceSkipped() { |
| if (is_in_session_oobe_) { |
| OnOobeFlowFinished(); |
| return; |
| } |
| // If the user finished with the PlayStore Terms of Service, advance to the |
| // user image screen. |
| ShowUserImageScreen(); |
| } |
| |
| void WizardController::OnArcTermsOfServiceAccepted() { |
| if (is_in_session_oobe_) { |
| ShowWaitForContainerReadyScreen(); |
| return; |
| } |
| // If the user finished with the PlayStore Terms of Service, advance to the |
| // user image screen. |
| ShowUserImageScreen(); |
| } |
| |
| void WizardController::OnVoiceInteractionValuePropSkipped() { |
| OnOobeFlowFinished(); |
| } |
| |
| void WizardController::OnVoiceInteractionValuePropAccepted() { |
| const Profile* profile = ProfileManager::GetActiveUserProfile(); |
| if (is_in_session_oobe_ && !arc::IsArcPlayStoreEnabledForProfile(profile)) { |
| ShowArcTermsOfServiceScreen(); |
| return; |
| } |
| ShowWaitForContainerReadyScreen(); |
| } |
| |
| void WizardController::OnWaitForContainerReadyFinished() { |
| OnOobeFlowFinished(); |
| StartVoiceInteractionSetupWizard(); |
| } |
| |
| void WizardController::OnControllerPairingFinished() { |
| ShowAutoEnrollmentCheckScreen(); |
| } |
| |
| void WizardController::OnAutoEnrollmentCheckCompleted() { |
| // 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::Bind( |
| &WizardController::OnDeviceDisabledChecked, |
| weak_factory_.GetWeakPtr())); |
| } |
| |
| void WizardController::OnOobeFlowFinished() { |
| if (is_in_session_oobe_) { |
| host_->SetStatusAreaVisible(true); |
| host_->Finalize(base::OnceClosure()); |
| host_ = nullptr; |
| return; |
| } |
| |
| if (!time_oobe_started_.is_null()) { |
| base::TimeDelta delta = base::Time::Now() - time_oobe_started_; |
| UMA_HISTOGRAM_CUSTOM_TIMES("OOBE.BootToSignInCompleted", delta, |
| base::TimeDelta::FromMilliseconds(10), |
| base::TimeDelta::FromMinutes(30), 100); |
| time_oobe_started_ = base::Time(); |
| } |
| |
| // Launch browser and delete login host controller. |
| BrowserThread::PostTask( |
| BrowserThread::UI, FROM_HERE, |
| base::BindOnce(&UserSessionManager::DoBrowserLaunch, |
| base::Unretained(UserSessionManager::GetInstance()), |
| ProfileManager::GetActiveUserProfile(), host_)); |
| host_ = nullptr; |
| } |
| |
| void WizardController::OnDeviceDisabledChecked(bool device_disabled) { |
| prescribed_enrollment_config_ = g_browser_process->platform_part() |
| ->browser_policy_connector_chromeos() |
| ->GetPrescribedEnrollmentConfig(); |
| if (device_disabled) { |
| ShowDeviceDisabledScreen(); |
| } else if (skip_update_enroll_after_eula_ || |
| prescribed_enrollment_config_.should_enroll()) { |
| StartEnrollmentScreen(skip_update_enroll_after_eula_); |
| } else { |
| PerformOOBECompletedActions(); |
| ShowLoginScreen(LoginScreenContext()); |
| } |
| } |
| |
| void WizardController::InitiateOOBEUpdate() { |
| if (IsRemoraRequisition()) { |
| VLOG(1) << "Skip OOBE Update for remora."; |
| OnUpdateCompleted(); |
| return; |
| } |
| |
| // If this is a Cellular First device, instruct UpdateEngine to allow |
| // updates over cellular data connections. |
| if (chromeos::switches::IsCellularFirstDevice()) { |
| DBusThreadManager::Get() |
| ->GetUpdateEngineClient() |
| ->SetUpdateOverCellularPermission( |
| true, base::Bind(&WizardController::StartOOBEUpdate, |
| weak_factory_.GetWeakPtr())); |
| } else { |
| StartOOBEUpdate(); |
| } |
| } |
| |
| void WizardController::StartOOBEUpdate() { |
| VLOG(1) << "StartOOBEUpdate"; |
| SetCurrentScreenSmooth(GetScreen(OobeScreen::SCREEN_OOBE_UPDATE), true); |
| UpdateScreen::Get(screen_manager())->StartNetworkCheck(); |
| } |
| |
| void WizardController::StartTimezoneResolve() { |
| if (!g_browser_process->platform_part() |
| ->GetTimezoneResolverManager() |
| ->TimeZoneResolverShouldBeRunning()) |
| return; |
| |
| geolocation_provider_.reset(new SimpleGeolocationProvider( |
| g_browser_process->system_request_context(), |
| SimpleGeolocationProvider::DefaultGeolocationProviderURL())); |
| geolocation_provider_->RequestGeolocation( |
| base::TimeDelta::FromSeconds(kResolveTimeZoneTimeoutSeconds), |
| false /* send_wifi_geolocation_data */, |
| false /* send_cellular_geolocation_data */, |
| base::Bind(&WizardController::OnLocationResolved, |
| weak_factory_.GetWeakPtr())); |
| } |
| |
| void WizardController::PerformPostEulaActions() { |
| DelayNetworkCall( |
| base::TimeDelta::FromMilliseconds(kDefaultNetworkRetryDelayMS), |
| base::Bind(&WizardController::StartTimezoneResolve, |
| weak_factory_.GetWeakPtr())); |
| DelayNetworkCall( |
| base::TimeDelta::FromMilliseconds(kDefaultNetworkRetryDelayMS), |
| ServicesCustomizationDocument::GetInstance() |
| ->EnsureCustomizationAppliedClosure()); |
| |
| // Now that EULA has been accepted (for official builds), enable portal check. |
| // ChromiumOS builds would go though this code path too. |
| NetworkHandler::Get()->network_state_handler()->SetCheckPortalList( |
| NetworkStateHandler::kDefaultCheckPortalList); |
| GetAutoEnrollmentController()->Start(); |
| host_->PrewarmAuthentication(); |
| network_portal_detector::GetInstance()->Enable(true); |
| } |
| |
| void WizardController::PerformOOBECompletedActions() { |
| // Avoid marking OOBE as completed multiple times if going from login screen |
| // to enrollment screen (and back). |
| if (oobe_marked_completed_) { |
| return; |
| } |
| |
| UMA_HISTOGRAM_COUNTS_100( |
| "HIDDetection.TimesDialogShownPerOOBECompleted", |
| GetLocalState()->GetInteger(prefs::kTimesHIDDialogShown)); |
| GetLocalState()->ClearPref(prefs::kTimesHIDDialogShown); |
| StartupUtils::MarkOobeCompleted(); |
| oobe_marked_completed_ = true; |
| |
| if (shark_connection_listener_.get()) |
| shark_connection_listener_->ResetController(); |
| } |
| |
| void WizardController::SetCurrentScreen(BaseScreen* new_current) { |
| SetCurrentScreenSmooth(new_current, false); |
| } |
| |
| void WizardController::ShowCurrentScreen() { |
| // ShowCurrentScreen may get called by smooth_show_timer_ even after |
| // flow has been switched to sign in screen (ExistingUserController). |
| if (!oobe_ui_) |
| return; |
| |
| // First remember how far have we reached so that we can resume if needed. |
| if (is_out_of_box_ && IsResumableScreen(current_screen_->screen_id())) { |
| StartupUtils::SaveOobePendingScreen( |
| GetOobeScreenName(current_screen_->screen_id())); |
| } |
| |
| smooth_show_timer_.Stop(); |
| |
| UpdateStatusAreaVisibilityForScreen(current_screen_->screen_id()); |
| current_screen_->Show(); |
| } |
| |
| void WizardController::SetCurrentScreenSmooth(BaseScreen* new_current, |
| bool use_smoothing) { |
| VLOG(1) << "SetCurrentScreenrSmooth: " |
| << GetOobeScreenName(new_current->screen_id()); |
| if (current_screen_ == new_current || new_current == nullptr || |
| oobe_ui_ == nullptr) { |
| return; |
| } |
| |
| smooth_show_timer_.Stop(); |
| |
| if (current_screen_) |
| current_screen_->Hide(); |
| |
| const OobeScreen screen = new_current->screen_id(); |
| if (IsOOBEStepToTrack(screen)) |
| screen_show_times_[GetOobeScreenName(screen)] = base::Time::Now(); |
| |
| previous_screen_ = current_screen_; |
| current_screen_ = new_current; |
| |
| oobe_ui_->UpdateLocalizedStringsIfNeeded(); |
| |
| if (use_smoothing) { |
| smooth_show_timer_.Start( |
| FROM_HERE, |
| base::TimeDelta::FromMilliseconds(kShowDelayMs), |
| this, |
| &WizardController::ShowCurrentScreen); |
| } else { |
| ShowCurrentScreen(); |
| } |
| } |
| |
| void WizardController::UpdateStatusAreaVisibilityForScreen(OobeScreen screen) { |
| if (screen == OobeScreen::SCREEN_OOBE_NETWORK) { |
| // Hide the status area initially; it only appears after OOBE first animates |
| // in. Keep it visible if the user goes back to the existing network screen. |
| host_->SetStatusAreaVisible( |
| screen_manager_->HasScreen(OobeScreen::SCREEN_OOBE_NETWORK)); |
| } else if (screen == OobeScreen::SCREEN_OOBE_RESET || |
| screen == OobeScreen::SCREEN_KIOSK_ENABLE || |
| screen == OobeScreen::SCREEN_KIOSK_AUTOLAUNCH || |
| screen == OobeScreen::SCREEN_OOBE_ENABLE_DEBUGGING || |
| screen == OobeScreen::SCREEN_WRONG_HWID || |
| screen == OobeScreen::SCREEN_ARC_KIOSK_SPLASH || |
| screen == OobeScreen::SCREEN_OOBE_CONTROLLER_PAIRING || |
| screen == OobeScreen::SCREEN_OOBE_HOST_PAIRING) { |
| host_->SetStatusAreaVisible(false); |
| } else { |
| host_->SetStatusAreaVisible(true); |
| } |
| } |
| |
| void WizardController::SetShowMdOobe(bool show) { |
| GetLocalState()->SetBoolean(prefs::kOobeMdMode, show); |
| } |
| |
| void WizardController::OnHIDScreenNecessityCheck(bool screen_needed) { |
| if (!oobe_ui_) |
| return; |
| |
| if (screen_needed) { |
| ShowHIDDetectionScreen(); |
| } else { |
| ShowNetworkScreen(); |
| } |
| } |
| |
| void WizardController::AdvanceToScreen(OobeScreen screen) { |
| if (screen == OobeScreen::SCREEN_OOBE_NETWORK) { |
| ShowNetworkScreen(); |
| } else if (screen == OobeScreen::SCREEN_SPECIAL_LOGIN) { |
| ShowLoginScreen(LoginScreenContext()); |
| } else if (screen == OobeScreen::SCREEN_OOBE_UPDATE) { |
| InitiateOOBEUpdate(); |
| } else if (screen == OobeScreen::SCREEN_USER_IMAGE_PICKER) { |
| ShowUserImageScreen(); |
| } else if (screen == OobeScreen::SCREEN_OOBE_EULA) { |
| ShowEulaScreen(); |
| } else if (screen == OobeScreen::SCREEN_OOBE_RESET) { |
| ShowResetScreen(); |
| } else if (screen == OobeScreen::SCREEN_KIOSK_ENABLE) { |
| ShowKioskEnableScreen(); |
| } else if (screen == OobeScreen::SCREEN_KIOSK_AUTOLAUNCH) { |
| ShowKioskAutolaunchScreen(); |
| } else if (screen == OobeScreen::SCREEN_OOBE_ENABLE_DEBUGGING) { |
| ShowEnableDebuggingScreen(); |
| } else if (screen == OobeScreen::SCREEN_OOBE_ENROLLMENT) { |
| ShowEnrollmentScreen(); |
| } else if (screen == OobeScreen::SCREEN_TERMS_OF_SERVICE) { |
| ShowTermsOfServiceScreen(); |
| } else if (screen == OobeScreen::SCREEN_ARC_TERMS_OF_SERVICE) { |
| ShowArcTermsOfServiceScreen(); |
| } else if (screen == OobeScreen::SCREEN_WRONG_HWID) { |
| ShowWrongHWIDScreen(); |
| } else if (screen == OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK) { |
| ShowAutoEnrollmentCheckScreen(); |
| } else if (screen == OobeScreen::SCREEN_CREATE_SUPERVISED_USER_FLOW) { |
| ShowSupervisedUserCreationScreen(); |
| } else if (screen == OobeScreen::SCREEN_APP_LAUNCH_SPLASH) { |
| AutoLaunchKioskApp(); |
| } else if (screen == OobeScreen::SCREEN_ARC_KIOSK_SPLASH) { |
| ShowArcKioskSplashScreen(); |
| } else if (screen == OobeScreen::SCREEN_OOBE_HID_DETECTION) { |
| ShowHIDDetectionScreen(); |
| } else if (screen == OobeScreen::SCREEN_OOBE_CONTROLLER_PAIRING) { |
| ShowControllerPairingScreen(); |
| } else if (screen == OobeScreen::SCREEN_OOBE_HOST_PAIRING) { |
| ShowHostPairingScreen(); |
| } else if (screen == OobeScreen::SCREEN_DEVICE_DISABLED) { |
| ShowDeviceDisabledScreen(); |
| } else if (screen == OobeScreen::SCREEN_ENCRYPTION_MIGRATION) { |
| ShowEncryptionMigrationScreen(); |
| } else if (screen == OobeScreen::SCREEN_VOICE_INTERACTION_VALUE_PROP) { |
| ShowVoiceInteractionValuePropScreen(); |
| } else if (screen == OobeScreen::SCREEN_WAIT_FOR_CONTAINER_READY) { |
| ShowWaitForContainerReadyScreen(); |
| } else if (screen != OobeScreen::SCREEN_TEST_NO_WINDOW) { |
| if (is_out_of_box_) { |
| time_oobe_started_ = base::Time::Now(); |
| if (IsRemoraPairingOobe() || IsControllerDetected()) { |
| ShowHostPairingScreen(); |
| } else if (CanShowHIDDetectionScreen()) { |
| hid_screen_ = GetScreen(OobeScreen::SCREEN_OOBE_HID_DETECTION); |
| base::Callback<void(bool)> on_check = base::Bind( |
| &WizardController::OnHIDScreenNecessityCheck, |
| weak_factory_.GetWeakPtr()); |
| oobe_ui_->GetHIDDetectionView()->CheckIsScreenRequired(on_check); |
| } else { |
| ShowNetworkScreen(); |
| } |
| } else { |
| ShowLoginScreen(LoginScreenContext()); |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // WizardController, BaseScreenDelegate overrides: |
| void WizardController::OnExit(BaseScreen& /* screen */, |
| ScreenExitCode exit_code, |
| const ::login::ScreenContext* /* context */) { |
| VLOG(1) << "Wizard screen exit code: " << ExitCodeToString(exit_code); |
| const OobeScreen previous_screen = current_screen_->screen_id(); |
| if (IsOOBEStepToTrack(previous_screen)) { |
| RecordUMAHistogramForOOBEStepCompletionTime( |
| previous_screen, |
| base::Time::Now() - |
| screen_show_times_[GetOobeScreenName(previous_screen)]); |
| } |
| switch (exit_code) { |
| case ScreenExitCode::HID_DETECTION_COMPLETED: |
| OnHIDDetectionCompleted(); |
| break; |
| case ScreenExitCode::NETWORK_CONNECTED: |
| OnNetworkConnected(); |
| break; |
| case ScreenExitCode::CONNECTION_FAILED: |
| OnConnectionFailed(); |
| break; |
| case ScreenExitCode::UPDATE_INSTALLED: |
| case ScreenExitCode::UPDATE_NOUPDATE: |
| OnUpdateCompleted(); |
| break; |
| case ScreenExitCode::UPDATE_ERROR_CHECKING_FOR_UPDATE: |
| OnUpdateErrorCheckingForUpdate(); |
| break; |
| case ScreenExitCode::UPDATE_ERROR_UPDATING: |
| OnUpdateErrorUpdating(false /* is_critical_update */); |
| break; |
| case ScreenExitCode::UPDATE_ERROR_UPDATING_CRITICAL_UPDATE: |
| OnUpdateErrorUpdating(true /* is_critical_update */); |
| break; |
| case ScreenExitCode::USER_IMAGE_SELECTED: |
| OnUserImageSelected(); |
| break; |
| case ScreenExitCode::EULA_ACCEPTED: |
| OnEulaAccepted(); |
| break; |
| case ScreenExitCode::EULA_BACK: |
| ShowNetworkScreen(); |
| break; |
| case ScreenExitCode::ENABLE_DEBUGGING_CANCELED: |
| OnDeviceModificationCanceled(); |
| break; |
| case ScreenExitCode::ENABLE_DEBUGGING_FINISHED: |
| OnDeviceModificationCanceled(); |
| break; |
| case ScreenExitCode::ENTERPRISE_AUTO_ENROLLMENT_CHECK_COMPLETED: |
| OnAutoEnrollmentCheckCompleted(); |
| break; |
| case ScreenExitCode::ENTERPRISE_ENROLLMENT_COMPLETED: |
| OnEnrollmentDone(); |
| break; |
| case ScreenExitCode::ENTERPRISE_ENROLLMENT_BACK: |
| retry_auto_enrollment_check_ = true; |
| ShowAutoEnrollmentCheckScreen(); |
| break; |
| case ScreenExitCode::RESET_CANCELED: |
| OnDeviceModificationCanceled(); |
| break; |
| case ScreenExitCode::KIOSK_AUTOLAUNCH_CANCELED: |
| OnKioskAutolaunchCanceled(); |
| break; |
| case ScreenExitCode::KIOSK_AUTOLAUNCH_CONFIRMED: |
| OnKioskAutolaunchConfirmed(); |
| break; |
| case ScreenExitCode::KIOSK_ENABLE_COMPLETED: |
| OnKioskEnableCompleted(); |
| break; |
| case ScreenExitCode::TERMS_OF_SERVICE_DECLINED: |
| OnTermsOfServiceDeclined(); |
| break; |
| case ScreenExitCode::TERMS_OF_SERVICE_ACCEPTED: |
| OnTermsOfServiceAccepted(); |
| break; |
| case ScreenExitCode::ARC_TERMS_OF_SERVICE_SKIPPED: |
| OnArcTermsOfServiceSkipped(); |
| break; |
| case ScreenExitCode::ARC_TERMS_OF_SERVICE_ACCEPTED: |
| OnArcTermsOfServiceAccepted(); |
| break; |
| case ScreenExitCode::WRONG_HWID_WARNING_SKIPPED: |
| OnWrongHWIDWarningSkipped(); |
| break; |
| case ScreenExitCode::CONTROLLER_PAIRING_FINISHED: |
| OnControllerPairingFinished(); |
| break; |
| case ScreenExitCode::VOICE_INTERACTION_VALUE_PROP_SKIPPED: |
| OnVoiceInteractionValuePropSkipped(); |
| break; |
| case ScreenExitCode::VOICE_INTERACTION_VALUE_PROP_ACCEPTED: |
| OnVoiceInteractionValuePropAccepted(); |
| break; |
| case ScreenExitCode::WAIT_FOR_CONTAINER_READY_FINISHED: |
| OnWaitForContainerReadyFinished(); |
| break; |
| default: |
| NOTREACHED(); |
| } |
| } |
| |
| void WizardController::ShowErrorScreen() { |
| VLOG(1) << "Showing error screen."; |
| SetCurrentScreen(GetScreen(OobeScreen::SCREEN_ERROR_MESSAGE)); |
| } |
| |
| void WizardController::HideErrorScreen(BaseScreen* parent_screen) { |
| DCHECK(parent_screen); |
| VLOG(1) << "Hiding error screen."; |
| SetCurrentScreen(parent_screen); |
| } |
| |
| void WizardController::SetUsageStatisticsReporting(bool val) { |
| usage_statistics_reporting_ = val; |
| } |
| |
| bool WizardController::GetUsageStatisticsReporting() const { |
| return usage_statistics_reporting_; |
| } |
| |
| void WizardController::SetHostNetwork() { |
| if (!shark_controller_) |
| return; |
| NetworkScreen* network_screen = NetworkScreen::Get(screen_manager()); |
| std::string onc_spec; |
| network_screen->GetConnectedWifiNetwork(&onc_spec); |
| if (!onc_spec.empty()) |
| shark_controller_->SetHostNetwork(onc_spec); |
| } |
| |
| void WizardController::SetHostConfiguration() { |
| if (!shark_controller_) |
| return; |
| NetworkScreen* network_screen = NetworkScreen::Get(screen_manager()); |
| shark_controller_->SetHostConfiguration( |
| true, // Eula must be accepted before we get this far. |
| network_screen->GetApplicationLocale(), network_screen->GetTimezone(), |
| GetUsageStatisticsReporting(), network_screen->GetInputMethod()); |
| } |
| |
| void WizardController::ConfigureHostRequested( |
| bool accepted_eula, |
| const std::string& lang, |
| const std::string& timezone, |
| bool send_reports, |
| const std::string& keyboard_layout) { |
| VLOG(1) << "ConfigureHost locale=" << lang << ", timezone=" << timezone |
| << ", keyboard_layout=" << keyboard_layout; |
| if (accepted_eula) // Always true. |
| StartupUtils::MarkEulaAccepted(); |
| SetUsageStatisticsReporting(send_reports); |
| |
| NetworkScreen* network_screen = NetworkScreen::Get(screen_manager()); |
| network_screen->SetApplicationLocaleAndInputMethod(lang, keyboard_layout); |
| network_screen->SetTimezone(timezone); |
| |
| // Don't block the OOBE update and the following enrollment process if there |
| // is available and valid network already. |
| const chromeos::NetworkState* network_state = chromeos::NetworkHandler::Get() |
| ->network_state_handler() |
| ->DefaultNetwork(); |
| if (NetworkAllowUpdate(network_state)) |
| InitiateOOBEUpdate(); |
| } |
| |
| void WizardController::AddNetworkRequested(const std::string& onc_spec) { |
| remora_controller_->OnNetworkConnectivityChanged( |
| pairing_chromeos::HostPairingController::CONNECTIVITY_CONNECTING); |
| |
| NetworkScreen* network_screen = NetworkScreen::Get(screen_manager()); |
| const chromeos::NetworkState* network_state = chromeos::NetworkHandler::Get() |
| ->network_state_handler() |
| ->DefaultNetwork(); |
| |
| if (NetworkAllowUpdate(network_state)) { |
| network_screen->CreateAndConnectNetworkFromOnc( |
| onc_spec, base::Bind(&base::DoNothing), |
| network_handler::ErrorCallback()); |
| } else { |
| network_screen->CreateAndConnectNetworkFromOnc( |
| onc_spec, base::Bind(&WizardController::OnSetHostNetworkSuccessful, |
| weak_factory_.GetWeakPtr()), |
| base::Bind(&WizardController::OnSetHostNetworkFailed, |
| weak_factory_.GetWeakPtr())); |
| } |
| } |
| |
| void WizardController::RebootHostRequested() { |
| DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart( |
| power_manager::REQUEST_RESTART_OTHER, "login wizard reboot host"); |
| } |
| |
| void WizardController::OnEnableDebuggingScreenRequested() { |
| if (!login_screen_started()) |
| AdvanceToScreen(OobeScreen::SCREEN_OOBE_ENABLE_DEBUGGING); |
| } |
| |
| void WizardController::OnAccessibilityStatusChanged( |
| const AccessibilityStatusEventDetails& details) { |
| enum AccessibilityNotificationType type = details.notification_type; |
| if (type == ACCESSIBILITY_MANAGER_SHUTDOWN) { |
| accessibility_subscription_.reset(); |
| return; |
| } else if (type != ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK || !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() { |
| KioskAppManager::App app_data; |
| std::string app_id = KioskAppManager::Get()->GetAutoLaunchApp(); |
| CHECK(KioskAppManager::Get()->GetApp(app_id, &app_data)); |
| |
| // Wait for the |CrosSettings| to become either trusted or permanently |
| // untrusted. |
| const CrosSettingsProvider::TrustedStatus status = |
| CrosSettings::Get()->PrepareTrustedValues(base::Bind( |
| &WizardController::AutoLaunchKioskApp, |
| weak_factory_.GetWeakPtr())); |
| 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. |
| GetErrorScreen()->SetUIState(NetworkError::UI_STATE_LOCAL_STATE_ERROR); |
| host_->SetStatusAreaVisible(false); |
| ShowErrorScreen(); |
| return; |
| } |
| |
| bool device_disabled = false; |
| CrosSettings::Get()->GetBoolean(kDeviceDisabled, &device_disabled); |
| if (device_disabled && system::DeviceDisablingManager:: |
| HonorDeviceDisablingDuringNormalOperation()) { |
| // If the device is disabled, bail out. A device disabled screen will be |
| // shown by the DeviceDisablingManager. |
| return; |
| } |
| |
| const bool diagnostic_mode = false; |
| const bool auto_launch = true; |
| host_->StartAppLaunch(app_id, diagnostic_mode, auto_launch); |
| } |
| |
| // static |
| void WizardController::SetZeroDelays() { |
| kShowDelayMs = 0; |
| zero_delay_enabled_ = true; |
| } |
| |
| // static |
| bool WizardController::IsZeroDelayEnabled() { |
| return zero_delay_enabled_; |
| } |
| |
| // static |
| bool WizardController::IsOOBEStepToTrack(OobeScreen screen_id) { |
| return (screen_id == OobeScreen::SCREEN_OOBE_HID_DETECTION || |
| screen_id == OobeScreen::SCREEN_OOBE_NETWORK || |
| screen_id == OobeScreen::SCREEN_OOBE_UPDATE || |
| screen_id == OobeScreen::SCREEN_USER_IMAGE_PICKER || |
| screen_id == OobeScreen::SCREEN_OOBE_EULA || |
| screen_id == OobeScreen::SCREEN_SPECIAL_LOGIN || |
| screen_id == OobeScreen::SCREEN_WRONG_HWID); |
| } |
| |
| // static |
| void WizardController::SkipPostLoginScreensForTesting() { |
| skip_post_login_screens_ = true; |
| } |
| |
| // static |
| bool WizardController::UsingHandsOffEnrollment() { |
| return policy::DeviceCloudPolicyManagerChromeOS:: |
| GetZeroTouchEnrollmentMode() == |
| policy::ZeroTouchEnrollmentMode::HANDS_OFF; |
| } |
| |
| void WizardController::OnLocalStateInitialized(bool /* succeeded */) { |
| if (GetLocalState()->GetInitializationStatus() != |
| PrefService::INITIALIZATION_STATUS_ERROR) { |
| return; |
| } |
| GetErrorScreen()->SetUIState(NetworkError::UI_STATE_LOCAL_STATE_ERROR); |
| host_->SetStatusAreaVisible(false); |
| ShowErrorScreen(); |
| } |
| |
| 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.get()); |
| // To check that "this" is not destroyed try to access some member |
| // (timezone_provider_) in this case. Expect crash here. |
| DCHECK(timezone_provider_.get()); |
| |
| timezone_resolved_ = true; |
| base::ScopedClosureRunner inform_test(on_timezone_resolved_for_testing_); |
| on_timezone_resolved_for_testing_.Reset(); |
| |
| VLOG(1) << "Resolved local timezone={" << timezone->ToStringForDebug() |
| << "}."; |
| |
| if (timezone->status != TimeZoneResponseData::OK) { |
| LOG(WARNING) << "Resolve TimeZone: failed to resolve timezone."; |
| return; |
| } |
| |
| policy::BrowserPolicyConnectorChromeOS* connector = |
| g_browser_process->platform_part()->browser_policy_connector_chromeos(); |
| if (connector->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 |
| << "'"; |
| chromeos::system::SetSystemAndSigninScreenTimezone(timezone->timeZoneId); |
| } |
| } |
| |
| TimeZoneProvider* WizardController::GetTimezoneProvider() { |
| if (!timezone_provider_) { |
| timezone_provider_.reset( |
| new TimeZoneProvider(g_browser_process->system_request_context(), |
| 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::TimeDelta::FromSeconds(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::Bind(&WizardController::OnTimezoneResolved, |
| base::Unretained(this))); |
| } |
| |
| bool WizardController::SetOnTimeZoneResolvedForTesting( |
| const base::Closure& callback) { |
| if (timezone_resolved_) |
| return false; |
| |
| on_timezone_resolved_for_testing_ = callback; |
| return true; |
| } |
| |
| bool WizardController::IsRemoraPairingOobe() const { |
| return base::CommandLine::ForCurrentProcess()->HasSwitch( |
| switches::kHostPairingOobe); |
| } |
| |
| bool WizardController::ShouldShowArcTerms() const { |
| const base::CommandLine* command_line = |
| base::CommandLine::ForCurrentProcess(); |
| if (!command_line->HasSwitch(chromeos::switches::kEnableArcOOBEOptIn)) { |
| VLOG(1) << "Skip ARC Terms of Service screen because ARC OOBE OptIn is " |
| << "disabled."; |
| return false; |
| } |
| if (!user_manager::UserManager::Get()->IsUserLoggedIn()) { |
| VLOG(1) << "Skip ARC Terms of Service screen because user is not " |
| << "logged in."; |
| return false; |
| } |
| |
| const Profile* profile = ProfileManager::GetActiveUserProfile(); |
| if (!arc::IsArcAllowedForProfile(profile)) { |
| VLOG(1) << "Skip ARC Terms of Service screen because ARC is not allowed."; |
| return false; |
| } |
| if (profile->GetPrefs()->IsManagedPreference(arc::prefs::kArcEnabled) && |
| !profile->GetPrefs()->GetBoolean(arc::prefs::kArcEnabled)) { |
| VLOG(1) << "Skip ARC Terms of Service screen because ARC is disabled."; |
| return false; |
| } |
| if (arc::IsActiveDirectoryUserForProfile(profile)) { |
| VLOG(1) << "Skip ARC Terms of Service screen because it does not apply to " |
| "Active Directory users."; |
| return false; |
| } |
| return true; |
| } |
| |
| bool WizardController::ShouldShowVoiceInteractionValueProp() const { |
| // If the OOBE flow was initiated from voice interaction shortcut, we will |
| // show Arc terms later. |
| if (!is_in_session_oobe_ && !arc::IsArcPlayStoreEnabledForProfile( |
| ProfileManager::GetActiveUserProfile())) { |
| VLOG(1) << "Skip Voice Interaction Value Prop screen because Arc Terms is " |
| << "skipped."; |
| return false; |
| } |
| if (!chromeos::switches::IsVoiceInteractionEnabled()) { |
| VLOG(1) << "Skip Voice Interaction Value Prop screen because voice " |
| << "interaction service is disabled."; |
| return false; |
| } |
| return true; |
| } |
| |
| void WizardController::StartVoiceInteractionSetupWizard() { |
| auto* service = |
| arc::ArcVoiceInteractionFrameworkService::GetForBrowserContext( |
| ProfileManager::GetActiveUserProfile()); |
| if (service) |
| service->StartVoiceInteractionSetupWizard(); |
| } |
| |
| void WizardController::MaybeStartListeningForSharkConnection() { |
| // We shouldn't be here if we are running pairing OOBE already. |
| if (IsControllerDetected()) |
| return; |
| |
| if (!shark_connection_listener_) { |
| shark_connection_listener_.reset( |
| new pairing_chromeos::SharkConnectionListener( |
| InputServiceProxy::GetInputServiceTaskRunner(), |
| base::Bind(&WizardController::OnSharkConnected, |
| weak_factory_.GetWeakPtr()))); |
| } |
| } |
| |
| void WizardController::OnSharkConnected( |
| std::unique_ptr<pairing_chromeos::HostPairingController> |
| remora_controller) { |
| VLOG(1) << "OnSharkConnected"; |
| remora_controller_ = std::move(remora_controller); |
| base::ThreadTaskRunnerHandle::Get()->DeleteSoon( |
| FROM_HERE, shark_connection_listener_.release()); |
| SetControllerDetectedPref(true); |
| ShowHostPairingScreen(); |
| } |
| |
| void WizardController::OnSetHostNetworkSuccessful() { |
| remora_controller_->OnNetworkConnectivityChanged( |
| pairing_chromeos::HostPairingController::CONNECTIVITY_CONNECTED); |
| InitiateOOBEUpdate(); |
| } |
| |
| void WizardController::OnSetHostNetworkFailed( |
| const std::string& error_name, |
| std::unique_ptr<base::DictionaryValue> error_data) { |
| std::string error_message; |
| JSONStringValueSerializer serializer(&error_message); |
| serializer.Serialize(*error_data); |
| error_message = error_name + ": " + error_message; |
| |
| remora_controller_->SetErrorCodeAndMessage( |
| static_cast<int>( |
| pairing_chromeos::HostPairingController::ErrorCode::NETWORK_ERROR), |
| error_message); |
| |
| remora_controller_->OnNetworkConnectivityChanged( |
| pairing_chromeos::HostPairingController::CONNECTIVITY_NONE); |
| } |
| |
| void WizardController::StartEnrollmentScreen(bool force_interactive) { |
| VLOG(1) << "Showing enrollment screen." |
| << " Forcing interactive enrollment: " << force_interactive << "."; |
| |
| // Determine the effective enrollment configuration. If there is a valid |
| // prescribed configuration, use that. If not, figure out which variant of |
| // manual enrollment is taking place. |
| policy::EnrollmentConfig effective_config = prescribed_enrollment_config_; |
| if (!effective_config.should_enroll() || |
| (force_interactive && !effective_config.should_enroll_interactively())) { |
| effective_config.mode = |
| prescribed_enrollment_config_.management_domain.empty() |
| ? policy::EnrollmentConfig::MODE_MANUAL |
| : policy::EnrollmentConfig::MODE_MANUAL_REENROLLMENT; |
| } |
| |
| EnrollmentScreen* screen = EnrollmentScreen::Get(screen_manager()); |
| screen->SetParameters(effective_config, shark_controller_.get()); |
| UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_OOBE_ENROLLMENT); |
| SetCurrentScreen(screen); |
| } |
| |
| AutoEnrollmentController* WizardController::GetAutoEnrollmentController() { |
| if (!auto_enrollment_controller_) |
| auto_enrollment_controller_ = base::MakeUnique<AutoEnrollmentController>(); |
| return auto_enrollment_controller_.get(); |
| } |
| |
| } // namespace chromeos |