Commit 2de24b99 authored by Aga Wronska's avatar Aga Wronska Committed by Commit Bot

demo mode: Show detailed demo mode setup error information.

When during demo mode setup error occurs the message displayed to the
user contains description of the problem and suggested recovery method.
It helps users as well as support and developers.

Bug: 889604
Test: demo setup unit and browser tests.
Change-Id: Ia2ea4b1d9e1b4667ca9dde139d3a4aaba3a58cd0
Reviewed-on: https://chromium-review.googlesource.com/c/1280311Reviewed-by: default avatarMichael Giuffrida <michaelpg@chromium.org>
Reviewed-by: default avatarRahul Chaturvedi <rkc@chromium.org>
Commit-Queue: Aga Wronska <agawronska@chromium.org>
Cr-Commit-Position: refs/heads/master@{#602425}
parent 2fcf3b65
...@@ -529,6 +529,8 @@ ...@@ -529,6 +529,8 @@
<message name="IDS_OOBE_EULA_ACCEPT_AND_CONTINUE_BUTTON_TEXT" desc="Label on a button on the Title of Terms of Service OOBE screen to accept EULA and continue."> <message name="IDS_OOBE_EULA_ACCEPT_AND_CONTINUE_BUTTON_TEXT" desc="Label on a button on the Title of Terms of Service OOBE screen to accept EULA and continue.">
Accept and continue Accept and continue
</message> </message>
<!-- Strings for the OOBE demo setup flow -->
<message name="IDS_OOBE_DEMO_SETUP_PREFERENCES_SCREEN_TITLE" desc="The title of the dialog that allows to choose demo setup preferences."> <message name="IDS_OOBE_DEMO_SETUP_PREFERENCES_SCREEN_TITLE" desc="The title of the dialog that allows to choose demo setup preferences.">
Choose your demo preferences Choose your demo preferences
</message> </message>
...@@ -541,12 +543,135 @@ ...@@ -541,12 +543,135 @@
<message name="IDS_OOBE_DEMO_SETUP_ERROR_SCREEN_TITLE" desc="The title of the dialog that is shown when demo mode setup failed."> <message name="IDS_OOBE_DEMO_SETUP_ERROR_SCREEN_TITLE" desc="The title of the dialog that is shown when demo mode setup failed.">
Couldn't start demo mode Couldn't start demo mode
</message> </message>
<message name="IDS_OOBE_DEMO_SETUP_ERROR_SCREEN_SUBTITLE" desc="The subtitle of the dialog that is shown when demo mode setup failed.">
Please try again
</message>
<message name="IDS_OOBE_DEMO_SETUP_ERROR_SCREEN_RETRY_BUTTON_LABEL" desc="The label of the button that is shown on error screen and that retries demo mode setup with the previously chosen configuration."> <message name="IDS_OOBE_DEMO_SETUP_ERROR_SCREEN_RETRY_BUTTON_LABEL" desc="The label of the button that is shown on error screen and that retries demo mode setup with the previously chosen configuration.">
OK OK
</message> </message>
<!-- Demo setup flow errors -->
<message name="IDS_DEMO_SETUP_NO_OFFLINE_RESOURCES_ERROR" desc="Error message shown on demo setup screen when offline demo resources are not available.">
Offline demo mode resources unavailable.
</message>
<message name="IDS_DEMO_SETUP_OFFLINE_POLICY_ERROR" desc="Error message shown on demo setup screen when loading or parsing offline policy failed.">
Could not read offline demo mode policy.
</message>
<message name="IDS_DEMO_SETUP_OFFLINE_STORE_ERROR" desc="Error message shown on demo setup screen when loading or parsing offline policy failed.">
Failed to install offline policy on the device.
</message>
<message name="IDS_DEMO_SETUP_OFFLINE_UNAVAILABLE_ERROR" desc="Error message shown on demo setup screen when offline demo mode is not available on the device.">
This device cannot be set up in offline demo mode.
</message>
<message name="IDS_DEMO_SETUP_COMPONENT_ERROR" desc="Error message shown on demo setup screen when loading online component with demo resources failed.">
Could not load online component with demo mode resources.
</message>
<message name="IDS_DEMO_SETUP_NO_STATE_KEYS_ERROR" desc="Error message shown on demo setup screen when the system failed to determine server-backed state keys.">
The system failed to determine device identifiers for this device.
</message>
<message name="IDS_DEMO_SETUP_ROBOT_ERROR" desc="Error message shown on demo setup screen upon failure to fetch the OAuth2 token for device-level API access.">
The system failed to authorize API access for this device.
</message>
<message name="IDS_DEMO_SETUP_ROBOT_STORE_ERROR" desc="Error message shown on demo setup screen upon failure to store the OAuth2 refresh token for device-level API access.">
The system failed to store the long-term API access token for this device.
</message>
<message name="IDS_DEMO_SETUP_BAD_MODE_ERROR" desc="Error message shown on demo setup screen upon receiving a bad mode on device registration.">
The supplied enrollment mode is not supported by this version of the operating system. Please make sure you are running the newest version.
</message>
<message name="IDS_DEMO_SETUP_CERT_FETCH_ERROR" desc="Error message shown when a registration certificate could not be obtained.">
A registration certificate could not be obtained.
</message>
<message name="IDS_DEMO_SETUP_POLICY_FETCH_ERROR" desc="Error message shown on demo setup screen upon a failed policy fetch.">
Error when fetching policy from the server.
</message>
<message name="IDS_DEMO_SETUP_POLICY_VALIDATION_ERROR" desc="Error message shown on demo setup screen upon a failure to validate downloaded policy.">
The policy downloaded from the server is invalid.
</message>
<message name="IDS_DEMO_SETUP_LOCK_TIMEOUT_ERROR" desc="Error message shown on demo setup screen when the initialization of the lockbox is taking too long.">
The initialization of the installation-time attributes has timed out.
</message>
<message name="IDS_DEMO_SETUP_LOCK_ERROR" desc="Error message shown on demo setup screen upon failure to lock the device mode.">
The system failed to establish the device installation-time attributes lock.
</message>
<message name="IDS_DEMO_SETUP_ALREADY_LOCKED_ERROR" desc="Error message shown on demo setup screen when device is already locked with different domain or mode.">
This device was locked to different domain or mode.
</message>
<message name="IDS_DEMO_SETUP_ONLINE_STORE_ERROR" desc="Error message shown on demo setup screen when the installation of the policy on the device failed.">
Failed to install policy on the device.
</message>
<message name="IDS_DEMO_SETUP_NO_MACHINE_IDENTIFICATION_ERROR" desc="Error message shown on demo setup screen when the system failed to determine the device model or serial number.">
The system failed to determine device model or serial number.
</message>
<message name="IDS_DEMO_SETUP_DM_TOKEN_STORE_ERROR" desc="Error message shown on demo setup screen when the system failed to save some part of the device configuration. e.g. token from the device management server.">
The system failed to save device configuration.
</message>
<message name="IDS_DEMO_SETUP_UNEXPECTED_ERROR" desc="Error message to show shown on demo setup screen when there is an fatal/unexpected error.">
Oops! Something went wrong while setting up demo mode.
</message>
<message name="IDS_DEMO_SETUP_INVALID_REQUEST_ERROR" desc="Error message to show on demo setup screen when request issued to DMServer was invalid.">
A problem with demo registration request occurred.
</message>
<message name="IDS_DEMO_SETUP_NETWORK_ERROR" desc="Error message to show on demo setup screen when network error occurred.">
Network error occurred.
</message>
<message name="IDS_DEMO_SETUP_TEMPORARY_ERROR" desc="Error message to show on demo setup screen when temporary error occurred.">
Temporary server error occurred.
</message>
<message name="IDS_DEMO_SETUP_RESPONSE_ERROR" desc="Error message to show on demo setup screen when management service sent an abnormal HTTP code.">
Management service sent HTTP error.
</message>
<message name="IDS_DEMO_SETUP_RESPONSE_DECODING_ERROR" desc="Error message to show on demo setup screen when decoding management server response failed.">
A problem occurred when decoding server response.
</message>
<message name="IDS_DEMO_SETUP_ACCOUNT_ERROR" desc="Error message to show on demo setup screen when there is a problem with the demo mode account.">
A problem with demo mode account occurred.
</message>
<message name="IDS_DEMO_SETUP_DEVICE_NOT_FOUND_ERROR" desc="Error message to show on demo setup screen when management service could not find the device.">
Missing device record.
</message>
<message name="IDS_DEMO_SETUP_INVALID_DM_TOKEN_ERROR" desc="Error message to show on demo setup screen when device management token is invalid.">
Device management token is invalid.
</message>
<message name="IDS_DEMO_SETUP_INVALID_SERIAL_NUMBER_ERROR" desc="Error message to show on demo setup screen when provided serial number is invalid.">
Device serial number is invalid.
</message>
<message name="IDS_DEMO_SETUP_DEVICE_ID_ERROR" desc="Error message to show on demo setup screen in case of conflicting device id.">
Conflicting device identifier.
</message>
<message name="IDS_DEMO_SETUP_LICENSE_ERROR" desc="Error message to show on demo setup screen when the demo domain has expired or exhausted licenses.">
A problem with demo mode device licenses occurred.
</message>
<message name="IDS_DEMO_SETUP_DEPROVISIONED_ERROR" desc="Error message to show on demo setup screen when enrollment fails because device has been deprovisioned on the server side.">
This demo device has been placed into a deprovisioned state.
</message>
<message name="IDS_DEMO_SETUP_DOMAIN_MISMATCH_ERROR" desc="Error message shown on demo setup screen when the device belongs to the domain different than demo mode.">
This device is marked for management by a different domain. Deprovision it from that domain before setting up demo mode.
</message>
<message name="IDS_DEMO_SETUP_SIGNING_ERROR" desc="Error message shown on demo setup screen when failure to sign request occurred.">
Request could not be signed.
</message>
<message name="IDS_DEMO_SETUP_POLICY_NOT_FOUND_ERROR" desc="Error message shown on demo setup screen when management server failed to find the policy to be applied to the device.">
Policy not found.
</message>
<message name="IDS_DEMO_SETUP_ARC_ERROR" desc="Error message shown when ARC is disabled.">
A problem with ARC++ occurred.
</message>
<!-- Demo setup error recovery suggestions -->
<message name="IDS_DEMO_SETUP_RECOVERY_RETRY" desc="Error recovery recommendation to retry demo setup. Shown on demo setup screen.">
Please try again.
</message>
<message name="IDS_DEMO_SETUP_RECOVERY_REBOOT" desc="Error recovery recommendation to reboot and retry demo setup. Shown on demo setup screen.">
Please reboot the device and try again.
</message>
<message name="IDS_DEMO_SETUP_RECOVERY_POWERWASH" desc="Error recovery recommendation to powerwash and retry demo setup. Shown on demo setup screen.">
Please powerwash the device and try again.
</message>
<message name="IDS_DEMO_SETUP_RECOVERY_CHECK_NETWORK" desc="Error recovery recommendation to check network and retry demo setup. Shown on demo setup screen.">
Please check your network connection and try again.
</message>
<message name="IDS_DEMO_SETUP_RECOVERY_OFFLINE_FATAL" desc="Error recovery recommendation to contact support. Shown on demo setup screen.">
This device might be only eligible for online demo mode. Please contact your support representative for more details.
</message>
<message name="IDS_DEMO_SETUP_RECOVERY_FATAL" desc="Error recovery recommendation to contact support. Shown on demo setup screen.">
Please retry. If you see this error again please contact your support representative.
</message>
<message name="IDS_LOGIN_SYNC_CONSENT_SCREEN_TITLE" desc="The title of the dialog that welcomes the user on the first log in, and explains Chrome Sync and privacy options."> <message name="IDS_LOGIN_SYNC_CONSENT_SCREEN_TITLE" desc="The title of the dialog that welcomes the user on the first log in, and explains Chrome Sync and privacy options.">
You're signed in! You're signed in!
</message> </message>
......
...@@ -243,6 +243,22 @@ class DemoSetupTest : public LoginManagerTest { ...@@ -243,6 +243,22 @@ class DemoSetupTest : public LoginManagerTest {
return js_checker().GetBool(query); return js_checker().GetBool(query);
} }
// Returns whether error message is shown on demo setup error screen and
// contains text consisting of strings identified by |error_message_id| and
// |recovery_message_id|.
bool IsErrorMessageShown(int error_message_id, int recovery_message_id) {
const std::string element_selector =
base::StrCat({ScreenToContentQuery(OobeScreen::SCREEN_OOBE_DEMO_SETUP),
".$.", DialogToStringId(DemoSetupDialog::kError),
".querySelector('div[slot=subtitle]')"});
const std::string query = base::StrCat(
{"!!", element_selector, " && ", element_selector, ".innerHTML == '",
l10n_util::GetStringUTF8(error_message_id), " ",
l10n_util::GetStringUTF8(recovery_message_id), "' && !",
element_selector, ".hidden"});
return js_checker().GetBool(query);
}
void SetPlayStoreTermsForTesting() { void SetPlayStoreTermsForTesting() {
EXPECT_TRUE( EXPECT_TRUE(
JSExecute("login.ArcTermsOfServiceScreen.setTosForTesting('Test " JSExecute("login.ArcTermsOfServiceScreen.setTosForTesting('Test "
...@@ -624,6 +640,9 @@ IN_PROC_BROWSER_TEST_F(DemoSetupTest, OnlineSetupFlowError) { ...@@ -624,6 +640,9 @@ IN_PROC_BROWSER_TEST_F(DemoSetupTest, OnlineSetupFlowError) {
// needed to be able to check it reliably. // needed to be able to check it reliably.
WaitForScreenDialog(OobeScreen::SCREEN_OOBE_DEMO_SETUP, WaitForScreenDialog(OobeScreen::SCREEN_OOBE_DEMO_SETUP,
DemoSetupDialog::kError); DemoSetupDialog::kError);
// Default error returned by MockDemoModeOnlineEnrollmentHelperCreator.
EXPECT_TRUE(IsErrorMessageShown(IDS_DEMO_SETUP_TEMPORARY_ERROR,
IDS_DEMO_SETUP_RECOVERY_RETRY));
EXPECT_FALSE(StartupUtils::IsOobeCompleted()); EXPECT_FALSE(StartupUtils::IsOobeCompleted());
EXPECT_FALSE(StartupUtils::IsDeviceRegistered()); EXPECT_FALSE(StartupUtils::IsDeviceRegistered());
} }
...@@ -680,6 +699,8 @@ IN_PROC_BROWSER_TEST_F(DemoSetupTest, OnlineSetupFlowCrosComponentFailure) { ...@@ -680,6 +699,8 @@ IN_PROC_BROWSER_TEST_F(DemoSetupTest, OnlineSetupFlowCrosComponentFailure) {
// needed to be able to check it reliably. // needed to be able to check it reliably.
WaitForScreenDialog(OobeScreen::SCREEN_OOBE_DEMO_SETUP, WaitForScreenDialog(OobeScreen::SCREEN_OOBE_DEMO_SETUP,
DemoSetupDialog::kError); DemoSetupDialog::kError);
EXPECT_TRUE(IsErrorMessageShown(IDS_DEMO_SETUP_COMPONENT_ERROR,
IDS_DEMO_SETUP_RECOVERY_CHECK_NETWORK));
EXPECT_FALSE(StartupUtils::IsOobeCompleted()); EXPECT_FALSE(StartupUtils::IsOobeCompleted());
EXPECT_FALSE(StartupUtils::IsDeviceRegistered()); EXPECT_FALSE(StartupUtils::IsDeviceRegistered());
} }
...@@ -787,6 +808,9 @@ IN_PROC_BROWSER_TEST_F(DemoSetupTest, OfflineSetupFlowError) { ...@@ -787,6 +808,9 @@ IN_PROC_BROWSER_TEST_F(DemoSetupTest, OfflineSetupFlowError) {
// needed to be able to check it reliably. // needed to be able to check it reliably.
WaitForScreenDialog(OobeScreen::SCREEN_OOBE_DEMO_SETUP, WaitForScreenDialog(OobeScreen::SCREEN_OOBE_DEMO_SETUP,
DemoSetupDialog::kError); DemoSetupDialog::kError);
// Default error returned by MockDemoModeOfflineEnrollmentHelperCreator.
EXPECT_TRUE(IsErrorMessageShown(IDS_DEMO_SETUP_LOCK_ERROR,
IDS_DEMO_SETUP_RECOVERY_POWERWASH));
EXPECT_FALSE(StartupUtils::IsOobeCompleted()); EXPECT_FALSE(StartupUtils::IsOobeCompleted());
EXPECT_FALSE(StartupUtils::IsDeviceRegistered()); EXPECT_FALSE(StartupUtils::IsDeviceRegistered());
......
...@@ -21,20 +21,26 @@ ...@@ -21,20 +21,26 @@
#include "chrome/browser/chromeos/policy/device_local_account.h" #include "chrome/browser/chromeos/policy/device_local_account.h"
#include "chrome/browser/chromeos/policy/device_local_account_policy_service.h" #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
#include "chrome/browser/chromeos/policy/enrollment_config.h" #include "chrome/browser/chromeos/policy/enrollment_config.h"
#include "chrome/browser/chromeos/policy/enrollment_status_chromeos.h"
#include "chrome/common/pref_names.h" #include "chrome/common/pref_names.h"
#include "chrome/grit/generated_resources.h"
#include "chromeos/chromeos_switches.h" #include "chromeos/chromeos_switches.h"
#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/settings/install_attributes.h"
#include "chromeos/system/statistics_provider.h" #include "chromeos/system/statistics_provider.h"
#include "components/arc/arc_util.h" #include "components/arc/arc_util.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
#include "google_apis/gaia/google_service_auth_error.h" #include "google_apis/gaia/google_service_auth_error.h"
#include "ui/base/l10n/l10n_util.h"
namespace chromeos { namespace chromeos {
namespace { namespace {
using ErrorCode = DemoSetupController::DemoSetupError::ErrorCode;
using RecoveryMethod = DemoSetupController::DemoSetupError::RecoveryMethod;
constexpr char kDemoRequisition[] = "cros-demo-mode"; constexpr char kDemoRequisition[] = "cros-demo-mode";
constexpr char kOfflineDevicePolicyFileName[] = "device_policy"; constexpr char kOfflineDevicePolicyFileName[] = "device_policy";
constexpr char kOfflineDeviceLocalAccountPolicyFileName[] = constexpr char kOfflineDeviceLocalAccountPolicyFileName[] =
...@@ -89,7 +95,7 @@ policy::CloudPolicyStore* GetDeviceLocalAccountPolicyStore( ...@@ -89,7 +95,7 @@ policy::CloudPolicyStore* GetDeviceLocalAccountPolicyStore(
return broker->core()->store(); return broker->core()->store();
} }
// A utility funciton of base::ReadFileToString which returns an optional // A utility function of base::ReadFileToString which returns an optional
// string. // string.
// TODO(mukai): move this to base/files. // TODO(mukai): move this to base/files.
base::Optional<std::string> ReadFileToOptionalString( base::Optional<std::string> ReadFileToOptionalString(
...@@ -124,11 +130,330 @@ bool IsOnlineFreCheckRequired() { ...@@ -124,11 +130,330 @@ bool IsOnlineFreCheckRequired() {
return block_dev_mode_value == "1"; return block_dev_mode_value == "1";
} }
DemoSetupController::DemoSetupError CreateFromClientStatus(
policy::DeviceManagementStatus status,
const std::string& debug_message) {
switch (status) {
case policy::DM_STATUS_SUCCESS:
return DemoSetupController::DemoSetupError(
ErrorCode::kUnexpectedError, RecoveryMethod::kUnknown, debug_message);
case policy::DM_STATUS_REQUEST_INVALID:
return DemoSetupController::DemoSetupError(
ErrorCode::kInvalidRequest, RecoveryMethod::kUnknown, debug_message);
case policy::DM_STATUS_REQUEST_FAILED:
return DemoSetupController::DemoSetupError(
ErrorCode::kRequestNetworkError, RecoveryMethod::kCheckNetwork,
debug_message);
case policy::DM_STATUS_TEMPORARY_UNAVAILABLE:
return DemoSetupController::DemoSetupError(
ErrorCode::kTemporaryUnavailable, RecoveryMethod::kRetry,
debug_message);
case policy::DM_STATUS_HTTP_STATUS_ERROR:
return DemoSetupController::DemoSetupError(
ErrorCode::kResponseError, RecoveryMethod::kUnknown, debug_message);
case policy::DM_STATUS_RESPONSE_DECODING_ERROR:
return DemoSetupController::DemoSetupError(
ErrorCode::kResponseDecodingError, RecoveryMethod::kUnknown,
debug_message);
case policy::DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED:
case policy::DM_STATUS_SERVICE_CONSUMER_ACCOUNT_WITH_PACKAGED_LICENSE:
case policy::DM_STATUS_SERVICE_ACTIVATION_PENDING:
return DemoSetupController::DemoSetupError(ErrorCode::kDemoAccountError,
RecoveryMethod::kUnknown,
debug_message);
case policy::DM_STATUS_SERVICE_DEVICE_NOT_FOUND:
return DemoSetupController::DemoSetupError(
ErrorCode::kDeviceNotFound, RecoveryMethod::kUnknown, debug_message);
case policy::DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID:
return DemoSetupController::DemoSetupError(
ErrorCode::kInvalidDMToken, RecoveryMethod::kUnknown, debug_message);
case policy::DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER:
return DemoSetupController::DemoSetupError(
ErrorCode::kInvalidSerialNumber, RecoveryMethod::kUnknown,
debug_message);
case policy::DM_STATUS_SERVICE_DEVICE_ID_CONFLICT:
return DemoSetupController::DemoSetupError(
ErrorCode::kDeviceIdError, RecoveryMethod::kUnknown, debug_message);
case policy::DM_STATUS_SERVICE_MISSING_LICENSES:
return DemoSetupController::DemoSetupError(
ErrorCode::kLicenseError, RecoveryMethod::kUnknown, debug_message);
case policy::DM_STATUS_SERVICE_DEPROVISIONED:
return DemoSetupController::DemoSetupError(
ErrorCode::kDeviceDeprovisioned, RecoveryMethod::kUnknown,
debug_message);
case policy::DM_STATUS_SERVICE_DOMAIN_MISMATCH:
return DemoSetupController::DemoSetupError(
ErrorCode::kDomainMismatch, RecoveryMethod::kUnknown, debug_message);
case policy::DM_STATUS_CANNOT_SIGN_REQUEST:
return DemoSetupController::DemoSetupError(
ErrorCode::kSigningError, RecoveryMethod::kPowerwash, debug_message);
case policy::DM_STATUS_SERVICE_POLICY_NOT_FOUND:
return DemoSetupController::DemoSetupError(
ErrorCode::kPolicyNotFound, RecoveryMethod::kUnknown, debug_message);
case policy::DM_STATUS_SERVICE_ARC_DISABLED:
return DemoSetupController::DemoSetupError(
ErrorCode::kArcError, RecoveryMethod::kUnknown, debug_message);
}
NOTREACHED() << "Demo mode setup received unsupported client status";
return DemoSetupController::DemoSetupError(
ErrorCode::kUnexpectedError, RecoveryMethod::kUnknown, debug_message);
}
DemoSetupController::DemoSetupError CreateFromLockStatus(
InstallAttributes::LockResult status,
const std::string& debug_message) {
switch (status) {
case InstallAttributes::LOCK_SUCCESS:
case InstallAttributes::LOCK_NOT_READY:
return DemoSetupController::DemoSetupError(
ErrorCode::kUnexpectedError, RecoveryMethod::kUnknown, debug_message);
case InstallAttributes::LOCK_TIMEOUT:
return DemoSetupController::DemoSetupError(
ErrorCode::kLockTimeout, RecoveryMethod::kReboot, debug_message);
case InstallAttributes::LOCK_BACKEND_INVALID:
case InstallAttributes::LOCK_SET_ERROR:
case InstallAttributes::LOCK_FINALIZE_ERROR:
case InstallAttributes::LOCK_READBACK_ERROR:
return DemoSetupController::DemoSetupError(
ErrorCode::kLockError, RecoveryMethod::kPowerwash, debug_message);
case InstallAttributes::LOCK_ALREADY_LOCKED:
case InstallAttributes::LOCK_WRONG_DOMAIN:
case InstallAttributes::LOCK_WRONG_MODE:
return DemoSetupController::DemoSetupError(
ErrorCode::kAlreadyLocked, RecoveryMethod::kPowerwash, debug_message);
}
NOTREACHED() << "Demo mode setup received unsupported lock status";
return DemoSetupController::DemoSetupError(
ErrorCode::kUnexpectedError, RecoveryMethod::kUnknown, debug_message);
}
} // namespace } // namespace
// static // static
constexpr char DemoSetupController::kDemoModeDomain[]; constexpr char DemoSetupController::kDemoModeDomain[];
// static
DemoSetupController::DemoSetupError
DemoSetupController::DemoSetupError::CreateFromEnrollmentStatus(
const policy::EnrollmentStatus& status) {
const std::string debug_message = base::StringPrintf(
"EnrollmentError: (status: %d, client_status: %d, store_status: %d, "
"validation_status: %d, lock_status: %d)",
status.status(), status.client_status(), status.store_status(),
status.validation_status(), status.lock_status());
switch (status.status()) {
case policy::EnrollmentStatus::SUCCESS:
return DemoSetupError(ErrorCode::kUnexpectedError,
RecoveryMethod::kUnknown, debug_message);
case policy::EnrollmentStatus::NO_STATE_KEYS:
return DemoSetupError(ErrorCode::kNoStateKeys, RecoveryMethod::kReboot,
debug_message);
case policy::EnrollmentStatus::REGISTRATION_FAILED:
return CreateFromClientStatus(status.client_status(), debug_message);
case policy::EnrollmentStatus::ROBOT_AUTH_FETCH_FAILED:
case policy::EnrollmentStatus::ROBOT_REFRESH_FETCH_FAILED:
return DemoSetupError(ErrorCode::kRobotFetchError,
RecoveryMethod::kCheckNetwork, debug_message);
case policy::EnrollmentStatus::ROBOT_REFRESH_STORE_FAILED:
return DemoSetupError(ErrorCode::kRobotStoreError,
RecoveryMethod::kReboot, debug_message);
case policy::EnrollmentStatus::REGISTRATION_BAD_MODE:
return DemoSetupError(ErrorCode::kBadMode, RecoveryMethod::kRetry,
debug_message);
case policy::EnrollmentStatus::REGISTRATION_CERT_FETCH_FAILED:
return DemoSetupError(ErrorCode::kCertFetchError, RecoveryMethod::kRetry,
debug_message);
case policy::EnrollmentStatus::POLICY_FETCH_FAILED:
return DemoSetupError(ErrorCode::kPolicyFetchError,
RecoveryMethod::kRetry, debug_message);
case policy::EnrollmentStatus::VALIDATION_FAILED:
return DemoSetupError(ErrorCode::kPolicyValidationError,
RecoveryMethod::kRetry, debug_message);
case policy::EnrollmentStatus::LOCK_ERROR:
return CreateFromLockStatus(status.lock_status(), debug_message);
case policy::EnrollmentStatus::STORE_ERROR:
return DemoSetupError(ErrorCode::kOnlineStoreError,
RecoveryMethod::kRetry, debug_message);
case policy::EnrollmentStatus::ATTRIBUTE_UPDATE_FAILED:
return DemoSetupError(ErrorCode::kUnexpectedError,
RecoveryMethod::kUnknown, debug_message);
case policy::EnrollmentStatus::NO_MACHINE_IDENTIFICATION:
return DemoSetupError(ErrorCode::kMachineIdentificationError,
RecoveryMethod::kUnknown, debug_message);
case policy::EnrollmentStatus::ACTIVE_DIRECTORY_POLICY_FETCH_FAILED:
return DemoSetupError(ErrorCode::kUnexpectedError,
RecoveryMethod::kReboot, debug_message);
case policy::EnrollmentStatus::DM_TOKEN_STORE_FAILED:
return DemoSetupError(ErrorCode::kDMTokenStoreError,
RecoveryMethod::kUnknown, debug_message);
case policy::EnrollmentStatus::LICENSE_REQUEST_FAILED:
return DemoSetupError(ErrorCode::kLicenseError, RecoveryMethod::kUnknown,
debug_message);
case policy::EnrollmentStatus::OFFLINE_POLICY_LOAD_FAILED:
case policy::EnrollmentStatus::OFFLINE_POLICY_DECODING_FAILED:
return DemoSetupError(ErrorCode::kOfflinePolicyError,
RecoveryMethod::kOnlineOnly, debug_message);
}
NOTREACHED() << "Demo mode setup received unsupported enrollment status";
return DemoSetupError(ErrorCode::kUnexpectedError, RecoveryMethod::kUnknown,
debug_message);
}
// static
DemoSetupController::DemoSetupError
DemoSetupController::DemoSetupError::CreateFromOtherEnrollmentError(
EnterpriseEnrollmentHelper::OtherError error) {
const std::string debug_message =
base::StringPrintf("Other error: %d", error);
switch (error) {
case EnterpriseEnrollmentHelper::OTHER_ERROR_DOMAIN_MISMATCH:
return DemoSetupError(ErrorCode::kAlreadyLocked,
RecoveryMethod::kPowerwash, debug_message);
case EnterpriseEnrollmentHelper::OTHER_ERROR_FATAL:
return DemoSetupError(ErrorCode::kUnexpectedError,
RecoveryMethod::kUnknown, debug_message);
}
NOTREACHED() << "Demo mode setup received unsupported enrollment error";
return DemoSetupError(ErrorCode::kUnexpectedError, RecoveryMethod::kUnknown,
debug_message);
}
// static
DemoSetupController::DemoSetupError
DemoSetupController::DemoSetupError::CreateFromComponentError(
component_updater::CrOSComponentManager::Error error) {
const std::string debug_message =
"Failed to load demo resources CrOS component with error: " +
std::to_string(static_cast<int>(error));
return DemoSetupError(ErrorCode::kOnlineComponentError,
RecoveryMethod::kCheckNetwork, debug_message);
}
DemoSetupController::DemoSetupError::DemoSetupError(
DemoSetupError::ErrorCode error_code,
DemoSetupError::RecoveryMethod recovery_method)
: error_code_(error_code), recovery_method_(recovery_method) {}
DemoSetupController::DemoSetupError::DemoSetupError(
DemoSetupError::ErrorCode error_code,
DemoSetupError::RecoveryMethod recovery_method,
const std::string& debug_message)
: error_code_(error_code),
recovery_method_(recovery_method),
debug_message_(debug_message) {}
DemoSetupController::DemoSetupError::~DemoSetupError() = default;
base::string16 DemoSetupController::DemoSetupError::GetLocalizedErrorMessage()
const {
switch (error_code_) {
case ErrorCode::kNoOfflineResources:
return l10n_util::GetStringUTF16(
IDS_DEMO_SETUP_NO_OFFLINE_RESOURCES_ERROR);
case ErrorCode::kOfflinePolicyError:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_OFFLINE_POLICY_ERROR);
case ErrorCode::kOfflinePolicyStoreError:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_OFFLINE_STORE_ERROR);
case ErrorCode::kOnlineFRECheckRequired:
return l10n_util::GetStringUTF16(
IDS_DEMO_SETUP_OFFLINE_UNAVAILABLE_ERROR);
case ErrorCode::kOnlineComponentError:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_COMPONENT_ERROR);
case ErrorCode::kNoStateKeys:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_NO_STATE_KEYS_ERROR);
case ErrorCode::kInvalidRequest:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_INVALID_REQUEST_ERROR);
case ErrorCode::kRequestNetworkError:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_NETWORK_ERROR);
case ErrorCode::kTemporaryUnavailable:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_TEMPORARY_ERROR);
case ErrorCode::kResponseError:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_RESPONSE_ERROR);
case ErrorCode::kResponseDecodingError:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_RESPONSE_DECODING_ERROR);
case ErrorCode::kDemoAccountError:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_ACCOUNT_ERROR);
case ErrorCode::kDeviceNotFound:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_DEVICE_NOT_FOUND_ERROR);
case ErrorCode::kInvalidDMToken:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_INVALID_DM_TOKEN_ERROR);
case ErrorCode::kInvalidSerialNumber:
return l10n_util::GetStringUTF16(
IDS_DEMO_SETUP_INVALID_SERIAL_NUMBER_ERROR);
case ErrorCode::kDeviceIdError:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_DEVICE_ID_ERROR);
case ErrorCode::kLicenseError:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_LICENSE_ERROR);
case ErrorCode::kDeviceDeprovisioned:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_DEPROVISIONED_ERROR);
case ErrorCode::kDomainMismatch:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_DOMAIN_MISMATCH_ERROR);
case ErrorCode::kSigningError:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_SIGNING_ERROR);
case ErrorCode::kPolicyNotFound:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_POLICY_NOT_FOUND_ERROR);
case ErrorCode::kArcError:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_ARC_ERROR);
case ErrorCode::kRobotFetchError:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_ROBOT_ERROR);
case ErrorCode::kRobotStoreError:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_ROBOT_STORE_ERROR);
case ErrorCode::kBadMode:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_BAD_MODE_ERROR);
case ErrorCode::kCertFetchError:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_CERT_FETCH_ERROR);
case ErrorCode::kPolicyFetchError:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_POLICY_FETCH_ERROR);
case ErrorCode::kPolicyValidationError:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_POLICY_VALIDATION_ERROR);
case ErrorCode::kLockTimeout:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_LOCK_TIMEOUT_ERROR);
case ErrorCode::kLockError:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_LOCK_ERROR);
case ErrorCode::kAlreadyLocked:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_ALREADY_LOCKED_ERROR);
case ErrorCode::kOnlineStoreError:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_ONLINE_STORE_ERROR);
case ErrorCode::kMachineIdentificationError:
return l10n_util::GetStringUTF16(
IDS_DEMO_SETUP_NO_MACHINE_IDENTIFICATION_ERROR);
case ErrorCode::kDMTokenStoreError:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_DM_TOKEN_STORE_ERROR);
case ErrorCode::kUnexpectedError:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_UNEXPECTED_ERROR);
}
NOTREACHED() << "No localized error message available for demo setup error.";
return base::string16();
}
base::string16
DemoSetupController::DemoSetupError::GetLocalizedRecoveryMessage() const {
switch (recovery_method_) {
case RecoveryMethod::kRetry:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_RECOVERY_RETRY);
case RecoveryMethod::kReboot:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_RECOVERY_REBOOT);
case RecoveryMethod::kPowerwash:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_RECOVERY_POWERWASH);
case RecoveryMethod::kCheckNetwork:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_RECOVERY_CHECK_NETWORK);
case RecoveryMethod::kOnlineOnly:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_RECOVERY_OFFLINE_FATAL);
case RecoveryMethod::kUnknown:
return l10n_util::GetStringUTF16(IDS_DEMO_SETUP_RECOVERY_FATAL);
}
NOTREACHED()
<< "No localized error message available for demo setup recovery method.";
return base::string16();
}
std::string DemoSetupController::DemoSetupError::GetDebugDescription() const {
return base::StringPrintf("DemoSetupError (code: %d, recovery: %d) : %s",
error_code_, recovery_method_,
debug_message_.c_str());
}
void DemoSetupController::RegisterLocalStatePrefs( void DemoSetupController::RegisterLocalStatePrefs(
PrefRegistrySimple* registry) { PrefRegistrySimple* registry) {
registry->RegisterIntegerPref( registry->RegisterIntegerPref(
...@@ -233,9 +558,7 @@ void DemoSetupController::OnDemoResourcesCrOSComponentLoaded( ...@@ -233,9 +558,7 @@ void DemoSetupController::OnDemoResourcesCrOSComponentLoaded(
DCHECK_EQ(demo_config_, DemoSession::DemoModeConfig::kOnline); DCHECK_EQ(demo_config_, DemoSession::DemoModeConfig::kOnline);
if (error != component_updater::CrOSComponentManager::Error::NONE) { if (error != component_updater::CrOSComponentManager::Error::NONE) {
SetupFailed("Failed to load demo resources CrOS component with error: " + SetupFailed(DemoSetupError::CreateFromComponentError(error));
std::to_string(static_cast<int>(error)),
DemoSetupError::kRecoverable);
return; return;
} }
...@@ -262,9 +585,10 @@ void DemoSetupController::EnrollOffline(const base::FilePath& policy_dir) { ...@@ -262,9 +585,10 @@ void DemoSetupController::EnrollOffline(const base::FilePath& policy_dir) {
if (IsOnlineFreCheckRequired()) { if (IsOnlineFreCheckRequired()) {
SetupFailed( SetupFailed(
"Cannot do offline demo mode setup, because online FRE check is " DemoSetupError(DemoSetupError::ErrorCode::kOnlineFRECheckRequired,
"required.", DemoSetupError::RecoveryMethod::kOnlineOnly,
DemoSetupError::kFatal); "Cannot do offline demo mode setup, because online "
"FRE check is required."));
return; return;
} }
...@@ -284,7 +608,9 @@ void DemoSetupController::OnOfflinePolicyFilesExisted(std::string* message, ...@@ -284,7 +608,9 @@ void DemoSetupController::OnOfflinePolicyFilesExisted(std::string* message,
DCHECK(!policy_dir_.empty()); DCHECK(!policy_dir_.empty());
if (!ok) { if (!ok) {
SetupFailed(*message, DemoSetupError::kRecoverable); SetupFailed(DemoSetupError(DemoSetupError::ErrorCode::kNoOfflineResources,
DemoSetupError::RecoveryMethod::kOnlineOnly,
*message));
return; return;
} }
...@@ -305,20 +631,12 @@ void DemoSetupController::OnAuthError(const GoogleServiceAuthError& error) { ...@@ -305,20 +631,12 @@ void DemoSetupController::OnAuthError(const GoogleServiceAuthError& error) {
} }
void DemoSetupController::OnEnrollmentError(policy::EnrollmentStatus status) { void DemoSetupController::OnEnrollmentError(policy::EnrollmentStatus status) {
// TODO(mukai): improve the message details. SetupFailed(DemoSetupError::CreateFromEnrollmentStatus(status));
SetupFailed(
base::StringPrintf(
"EnrollmentError: status: %d client_status: %d store_status: %d "
"validation_status: %d lock_status: %d",
status.status(), status.client_status(), status.store_status(),
status.validation_status(), status.lock_status()),
DemoSetupError::kRecoverable);
} }
void DemoSetupController::OnOtherError( void DemoSetupController::OnOtherError(
EnterpriseEnrollmentHelper::OtherError error) { EnterpriseEnrollmentHelper::OtherError error) {
SetupFailed(base::StringPrintf("Other error: %d", error), SetupFailed(DemoSetupError::CreateFromOtherEnrollmentError(error));
DemoSetupError::kRecoverable);
} }
void DemoSetupController::OnDeviceEnrolled( void DemoSetupController::OnDeviceEnrolled(
...@@ -378,15 +696,18 @@ void DemoSetupController::OnDeviceLocalAccountPolicyLoaded( ...@@ -378,15 +696,18 @@ void DemoSetupController::OnDeviceLocalAccountPolicyLoaded(
if (!blob.has_value()) { if (!blob.has_value()) {
// This is very unlikely to happen since the file existence is already // This is very unlikely to happen since the file existence is already
// checked as CheckOfflinePolicyFilesExist. // checked as CheckOfflinePolicyFilesExist.
SetupFailed("Policy file for the device local account not found", SetupFailed(
DemoSetupError::kFatal); DemoSetupError(DemoSetupError::ErrorCode::kOfflinePolicyError,
DemoSetupError::RecoveryMethod::kPowerwash,
"Policy file for the device local account not found"));
return; return;
} }
enterprise_management::PolicyFetchResponse policy; enterprise_management::PolicyFetchResponse policy;
if (!policy.ParseFromString(blob.value())) { if (!policy.ParseFromString(blob.value())) {
SetupFailed("Error parsing local account policy blob.", SetupFailed(DemoSetupError(DemoSetupError::ErrorCode::kOfflinePolicyError,
DemoSetupError::kFatal); DemoSetupError::RecoveryMethod::kPowerwash,
"Error parsing local account policy blob."));
return; return;
} }
...@@ -394,8 +715,9 @@ void DemoSetupController::OnDeviceLocalAccountPolicyLoaded( ...@@ -394,8 +715,9 @@ void DemoSetupController::OnDeviceLocalAccountPolicyLoaded(
enterprise_management::PolicyData policy_data; enterprise_management::PolicyData policy_data;
if (policy.policy_data().empty() || if (policy.policy_data().empty() ||
!policy_data.ParseFromString(policy.policy_data())) { !policy_data.ParseFromString(policy.policy_data())) {
SetupFailed("Error parsing local account policy data.", SetupFailed(DemoSetupError(DemoSetupError::ErrorCode::kOfflinePolicyError,
DemoSetupError::kFatal); DemoSetupError::RecoveryMethod::kPowerwash,
"Error parsing local account policy data."));
return; return;
} }
...@@ -408,8 +730,10 @@ void DemoSetupController::OnDeviceLocalAccountPolicyLoaded( ...@@ -408,8 +730,10 @@ void DemoSetupController::OnDeviceLocalAccountPolicyLoaded(
} }
if (!device_local_account_policy_store_) { if (!device_local_account_policy_store_) {
SetupFailed("Can't find the store for the local account policy.", SetupFailed(
DemoSetupError::kFatal); DemoSetupError(DemoSetupError::ErrorCode::kOfflinePolicyStoreError,
DemoSetupError::RecoveryMethod::kPowerwash,
"Can't find the store for the local account policy."));
return; return;
} }
device_local_account_policy_store_->AddObserver(this); device_local_account_policy_store_->AddObserver(this);
...@@ -426,10 +750,9 @@ void DemoSetupController::OnDeviceRegistered() { ...@@ -426,10 +750,9 @@ void DemoSetupController::OnDeviceRegistered() {
std::move(on_setup_success_).Run(); std::move(on_setup_success_).Run();
} }
void DemoSetupController::SetupFailed(const std::string& message, void DemoSetupController::SetupFailed(const DemoSetupError& error) {
DemoSetupError error) {
Reset(); Reset();
LOG(ERROR) << message << " fatal=" << (error == DemoSetupError::kFatal); LOG(ERROR) << error.GetDebugDescription();
if (!on_setup_error_.is_null()) if (!on_setup_error_.is_null())
std::move(on_setup_error_).Run(error); std::move(on_setup_error_).Run(error);
} }
...@@ -463,8 +786,10 @@ void DemoSetupController::OnStoreLoaded(policy::CloudPolicyStore* store) { ...@@ -463,8 +786,10 @@ void DemoSetupController::OnStoreLoaded(policy::CloudPolicyStore* store) {
void DemoSetupController::OnStoreError(policy::CloudPolicyStore* store) { void DemoSetupController::OnStoreError(policy::CloudPolicyStore* store) {
DCHECK_EQ(store, device_local_account_policy_store_); DCHECK_EQ(store, device_local_account_policy_store_);
SetupFailed("Failed to store the local account policy", SetupFailed(
DemoSetupError::kFatal); DemoSetupError(DemoSetupError::ErrorCode::kOfflinePolicyStoreError,
DemoSetupError::RecoveryMethod::kPowerwash,
"Failed to store the local account policy"));
} }
} // namespace chromeos } // namespace chromeos
...@@ -11,8 +11,10 @@ ...@@ -11,8 +11,10 @@
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "chrome/browser/chromeos/login/demo_mode/demo_session.h" #include "chrome/browser/chromeos/login/demo_mode/demo_session.h"
#include "chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper.h" #include "chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper.h"
#include "chrome/browser/chromeos/policy/enrollment_status_chromeos.h"
#include "chrome/browser/component_updater/cros_component_installer_chromeos.h" #include "chrome/browser/component_updater/cros_component_installer_chromeos.h"
#include "components/policy/core/common/cloud/cloud_policy_store.h" #include "components/policy/core/common/cloud/cloud_policy_store.h"
...@@ -29,19 +31,130 @@ class DemoSetupController ...@@ -29,19 +31,130 @@ class DemoSetupController
: public EnterpriseEnrollmentHelper::EnrollmentStatusConsumer, : public EnterpriseEnrollmentHelper::EnrollmentStatusConsumer,
public policy::CloudPolicyStore::Observer { public policy::CloudPolicyStore::Observer {
public: public:
// Type of demo mode setup error. // Contains information related to setup error.
enum class DemoSetupError { class DemoSetupError {
// Recoverable or temporary demo mode setup error. Another attempt to setup public:
// demo mode may succeed. // Type of setup error.
kRecoverable, enum class ErrorCode {
// Fatal demo mode setup error. Device requires powerwash to recover from // Offline resources not available on device.
// the resulting state. kNoOfflineResources,
kFatal, // Cannot load or parse offline policy.
kOfflinePolicyError,
// Local account policy store error.
kOfflinePolicyStoreError,
// Cannot perform offline setup without online FRE check.
kOnlineFRECheckRequired,
// Cannot load online component.
kOnlineComponentError,
// Invalid request to DMServer.
kInvalidRequest,
// Request to DMServer failed, because of network error.
kRequestNetworkError,
// DMServer temporary unavailable.
kTemporaryUnavailable,
// DMServer returned abnormal response code.
kResponseError,
// DMServer response cannot be decoded.
kResponseDecodingError,
// Device management not supported for demo account.
kDemoAccountError,
// DMServer cannot find the device.
kDeviceNotFound,
// Invalid device management token.
kInvalidDMToken,
// Serial number invalid or unknown to DMServer,
kInvalidSerialNumber,
// Device id conflict.
kDeviceIdError,
// Not enough licenses or domain expired.
kLicenseError,
// Device was deprovisioned.ec
kDeviceDeprovisioned,
// Device belongs to different domain (FRE).
kDomainMismatch,
// Management request could not be signed by the client.
kSigningError,
// DMServer could not find policy for the device.
kPolicyNotFound,
// ARC disabled for demo domain.
kArcError,
// Cannot determine server-backed state keys.
kNoStateKeys,
// Failed to fetch robot account auth or refresh token.
kRobotFetchError,
// Failed to fetch robot account refresh token.
kRobotStoreError,
// Unsuppored device mode returned by the server.
kBadMode,
// Could not fetch registration cert,
kCertFetchError,
// Could not fetch the policy.
kPolicyFetchError,
// Policy validation failed.
kPolicyValidationError,
// Timeout during locking the device.
kLockTimeout,
// Error during locking the device.
kLockError,
// Device locked to different domain on mode.
kAlreadyLocked,
// Error while installing online policy.
kOnlineStoreError,
// Could not determine device model or serial number.
kMachineIdentificationError,
// Could not store DM token.
kDMTokenStoreError,
// Unexpected/fatal error.
kUnexpectedError,
};
// Type of recommended recovery from the setup error.
enum class RecoveryMethod {
// Retry demo setup.
kRetry,
// Reboot and retry demo setup.
kReboot,
// Powerwash and retry demo setup.
kPowerwash,
// Check network and retry demo setup.
kCheckNetwork,
// Cannot perform offline setup - online setup might work.
kOnlineOnly,
// Unknown recovery method.
kUnknown,
};
static DemoSetupError CreateFromEnrollmentStatus(
const policy::EnrollmentStatus& status);
static DemoSetupError CreateFromOtherEnrollmentError(
EnterpriseEnrollmentHelper::OtherError error);
static DemoSetupError CreateFromComponentError(
component_updater::CrOSComponentManager::Error error);
DemoSetupError(ErrorCode error_code, RecoveryMethod recovery_method);
DemoSetupError(ErrorCode error_code,
RecoveryMethod recovery_method,
const std::string& debug_message);
~DemoSetupError();
ErrorCode error_code() const { return error_code_; }
RecoveryMethod recovery_method() const { return recovery_method_; }
base::string16 GetLocalizedErrorMessage() const;
base::string16 GetLocalizedRecoveryMessage() const;
std::string GetDebugDescription() const;
private:
ErrorCode error_code_;
RecoveryMethod recovery_method_;
std::string debug_message_;
}; };
// Demo mode setup callbacks. // Demo mode setup callbacks.
using OnSetupSuccess = base::OnceClosure; using OnSetupSuccess = base::OnceClosure;
using OnSetupError = base::OnceCallback<void(DemoSetupError)>; using OnSetupError = base::OnceCallback<void(const DemoSetupError&)>;
// Domain that demo mode devices are enrolled into. // Domain that demo mode devices are enrolled into.
static constexpr char kDemoModeDomain[] = "cros-demo-mode.com"; static constexpr char kDemoModeDomain[] = "cros-demo-mode.com";
...@@ -129,8 +242,8 @@ class DemoSetupController ...@@ -129,8 +242,8 @@ class DemoSetupController
// is completed. This is the last step of demo mode setup flow. // is completed. This is the last step of demo mode setup flow.
void OnDeviceRegistered(); void OnDeviceRegistered();
// Finish the flow with an error message. // Finish the flow with an error.
void SetupFailed(const std::string& message, DemoSetupError error); void SetupFailed(const DemoSetupError& error);
// Clears the internal state. // Clears the internal state.
void Reset(); void Reset();
......
...@@ -46,7 +46,7 @@ class DemoSetupControllerTestHelper { ...@@ -46,7 +46,7 @@ class DemoSetupControllerTestHelper {
: run_loop_(std::make_unique<base::RunLoop>()) {} : run_loop_(std::make_unique<base::RunLoop>()) {}
virtual ~DemoSetupControllerTestHelper() = default; virtual ~DemoSetupControllerTestHelper() = default;
void OnSetupError(DemoSetupController::DemoSetupError error) { void OnSetupError(const DemoSetupController::DemoSetupError& error) {
EXPECT_FALSE(succeeded_.has_value()); EXPECT_FALSE(succeeded_.has_value());
succeeded_ = false; succeeded_ = false;
error_ = error; error_ = error;
...@@ -67,9 +67,11 @@ class DemoSetupControllerTestHelper { ...@@ -67,9 +67,11 @@ class DemoSetupControllerTestHelper {
return succeeded_.has_value() && succeeded_.value() == expected; return succeeded_.has_value() && succeeded_.value() == expected;
} }
// Returns true if it receives a fatal error. // Returns true if powerwash is required to recover from the error.
bool IsErrorFatal() const { bool RequiresPowerwash() const {
return error_ == DemoSetupController::DemoSetupError::kFatal; return error_.has_value() &&
error_->recovery_method() ==
DemoSetupController::DemoSetupError::RecoveryMethod::kPowerwash;
} }
void Reset() { void Reset() {
...@@ -79,8 +81,7 @@ class DemoSetupControllerTestHelper { ...@@ -79,8 +81,7 @@ class DemoSetupControllerTestHelper {
private: private:
base::Optional<bool> succeeded_; base::Optional<bool> succeeded_;
DemoSetupController::DemoSetupError error_ = base::Optional<DemoSetupController::DemoSetupError> error_;
DemoSetupController::DemoSetupError::kRecoverable;
std::unique_ptr<base::RunLoop> run_loop_; std::unique_ptr<base::RunLoop> run_loop_;
DISALLOW_COPY_AND_ASSIGN(DemoSetupControllerTestHelper); DISALLOW_COPY_AND_ASSIGN(DemoSetupControllerTestHelper);
...@@ -177,7 +178,7 @@ TEST_F(DemoSetupControllerTest, OfflineDeviceLocalAccountPolicyLoadFailure) { ...@@ -177,7 +178,7 @@ TEST_F(DemoSetupControllerTest, OfflineDeviceLocalAccountPolicyLoadFailure) {
base::Unretained(helper_.get()))); base::Unretained(helper_.get())));
EXPECT_TRUE(helper_->WaitResult(false)); EXPECT_TRUE(helper_->WaitResult(false));
EXPECT_FALSE(helper_->IsErrorFatal()); EXPECT_FALSE(helper_->RequiresPowerwash());
EXPECT_EQ("", GetDeviceRequisition()); EXPECT_EQ("", GetDeviceRequisition());
} }
...@@ -203,7 +204,7 @@ TEST_F(DemoSetupControllerTest, OfflineDeviceLocalAccountPolicyStoreFailed) { ...@@ -203,7 +204,7 @@ TEST_F(DemoSetupControllerTest, OfflineDeviceLocalAccountPolicyStoreFailed) {
base::Unretained(helper_.get()))); base::Unretained(helper_.get())));
EXPECT_TRUE(helper_->WaitResult(false)); EXPECT_TRUE(helper_->WaitResult(false));
EXPECT_TRUE(helper_->IsErrorFatal()); EXPECT_TRUE(helper_->RequiresPowerwash());
EXPECT_EQ("", GetDeviceRequisition()); EXPECT_EQ("", GetDeviceRequisition());
} }
...@@ -224,7 +225,7 @@ TEST_F(DemoSetupControllerTest, OfflineInvalidDeviceLocalAccountPolicyBlob) { ...@@ -224,7 +225,7 @@ TEST_F(DemoSetupControllerTest, OfflineInvalidDeviceLocalAccountPolicyBlob) {
base::Unretained(helper_.get()))); base::Unretained(helper_.get())));
EXPECT_TRUE(helper_->WaitResult(false)); EXPECT_TRUE(helper_->WaitResult(false));
EXPECT_TRUE(helper_->IsErrorFatal()); EXPECT_TRUE(helper_->RequiresPowerwash());
EXPECT_EQ("", GetDeviceRequisition()); EXPECT_EQ("", GetDeviceRequisition());
} }
...@@ -248,7 +249,7 @@ TEST_F(DemoSetupControllerTest, OfflineError) { ...@@ -248,7 +249,7 @@ TEST_F(DemoSetupControllerTest, OfflineError) {
base::Unretained(helper_.get()))); base::Unretained(helper_.get())));
EXPECT_TRUE(helper_->WaitResult(false)); EXPECT_TRUE(helper_->WaitResult(false));
EXPECT_FALSE(helper_->IsErrorFatal()); EXPECT_TRUE(helper_->RequiresPowerwash());
EXPECT_EQ("", GetDeviceRequisition()); EXPECT_EQ("", GetDeviceRequisition());
} }
...@@ -279,7 +280,7 @@ TEST_F(DemoSetupControllerTest, OnlineError) { ...@@ -279,7 +280,7 @@ TEST_F(DemoSetupControllerTest, OnlineError) {
base::Unretained(helper_.get()))); base::Unretained(helper_.get())));
EXPECT_TRUE(helper_->WaitResult(false)); EXPECT_TRUE(helper_->WaitResult(false));
EXPECT_FALSE(helper_->IsErrorFatal()); EXPECT_FALSE(helper_->RequiresPowerwash());
EXPECT_EQ("", GetDeviceRequisition()); EXPECT_EQ("", GetDeviceRequisition());
} }
...@@ -298,7 +299,7 @@ TEST_F(DemoSetupControllerTest, OnlineComponentError) { ...@@ -298,7 +299,7 @@ TEST_F(DemoSetupControllerTest, OnlineComponentError) {
base::Unretained(helper_.get()))); base::Unretained(helper_.get())));
EXPECT_TRUE(helper_->WaitResult(false)); EXPECT_TRUE(helper_->WaitResult(false));
EXPECT_FALSE(helper_->IsErrorFatal()); EXPECT_FALSE(helper_->RequiresPowerwash());
EXPECT_EQ("", GetDeviceRequisition()); EXPECT_EQ("", GetDeviceRequisition());
} }
...@@ -314,7 +315,7 @@ TEST_F(DemoSetupControllerTest, EnrollTwice) { ...@@ -314,7 +315,7 @@ TEST_F(DemoSetupControllerTest, EnrollTwice) {
base::Unretained(helper_.get()))); base::Unretained(helper_.get())));
EXPECT_TRUE(helper_->WaitResult(false)); EXPECT_TRUE(helper_->WaitResult(false));
EXPECT_FALSE(helper_->IsErrorFatal()); EXPECT_FALSE(helper_->RequiresPowerwash());
EXPECT_EQ("", GetDeviceRequisition()); EXPECT_EQ("", GetDeviceRequisition());
helper_->Reset(); helper_->Reset();
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#include "chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper_mock.h" #include "chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper_mock.h"
#include "chrome/browser/chromeos/policy/enrollment_config.h" #include "chrome/browser/chromeos/policy/enrollment_config.h"
#include "chrome/browser/chromeos/policy/enrollment_status_chromeos.h" #include "chrome/browser/chromeos/policy/enrollment_status_chromeos.h"
#include "chromeos/settings/install_attributes.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -40,8 +42,9 @@ EnterpriseEnrollmentHelper* MockDemoModeOnlineEnrollmentHelperCreator( ...@@ -40,8 +42,9 @@ EnterpriseEnrollmentHelper* MockDemoModeOnlineEnrollmentHelperCreator(
} else { } else {
// TODO(agawronska): Test different error types. // TODO(agawronska): Test different error types.
mock->status_consumer()->OnEnrollmentError( mock->status_consumer()->OnEnrollmentError(
policy::EnrollmentStatus::ForStatus( policy::EnrollmentStatus::ForRegistrationError(
policy::EnrollmentStatus::REGISTRATION_FAILED)); policy::DeviceManagementStatus::
DM_STATUS_TEMPORARY_UNAVAILABLE));
} }
})); }));
return mock; return mock;
...@@ -66,8 +69,8 @@ EnterpriseEnrollmentHelper* MockDemoModeOfflineEnrollmentHelperCreator( ...@@ -66,8 +69,8 @@ EnterpriseEnrollmentHelper* MockDemoModeOfflineEnrollmentHelperCreator(
} else { } else {
// TODO(agawronska): Test different error types. // TODO(agawronska): Test different error types.
mock->status_consumer()->OnEnrollmentError( mock->status_consumer()->OnEnrollmentError(
policy::EnrollmentStatus::ForStatus( policy::EnrollmentStatus::ForLockError(
policy::EnrollmentStatus::Status::LOCK_ERROR)); chromeos::InstallAttributes::LOCK_READBACK_ERROR));
} }
})); }));
return mock; return mock;
......
...@@ -52,10 +52,6 @@ void DemoSetupScreen::OnUserAction(const std::string& action_id) { ...@@ -52,10 +52,6 @@ void DemoSetupScreen::OnUserAction(const std::string& action_id) {
} }
} }
void DemoSetupScreen::OnSetupError(DemoSetupController::DemoSetupError error) {
// TODO(mukai): propagate |error| information and change the error message.
view_->OnSetupFinished(false, std::string());
}
void DemoSetupScreen::StartEnrollment() { void DemoSetupScreen::StartEnrollment() {
// Demo setup screen is only shown in OOBE. // Demo setup screen is only shown in OOBE.
...@@ -68,6 +64,11 @@ void DemoSetupScreen::StartEnrollment() { ...@@ -68,6 +64,11 @@ void DemoSetupScreen::StartEnrollment() {
weak_ptr_factory_.GetWeakPtr())); weak_ptr_factory_.GetWeakPtr()));
} }
void DemoSetupScreen::OnSetupError(
const DemoSetupController::DemoSetupError& error) {
view_->OnSetupFailed(error);
}
void DemoSetupScreen::OnSetupSuccess() { void DemoSetupScreen::OnSetupSuccess() {
Finish(ScreenExitCode::DEMO_MODE_SETUP_FINISHED); Finish(ScreenExitCode::DEMO_MODE_SETUP_FINISHED);
} }
......
...@@ -38,7 +38,7 @@ class DemoSetupScreen : public BaseScreen { ...@@ -38,7 +38,7 @@ class DemoSetupScreen : public BaseScreen {
void StartEnrollment(); void StartEnrollment();
// Called when the setup flow finished with error. // Called when the setup flow finished with error.
void OnSetupError(DemoSetupController::DemoSetupError error); void OnSetupError(const DemoSetupController::DemoSetupError& error);
// Called when the setup flow finished successfully. // Called when the setup flow finished successfully.
void OnSetupSuccess(); void OnSetupSuccess();
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <string> #include <string>
#include "chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h"
#include "chrome/browser/chromeos/login/oobe_screen.h" #include "chrome/browser/chromeos/login/oobe_screen.h"
namespace chromeos { namespace chromeos {
...@@ -29,8 +30,12 @@ class DemoSetupScreenView { ...@@ -29,8 +30,12 @@ class DemoSetupScreenView {
// Sets view and screen. // Sets view and screen.
virtual void Bind(DemoSetupScreen* screen) = 0; virtual void Bind(DemoSetupScreen* screen) = 0;
// Handles setup result. // Handles successful setup.
virtual void OnSetupFinished(bool is_success, const std::string& message) = 0; virtual void OnSetupSucceeded() = 0;
// Handles setup failure.
virtual void OnSetupFailed(
const DemoSetupController::DemoSetupError& error) = 0;
}; };
} // namespace chromeos } // namespace chromeos
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_MOCK_DEMO_SETUP_SCREEN_H_ #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_MOCK_DEMO_SETUP_SCREEN_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_MOCK_DEMO_SETUP_SCREEN_H_ #define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_MOCK_DEMO_SETUP_SCREEN_H_
#include "chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h"
#include "chrome/browser/chromeos/login/screens/demo_setup_screen.h" #include "chrome/browser/chromeos/login/screens/demo_setup_screen.h"
#include "chrome/browser/chromeos/login/screens/demo_setup_screen_view.h" #include "chrome/browser/chromeos/login/screens/demo_setup_screen_view.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
...@@ -26,8 +27,9 @@ class MockDemoSetupScreenView : public DemoSetupScreenView { ...@@ -26,8 +27,9 @@ class MockDemoSetupScreenView : public DemoSetupScreenView {
MOCK_METHOD0(Show, void()); MOCK_METHOD0(Show, void());
MOCK_METHOD0(Hide, void()); MOCK_METHOD0(Hide, void());
MOCK_METHOD1(MockBind, void(DemoSetupScreen* screen)); MOCK_METHOD1(MockBind, void(DemoSetupScreen* screen));
MOCK_METHOD2(OnSetupFinished, MOCK_METHOD0(OnSetupSucceeded, void());
void(bool is_success, const std::string& message)); MOCK_METHOD1(OnSetupFailed,
void(const DemoSetupController::DemoSetupError& error));
void Bind(DemoSetupScreen* screen) override; void Bind(DemoSetupScreen* screen) override;
......
...@@ -45,9 +45,7 @@ ...@@ -45,9 +45,7 @@
icon1x="demo-setup-32:computer" icon2x="demo-setup-64:computer"> icon1x="demo-setup-32:computer" icon2x="demo-setup-64:computer">
</hd-iron-icon> </hd-iron-icon>
<h1 slot="title">[[i18nDynamic(locale, 'demoSetupErrorScreenTitle')]]</h1> <h1 slot="title">[[i18nDynamic(locale, 'demoSetupErrorScreenTitle')]]</h1>
<div slot="subtitle"> <div slot="subtitle">[[errorMessage_]]</div>
[[i18nDynamic(locale, 'demoSetupErrorScreenSubtitle')]]
</div>
<div slot="footer" class="flex layout vertical center center-justified"> <div slot="footer" class="flex layout vertical center center-justified">
<img srcset="images/alert-illustration_1x.svg 1x, <img srcset="images/alert-illustration_1x.svg 1x,
images/alert-illustration_2x.svg 2x"> images/alert-illustration_2x.svg 2x">
......
...@@ -13,6 +13,12 @@ Polymer({ ...@@ -13,6 +13,12 @@ Polymer({
behaviors: [I18nBehavior, OobeDialogHostBehavior], behaviors: [I18nBehavior, OobeDialogHostBehavior],
properties: { properties: {
/** Error message displayed on demoSetupErrorDialog screen. */
errorMessage_: {
type: String,
value: '',
},
/** Ordered array of screen ids that are a part of demo setup flow. */ /** Ordered array of screen ids that are a part of demo setup flow. */
screens_: { screens_: {
type: Array, type: Array,
...@@ -34,16 +40,18 @@ Polymer({ ...@@ -34,16 +40,18 @@ Polymer({
this.i18nUpdateLocale(); this.i18nUpdateLocale();
}, },
/** Called when demo mode setup succeeded. */
onSetupSucceeded: function() {
this.errorMessage_ = '';
},
/** /**
* Called when demo mode setup finished. * Called when demo mode setup failed.
* @param {boolean} isSuccess Whether demo setup finished successfully. * @param {string} message Error message to be displayed to the user.
* @param {string} message Error message to be displayed to the user if setup
* finished with an error.
*/ */
onSetupFinished: function(isSuccess, message) { onSetupFailed: function(message) {
if (!isSuccess) { this.errorMessage_ = message;
this.showScreen_('demoSetupErrorDialog'); this.showScreen_('demoSetupErrorDialog');
}
}, },
/** /**
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
login.createScreen('DemoSetupScreen', 'demo-setup', function() { login.createScreen('DemoSetupScreen', 'demo-setup', function() {
return { return {
EXTERNAL_API: ['onSetupFinished'], EXTERNAL_API: ['onSetupSucceeded', 'onSetupFailed'],
/** /**
* Demo setup module. * Demo setup module.
...@@ -37,14 +37,17 @@ login.createScreen('DemoSetupScreen', 'demo-setup', function() { ...@@ -37,14 +37,17 @@ login.createScreen('DemoSetupScreen', 'demo-setup', function() {
this.demoSetupModule_.reset(); this.demoSetupModule_.reset();
}, },
/** Called when demo mode setup succeeded. */
onSetupSucceeded: function() {
this.demoSetupModule_.onSetupSucceeded();
},
/** /**
* Called when demo mode setup finished. * Called when demo mode setup failed.
* @param {boolean} isSuccess Whether demo setup finished successfully. * @param {string} message Error message to be displayed to the user.
* @param {string} message Error message to be displayed to the user,
* populated if setup finished with an error.
*/ */
onSetupFinished: function(isSuccess, message) { onSetupFailed: function(message) {
this.demoSetupModule_.onSetupFinished(isSuccess, message); this.demoSetupModule_.onSetupFailed(message);
}, },
}; };
}); });
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
#include "chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chromeos/login/oobe_screen.h" #include "chrome/browser/chromeos/login/oobe_screen.h"
#include "chrome/browser/chromeos/login/screens/demo_setup_screen.h" #include "chrome/browser/chromeos/login/screens/demo_setup_screen.h"
#include "chrome/grit/generated_resources.h" #include "chrome/grit/generated_resources.h"
...@@ -38,9 +41,16 @@ void DemoSetupScreenHandler::Bind(DemoSetupScreen* screen) { ...@@ -38,9 +41,16 @@ void DemoSetupScreenHandler::Bind(DemoSetupScreen* screen) {
BaseScreenHandler::SetBaseScreen(screen); BaseScreenHandler::SetBaseScreen(screen);
} }
void DemoSetupScreenHandler::OnSetupFinished(bool is_success, void DemoSetupScreenHandler::OnSetupFailed(
const std::string& message) { const DemoSetupController::DemoSetupError& error) {
CallJS("onSetupFinished", is_success, message); CallJS("onSetupFailed",
base::JoinString({error.GetLocalizedErrorMessage(),
error.GetLocalizedRecoveryMessage()},
base::UTF8ToUTF16(" ")));
}
void DemoSetupScreenHandler::OnSetupSucceeded() {
CallJS("onSetupSucceeded");
} }
void DemoSetupScreenHandler::Initialize() {} void DemoSetupScreenHandler::Initialize() {}
...@@ -51,8 +61,6 @@ void DemoSetupScreenHandler::DeclareLocalizedValues( ...@@ -51,8 +61,6 @@ void DemoSetupScreenHandler::DeclareLocalizedValues(
IDS_OOBE_DEMO_SETUP_PROGRESS_SCREEN_TITLE); IDS_OOBE_DEMO_SETUP_PROGRESS_SCREEN_TITLE);
builder->Add("demoSetupErrorScreenTitle", builder->Add("demoSetupErrorScreenTitle",
IDS_OOBE_DEMO_SETUP_ERROR_SCREEN_TITLE); IDS_OOBE_DEMO_SETUP_ERROR_SCREEN_TITLE);
builder->Add("demoSetupErrorScreenSubtitle",
IDS_OOBE_DEMO_SETUP_ERROR_SCREEN_SUBTITLE);
builder->Add("demoSetupErrorScreenRetryButtonLabel", builder->Add("demoSetupErrorScreenRetryButtonLabel",
IDS_OOBE_DEMO_SETUP_ERROR_SCREEN_RETRY_BUTTON_LABEL); IDS_OOBE_DEMO_SETUP_ERROR_SCREEN_RETRY_BUTTON_LABEL);
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_DEMO_SETUP_SCREEN_HANDLER_H_ #ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_DEMO_SETUP_SCREEN_HANDLER_H_
#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_DEMO_SETUP_SCREEN_HANDLER_H_ #define CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_DEMO_SETUP_SCREEN_HANDLER_H_
#include "chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h"
#include "chrome/browser/chromeos/login/screens/demo_setup_screen_view.h" #include "chrome/browser/chromeos/login/screens/demo_setup_screen_view.h"
#include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
...@@ -24,7 +25,8 @@ class DemoSetupScreenHandler : public BaseScreenHandler, ...@@ -24,7 +25,8 @@ class DemoSetupScreenHandler : public BaseScreenHandler,
void Show() override; void Show() override;
void Hide() override; void Hide() override;
void Bind(DemoSetupScreen* screen) override; void Bind(DemoSetupScreen* screen) override;
void OnSetupFinished(bool is_success, const std::string& message) override; void OnSetupFailed(const DemoSetupController::DemoSetupError& error) override;
void OnSetupSucceeded() override;
// BaseScreenHandler: // BaseScreenHandler:
void Initialize() override; void Initialize() override;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment