diff options
25 files changed, 866 insertions, 439 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 92c4cb7..12bc515 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -5622,6 +5622,109 @@ Keep your key file in a safe place. You will need it to create new versions of y PPAPI (unsandboxed) </message> + <!-- policy status messages --> + <message name="IDS_POLICY_DM_STATUS_SUCCESS" desc="Message indicating a successful device management server call."> + Request succeeded + </message> + <message name="IDS_POLICY_DM_STATUS_REQUEST_INVALID" desc="Message indicating a bad request to the enterprise server."> + Invalid request or request parameters + </message> + <message name="IDS_POLICY_DM_STATUS_REQUEST_FAILED" desc="Message indicating the request to the enterprise server failed in the network."> + Network error + </message> + <message name="IDS_POLICY_DM_STATUS_TEMPORARY_UNAVAILABLE" desc="Message indicating a temporary problem on the enterprise server."> + Temporary server error + </message> + <message name="IDS_POLICY_DM_STATUS_HTTP_STATUS_ERROR" desc="Message indicating an abnormal response code from the enterprise server."> + HTTP error + </message> + <message name="IDS_POLICY_DM_STATUS_RESPONSE_DECODING_ERROR" desc="Message indicating a problem decoding a response from the enterprise server."> + Failed to decode response + </message> + <message name="IDS_POLICY_DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED" desc="Message indicating that enterprise management is not applicable to the user/device."> + Management not supported + </message> + <message name="IDS_POLICY_DM_STATUS_SERVICE_DEVICE_NOT_FOUND" desc="Message indicating the enterprise server is missing a device record."> + Missing device record + </message> + <message name="IDS_POLICY_DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID" desc="Message indicating the token used to authenticate to the enterprise server is invalid."> + Invalid device management token + </message> + <message name="IDS_POLICY_DM_STATUS_SERVICE_ACTIVATION_PENDING" desc="Message indicating enterprise management must first be activated for this user/device."> + Activation is pending on the server + </message> + <message name="IDS_POLICY_DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER" desc="Message indicating the provided device serial number is invalid."> + Device serial number is invalid + </message> + <message name="IDS_POLICY_DM_STATUS_SERVICE_DEVICE_ID_CONFLICT" desc="Message indicating the chosen device identifier is already used."> + Conflicting device identifier + </message> + <message name="IDS_POLICY_DM_STATUS_SERVICE_MISSING_LICENSES" desc="Message indicating the enterprise server doesn't have enough licenses to allow management."> + Licenses exhausted + </message> + <message name="IDS_POLICY_DM_STATUS_SERVICE_POLICY_NOT_FOUND" desc="Message indicating that the enterprise server failed to find the policy to be applied to the device."> + Policy not found + </message> + <message name="IDS_POLICY_DM_STATUS_UNKNOWN_ERROR" desc="Message indicating an unknown error from the enterprise server."> + Unknown error + </message> + + <message name="IDS_POLICY_VALIDATION_OK" desc="Message indicating successful policy validation."> + Validation successful + </message> + <message name="IDS_POLICY_VALIDATION_BAD_SIGNATURE" desc="Message indicating a bad signature on policy validation."> + Bad signature + </message> + <message name="IDS_POLICY_VALIDATION_ERROR_CODE_PRESENT" desc="Message indicating policy validation failure due to an error code in the policy."> + Error code present in the policy response + </message> + <message name="IDS_POLICY_VALIDATION_PAYLOAD_PARSE_ERROR" desc="Message indicating a policy parse error during policy validation."> + Error parsing policy + </message> + <message name="IDS_POLICY_VALIDATION_WRONG_POLICY_TYPE" desc="Message indicating the policy did not have the expected type."> + Wrong policy type + </message> + <message name="IDS_POLICY_VALIDATION_BAD_TIMESTAMP" desc="Message indicating the policy timestamp is bad."> + Bad policy timestamp + </message> + <message name="IDS_POLICY_VALIDATION_WRONG_TOKEN" desc="Message indicating the policy token is different from the one expected."> + Returned policy token doesn't match current token + </message> + <message name="IDS_POLICY_VALIDATION_BAD_USERNAME" desc="Message indicating policy validation failed due to bad username/domain."> + Wrong policy subject + </message> + <message name="IDS_POLICY_VALIDATION_POLICY_PARSE_ERROR" desc="Message indicating a parse error in policy."> + Error parsing policy settings + </message> + <message name="IDS_POLICY_VALIDATION_UNKNOWN_ERROR" desc="Message indicating unknown error in policy validation."> + Unknown error + </message> + + <message name="IDS_POLICY_STORE_STATUS_OK" desc="Message indicating a healthy policy store."> + Policy cache OK + </message> + <message name="IDS_POLICY_STORE_STATUS_LOAD_ERROR" desc="Message indicating a failure to load policy."> + Failed to load policy settings + </message> + <message name="IDS_POLICY_STORE_STATUS_STORE_ERROR" desc="Message indicating a failure to store policy."> + Failed to store policy settings + </message> + <message name="IDS_POLICY_STORE_STATUS_PARSE_ERROR" desc="Message indicating a parse error on loading policy"> + Policy parse error + </message> + <message name="IDS_POLICY_STORE_STATUS_SERIALIZE_ERROR" desc="Message indicating an error preparing policy for storage."> + Serialization error + </message> + <message name="IDS_POLICY_STORE_STATUS_VALIDATION_ERROR" desc="Message indicating policy validation on store/load failed."> + Validation error: <ph name="VALIDATION_ERROR">$1<ex>Bad signature</ex></ph>. + </message> + <message name="IDS_POLICY_STORE_STATUS_BAD_STATE" desc="Message indicating policy cannot be stored/loaded due to the backend being in bad state."> + Backing store in bad state + </message> + <message name="IDS_POLICY_STORE_STATUS_UNKNOWN_ERROR" desc="Message indicating an unknown error with the policy cache."> + Unknown error + </message> + <!-- about:policy --> <message name="IDS_POLICY_TITLE" desc="The title for the about:policies page."> Policies @@ -14284,33 +14387,48 @@ Some features may be unavailable. Please check that the profile exists and you <!-- Strings for the new-style OAuth-based enterprise enrollment page --> <if expr="pp_ifdef('chromeos')"> - <message name="IDS_ENTERPRISE_ENROLLMENT_ACCOUNT_ERROR" desc="Error message to show when there is a problem with the user account."> - This user account is not eligible for the service. + <message name="IDS_ENTERPRISE_ENROLLMENT_STATUS_REGISTRATION_FAILED" desc="Error message shown on the enrollment screen upon failed device registration."> + Error when registering the device with the server: <ph name="CLIENT_ERROR">$1<ex>Failed to connect to the server</ex></ph>. </message> - <message name="IDS_ENTERPRISE_ENROLLMENT_FATAL_AUTH_ERROR" desc="Error message to show when there is an unrecoverable error while authenticating with GAIA."> - Oops! Something went wrong when trying to authenticate you. Please double-check your login credentials and try again. - </message> - <message name="IDS_ENTERPRISE_ENROLLMENT_NETWORK_ENROLLMENT_ERROR" desc="Error message to show when there is a network problem talking to the device management server."> - Oops! A network communication problem occurred while trying to enroll this device. Please check your network connection and try again. - </message> - <message name="IDS_ENTERPRISE_ENROLLMENT_FATAL_ENROLLMENT_ERROR" desc="Error message to show when there is an unrecoverable error while performing enrollment."> - Oops! Something went really wrong while enrolling this device. Please try again or contact your support representative. + <message name="IDS_ENTERPRISE_ENROLLMENT_STATUS_REGISTRATION_BAD_MODE" desc="Error message shown on the enrollment 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 and try again. </message> - <message name="IDS_ENTERPRISE_AUTO_ENROLLMENT_ERROR" desc="Error message to show when auto-enrollment is not supported for the enrollment mode supplied by the DMServer."> - Oops! Something went wrong while auto-enrolling this device. Please try again from the login screen using the Ctrl-Alt-E key combination, or contact your support representative. + <message name="IDS_ENTERPRISE_ENROLLMENT_STATUS_POLICY_FETCH_FAILED" desc="Error message shown on the enrollment screen upon a failed policy fetch."> + Error when fetching policy settings from the server: <ph name="CLIENT_ERROR">$1<ex>Failed to connect to the server</ex></ph>. </message> - <message name="IDS_ENTERPRISE_ENROLLMENT_SERIAL_NUMBER_ERROR" desc="Error message to show when the serial number reported by the device cannot be enrolled in the requested domain."> - This device cannot be enrolled in the domain this user account belongs to. + <message name="IDS_ENTERPRISE_ENROLLMENT_STATUS_VALIDATION_FAILED" desc="Error message shown on the enrollment screen upon a failure to validate downloaded policy."> + The policy downloaded from the server is invalid: <ph name="VALIDATION_ERROR">$1<ex>Invalid signature</ex></ph>. </message> - <message name="IDS_ENTERPRISE_ENROLLMENT_MODE_ERROR" desc="Error message to show when the DM Server didn't send or send unsupported enrollment mode to the client."> - The supplied enrollment mode is not supported by this version of the operating system. Please make sure you are running the newest version and try again. + <message name="IDS_ENTERPRISE_ENROLLMENT_STATUS_LOCK_ERROR" desc="Error message shown on the enrollment screen upon failure to lock the device mode."> + Oops! The system failed to establish the device installation-time attributes lock. </message> - <message name="IDS_ENTERPRISE_LOCKBOX_TIMEOUT_ERROR" desc="Error message to show when the initialization of the lockbox is taking too long."> + <message name="IDS_ENTERPRISE_ENROLLMENT_STATUS_LOCK_TIMEOUT" desc="Error message to show when the initialization of the lockbox is taking too long."> Oops! The initialization of the installation-time attributes has timed out. Please contact your support representative. </message> - <message name="IDS_ENTERPRISE_ENROLLMENT_DOMAIN_MISMATCH_ERROR" desc="Error message to show when the user used to re-enroll the device does not belong to the domain that the device was originally enrolled into."> + <message name="IDS_ENTERPRISE_ENROLLMENT_STATUS_LOCK_WRONG_USER" desc="Error message to show when the user used to re-enroll the device does not belong to the domain that the device was originally enrolled into."> This user account does not belong to the domain that the device is enrolled to. If you want to enroll to a different domain you need to go through device recovery first. </message> + <message name="IDS_ENTERPRISE_ENROLLMENT_STATUS_STORE_ERROR" desc="Error message shown on the enrollment screen when the installation of the policy on the device fails."> + Failed to install policy settings on the device: <ph name="VALIDATION_ERROR">$1<ex>Policy parsing failed</ex></ph>. + </message> + <message name="IDS_ENTERPRISE_ENROLLMENT_AUTH_FATAL_ERROR" desc="Error message to show when there is an unrecoverable error while authenticating with GAIA."> + Oops! Something went wrong when trying to authenticate you. Please double-check your login credentials and try again. + </message> + <message name="IDS_ENTERPRISE_ENROLLMENT_AUTH_ACCOUNT_ERROR" desc="Error message to show when there is a problem with the user account."> + This user account is not eligible for the service. + </message> + <message name="IDS_ENTERPRISE_ENROLLMENT_AUTH_NETWORK_ERROR" desc="Error message to show when there is a network problem when authenticating for enrollment."> + Oops! A network communication problem occurred during authentication. Please check your network connection and try again. + </message> + <message name="IDS_ENTERPRISE_AUTO_ENROLLMENT_BAD_MODE" desc="Error message to show when auto-enrollment is not supported for the enrollment mode supplied by the DMServer."> + Oops! Something went wrong while auto-enrolling this device. Please try again from the login screen using the Ctrl-Alt-E key combination, or contact your support representative. + </message> + <message name="IDS_ENTERPRISE_ENROLLMENT_FATAL_ENROLLMENT_ERROR" desc="Error message to show when there is an unrecoverable error while performing enrollment."> + Oops! Something went really wrong while enrolling this device. Please try again or contact your support representative. + </message> + <message name="IDS_ENTERPRISE_ENROLLMENT_ACCOUNT_ERROR" desc="Error message to show when there is a problem with the user account."> + This user account is not eligible for the service. + </message> <message name="IDS_ENTERPRISE_ENROLLMENT_MISSING_LICENSES_ERROR" desc="Error message to show when the domain the device is trying to enroll into has expired or exhausted licenses."> You do not have enough software licenses to enroll this device. Please contact sales to purchase more. If you believe you're seeing this message in error, please contact support. </message> diff --git a/chrome/browser/automation/automation_provider_observers.h b/chrome/browser/automation/automation_provider_observers.h index ae2b220..6bc2e6b 100644 --- a/chrome/browser/automation/automation_provider_observers.h +++ b/chrome/browser/automation/automation_provider_observers.h @@ -26,7 +26,6 @@ #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/cros/network_library.h" #include "chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen.h" -#include "chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen_actor.h" #include "chrome/browser/chromeos/login/login_status_consumer.h" #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/chromeos/login/wizard_controller.h" @@ -940,19 +939,16 @@ class VirtualConnectObserver // Waits for enterprise device enrollment to complete and returns the status to // the automation provider. class EnrollmentObserver - : public chromeos::EnterpriseEnrollmentScreenActor::Observer { + : public chromeos::EnterpriseEnrollmentScreen::TestingObserver { public: EnrollmentObserver(AutomationProvider* automation, - IPC::Message* reply_message, - chromeos::EnterpriseEnrollmentScreenActor* enrollment_screen_actor, - chromeos::EnterpriseEnrollmentScreen* enrollment_screen); + IPC::Message* reply_message, + chromeos::EnterpriseEnrollmentScreen* enrollment_screen); virtual ~EnrollmentObserver(); - // chromeos::EnterpriseEnrollmentScreenActor::Observer implementation. - virtual void OnEnrollmentComplete( - chromeos::EnterpriseEnrollmentScreenActor* enrollment_screen_actor, - bool succeeded); + // chromeos::EnterpriseEnrollmentScreen::Observer implementation. + virtual void OnEnrollmentComplete(bool succeeded); private: base::WeakPtr<AutomationProvider> automation_; diff --git a/chrome/browser/automation/automation_provider_observers_chromeos.cc b/chrome/browser/automation/automation_provider_observers_chromeos.cc index fb9c87a..02f036f 100644 --- a/chrome/browser/automation/automation_provider_observers_chromeos.cc +++ b/chrome/browser/automation/automation_provider_observers_chromeos.cc @@ -425,20 +425,17 @@ chromeos::VirtualNetwork* VirtualConnectObserver::GetVirtualNetwork( EnrollmentObserver::EnrollmentObserver(AutomationProvider* automation, IPC::Message* reply_message, - chromeos::EnterpriseEnrollmentScreenActor* enrollment_screen_actor, chromeos::EnterpriseEnrollmentScreen* enrollment_screen) : automation_(automation->AsWeakPtr()), reply_message_(reply_message), enrollment_screen_(enrollment_screen) { - enrollment_screen_actor->AddObserver(this); + enrollment_screen_->AddTestingObserver(this); } EnrollmentObserver::~EnrollmentObserver() {} -void EnrollmentObserver::OnEnrollmentComplete( - chromeos::EnterpriseEnrollmentScreenActor* enrollment_screen_actor, - bool succeeded) { - enrollment_screen_actor->RemoveObserver(this); +void EnrollmentObserver::OnEnrollmentComplete(bool succeeded) { + enrollment_screen_->RemoveTestingObserver(this); if (automation_) { if (succeeded) { AutomationJSONReply(automation_, diff --git a/chrome/browser/automation/testing_automation_provider_chromeos.cc b/chrome/browser/automation/testing_automation_provider_chromeos.cc index 1b8eeca..087b1fe 100644 --- a/chrome/browser/automation/testing_automation_provider_chromeos.cc +++ b/chrome/browser/automation/testing_automation_provider_chromeos.cc @@ -34,8 +34,8 @@ #include "chrome/browser/chromeos/login/webui_login_display_host.h" #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/options/take_photo_dialog.h" -#include "chrome/browser/chromeos/proxy_cros_settings_parser.h" #include "chrome/browser/chromeos/proxy_config_service_impl.h" +#include "chrome/browser/chromeos/proxy_cros_settings_parser.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/chromeos/settings/cros_settings_names.h" #include "chrome/browser/chromeos/system/timezone_settings.h" @@ -1220,8 +1220,7 @@ void TestingAutomationProvider::EnrollEnterpriseDevice( return; } // Set up an observer (it will delete itself). - new EnrollmentObserver(this, reply_message, enroll_screen->GetActor(), - enroll_screen); + new EnrollmentObserver(this, reply_message, enroll_screen); enroll_screen->GetActor()->SubmitTestCredentials(user, password); } diff --git a/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen.cc b/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen.cc index 2121616..a1f4805 100644 --- a/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen.cc +++ b/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen.cc @@ -5,12 +5,14 @@ #include "chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen.h" #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/logging.h" #include "base/message_loop.h" #include "base/metrics/histogram.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/cros/cryptohome_library.h" +#include "chrome/browser/chromeos/login/login_utils.h" #include "chrome/browser/chromeos/login/screen_observer.h" #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/policy/auto_enrollment_client.h" @@ -20,6 +22,7 @@ #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/session_manager_client.h" #include "google_apis/gaia/gaia_auth_util.h" +#include "google_apis/gaia/google_service_auth_error.h" namespace chromeos { @@ -30,6 +33,12 @@ const int kLockRetryIntervalMs = 500; // Maximum time to retry InstallAttrs initialization before we give up. const int kLockRetryTimeoutMs = 10 * 60 * 1000; // 10 minutes. +void UMA(int sample) { + UMA_HISTOGRAM_ENUMERATION(policy::kMetricEnrollment, + sample, + policy::kMetricEnrollmentSize); +} + } // namespace EnterpriseEnrollmentScreen::EnterpriseEnrollmentScreen( @@ -38,10 +47,9 @@ EnterpriseEnrollmentScreen::EnterpriseEnrollmentScreen( : WizardScreen(observer), actor_(actor), is_auto_enrollment_(false), - is_showing_(false), + enrollment_failed_once_(false), lockbox_init_duration_(0), ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { - actor_->SetController(this); // Init the TPM if it has not been done until now (in debug build we might // have not done that yet). chromeos::CryptohomeLibrary* cryptohome = @@ -60,6 +68,7 @@ void EnterpriseEnrollmentScreen::SetParameters(bool is_auto_enrollment, const std::string& user) { is_auto_enrollment_ = is_auto_enrollment; user_ = user.empty() ? user : gaia::CanonicalizeEmail(user); + actor_->SetParameters(this, is_auto_enrollment_, user_); } void EnterpriseEnrollmentScreen::PrepareToShow() { @@ -67,126 +76,215 @@ void EnterpriseEnrollmentScreen::PrepareToShow() { } void EnterpriseEnrollmentScreen::Show() { - is_showing_ = true; - actor_->Show(); + if (is_auto_enrollment_ && !enrollment_failed_once_) { + actor_->Show(); + UMA(policy::kMetricEnrollmentAutoStarted); + actor_->ShowEnrollmentSpinnerScreen(); + actor_->FetchOAuthToken(); + } else { + actor_->ResetAuth(base::Bind(&EnterpriseEnrollmentScreen::ShowSigninScreen, + weak_ptr_factory_.GetWeakPtr())); + } } void EnterpriseEnrollmentScreen::Hide() { - is_showing_ = false; actor_->Hide(); + weak_ptr_factory_.InvalidateWeakPtrs(); } std::string EnterpriseEnrollmentScreen::GetName() const { return WizardController::kEnterpriseEnrollmentScreenName; } +void EnterpriseEnrollmentScreen::OnLoginDone(const std::string& user) { + user_ = gaia::CanonicalizeEmail(user); + + UMA(is_auto_enrollment_ ? policy::kMetricEnrollmentAutoRetried + : policy::kMetricEnrollmentStarted); + + actor_->ShowEnrollmentSpinnerScreen(); + actor_->FetchOAuthToken(); +} + +void EnterpriseEnrollmentScreen::OnAuthError( + const GoogleServiceAuthError& error) { + enrollment_failed_once_ = true; + actor_->ShowAuthError(error); + NotifyTestingObservers(false); + + switch (error.state()) { + case GoogleServiceAuthError::NONE: + case GoogleServiceAuthError::CAPTCHA_REQUIRED: + case GoogleServiceAuthError::TWO_FACTOR: + case GoogleServiceAuthError::HOSTED_NOT_ALLOWED: + case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: + case GoogleServiceAuthError::REQUEST_CANCELED: + UMAFailure(policy::kMetricEnrollmentLoginFailed); + LOG(ERROR) << "Auth error " << error.state(); + return; + case GoogleServiceAuthError::USER_NOT_SIGNED_UP: + case GoogleServiceAuthError::ACCOUNT_DELETED: + case GoogleServiceAuthError::ACCOUNT_DISABLED: + UMAFailure(policy::kMetricEnrollmentNotSupported); + LOG(ERROR) << "Account error " << error.state(); + return; + case GoogleServiceAuthError::CONNECTION_FAILED: + case GoogleServiceAuthError::SERVICE_UNAVAILABLE: + UMAFailure(policy::kMetricEnrollmentNetworkFailed); + LOG(WARNING) << "Network error " << error.state(); + return; + case GoogleServiceAuthError::NUM_STATES: + break; + } + + NOTREACHED(); + UMAFailure(policy::kMetricEnrollmentOtherFailed); +} + void EnterpriseEnrollmentScreen::OnOAuthTokenAvailable( - const std::string& user, const std::string& token) { - user_ = gaia::CanonicalizeEmail(user); RegisterForDevicePolicy(token); } -void EnterpriseEnrollmentScreen::OnConfirmationClosed(bool go_back_to_signin) { +void EnterpriseEnrollmentScreen::OnRetry() { + actor_->ResetAuth(base::Bind(&EnterpriseEnrollmentScreen::ShowSigninScreen, + weak_ptr_factory_.GetWeakPtr())); +} + +void EnterpriseEnrollmentScreen::OnCancel() { + if (is_auto_enrollment_) + policy::AutoEnrollmentClient::CancelAutoEnrollment(); + UMA(is_auto_enrollment_ ? policy::kMetricEnrollmentAutoCancelled + : policy::kMetricEnrollmentCancelled); + actor_->ResetAuth( + base::Bind(&ScreenObserver::OnExit, + base::Unretained(get_screen_observer()), + ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED)); + NotifyTestingObservers(false); +} + +void EnterpriseEnrollmentScreen::OnConfirmationClosed() { // If the machine has been put in KIOSK mode we have to restart the session // here to go in the proper KIOSK mode login screen. - policy::BrowserPolicyConnector* policy_connector = - g_browser_process->browser_policy_connector(); - if (policy_connector && policy_connector->GetDeviceCloudPolicyDataStore() && - policy_connector->GetDeviceCloudPolicyDataStore()->device_mode() == + if (g_browser_process->browser_policy_connector()->GetDeviceMode() == policy::DEVICE_MODE_KIOSK) { DBusThreadManager::Get()->GetSessionManagerClient()->StopSession(); return; } - get_screen_observer()->OnExit(go_back_to_signin ? - ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED : - ScreenObserver::ENTERPRISE_AUTO_MAGIC_ENROLLMENT_COMPLETED); -} - -bool EnterpriseEnrollmentScreen::IsAutoEnrollment(std::string* user) { - if (is_auto_enrollment_) - *user = user_; - return is_auto_enrollment_; + if (is_auto_enrollment_ && + !enrollment_failed_once_ && + !user_.empty() && + LoginUtils::IsWhitelisted(user_)) { + actor_->ShowLoginSpinnerScreen(); + get_screen_observer()->OnExit( + ScreenObserver::ENTERPRISE_AUTO_MAGIC_ENROLLMENT_COMPLETED); + } else { + actor_->ResetAuth( + base::Bind(&ScreenObserver::OnExit, + base::Unretained(get_screen_observer()), + ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED)); + } } void EnterpriseEnrollmentScreen::OnPolicyStateChanged( policy::CloudPolicySubsystem::PolicySubsystemState state, policy::CloudPolicySubsystem::ErrorDetails error_details) { - if (is_showing_) { - switch (state) { - case policy::CloudPolicySubsystem::UNENROLLED: - switch (error_details) { - case policy::CloudPolicySubsystem::BAD_SERIAL_NUMBER: - actor_->ShowEnrollmentError( - EnterpriseEnrollmentScreenActor::SERIAL_NUMBER_ERROR); - break; - case policy::CloudPolicySubsystem::BAD_ENROLLMENT_MODE: - actor_->ShowEnrollmentError( - EnterpriseEnrollmentScreenActor::ENROLLMENT_MODE_ERROR); - break; - case policy::CloudPolicySubsystem::MISSING_LICENSES: - actor_->ShowEnrollmentError( - EnterpriseEnrollmentScreenActor::MISSING_LICENSES_ERROR); - break; - default: // Still working... - return; - } - break; - case policy::CloudPolicySubsystem::BAD_GAIA_TOKEN: - case policy::CloudPolicySubsystem::LOCAL_ERROR: - actor_->ShowEnrollmentError( - EnterpriseEnrollmentScreenActor::FATAL_ERROR); - break; - case policy::CloudPolicySubsystem::UNMANAGED: - actor_->ShowEnrollmentError( - EnterpriseEnrollmentScreenActor::ACCOUNT_ERROR); - break; - case policy::CloudPolicySubsystem::NETWORK_ERROR: - actor_->ShowEnrollmentError( - EnterpriseEnrollmentScreenActor::NETWORK_ERROR); - break; - case policy::CloudPolicySubsystem::TOKEN_FETCHED: - if (!is_auto_enrollment_ || - g_browser_process->browser_policy_connector()-> - GetDeviceCloudPolicyDataStore()->device_mode() == - policy::DEVICE_MODE_ENTERPRISE) { - WriteInstallAttributesData(); + switch (state) { + case policy::CloudPolicySubsystem::UNENROLLED: + switch (error_details) { + case policy::CloudPolicySubsystem::BAD_SERIAL_NUMBER: + ReportEnrollmentStatus( + policy::EnrollmentStatus::ForRegistrationError( + policy::DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER)); + break; + case policy::CloudPolicySubsystem::BAD_ENROLLMENT_MODE: + ReportEnrollmentStatus( + policy::EnrollmentStatus::ForStatus( + policy::EnrollmentStatus::STATUS_REGISTRATION_BAD_MODE)); + break; + case policy::CloudPolicySubsystem::MISSING_LICENSES: + ReportEnrollmentStatus( + policy::EnrollmentStatus::ForRegistrationError( + policy::DM_STATUS_SERVICE_MISSING_LICENSES)); + break; + default: // Still working... return; - } else { - LOG(ERROR) << "Enrollment can not proceed because Auto-enrollment is " - << "not supported for non-enterprise enrollment modes."; - policy::AutoEnrollmentClient::CancelAutoEnrollment(); - is_auto_enrollment_ = false; - actor_->ShowEnrollmentError( - EnterpriseEnrollmentScreenActor::AUTO_ENROLLMENT_ERROR); - // Set the error state to something distinguishable in the logs. - state = policy::CloudPolicySubsystem::LOCAL_ERROR; - error_details = policy::CloudPolicySubsystem::AUTO_ENROLLMENT_ERROR; - } - break; - case policy::CloudPolicySubsystem::SUCCESS: - // Success! - registrar_.reset(); - actor_->ShowConfirmationScreen(); + } + break; + case policy::CloudPolicySubsystem::BAD_GAIA_TOKEN: + ReportEnrollmentStatus( + policy::EnrollmentStatus::ForRegistrationError( + policy::DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID)); + break; + case policy::CloudPolicySubsystem::LOCAL_ERROR: + ReportEnrollmentStatus( + policy::EnrollmentStatus::ForStoreError( + policy::CloudPolicyStore::STATUS_STORE_ERROR, + policy::CloudPolicyValidatorBase::VALIDATION_OK)); + break; + case policy::CloudPolicySubsystem::UNMANAGED: + ReportEnrollmentStatus( + policy::EnrollmentStatus::ForRegistrationError( + policy::DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED)); + break; + case policy::CloudPolicySubsystem::NETWORK_ERROR: + ReportEnrollmentStatus( + policy::EnrollmentStatus::ForRegistrationError( + policy::DM_STATUS_REQUEST_FAILED)); + break; + case policy::CloudPolicySubsystem::TOKEN_FETCHED: + if (!is_auto_enrollment_ || + g_browser_process->browser_policy_connector()-> + GetDeviceCloudPolicyDataStore()->device_mode() == + policy::DEVICE_MODE_ENTERPRISE) { + WriteInstallAttributesData(); return; - } - // We have an error. - if (!is_auto_enrollment_) { - UMA_HISTOGRAM_ENUMERATION(policy::kMetricEnrollment, - policy::kMetricEnrollmentPolicyFailed, - policy::kMetricEnrollmentSize); - } - LOG(WARNING) << "Policy subsystem error during enrollment: " << state - << " details: " << error_details; + } else { + LOG(ERROR) << "Enrollment cannot proceed because Auto-enrollment is " + << "not supported for non-enterprise enrollment modes."; + policy::AutoEnrollmentClient::CancelAutoEnrollment(); + is_auto_enrollment_ = false; + UMAFailure(policy::kMetricEnrollmentAutoEnrollmentNotSupported); + actor_->ShowUIError( + EnterpriseEnrollmentScreenActor::UI_ERROR_AUTO_ENROLLMENT_BAD_MODE); + NotifyTestingObservers(false); + // Set the error state to something distinguishable in the logs. + state = policy::CloudPolicySubsystem::LOCAL_ERROR; + error_details = policy::CloudPolicySubsystem::AUTO_ENROLLMENT_ERROR; + } + break; + case policy::CloudPolicySubsystem::SUCCESS: + // Success! + registrar_.reset(); + ReportEnrollmentStatus( + policy::EnrollmentStatus::ForStatus( + policy::EnrollmentStatus::STATUS_SUCCESS)); + return; } + // We have an error. + if (!is_auto_enrollment_) + UMAFailure(policy::kMetricEnrollmentPolicyFailed); + + LOG(WARNING) << "Policy subsystem error during enrollment: " << state + << " details: " << error_details; + // Stop the policy infrastructure. registrar_.reset(); g_browser_process->browser_policy_connector()->ResetDevicePolicy(); } +void EnterpriseEnrollmentScreen::AddTestingObserver(TestingObserver* observer) { + observers_.AddObserver(observer); +} + +void EnterpriseEnrollmentScreen::RemoveTestingObserver( + TestingObserver* observer) { + observers_.RemoveObserver(observer); +} + void EnterpriseEnrollmentScreen::WriteInstallAttributesData() { // Since this method is also called directly. weak_ptr_factory_.InvalidateWeakPtrs(); @@ -213,26 +311,32 @@ void EnterpriseEnrollmentScreen::WriteInstallAttributesData() { base::TimeDelta::FromMilliseconds(kLockRetryIntervalMs)); lockbox_init_duration_ += kLockRetryIntervalMs; } else { - actor_->ShowEnrollmentError( - EnterpriseEnrollmentScreenActor::LOCKBOX_TIMEOUT_ERROR); + ReportEnrollmentStatus( + policy::EnrollmentStatus::ForStatus( + policy::EnrollmentStatus::STATUS_LOCK_TIMEOUT)); } return; } case policy::EnterpriseInstallAttributes::LOCK_BACKEND_ERROR: { - actor_->ShowEnrollmentError( - EnterpriseEnrollmentScreenActor::FATAL_ERROR); + ReportEnrollmentStatus( + policy::EnrollmentStatus::ForStatus( + policy::EnrollmentStatus::STATUS_LOCK_ERROR)); return; } case policy::EnterpriseInstallAttributes::LOCK_WRONG_USER: { LOG(ERROR) << "Enrollment can not proceed because the InstallAttrs " << "has been locked already!"; - actor_->ShowEnrollmentError( - EnterpriseEnrollmentScreenActor::FATAL_ERROR); + ReportEnrollmentStatus( + policy::EnrollmentStatus::ForStatus( + policy::EnrollmentStatus::STATUS_LOCK_WRONG_USER)); return; } } NOTREACHED(); + ReportEnrollmentStatus( + policy::EnrollmentStatus::ForStatus( + policy::EnrollmentStatus::STATUS_LOCK_ERROR)); } void EnterpriseEnrollmentScreen::RegisterForDevicePolicy( @@ -249,12 +353,13 @@ void EnterpriseEnrollmentScreen::RegisterForDevicePolicy( connector->GetEnterpriseDomain() != gaia::ExtractDomainName(user_)) { LOG(ERROR) << "Trying to re-enroll to a different domain than " << connector->GetEnterpriseDomain(); - if (is_showing_) { - actor_->ShowEnrollmentError( - EnterpriseEnrollmentScreenActor::DOMAIN_MISMATCH_ERROR); - } + UMAFailure(policy::kMetricEnrollmentWrongUserError); + actor_->ShowUIError( + EnterpriseEnrollmentScreenActor::UI_ERROR_DOMAIN_MISMATCH); + NotifyTestingObservers(false); return; } + // Make sure the device policy subsystem is in a clean slate. connector->ResetDevicePolicy(); connector->ScheduleServiceInitialization(0); @@ -268,10 +373,86 @@ void EnterpriseEnrollmentScreen::RegisterForDevicePolicy( return; } NOTREACHED(); - if (is_showing_) { - actor_->ShowEnrollmentError( - EnterpriseEnrollmentScreenActor::FATAL_ERROR); + UMAFailure(policy::kMetricEnrollmentOtherFailed); + actor_->ShowUIError(EnterpriseEnrollmentScreenActor::UI_ERROR_FATAL); + NotifyTestingObservers(false); +} + +void EnterpriseEnrollmentScreen::ReportEnrollmentStatus( + policy::EnrollmentStatus status) { + bool success = status.status() == policy::EnrollmentStatus::STATUS_SUCCESS; + enrollment_failed_once_ |= !success; + actor_->ShowEnrollmentStatus(status); + NotifyTestingObservers(success); + + switch (status.status()) { + case policy::EnrollmentStatus::STATUS_SUCCESS: + UMA(is_auto_enrollment_ ? policy::kMetricEnrollmentAutoOK + : policy::kMetricEnrollmentOK); + return; + case policy::EnrollmentStatus::STATUS_REGISTRATION_FAILED: + case policy::EnrollmentStatus::STATUS_POLICY_FETCH_FAILED: + switch (status.client_status()) { + case policy::DM_STATUS_SUCCESS: + case policy::DM_STATUS_REQUEST_INVALID: + case policy::DM_STATUS_SERVICE_DEVICE_NOT_FOUND: + case policy::DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID: + case policy::DM_STATUS_SERVICE_ACTIVATION_PENDING: + case policy::DM_STATUS_SERVICE_DEVICE_ID_CONFLICT: + case policy::DM_STATUS_SERVICE_POLICY_NOT_FOUND: + UMAFailure(policy::kMetricEnrollmentOtherFailed); + return; + case policy::DM_STATUS_REQUEST_FAILED: + case policy::DM_STATUS_TEMPORARY_UNAVAILABLE: + case policy::DM_STATUS_HTTP_STATUS_ERROR: + case policy::DM_STATUS_RESPONSE_DECODING_ERROR: + UMAFailure(policy::kMetricEnrollmentNetworkFailed); + return; + case policy::DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED: + UMAFailure(policy::kMetricEnrollmentNotSupported); + return; + case policy::DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER: + UMAFailure(policy::kMetricEnrollmentInvalidSerialNumber); + return; + case policy::DM_STATUS_SERVICE_MISSING_LICENSES: + UMAFailure(policy::kMetricMissingLicensesError); + return; + } + break; + case policy::EnrollmentStatus::STATUS_REGISTRATION_BAD_MODE: + UMAFailure(policy::kMetricEnrollmentInvalidEnrollmentMode); + return; + case policy::EnrollmentStatus::STATUS_LOCK_TIMEOUT: + UMAFailure(policy::kMetricLockboxTimeoutError); + return; + case policy::EnrollmentStatus::STATUS_LOCK_WRONG_USER: + UMAFailure(policy::kMetricEnrollmentWrongUserError); + return; + case policy::EnrollmentStatus::STATUS_VALIDATION_FAILED: + case policy::EnrollmentStatus::STATUS_STORE_ERROR: + case policy::EnrollmentStatus::STATUS_LOCK_ERROR: + UMAFailure(policy::kMetricEnrollmentOtherFailed); + return; } + + NOTREACHED(); + UMAFailure(policy::kMetricEnrollmentOtherFailed); +} + +void EnterpriseEnrollmentScreen::UMAFailure(int sample) { + if (is_auto_enrollment_) + sample = policy::kMetricEnrollmentAutoFailed; + UMA(sample); +} + +void EnterpriseEnrollmentScreen::ShowSigninScreen() { + actor_->Show(); + actor_->ShowSigninScreen(); +} + +void EnterpriseEnrollmentScreen::NotifyTestingObservers(bool succeeded) { + FOR_EACH_OBSERVER(TestingObserver, observers_, + OnEnrollmentComplete(succeeded)); } } // namespace chromeos diff --git a/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen.h b/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen.h index a75d299..9d5ec8f 100644 --- a/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen.h +++ b/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen.h @@ -10,9 +10,12 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/memory/weak_ptr.h" +#include "base/observer_list.h" #include "chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen_actor.h" #include "chrome/browser/chromeos/login/wizard_screen.h" +#include "chrome/browser/policy/cloud_policy_constants.h" #include "chrome/browser/policy/cloud_policy_subsystem.h" +#include "chrome/browser/policy/device_cloud_policy_manager_chromeos.h" namespace chromeos { @@ -25,6 +28,15 @@ class EnterpriseEnrollmentScreen public EnterpriseEnrollmentScreenActor::Controller, public policy::CloudPolicySubsystem::Observer { public: + // Used in PyAuto testing. + class TestingObserver { + public: + virtual ~TestingObserver() {} + + // Notifies observers of a change in enrollment state. + virtual void OnEnrollmentComplete(bool succeeded) = 0; + }; + EnterpriseEnrollmentScreen(ScreenObserver* observer, EnterpriseEnrollmentScreenActor* actor); virtual ~EnterpriseEnrollmentScreen(); @@ -39,10 +51,12 @@ class EnterpriseEnrollmentScreen virtual std::string GetName() const OVERRIDE; // EnterpriseEnrollmentScreenActor::Controller implementation: - virtual void OnOAuthTokenAvailable(const std::string& user, - const std::string& token) OVERRIDE; - virtual void OnConfirmationClosed(bool go_back_to_signin) OVERRIDE; - virtual bool IsAutoEnrollment(std::string* user) OVERRIDE; + virtual void OnLoginDone(const std::string& user) OVERRIDE; + virtual void OnAuthError(const GoogleServiceAuthError& error) OVERRIDE; + virtual void OnOAuthTokenAvailable(const std::string& oauth_token) OVERRIDE; + virtual void OnRetry() OVERRIDE; + virtual void OnCancel() OVERRIDE; + virtual void OnConfirmationClosed() OVERRIDE; // CloudPolicySubsystem::Observer implementation: virtual void OnPolicyStateChanged( @@ -54,6 +68,10 @@ class EnterpriseEnrollmentScreen return actor_; } + // Used for testing. + void AddTestingObserver(TestingObserver* observer); + void RemoveTestingObserver(TestingObserver* observer); + private: // Starts the Lockbox storage process. void WriteInstallAttributesData(); @@ -61,14 +79,32 @@ class EnterpriseEnrollmentScreen // Kicks off the policy infrastructure to register with the service. void RegisterForDevicePolicy(const std::string& token); + // Handles enrollment completion. Logs a UMA sample and requests the actor to + // show the specified enrollment status. + void ReportEnrollmentStatus(policy::EnrollmentStatus status); + + // Logs a UMA event in the kMetricEnrollment histogram. If auto-enrollment is + // on |sample| is ignored and a kMetricEnrollmentAutoFailed sample is logged + // instead. + void UMAFailure(int sample); + + // Shows the signin screen. Used as a callback to run after auth reset. + void ShowSigninScreen(); + + // Notifies testing observers about the result of the enrollment. + void NotifyTestingObservers(bool succeeded); + EnterpriseEnrollmentScreenActor* actor_; bool is_auto_enrollment_; - bool is_showing_; + bool enrollment_failed_once_; std::string user_; int lockbox_init_duration_; scoped_ptr<policy::CloudPolicySubsystem::ObserverRegistrar> registrar_; base::WeakPtrFactory<EnterpriseEnrollmentScreen> weak_ptr_factory_; + // Observers. + ObserverList<TestingObserver, true> observers_; + DISALLOW_COPY_AND_ASSIGN(EnterpriseEnrollmentScreen); }; diff --git a/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen_actor.cc b/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen_actor.cc deleted file mode 100644 index 7d7e072..0000000 --- a/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen_actor.cc +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2011 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/enrollment/enterprise_enrollment_screen_actor.h" - -namespace chromeos { - -EnterpriseEnrollmentScreenActor::EnterpriseEnrollmentScreenActor() {} - -EnterpriseEnrollmentScreenActor::~EnterpriseEnrollmentScreenActor() {} - -void EnterpriseEnrollmentScreenActor::AddObserver(Observer* obs) { - observer_list_.AddObserver(obs); -} - -void EnterpriseEnrollmentScreenActor::RemoveObserver(Observer* obs) { - observer_list_.RemoveObserver(obs); -} - -void EnterpriseEnrollmentScreenActor::NotifyObservers(bool succeeded) { - FOR_EACH_OBSERVER(Observer, observer_list_, - OnEnrollmentComplete(this, succeeded)); -} - -} // namespace chromeos diff --git a/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen_actor.h b/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen_actor.h index afa1d1b..445f013 100644 --- a/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen_actor.h +++ b/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen_actor.h @@ -8,7 +8,8 @@ #include <string> #include "base/basictypes.h" -#include "base/observer_list.h" +#include "base/callback_forward.h" +#include "chrome/browser/policy/enrollment_status_chromeos.h" class GoogleServiceAuthError; @@ -17,17 +18,29 @@ namespace chromeos { // Interface class for the enterprise enrollment screen actor. class EnterpriseEnrollmentScreenActor { public: - // Enumeration of the possible errors that can occur during enrollment. + // Enumeration of the possible errors that can occur during enrollment which + // are not covered by GoogleServiceAuthError or EnrollmentStatus. + enum UIError { + // Existing enrollment domain doesn't match authentication user. + UI_ERROR_DOMAIN_MISMATCH, + // Requested device mode not supported with auto enrollment. + UI_ERROR_AUTO_ENROLLMENT_BAD_MODE, + // Unexpected error condition, indicates a bug in the code. + UI_ERROR_FATAL, + }; + + // TODO(mnissler): Remove this enum once enrollment has been switched to + // DeviceCloudPolicyManagerChromeOS (http://crbug.com/108928) for good. enum EnrollmentError { + DOMAIN_MISMATCH_ERROR, + FATAL_ERROR, ACCOUNT_ERROR, SERIAL_NUMBER_ERROR, ENROLLMENT_MODE_ERROR, FATAL_AUTH_ERROR, - FATAL_ERROR, AUTO_ENROLLMENT_ERROR, NETWORK_ERROR, LOCKBOX_TIMEOUT_ERROR, - DOMAIN_MISMATCH_ERROR, MISSING_LICENSES_ERROR, }; @@ -37,33 +50,20 @@ class EnterpriseEnrollmentScreenActor { public: virtual ~Controller() {} - virtual void OnOAuthTokenAvailable(const std::string& user, - const std::string& oauth_token) = 0; - virtual void OnConfirmationClosed(bool go_back_to_signin) = 0; - virtual bool IsAutoEnrollment(std::string* user) = 0; - }; - - // Used in PyAuto testing. - class Observer { - public: - virtual ~Observer() {} - - // Notifies observers of a change in enrollment state. - virtual void OnEnrollmentComplete( - EnterpriseEnrollmentScreenActor* enrollment_screen, - bool succeeded) = 0; + virtual void OnLoginDone(const std::string& user) = 0; + virtual void OnAuthError(const GoogleServiceAuthError& error) = 0; + virtual void OnOAuthTokenAvailable(const std::string& oauth_token) = 0; + virtual void OnRetry() = 0; + virtual void OnCancel() = 0; + virtual void OnConfirmationClosed() = 0; }; - EnterpriseEnrollmentScreenActor(); + virtual ~EnterpriseEnrollmentScreenActor() {} - virtual ~EnterpriseEnrollmentScreenActor(); - - void AddObserver(Observer* obs); - - void RemoveObserver(Observer* obs); - - // Sets the controller. - virtual void SetController(Controller* controller) = 0; + // Initializes the actor with parameters. + virtual void SetParameters(Controller* controller, + bool is_auto_enrollment, + const std::string& user) = 0; // Prepare the contents to showing. virtual void PrepareToShow() = 0; @@ -74,25 +74,34 @@ class EnterpriseEnrollmentScreenActor { // Hides the contents of the screen. virtual void Hide() = 0; - // Switches to the confirmation screen. - virtual void ShowConfirmationScreen() = 0; + // Starts fetching the OAuth token. + virtual void FetchOAuthToken() = 0; + + // Resets the authentication state and invokes the passed callback on + // completion. + virtual void ResetAuth(const base::Closure& callback) = 0; + + // Shows the signin screen. + virtual void ShowSigninScreen() = 0; + + // Shows the spinner screen for enrollment. + virtual void ShowEnrollmentSpinnerScreen() = 0; + + // Shows the spinner screen for login after auto-enrollment. + virtual void ShowLoginSpinnerScreen() = 0; // Show an authentication error. virtual void ShowAuthError(const GoogleServiceAuthError& error) = 0; // Show non-authentication error. - virtual void ShowEnrollmentError(EnrollmentError error_code) = 0; + virtual void ShowUIError(UIError error) = 0; + + // Update the UI to report the |status| of the enrollment procedure. + virtual void ShowEnrollmentStatus(policy::EnrollmentStatus status) = 0; // Used for testing only. virtual void SubmitTestCredentials(const std::string& email, const std::string& password) = 0; - - protected: - void NotifyObservers(bool succeeded); - - private: - // Observers. - ObserverList<Observer> observer_list_; }; } // namespace chromeos diff --git a/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen_browsertest.cc b/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen_browsertest.cc index d591723..c663546 100644 --- a/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen_browsertest.cc +++ b/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen_browsertest.cc @@ -3,13 +3,16 @@ // found in the LICENSE file. #include "base/basictypes.h" +#include "base/run_loop.h" #include "chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen.h" #include "chrome/browser/chromeos/login/mock_screen_observer.h" #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/login/wizard_in_process_browser_test.h" +#include "content/public/test/test_utils.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using testing::InvokeWithoutArgs; using testing::Mock; namespace chromeos { @@ -31,6 +34,7 @@ IN_PROC_BROWSER_TEST_F(EnterpriseEnrollmentScreenTest, TestCancel) { WizardController::default_controller()->GetEnterpriseEnrollmentScreen(); ASSERT_TRUE(enterprise_enrollment_screen != NULL); + base::RunLoop run_loop; MockScreenObserver mock_screen_observer; static_cast<WizardScreen*>(enterprise_enrollment_screen)->screen_observer_ = &mock_screen_observer; @@ -39,8 +43,10 @@ IN_PROC_BROWSER_TEST_F(EnterpriseEnrollmentScreenTest, TestCancel) { enterprise_enrollment_screen); EXPECT_CALL(mock_screen_observer, - OnExit(ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED)); - enterprise_enrollment_screen->OnConfirmationClosed(true); + OnExit(ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED)) + .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); + enterprise_enrollment_screen->OnCancel(); + content::RunThisRunLoop(&run_loop); Mock::VerifyAndClearExpectations(&mock_screen_observer); static_cast<WizardScreen*>(enterprise_enrollment_screen)->screen_observer_ = diff --git a/chrome/browser/chromeos/login/enrollment/mock_enterprise_enrollment_screen.h b/chrome/browser/chromeos/login/enrollment/mock_enterprise_enrollment_screen.h index b60c4d2d..add7e1e 100644 --- a/chrome/browser/chromeos/login/enrollment/mock_enterprise_enrollment_screen.h +++ b/chrome/browser/chromeos/login/enrollment/mock_enterprise_enrollment_screen.h @@ -25,14 +25,18 @@ class MockEnterpriseEnrollmentScreenActor MockEnterpriseEnrollmentScreenActor(); virtual ~MockEnterpriseEnrollmentScreenActor(); - MOCK_METHOD1(SetController, - void(EnterpriseEnrollmentScreenActor::Controller* controller)); + MOCK_METHOD3(SetParameters, void(Controller*, bool, const std::string&)); MOCK_METHOD0(PrepareToShow, void()); MOCK_METHOD0(Show, void()); MOCK_METHOD0(Hide, void()); - MOCK_METHOD0(ShowConfirmationScreen, void()); - MOCK_METHOD1(ShowAuthError, void(const GoogleServiceAuthError& error)); - MOCK_METHOD1(ShowEnrollmentError, void(EnrollmentError error_code)); + MOCK_METHOD0(FetchOAuthToken, void()); + MOCK_METHOD1(ResetAuth, void(const base::Closure&)); + MOCK_METHOD0(ShowSigninScreen, void()); + MOCK_METHOD0(ShowEnrollmentSpinnerScreen, void()); + MOCK_METHOD0(ShowLoginSpinnerScreen, void()); + MOCK_METHOD1(ShowAuthError, void(const GoogleServiceAuthError&)); + MOCK_METHOD1(ShowUIError, void(UIError)); + MOCK_METHOD1(ShowEnrollmentStatus, void(policy::EnrollmentStatus status)); MOCK_METHOD2(SubmitTestCredentials, void(const std::string& email, const std::string& password)); }; diff --git a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc index a31c00f..379fcb5 100644 --- a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc +++ b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc @@ -262,8 +262,6 @@ IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, EnterpriseEnrollmentScreen* screen = WizardController::default_controller()->GetEnterpriseEnrollmentScreen(); EXPECT_EQ(screen, WizardController::default_controller()->current_screen()); - std::string user; - EXPECT_FALSE(screen->IsAutoEnrollment(&user)); OnExit(ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED); EXPECT_FALSE(ExistingUserController::current_controller() == NULL); @@ -295,8 +293,6 @@ IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, EnterpriseEnrollmentScreen* screen = WizardController::default_controller()->GetEnterpriseEnrollmentScreen(); EXPECT_EQ(screen, WizardController::default_controller()->current_screen()); - std::string user; - EXPECT_TRUE(screen->IsAutoEnrollment(&user)); // This is the main expectation: after auto-enrollment, login is resumed. EXPECT_CALL(mock_consumer, OnLoginSuccess(_, _, _, _)).Times(1); OnExit(ScreenObserver::ENTERPRISE_AUTO_MAGIC_ENROLLMENT_COMPLETED); diff --git a/chrome/browser/policy/cloud_policy_constants.h b/chrome/browser/policy/cloud_policy_constants.h index 467b0be..c9b46ad 100644 --- a/chrome/browser/policy/cloud_policy_constants.h +++ b/chrome/browser/policy/cloud_policy_constants.h @@ -77,7 +77,7 @@ enum DeviceManagementStatus { // Service error: The device id used for registration is already taken. DM_STATUS_SERVICE_DEVICE_ID_CONFLICT, // Service error: The licenses have expired or have been exhausted. - DM_STATUS_MISSING_LICENSES, + DM_STATUS_SERVICE_MISSING_LICENSES, // Service error: Policy not found. Error code defined by the DM folks. DM_STATUS_SERVICE_POLICY_NOT_FOUND = 902, }; diff --git a/chrome/browser/policy/cloud_policy_controller.cc b/chrome/browser/policy/cloud_policy_controller.cc index e488100..90c236b 100644 --- a/chrome/browser/policy/cloud_policy_controller.cc +++ b/chrome/browser/policy/cloud_policy_controller.cc @@ -95,7 +95,7 @@ void SampleErrorStatus(DeviceManagementStatus status) { case DM_STATUS_TEMPORARY_UNAVAILABLE: case DM_STATUS_SERVICE_ACTIVATION_PENDING: case DM_STATUS_HTTP_STATUS_ERROR: - case DM_STATUS_MISSING_LICENSES: + case DM_STATUS_SERVICE_MISSING_LICENSES: sample = kMetricPolicyFetchServerFailed; break; } @@ -219,7 +219,7 @@ void CloudPolicyController::OnPolicyFetchCompleted( token_fetcher_->SetSerialNumberInvalidState(); SetState(STATE_TOKEN_ERROR); return; - case DM_STATUS_MISSING_LICENSES: + case DM_STATUS_SERVICE_MISSING_LICENSES: VLOG(1) << "There are no valid licenses for this domain left."; token_fetcher_->SetMissingLicensesState(); SetState(STATE_TOKEN_UNMANAGED); diff --git a/chrome/browser/policy/cloud_policy_controller_unittest.cc b/chrome/browser/policy/cloud_policy_controller_unittest.cc index dcea441..c96017ca5 100644 --- a/chrome/browser/policy/cloud_policy_controller_unittest.cc +++ b/chrome/browser/policy/cloud_policy_controller_unittest.cc @@ -278,7 +278,7 @@ TEST_F(CloudPolicyControllerTest, MissingLicenses) { "who@what.com", "auth", true); EXPECT_CALL(service_, CreateJob(DeviceManagementRequestJob::TYPE_POLICY_FETCH)) - .WillOnce(service_.FailJob(DM_STATUS_MISSING_LICENSES)); + .WillOnce(service_.FailJob(DM_STATUS_SERVICE_MISSING_LICENSES)); EXPECT_CALL(*token_fetcher_.get(), SetMissingLicensesState()).Times(1); CreateNewController(); loop_.RunAllPending(); diff --git a/chrome/browser/policy/cloud_policy_refresh_scheduler.cc b/chrome/browser/policy/cloud_policy_refresh_scheduler.cc index da011df..a0d9821 100644 --- a/chrome/browser/policy/cloud_policy_refresh_scheduler.cc +++ b/chrome/browser/policy/cloud_policy_refresh_scheduler.cc @@ -171,7 +171,7 @@ void CloudPolicyRefreshScheduler::ScheduleRefresh() { case DM_STATUS_SERVICE_DEVICE_NOT_FOUND: case DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER: case DM_STATUS_SERVICE_DEVICE_ID_CONFLICT: - case DM_STATUS_MISSING_LICENSES: + case DM_STATUS_SERVICE_MISSING_LICENSES: // Need a re-registration, no use in retrying. return; } diff --git a/chrome/browser/policy/cloud_policy_refresh_scheduler_unittest.cc b/chrome/browser/policy/cloud_policy_refresh_scheduler_unittest.cc index 9fcf048..c74699d 100644 --- a/chrome/browser/policy/cloud_policy_refresh_scheduler_unittest.cc +++ b/chrome/browser/policy/cloud_policy_refresh_scheduler_unittest.cc @@ -233,7 +233,7 @@ static const ClientErrorTestParam kClientErrorTestCases[] = { kPolicyRefreshRate, 1 }, { DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER, -1, 1 }, - { DM_STATUS_MISSING_LICENSES, + { DM_STATUS_SERVICE_MISSING_LICENSES, -1, 1 }, { DM_STATUS_SERVICE_DEVICE_ID_CONFLICT, -1, 1 }, diff --git a/chrome/browser/policy/device_management_service.cc b/chrome/browser/policy/device_management_service.cc index 961b04f..bbc7a07 100644 --- a/chrome/browser/policy/device_management_service.cc +++ b/chrome/browser/policy/device_management_service.cc @@ -340,7 +340,7 @@ void DeviceManagementRequestJobImpl::HandleResponse( ReportError(DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID); return; case kMissingLicenses: - ReportError(DM_STATUS_MISSING_LICENSES); + ReportError(DM_STATUS_SERVICE_MISSING_LICENSES); return; case kDeviceManagementNotAllowed: ReportError(DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED); diff --git a/chrome/browser/policy/device_management_service_unittest.cc b/chrome/browser/policy/device_management_service_unittest.cc index be343b6..abb907d 100644 --- a/chrome/browser/policy/device_management_service_unittest.cc +++ b/chrome/browser/policy/device_management_service_unittest.cc @@ -270,7 +270,7 @@ INSTANTIATE_TEST_CASE_P( 412, PROTO_STRING(kResponseEmpty)), FailedRequestParams( - DM_STATUS_MISSING_LICENSES, + DM_STATUS_SERVICE_MISSING_LICENSES, net::URLRequestStatus::SUCCESS, 402, PROTO_STRING(kResponseEmpty)))); diff --git a/chrome/browser/policy/device_token_fetcher.cc b/chrome/browser/policy/device_token_fetcher.cc index 1cddd69..2427df6 100644 --- a/chrome/browser/policy/device_token_fetcher.cc +++ b/chrome/browser/policy/device_token_fetcher.cc @@ -60,7 +60,7 @@ void SampleErrorStatus(DeviceManagementStatus status) { case DM_STATUS_RESPONSE_DECODING_ERROR: sample = kMetricTokenFetchBadResponse; break; - case DM_STATUS_MISSING_LICENSES: + case DM_STATUS_SERVICE_MISSING_LICENSES: sample = kMetricMissingLicenses; break; case DM_STATUS_TEMPORARY_UNAVAILABLE: @@ -255,7 +255,7 @@ void DeviceTokenFetcher::OnTokenFetchCompleted( case DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER: SetSerialNumberInvalidState(); return; - case DM_STATUS_MISSING_LICENSES: + case DM_STATUS_SERVICE_MISSING_LICENSES: SetMissingLicensesState(); return; case DM_STATUS_REQUEST_INVALID: diff --git a/chrome/browser/policy/message_util.cc b/chrome/browser/policy/message_util.cc new file mode 100644 index 0000000..e4ca37a --- /dev/null +++ b/chrome/browser/policy/message_util.cc @@ -0,0 +1,121 @@ +// 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/policy/message_util.h" + +#include "base/logging.h" +#include "grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" + +namespace policy { + +namespace { + +int GetIDSForDMStatus(DeviceManagementStatus status) { + switch (status) { + case DM_STATUS_SUCCESS: + return IDS_POLICY_DM_STATUS_SUCCESS; + case DM_STATUS_REQUEST_INVALID: + return IDS_POLICY_DM_STATUS_REQUEST_INVALID; + case DM_STATUS_REQUEST_FAILED: + return IDS_POLICY_DM_STATUS_REQUEST_FAILED; + case DM_STATUS_TEMPORARY_UNAVAILABLE: + return IDS_POLICY_DM_STATUS_TEMPORARY_UNAVAILABLE; + case DM_STATUS_HTTP_STATUS_ERROR: + return IDS_POLICY_DM_STATUS_HTTP_STATUS_ERROR; + case DM_STATUS_RESPONSE_DECODING_ERROR: + return IDS_POLICY_DM_STATUS_RESPONSE_DECODING_ERROR; + case DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED: + return IDS_POLICY_DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED; + case DM_STATUS_SERVICE_DEVICE_NOT_FOUND: + return IDS_POLICY_DM_STATUS_SERVICE_DEVICE_NOT_FOUND; + case DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID: + return IDS_POLICY_DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID; + case DM_STATUS_SERVICE_ACTIVATION_PENDING: + return IDS_POLICY_DM_STATUS_SERVICE_ACTIVATION_PENDING; + case DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER: + return IDS_POLICY_DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER; + case DM_STATUS_SERVICE_DEVICE_ID_CONFLICT: + return IDS_POLICY_DM_STATUS_SERVICE_DEVICE_ID_CONFLICT; + case DM_STATUS_SERVICE_MISSING_LICENSES: + return IDS_POLICY_DM_STATUS_SERVICE_MISSING_LICENSES; + case DM_STATUS_SERVICE_POLICY_NOT_FOUND: + return IDS_POLICY_DM_STATUS_SERVICE_POLICY_NOT_FOUND; + } + NOTREACHED() << "Unhandled DM status " << status; + return IDS_POLICY_DM_STATUS_UNKNOWN_ERROR; +} + +int GetIDSForValidationStatus(CloudPolicyValidatorBase::Status status) { + switch (status) { + case CloudPolicyValidatorBase::VALIDATION_OK: + return IDS_POLICY_VALIDATION_OK; + case CloudPolicyValidatorBase::VALIDATION_BAD_SIGNATURE: + return IDS_POLICY_VALIDATION_BAD_SIGNATURE; + case CloudPolicyValidatorBase::VALIDATION_ERROR_CODE_PRESENT: + return IDS_POLICY_VALIDATION_ERROR_CODE_PRESENT; + case CloudPolicyValidatorBase::VALIDATION_PAYLOAD_PARSE_ERROR: + return IDS_POLICY_VALIDATION_PAYLOAD_PARSE_ERROR; + case CloudPolicyValidatorBase::VALIDATION_WRONG_POLICY_TYPE: + return IDS_POLICY_VALIDATION_WRONG_POLICY_TYPE; + case CloudPolicyValidatorBase::VALIDATION_BAD_TIMESTAMP: + return IDS_POLICY_VALIDATION_BAD_TIMESTAMP; + case CloudPolicyValidatorBase::VALIDATION_WRONG_TOKEN: + return IDS_POLICY_VALIDATION_WRONG_TOKEN; + case CloudPolicyValidatorBase::VALIDATION_BAD_USERNAME: + return IDS_POLICY_VALIDATION_BAD_USERNAME; + case CloudPolicyValidatorBase::VALIDATION_POLICY_PARSE_ERROR: + return IDS_POLICY_VALIDATION_POLICY_PARSE_ERROR; + } + NOTREACHED() << "Unhandled validation status " << status; + return IDS_POLICY_VALIDATION_UNKNOWN_ERROR; +} + +int GetIDSForStoreStatus(CloudPolicyStore::Status status) { + switch (status) { + case CloudPolicyStore::STATUS_OK: + return IDS_POLICY_STORE_STATUS_OK; + case CloudPolicyStore::STATUS_LOAD_ERROR: + return IDS_POLICY_STORE_STATUS_LOAD_ERROR; + case CloudPolicyStore::STATUS_STORE_ERROR: + return IDS_POLICY_STORE_STATUS_STORE_ERROR; + case CloudPolicyStore::STATUS_PARSE_ERROR: + return IDS_POLICY_STORE_STATUS_PARSE_ERROR; + case CloudPolicyStore::STATUS_SERIALIZE_ERROR: + return IDS_POLICY_STORE_STATUS_SERIALIZE_ERROR; + case CloudPolicyStore::STATUS_VALIDATION_ERROR: + // This is handled separately below to include the validation error. + break; + case CloudPolicyStore::STATUS_BAD_STATE: + return IDS_POLICY_STORE_STATUS_BAD_STATE; + } + NOTREACHED() << "Unhandled store status " << status; + return IDS_POLICY_STORE_STATUS_UNKNOWN_ERROR; +} + +} // namespace + +string16 FormatDeviceManagementStatus(DeviceManagementStatus status) { + return l10n_util::GetStringUTF16(GetIDSForDMStatus(status)); +} + +string16 FormatValidationStatus( + CloudPolicyValidatorBase::Status validation_status) { + return l10n_util::GetStringUTF16( + GetIDSForValidationStatus(validation_status)); +} + +string16 FormatStoreStatus(CloudPolicyStore::Status store_status, + CloudPolicyValidatorBase::Status validation_status) { + if (store_status == CloudPolicyStore::STATUS_VALIDATION_ERROR) { + return l10n_util::GetStringFUTF16( + IDS_POLICY_STORE_STATUS_VALIDATION_ERROR, + l10n_util::GetStringUTF16( + GetIDSForValidationStatus(validation_status))); + } + + return l10n_util::GetStringUTF16(GetIDSForStoreStatus(store_status)); +} + +} // namespace policy diff --git a/chrome/browser/policy/message_util.h b/chrome/browser/policy/message_util.h new file mode 100644 index 0000000..051c3a4 --- /dev/null +++ b/chrome/browser/policy/message_util.h @@ -0,0 +1,30 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_POLICY_MESSAGE_UTIL_H_ +#define CHROME_BROWSER_POLICY_MESSAGE_UTIL_H_ + +#include "base/string16.h" +#include "chrome/browser/policy/cloud_policy_constants.h" +#include "chrome/browser/policy/cloud_policy_store.h" +#include "chrome/browser/policy/cloud_policy_validator.h" + +namespace policy { + +// Returns a string describing |status| suitable for display in UI. +string16 FormatDeviceManagementStatus(DeviceManagementStatus status); + +// Returns a string describing |validation_status| suitable for display in UI. +string16 FormatValidationStatus( + CloudPolicyValidatorBase::Status validation_status); + +// Returns a textual description of |store_status| for display in the UI. If +// |store_status| is STATUS_VALIDATION_FAILED, |validation_status| will be +// consulted to create a description of the validation failure. +string16 FormatStoreStatus(CloudPolicyStore::Status store_status, + CloudPolicyValidatorBase::Status validation_status); + +} // namespace policy + +#endif // CHROME_BROWSER_POLICY_MESSAGE_UTIL_H_ diff --git a/chrome/browser/ui/webui/chromeos/login/enterprise_oauth_enrollment_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/enterprise_oauth_enrollment_screen_handler.cc index f7dff5b..1860f32 100644 --- a/chrome/browser/ui/webui/chromeos/login/enterprise_oauth_enrollment_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/enterprise_oauth_enrollment_screen_handler.cc @@ -9,13 +9,10 @@ #include "base/callback.h" #include "base/command_line.h" #include "base/message_loop.h" -#include "base/metrics/histogram.h" #include "chrome/browser/browsing_data/browsing_data_helper.h" #include "chrome/browser/browsing_data/browsing_data_remover.h" -#include "chrome/browser/chromeos/login/login_utils.h" #include "chrome/browser/net/gaia/gaia_oauth_fetcher.h" -#include "chrome/browser/policy/auto_enrollment_client.h" -#include "chrome/browser/policy/enterprise_metrics.h" +#include "chrome/browser/policy/message_util.h" #include "chrome/browser/profiles/profile.h" #include "content/public/browser/web_contents.h" #include "google_apis/gaia/gaia_auth_util.h" @@ -78,12 +75,6 @@ class TokenRevoker : public GaiaOAuthConsumer { DISALLOW_COPY_AND_ASSIGN(TokenRevoker); }; -void UMA(int sample) { - UMA_HISTOGRAM_ENUMERATION(policy::kMetricEnrollment, - sample, - policy::kMetricEnrollmentSize); -} - } // namespace namespace chromeos { @@ -94,7 +85,6 @@ EnterpriseOAuthEnrollmentScreenHandler::EnterpriseOAuthEnrollmentScreenHandler() : controller_(NULL), show_on_init_(false), is_auto_enrollment_(false), - enrollment_failed_once_(false), browsing_data_remover_(NULL) { } @@ -124,39 +114,67 @@ void EnterpriseOAuthEnrollmentScreenHandler::RegisterMessages() { // EnterpriseOAuthEnrollmentScreenHandler // EnterpriseEnrollmentScreenActor implementation ------------------------- -void EnterpriseOAuthEnrollmentScreenHandler::SetController( - Controller* controller) { +void EnterpriseOAuthEnrollmentScreenHandler::SetParameters( + Controller* controller, + bool is_auto_enrollment, + const std::string& user) { controller_ = controller; + is_auto_enrollment_ = is_auto_enrollment; + if (is_auto_enrollment_) + user_ = user; } void EnterpriseOAuthEnrollmentScreenHandler::PrepareToShow() { } void EnterpriseOAuthEnrollmentScreenHandler::Show() { - if (!page_is_ready()) { + if (!page_is_ready()) show_on_init_ = true; + else + DoShow(); +} + +void EnterpriseOAuthEnrollmentScreenHandler::Hide() { +} + +void EnterpriseOAuthEnrollmentScreenHandler::FetchOAuthToken() { + Profile* profile = Profile::FromWebUI(web_ui()); + oauth_fetcher_.reset( + new GaiaOAuthFetcher(this, + profile->GetRequestContext(), + GaiaConstants::kDeviceManagementServiceOAuth)); + oauth_fetcher_->SetAutoFetchLimit( + GaiaOAuthFetcher::OAUTH2_SERVICE_ACCESS_TOKEN); + oauth_fetcher_->StartGetOAuthTokenRequest(); +} + +void EnterpriseOAuthEnrollmentScreenHandler::ResetAuth( + const base::Closure& callback) { + oauth_fetcher_.reset(); + + auth_reset_callbacks_.push_back(callback); + if (browsing_data_remover_) return; - } - std::string user; - is_auto_enrollment_ = controller_ && controller_->IsAutoEnrollment(&user); - if (is_auto_enrollment_) - user_ = gaia::SanitizeEmail(user); - enrollment_failed_once_ = false; + Profile* profile = Profile::FromBrowserContext( + web_ui()->GetWebContents()->GetBrowserContext()); + browsing_data_remover_ = + BrowsingDataRemover::CreateForUnboundedRange(profile); + browsing_data_remover_->AddObserver(this); + browsing_data_remover_->Remove(BrowsingDataRemover::REMOVE_SITE_DATA, + BrowsingDataHelper::UNPROTECTED_WEB); +} - DoShow(); +void EnterpriseOAuthEnrollmentScreenHandler::ShowSigninScreen() { + ShowStep(kEnrollmentStepSignin); } -void EnterpriseOAuthEnrollmentScreenHandler::Hide() { +void EnterpriseOAuthEnrollmentScreenHandler::ShowEnrollmentSpinnerScreen() { + ShowWorking(IDS_ENTERPRISE_ENROLLMENT_WORKING); } -void EnterpriseOAuthEnrollmentScreenHandler::ShowConfirmationScreen() { - UMA(is_auto_enrollment_ ? policy::kMetricEnrollmentAutoOK : - policy::kMetricEnrollmentOK); - ShowStep(kEnrollmentStepSuccess); - if (!is_auto_enrollment_ || enrollment_failed_once_) - ResetAuth(); - NotifyObservers(true); +void EnterpriseOAuthEnrollmentScreenHandler::ShowLoginSpinnerScreen() { + ShowWorking(IDS_ENTERPRISE_ENROLLMENT_RESUMING_LOGIN); } void EnterpriseOAuthEnrollmentScreenHandler::ShowAuthError( @@ -168,83 +186,97 @@ void EnterpriseOAuthEnrollmentScreenHandler::ShowAuthError( case GoogleServiceAuthError::HOSTED_NOT_ALLOWED: case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: case GoogleServiceAuthError::REQUEST_CANCELED: - LOG(ERROR) << "Auth error " << error.state(); - ShowEnrollmentError(FATAL_AUTH_ERROR); + ShowError(IDS_ENTERPRISE_ENROLLMENT_AUTH_FATAL_ERROR, false); return; case GoogleServiceAuthError::USER_NOT_SIGNED_UP: case GoogleServiceAuthError::ACCOUNT_DELETED: case GoogleServiceAuthError::ACCOUNT_DISABLED: - LOG(ERROR) << "Account error " << error.state(); - ShowEnrollmentError(ACCOUNT_ERROR); + ShowError(IDS_ENTERPRISE_ENROLLMENT_AUTH_ACCOUNT_ERROR, true); return; case GoogleServiceAuthError::CONNECTION_FAILED: case GoogleServiceAuthError::SERVICE_UNAVAILABLE: - LOG(WARNING) << "Network error " << error.state(); - ShowEnrollmentError(NETWORK_ERROR); + ShowError(IDS_ENTERPRISE_ENROLLMENT_AUTH_NETWORK_ERROR, true); return; case GoogleServiceAuthError::NUM_STATES: break; } - UMAFailure(policy::kMetricEnrollmentOtherFailed); NOTREACHED(); } -void EnterpriseOAuthEnrollmentScreenHandler::ShowEnrollmentError( - EnrollmentError error_code) { - switch (error_code) { - case ACCOUNT_ERROR: - UMAFailure(policy::kMetricEnrollmentNotSupported); - ShowError(IDS_ENTERPRISE_ENROLLMENT_ACCOUNT_ERROR, true); - break; - case SERIAL_NUMBER_ERROR: - UMAFailure(policy::kMetricEnrollmentInvalidSerialNumber); - ShowError(IDS_ENTERPRISE_ENROLLMENT_SERIAL_NUMBER_ERROR, true); - break; - case ENROLLMENT_MODE_ERROR: - UMAFailure(policy::kMetricEnrollmentInvalidEnrollmentMode); - ShowError(IDS_ENTERPRISE_ENROLLMENT_MODE_ERROR, false); - break; - case FATAL_AUTH_ERROR: - UMAFailure(policy::kMetricEnrollmentLoginFailed); - ShowError(IDS_ENTERPRISE_ENROLLMENT_FATAL_AUTH_ERROR, false); - break; - case AUTO_ENROLLMENT_ERROR: { - UMAFailure(policy::kMetricEnrollmentAutoEnrollmentNotSupported); - // The reason for showing this error is that we have been trying to - // auto-enroll and this failed, so we have to verify whether - // auto-enrollment is on, and if so switch it off, update the UI - // accordingly and show the error message. - std::string user; - is_auto_enrollment_ = controller_ && controller_->IsAutoEnrollment(&user); - base::FundamentalValue value(is_auto_enrollment_); - web_ui()->CallJavascriptFunction( - "oobe.OAuthEnrollmentScreen.setIsAutoEnrollment", value); - - ShowError(IDS_ENTERPRISE_AUTO_ENROLLMENT_ERROR, false); - break; - } - case NETWORK_ERROR: - UMAFailure(policy::kMetricEnrollmentNetworkFailed); - ShowError(IDS_ENTERPRISE_ENROLLMENT_NETWORK_ENROLLMENT_ERROR, true); - break; - case LOCKBOX_TIMEOUT_ERROR: - UMAFailure(policy::kMetricLockboxTimeoutError); - ShowError(IDS_ENTERPRISE_LOCKBOX_TIMEOUT_ERROR, true); - break; - case DOMAIN_MISMATCH_ERROR: - UMAFailure(policy::kMetricEnrollmentWrongUserError); - ShowError(IDS_ENTERPRISE_ENROLLMENT_DOMAIN_MISMATCH_ERROR, true); - break; - case MISSING_LICENSES_ERROR: - UMAFailure(policy::kMetricMissingLicensesError); - ShowError(IDS_ENTERPRISE_ENROLLMENT_MISSING_LICENSES_ERROR, true); - break; - case FATAL_ERROR: - default: - UMAFailure(policy::kMetricEnrollmentOtherFailed); - ShowError(IDS_ENTERPRISE_ENROLLMENT_FATAL_ENROLLMENT_ERROR, false); +void EnterpriseOAuthEnrollmentScreenHandler::ShowUIError(UIError error) { + switch (error) { + case UI_ERROR_DOMAIN_MISMATCH: + ShowError(IDS_ENTERPRISE_ENROLLMENT_STATUS_LOCK_WRONG_USER, true); + return; + case UI_ERROR_AUTO_ENROLLMENT_BAD_MODE: + ShowError(IDS_ENTERPRISE_AUTO_ENROLLMENT_BAD_MODE, true); + return; + case UI_ERROR_FATAL: + ShowError(IDS_ENTERPRISE_ENROLLMENT_FATAL_ENROLLMENT_ERROR, true); + return; + } + NOTREACHED(); +} + +void EnterpriseOAuthEnrollmentScreenHandler::ShowEnrollmentStatus( + policy::EnrollmentStatus status) { + switch (status.status()) { + case policy::EnrollmentStatus::STATUS_SUCCESS: + ShowStep(kEnrollmentStepSuccess); + return; + case policy::EnrollmentStatus::STATUS_REGISTRATION_FAILED: + // Some special cases for generating a nicer message that's more helpful. + switch (status.client_status()) { + case policy::DM_STATUS_SERVICE_MISSING_LICENSES: + ShowError(IDS_ENTERPRISE_ENROLLMENT_MISSING_LICENSES_ERROR, true); + break; + case policy::DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED: + ShowError(IDS_ENTERPRISE_ENROLLMENT_ACCOUNT_ERROR, true); + break; + default: + ShowErrorMessage( + l10n_util::GetStringFUTF8( + IDS_ENTERPRISE_ENROLLMENT_STATUS_REGISTRATION_FAILED, + policy::FormatDeviceManagementStatus(status.client_status())), + true); + } + return; + case policy::EnrollmentStatus::STATUS_REGISTRATION_BAD_MODE: + ShowError(IDS_ENTERPRISE_ENROLLMENT_STATUS_REGISTRATION_BAD_MODE, false); + return; + case policy::EnrollmentStatus::STATUS_POLICY_FETCH_FAILED: + ShowErrorMessage( + l10n_util::GetStringFUTF8( + IDS_ENTERPRISE_ENROLLMENT_STATUS_POLICY_FETCH_FAILED, + policy::FormatDeviceManagementStatus(status.client_status())), + true); + return; + case policy::EnrollmentStatus::STATUS_VALIDATION_FAILED: + ShowErrorMessage( + l10n_util::GetStringFUTF8( + IDS_ENTERPRISE_ENROLLMENT_STATUS_POLICY_FETCH_FAILED, + policy::FormatValidationStatus(status.validation_status())), + true); + return; + case policy::EnrollmentStatus::STATUS_LOCK_ERROR: + ShowError(IDS_ENTERPRISE_ENROLLMENT_STATUS_LOCK_ERROR, false); + return; + case policy::EnrollmentStatus::STATUS_LOCK_TIMEOUT: + ShowError(IDS_ENTERPRISE_ENROLLMENT_STATUS_LOCK_TIMEOUT, false); + return; + case policy::EnrollmentStatus::STATUS_LOCK_WRONG_USER: + ShowError(IDS_ENTERPRISE_ENROLLMENT_STATUS_LOCK_WRONG_USER, true); + return; + case policy::EnrollmentStatus::STATUS_STORE_ERROR: + ShowErrorMessage( + l10n_util::GetStringFUTF8( + IDS_ENTERPRISE_ENROLLMENT_STATUS_STORE_ERROR, + policy::FormatStoreStatus(status.store_status(), + status.validation_status())), + true); + return; } - NotifyObservers(false); + NOTREACHED(); } void EnterpriseOAuthEnrollmentScreenHandler::SubmitTestCredentials( @@ -303,7 +335,8 @@ void EnterpriseOAuthEnrollmentScreenHandler::GetLocalizedStrings( void EnterpriseOAuthEnrollmentScreenHandler::OnGetOAuthTokenFailure( const GoogleServiceAuthError& error) { - ShowEnrollmentError(FATAL_AUTH_ERROR); + if (controller_) + controller_->OnAuthError(error); } void EnterpriseOAuthEnrollmentScreenHandler::OnOAuthGetAccessTokenSuccess( @@ -315,7 +348,8 @@ void EnterpriseOAuthEnrollmentScreenHandler::OnOAuthGetAccessTokenSuccess( void EnterpriseOAuthEnrollmentScreenHandler::OnOAuthGetAccessTokenFailure( const GoogleServiceAuthError& error) { - ShowAuthError(error); + if (controller_) + controller_->OnAuthError(error); } void EnterpriseOAuthEnrollmentScreenHandler::OnOAuthWrapBridgeSuccess( @@ -326,18 +360,19 @@ void EnterpriseOAuthEnrollmentScreenHandler::OnOAuthWrapBridgeSuccess( wrap_token_ = token; - if (!controller_ || user_.empty()) { + if (!controller_) { NOTREACHED(); return; } - controller_->OnOAuthTokenAvailable(user_, token); + controller_->OnOAuthTokenAvailable(token); } void EnterpriseOAuthEnrollmentScreenHandler::OnOAuthWrapBridgeFailure( const std::string& service_scope, const GoogleServiceAuthError& error) { - ShowAuthError(error); + if (controller_) + controller_->OnAuthError(error); } void EnterpriseOAuthEnrollmentScreenHandler::OnUserInfoSuccess( @@ -354,9 +389,11 @@ void EnterpriseOAuthEnrollmentScreenHandler::OnBrowsingDataRemoverDone() { browsing_data_remover_->RemoveObserver(this); browsing_data_remover_ = NULL; - if (!action_on_browsing_data_removed_.is_null()) { - action_on_browsing_data_removed_.Run(); - action_on_browsing_data_removed_.Reset(); + std::vector<base::Closure> callbacks_to_run; + callbacks_to_run.swap(auth_reset_callbacks_); + for (std::vector<base::Closure>::iterator callback(callbacks_to_run.begin()); + callback != callbacks_to_run.end(); ++callback) { + callback->Run(); } } @@ -364,50 +401,23 @@ void EnterpriseOAuthEnrollmentScreenHandler::OnBrowsingDataRemoverDone() { void EnterpriseOAuthEnrollmentScreenHandler::HandleClose( const base::ListValue* value) { - bool back_to_signin = true; - std::string reason; CHECK_EQ(1U, value->GetSize()); CHECK(value->GetString(0, &reason)); - if (reason == "cancel") { - DCHECK(!is_auto_enrollment_); - UMA(policy::kMetricEnrollmentCancelled); - } else if (reason == "autocancel") { - // Store the user's decision so that the sign-in screen doesn't go - // automatically to the enrollment screen again. - policy::AutoEnrollmentClient::CancelAutoEnrollment(); - UMA(policy::kMetricEnrollmentAutoCancelled); - } else if (reason == "done") { - // If the user account used for enrollment is not whitelisted, send the user - // back to the login screen. In that case, clear the profile data too. - bool is_whitelisted = !user_.empty() && LoginUtils::IsWhitelisted(user_); - - // If enrollment failed at least once, the profile was cleared and the user - // had to retry with another account, or even cancelled the whole thing. - // In that case, go back to the sign-in screen; otherwise, if this was an - // auto-enrollment, resume the pending signin. - back_to_signin = !is_auto_enrollment_ || - enrollment_failed_once_ || - !is_whitelisted; - } else { + if (!controller_) { NOTREACHED(); + return; } - RevokeTokens(); + if (reason == "cancel" || reason == "autocancel") + controller_->OnCancel(); + else if (reason == "done") + controller_->OnConfirmationClosed(); + else + NOTREACHED(); - if (back_to_signin) { - // Clean the profile before going back to signin. - action_on_browsing_data_removed_ = - base::Bind(&EnterpriseOAuthEnrollmentScreenHandler::DoClose, - base::Unretained(this), - true); - ResetAuth(); - } else { - // Not going back to sign-in, letting the initial sign-in resume instead. - // In that case, keep the profile data. - DoClose(false); - } + RevokeTokens(); } void EnterpriseOAuthEnrollmentScreenHandler::HandleCompleteLogin( @@ -423,42 +433,20 @@ void EnterpriseOAuthEnrollmentScreenHandler::HandleCompleteLogin( return; } - user_ = gaia::SanitizeEmail(user); - EnrollAfterLogin(); + controller_->OnLoginDone(gaia::SanitizeEmail(user)); } void EnterpriseOAuthEnrollmentScreenHandler::HandleRetry( const base::ListValue* value) { - // Trigger browsing data removal to make sure we start from a clean slate. - action_on_browsing_data_removed_ = - base::Bind(&EnterpriseOAuthEnrollmentScreenHandler::DoShow, - base::Unretained(this)); - ResetAuth(); -} - -void EnterpriseOAuthEnrollmentScreenHandler::EnrollAfterLogin() { - DCHECK(!user_.empty()); - if (is_auto_enrollment_) { - UMA(enrollment_failed_once_ ? policy::kMetricEnrollmentAutoRetried : - policy::kMetricEnrollmentAutoStarted); - } else { - UMA(policy::kMetricEnrollmentStarted); + if (!controller_) { + NOTREACHED(); + return; } - Profile* profile = Profile::FromWebUI(web_ui()); - oauth_fetcher_.reset( - new GaiaOAuthFetcher(this, - profile->GetRequestContext(), - GaiaConstants::kDeviceManagementServiceOAuth)); - oauth_fetcher_->SetAutoFetchLimit( - GaiaOAuthFetcher::OAUTH2_SERVICE_ACCESS_TOKEN); - oauth_fetcher_->StartGetOAuthTokenRequest(); - ShowWorking(IDS_ENTERPRISE_ENROLLMENT_WORKING); + controller_->OnRetry(); } void EnterpriseOAuthEnrollmentScreenHandler::ShowStep(const char* step) { - RevokeTokens(); - base::StringValue step_value(step); web_ui()->CallJavascriptFunction("oobe.OAuthEnrollmentScreen.showStep", step_value); @@ -466,10 +454,14 @@ void EnterpriseOAuthEnrollmentScreenHandler::ShowStep(const char* step) { void EnterpriseOAuthEnrollmentScreenHandler::ShowError(int message_id, bool retry) { + ShowErrorMessage(l10n_util::GetStringUTF8(message_id), retry); +} + +void EnterpriseOAuthEnrollmentScreenHandler::ShowErrorMessage( + const std::string& message, + bool retry) { RevokeTokens(); - enrollment_failed_once_ = true; - const std::string message(l10n_util::GetStringUTF8(message_id)); base::StringValue message_value(message); base::FundamentalValue retry_value(retry); web_ui()->CallJavascriptFunction("oobe.OAuthEnrollmentScreen.showError", @@ -484,21 +476,6 @@ void EnterpriseOAuthEnrollmentScreenHandler::ShowWorking(int message_id) { message_value); } -void EnterpriseOAuthEnrollmentScreenHandler::ResetAuth() { - oauth_fetcher_.reset(); - - if (browsing_data_remover_) - return; - - Profile* profile = Profile::FromBrowserContext( - web_ui()->GetWebContents()->GetBrowserContext()); - browsing_data_remover_ = - BrowsingDataRemover::CreateForUnboundedRange(profile); - browsing_data_remover_->AddObserver(this); - browsing_data_remover_->Remove(BrowsingDataRemover::REMOVE_SITE_DATA, - BrowsingDataHelper::UNPROTECTED_WEB); -} - void EnterpriseOAuthEnrollmentScreenHandler::RevokeTokens() { Profile* profile = Profile::FromBrowserContext( web_ui()->GetWebContents()->GetBrowserContext()); @@ -531,28 +508,6 @@ void EnterpriseOAuthEnrollmentScreenHandler::DoShow() { } ShowScreen("oauth-enrollment", &screen_data); - - if (is_auto_enrollment_ && !enrollment_failed_once_) - EnrollAfterLogin(); -} - -void EnterpriseOAuthEnrollmentScreenHandler::DoClose(bool back_to_signin) { - if (!controller_) { - NOTREACHED(); - return; - } - - if (!back_to_signin) { - // Show a progress spinner while profile creation is resuming. - ShowWorking(IDS_ENTERPRISE_ENROLLMENT_RESUMING_LOGIN); - } - controller_->OnConfirmationClosed(back_to_signin); -} - -void EnterpriseOAuthEnrollmentScreenHandler::UMAFailure(int sample) { - if (is_auto_enrollment_) - sample = policy::kMetricEnrollmentAutoFailed; - UMA(sample); } } // namespace chromeos diff --git a/chrome/browser/ui/webui/chromeos/login/enterprise_oauth_enrollment_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/enterprise_oauth_enrollment_screen_handler.h index fb8146e..e26d85a 100644 --- a/chrome/browser/ui/webui/chromeos/login/enterprise_oauth_enrollment_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/enterprise_oauth_enrollment_screen_handler.h @@ -6,6 +6,7 @@ #define CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_ENTERPRISE_OAUTH_ENROLLMENT_SCREEN_HANDLER_H_ #include <string> +#include <vector> #include "base/basictypes.h" #include "base/callback_forward.h" @@ -35,13 +36,20 @@ class EnterpriseOAuthEnrollmentScreenHandler virtual void RegisterMessages() OVERRIDE; // Implements EnterpriseEnrollmentScreenActor: - virtual void SetController(Controller* controller) OVERRIDE; + virtual void SetParameters(Controller* controller, + bool is_auto_enrollment, + const std::string& user) OVERRIDE; virtual void PrepareToShow() OVERRIDE; virtual void Show() OVERRIDE; virtual void Hide() OVERRIDE; - virtual void ShowConfirmationScreen() OVERRIDE; + virtual void FetchOAuthToken() OVERRIDE; + virtual void ResetAuth(const base::Closure& callback) OVERRIDE; + virtual void ShowSigninScreen() OVERRIDE; + virtual void ShowEnrollmentSpinnerScreen() OVERRIDE; + virtual void ShowLoginSpinnerScreen() OVERRIDE; virtual void ShowAuthError(const GoogleServiceAuthError& error) OVERRIDE; - virtual void ShowEnrollmentError(EnrollmentError error_code) OVERRIDE; + virtual void ShowEnrollmentStatus(policy::EnrollmentStatus status) OVERRIDE; + virtual void ShowUIError(UIError error_code) OVERRIDE; virtual void SubmitTestCredentials(const std::string& email, const std::string& password) OVERRIDE; @@ -75,22 +83,18 @@ class EnterpriseOAuthEnrollmentScreenHandler void HandleCompleteLogin(const base::ListValue* args); void HandleRetry(const base::ListValue* args); - // Proceeds with the enrollment process after a successful login. - void EnrollAfterLogin(); - // Shows a given enrollment step. void ShowStep(const char* step); - // Display the given i18n string as error message. + // Display the given i18n resource as error message. void ShowError(int message_id, bool retry); + // Display the given string as error message. + void ShowErrorMessage(const std::string& message, bool retry); + // Display the given i18n string as a progress message. void ShowWorking(int message_id); - // Resets the authentication machinery and clears cookies. Will invoke - // |action_on_browsing_data_removed_| once cookies are cleared. - void ResetAuth(); - // Starts asynchronous token revocation requests if there are tokens present. void RevokeTokens(); @@ -136,8 +140,8 @@ class EnterpriseOAuthEnrollmentScreenHandler // The browsing data remover instance currently active, if any. BrowsingDataRemover* browsing_data_remover_; - // What to do when browsing data is removed. - base::Closure action_on_browsing_data_removed_; + // The callbacks to invoke after browsing data has been cleared. + std::vector<base::Closure> auth_reset_callbacks_; DISALLOW_COPY_AND_ASSIGN(EnterpriseOAuthEnrollmentScreenHandler); }; diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 90dc6c7..a489640 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1358,6 +1358,8 @@ 'browser/policy/enterprise_metrics.h', 'browser/policy/managed_mode_policy_provider.cc', 'browser/policy/managed_mode_policy_provider.h', + 'browser/policy/message_util.cc', + 'browser/policy/message_util.h', 'browser/policy/network_configuration_updater.cc', 'browser/policy/network_configuration_updater.h', 'browser/policy/policy_bundle.cc', diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi index 51d097c..d3ec4c3 100644 --- a/chrome/chrome_browser_chromeos.gypi +++ b/chrome/chrome_browser_chromeos.gypi @@ -361,7 +361,6 @@ 'browser/chromeos/login/default_user_images.h', 'browser/chromeos/login/enrollment/enterprise_enrollment_screen.cc', 'browser/chromeos/login/enrollment/enterprise_enrollment_screen.h', - 'browser/chromeos/login/enrollment/enterprise_enrollment_screen_actor.cc', 'browser/chromeos/login/enrollment/enterprise_enrollment_screen_actor.h', 'browser/chromeos/login/eula_screen.cc', 'browser/chromeos/login/eula_screen.h', |