| // 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/ui/webui/chromeos/login/enrollment_screen_handler.h" |
| |
| #include <algorithm> |
| |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| #include "base/compiler_specific.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/values.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/browsing_data/browsing_data_helper.h" |
| #include "chrome/browser/browsing_data/browsing_data_remover.h" |
| #include "chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h" |
| #include "chrome/browser/policy/cloud/message_util.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" |
| #include "content/public/browser/web_contents.h" |
| #include "google_apis/gaia/gaia_auth_fetcher.h" |
| #include "google_apis/gaia/gaia_auth_util.h" |
| #include "google_apis/gaia/gaia_constants.h" |
| #include "google_apis/gaia/gaia_urls.h" |
| #include "google_apis/gaia/google_service_auth_error.h" |
| #include "grit/chromium_strings.h" |
| #include "grit/generated_resources.h" |
| #include "ui/base/l10n/l10n_util.h" |
| |
| namespace { |
| |
| const char kJsScreenPath[] = "login.OAuthEnrollmentScreen"; |
| |
| // Start page of GAIA authentication extension. |
| const char kGaiaExtStartPage[] = |
| "chrome-extension://mfffpogegjflfpflabcdkioaeobkgjik/main.html"; |
| |
| // Enrollment step names. |
| const char kEnrollmentStepSignin[] = "signin"; |
| const char kEnrollmentStepSuccess[] = "success"; |
| |
| // A helper class that takes care of asynchronously revoking a given token. |
| class TokenRevoker : public GaiaAuthConsumer { |
| public: |
| TokenRevoker() |
| : gaia_fetcher_(this, |
| GaiaConstants::kChromeOSSource, |
| g_browser_process->system_request_context()) {} |
| virtual ~TokenRevoker() {} |
| |
| void Start(const std::string& token) { |
| gaia_fetcher_.StartRevokeOAuth2Token(token); |
| } |
| |
| // GaiaAuthConsumer: |
| virtual void OnOAuth2RevokeTokenCompleted() OVERRIDE { |
| base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| } |
| |
| private: |
| GaiaAuthFetcher gaia_fetcher_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TokenRevoker); |
| }; |
| |
| } // namespace |
| |
| namespace chromeos { |
| |
| // EnrollmentScreenHandler, public ------------------------------ |
| |
| EnrollmentScreenHandler::EnrollmentScreenHandler() |
| : BaseScreenHandler(kJsScreenPath), |
| controller_(NULL), |
| show_on_init_(false), |
| is_auto_enrollment_(false), |
| can_exit_enrollment_(true), |
| browsing_data_remover_(NULL) { |
| } |
| |
| EnrollmentScreenHandler::~EnrollmentScreenHandler() { |
| if (browsing_data_remover_) |
| browsing_data_remover_->RemoveObserver(this); |
| } |
| |
| // EnrollmentScreenHandler, WebUIMessageHandler implementation -- |
| |
| void EnrollmentScreenHandler::RegisterMessages() { |
| AddCallback("oauthEnrollClose", |
| &EnrollmentScreenHandler::HandleClose); |
| AddCallback("oauthEnrollCompleteLogin", |
| &EnrollmentScreenHandler::HandleCompleteLogin); |
| AddCallback("oauthEnrollRetry", |
| &EnrollmentScreenHandler::HandleRetry); |
| } |
| |
| // EnrollmentScreenHandler |
| // EnrollmentScreenActor implementation ----------------------------------- |
| |
| void EnrollmentScreenHandler::SetParameters(Controller* controller, |
| bool is_auto_enrollment, |
| bool can_exit_enrollment, |
| const std::string& user) { |
| controller_ = controller; |
| is_auto_enrollment_ = is_auto_enrollment; |
| can_exit_enrollment_ = can_exit_enrollment; |
| if (is_auto_enrollment_) |
| user_ = user; |
| } |
| |
| void EnrollmentScreenHandler::PrepareToShow() { |
| } |
| |
| void EnrollmentScreenHandler::Show() { |
| if (!page_is_ready()) |
| show_on_init_ = true; |
| else |
| DoShow(); |
| } |
| |
| void EnrollmentScreenHandler::Hide() { |
| } |
| |
| void EnrollmentScreenHandler::FetchOAuthToken() { |
| Profile* profile = Profile::FromWebUI(web_ui()); |
| oauth_fetcher_.reset( |
| new policy::PolicyOAuth2TokenFetcher( |
| profile->GetRequestContext(), |
| g_browser_process->system_request_context(), |
| base::Bind(&EnrollmentScreenHandler::OnTokenFetched, |
| base::Unretained(this)))); |
| oauth_fetcher_->Start(); |
| } |
| |
| void EnrollmentScreenHandler::ResetAuth(const base::Closure& callback) { |
| auth_reset_callbacks_.push_back(callback); |
| if (browsing_data_remover_) |
| return; |
| |
| if (oauth_fetcher_) { |
| if (!oauth_fetcher_->oauth2_access_token().empty()) |
| (new TokenRevoker())->Start(oauth_fetcher_->oauth2_access_token()); |
| |
| if (!oauth_fetcher_->oauth2_refresh_token().empty()) |
| (new TokenRevoker())->Start(oauth_fetcher_->oauth2_refresh_token()); |
| } |
| |
| 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 EnrollmentScreenHandler::ShowSigninScreen() { |
| ShowStep(kEnrollmentStepSignin); |
| } |
| |
| void EnrollmentScreenHandler::ShowEnrollmentSpinnerScreen() { |
| ShowWorking(IDS_ENTERPRISE_ENROLLMENT_WORKING); |
| } |
| |
| void EnrollmentScreenHandler::ShowLoginSpinnerScreen() { |
| ShowWorking(IDS_ENTERPRISE_ENROLLMENT_RESUMING_LOGIN); |
| } |
| |
| void EnrollmentScreenHandler::ShowAuthError( |
| const GoogleServiceAuthError& error) { |
| 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: |
| case GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE: |
| case GoogleServiceAuthError::SERVICE_ERROR: |
| ShowError(IDS_ENTERPRISE_ENROLLMENT_AUTH_FATAL_ERROR, false); |
| return; |
| case GoogleServiceAuthError::USER_NOT_SIGNED_UP: |
| case GoogleServiceAuthError::ACCOUNT_DELETED: |
| case GoogleServiceAuthError::ACCOUNT_DISABLED: |
| ShowError(IDS_ENTERPRISE_ENROLLMENT_AUTH_ACCOUNT_ERROR, true); |
| return; |
| case GoogleServiceAuthError::CONNECTION_FAILED: |
| case GoogleServiceAuthError::SERVICE_UNAVAILABLE: |
| ShowError(IDS_ENTERPRISE_ENROLLMENT_AUTH_NETWORK_ERROR, true); |
| return; |
| case GoogleServiceAuthError::NUM_STATES: |
| break; |
| } |
| NOTREACHED(); |
| } |
| |
| void EnrollmentScreenHandler::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 EnrollmentScreenHandler::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_ROBOT_AUTH_FETCH_FAILED: |
| ShowError(IDS_ENTERPRISE_ENROLLMENT_ROBOT_AUTH_FETCH_FAILED, true); |
| return; |
| case policy::EnrollmentStatus::STATUS_ROBOT_REFRESH_FETCH_FAILED: |
| ShowError(IDS_ENTERPRISE_ENROLLMENT_ROBOT_REFRESH_FETCH_FAILED, true); |
| return; |
| case policy::EnrollmentStatus::STATUS_ROBOT_REFRESH_STORE_FAILED: |
| ShowError(IDS_ENTERPRISE_ENROLLMENT_ROBOT_REFRESH_STORE_FAILED, 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_VALIDATION_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; |
| } |
| NOTREACHED(); |
| } |
| |
| // EnrollmentScreenHandler BaseScreenHandler implementation ----- |
| |
| void EnrollmentScreenHandler::Initialize() { |
| if (show_on_init_) { |
| Show(); |
| show_on_init_ = false; |
| } |
| } |
| |
| void EnrollmentScreenHandler::DeclareLocalizedValues( |
| LocalizedValuesBuilder* builder) { |
| builder->Add("oauthEnrollScreenTitle", |
| IDS_ENTERPRISE_ENROLLMENT_SCREEN_TITLE); |
| builder->Add("oauthEnrollRetry", IDS_ENTERPRISE_ENROLLMENT_RETRY); |
| builder->Add("oauthEnrollCancel", IDS_ENTERPRISE_ENROLLMENT_CANCEL); |
| builder->Add("oauthEnrollDone", IDS_ENTERPRISE_ENROLLMENT_DONE); |
| builder->Add("oauthEnrollSuccess", IDS_ENTERPRISE_ENROLLMENT_SUCCESS); |
| builder->Add("oauthEnrollExplain", IDS_ENTERPRISE_ENROLLMENT_EXPLAIN); |
| builder->Add("oauthEnrollExplainLink", |
| IDS_ENTERPRISE_ENROLLMENT_EXPLAIN_LINK); |
| builder->Add("oauthEnrollExplainButton", |
| IDS_ENTERPRISE_ENROLLMENT_EXPLAIN_BUTTON); |
| builder->Add("oauthEnrollCancelAutoEnrollmentReally", |
| IDS_ENTERPRISE_ENROLLMENT_CANCEL_AUTO_REALLY); |
| builder->Add("oauthEnrollCancelAutoEnrollmentConfirm", |
| IDS_ENTERPRISE_ENROLLMENT_CANCEL_AUTO_CONFIRM); |
| builder->Add("oauthEnrollCancelAutoEnrollmentGoBack", |
| IDS_ENTERPRISE_ENROLLMENT_CANCEL_AUTO_GO_BACK); |
| } |
| |
| void EnrollmentScreenHandler::OnBrowsingDataRemoverDone() { |
| browsing_data_remover_->RemoveObserver(this); |
| browsing_data_remover_ = NULL; |
| |
| 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(); |
| } |
| } |
| |
| // EnrollmentScreenHandler, private ----------------------------- |
| |
| void EnrollmentScreenHandler::HandleClose(const std::string& reason) { |
| if (!controller_) { |
| NOTREACHED(); |
| return; |
| } |
| |
| if (reason == "cancel" || reason == "autocancel") |
| controller_->OnCancel(); |
| else if (reason == "done") |
| controller_->OnConfirmationClosed(); |
| else |
| NOTREACHED(); |
| } |
| |
| void EnrollmentScreenHandler::HandleCompleteLogin(const std::string& user) { |
| if (!controller_) { |
| NOTREACHED(); |
| return; |
| } |
| controller_->OnLoginDone(gaia::SanitizeEmail(user)); |
| } |
| |
| void EnrollmentScreenHandler::HandleRetry() { |
| if (!controller_) { |
| NOTREACHED(); |
| return; |
| } |
| controller_->OnRetry(); |
| } |
| |
| void EnrollmentScreenHandler::ShowStep(const char* step) { |
| CallJS("showStep", std::string(step)); |
| } |
| |
| void EnrollmentScreenHandler::ShowError(int message_id, bool retry) { |
| ShowErrorMessage(l10n_util::GetStringUTF8(message_id), retry); |
| } |
| |
| void EnrollmentScreenHandler::ShowErrorMessage(const std::string& message, |
| bool retry) { |
| CallJS("showError", message, retry); |
| } |
| |
| void EnrollmentScreenHandler::ShowWorking(int message_id) { |
| CallJS("showWorking", l10n_util::GetStringUTF16(message_id)); |
| } |
| |
| void EnrollmentScreenHandler::OnTokenFetched( |
| const std::string& token, |
| const GoogleServiceAuthError& error) { |
| if (!controller_) |
| return; |
| |
| if (error.state() != GoogleServiceAuthError::NONE) |
| controller_->OnAuthError(error); |
| else |
| controller_->OnOAuthTokenAvailable(token); |
| } |
| |
| void EnrollmentScreenHandler::DoShow() { |
| DictionaryValue screen_data; |
| screen_data.SetString("signin_url", kGaiaExtStartPage); |
| screen_data.SetString("gaiaUrl", GaiaUrls::GetInstance()->gaia_url().spec()); |
| screen_data.SetBoolean("is_auto_enrollment", is_auto_enrollment_); |
| screen_data.SetBoolean("prevent_cancellation", !can_exit_enrollment_); |
| |
| ShowScreen(OobeUI::kScreenOobeEnrollment, &screen_data); |
| } |
| |
| } // namespace chromeos |