1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h"
10 #include "base/bind_helpers.h"
11 #include "base/compiler_specific.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/values.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/browsing_data/browsing_data_helper.h"
16 #include "chrome/browser/browsing_data/browsing_data_remover.h"
17 #include "chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/ui/webui/chromeos/login/authenticated_user_email_retriever.h"
20 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
21 #include "components/policy/core/browser/cloud/message_util.h"
22 #include "content/public/browser/web_contents.h"
23 #include "google_apis/gaia/gaia_auth_fetcher.h"
24 #include "google_apis/gaia/gaia_auth_util.h"
25 #include "google_apis/gaia/gaia_constants.h"
26 #include "google_apis/gaia/gaia_urls.h"
27 #include "google_apis/gaia/google_service_auth_error.h"
28 #include "grit/chromium_strings.h"
29 #include "grit/generated_resources.h"
30 #include "net/url_request/url_request_context_getter.h"
31 #include "ui/base/l10n/l10n_util.h"
36 const char kJsScreenPath[] = "login.OAuthEnrollmentScreen";
38 // Start page of GAIA authentication extension.
39 const char kGaiaExtStartPage[] =
40 "chrome-extension://mfffpogegjflfpflabcdkioaeobkgjik/main.html";
42 // Enrollment step names.
43 const char kEnrollmentStepSignin[] = "signin";
44 const char kEnrollmentStepSuccess[] = "success";
46 // Enrollment mode strings.
47 const char kEnrollmentModeManual[] = "manual";
48 const char kEnrollmentModeForced[] = "forced";
49 const char kEnrollmentModeAuto[] = "auto";
51 std::string EnrollmentModeToString(EnrollmentScreenActor::EnrollmentMode mode) {
53 case EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL:
54 return kEnrollmentModeManual;
55 case EnrollmentScreenActor::ENROLLMENT_MODE_FORCED:
56 return kEnrollmentModeForced;
57 case EnrollmentScreenActor::ENROLLMENT_MODE_AUTO:
58 return kEnrollmentModeAuto;
61 NOTREACHED() << "Bad enrollment mode " << mode;
62 return kEnrollmentModeManual;
65 // A helper class that takes care of asynchronously revoking a given token.
66 class TokenRevoker : public GaiaAuthConsumer {
70 GaiaConstants::kChromeOSSource,
71 g_browser_process->system_request_context()) {}
72 virtual ~TokenRevoker() {}
74 void Start(const std::string& token) {
75 gaia_fetcher_.StartRevokeOAuth2Token(token);
79 virtual void OnOAuth2RevokeTokenCompleted() OVERRIDE {
80 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
84 GaiaAuthFetcher gaia_fetcher_;
86 DISALLOW_COPY_AND_ASSIGN(TokenRevoker);
91 // EnrollmentScreenHandler, public ------------------------------
93 EnrollmentScreenHandler::EnrollmentScreenHandler()
94 : BaseScreenHandler(kJsScreenPath),
97 enrollment_mode_(ENROLLMENT_MODE_MANUAL),
98 browsing_data_remover_(NULL) {
99 set_async_assets_load_id(OobeUI::kScreenOobeEnrollment);
102 EnrollmentScreenHandler::~EnrollmentScreenHandler() {
103 if (browsing_data_remover_)
104 browsing_data_remover_->RemoveObserver(this);
107 // EnrollmentScreenHandler, WebUIMessageHandler implementation --
109 void EnrollmentScreenHandler::RegisterMessages() {
110 AddCallback("oauthEnrollRetrieveAuthenticatedUserEmail",
111 &EnrollmentScreenHandler::HandleRetrieveAuthenticatedUserEmail);
112 AddCallback("oauthEnrollClose",
113 &EnrollmentScreenHandler::HandleClose);
114 AddCallback("oauthEnrollCompleteLogin",
115 &EnrollmentScreenHandler::HandleCompleteLogin);
116 AddCallback("oauthEnrollRetry",
117 &EnrollmentScreenHandler::HandleRetry);
120 // EnrollmentScreenHandler
121 // EnrollmentScreenActor implementation -----------------------------------
123 void EnrollmentScreenHandler::SetParameters(
124 Controller* controller,
125 EnrollmentMode enrollment_mode,
126 const std::string& management_domain) {
127 controller_ = controller;
128 enrollment_mode_ = enrollment_mode;
129 management_domain_ = management_domain;
132 void EnrollmentScreenHandler::PrepareToShow() {
135 void EnrollmentScreenHandler::Show() {
136 if (!page_is_ready())
137 show_on_init_ = true;
142 void EnrollmentScreenHandler::Hide() {
145 void EnrollmentScreenHandler::FetchOAuthToken() {
146 Profile* profile = Profile::FromWebUI(web_ui());
147 oauth_fetcher_.reset(
148 new policy::PolicyOAuth2TokenFetcher(
149 profile->GetRequestContext(),
150 g_browser_process->system_request_context(),
151 base::Bind(&EnrollmentScreenHandler::OnTokenFetched,
152 base::Unretained(this))));
153 oauth_fetcher_->Start();
156 void EnrollmentScreenHandler::ResetAuth(const base::Closure& callback) {
157 auth_reset_callbacks_.push_back(callback);
158 if (browsing_data_remover_)
161 if (oauth_fetcher_) {
162 if (!oauth_fetcher_->oauth2_access_token().empty())
163 (new TokenRevoker())->Start(oauth_fetcher_->oauth2_access_token());
165 if (!oauth_fetcher_->oauth2_refresh_token().empty())
166 (new TokenRevoker())->Start(oauth_fetcher_->oauth2_refresh_token());
169 Profile* profile = Profile::FromBrowserContext(
170 web_ui()->GetWebContents()->GetBrowserContext());
171 browsing_data_remover_ =
172 BrowsingDataRemover::CreateForUnboundedRange(profile);
173 browsing_data_remover_->AddObserver(this);
174 browsing_data_remover_->Remove(BrowsingDataRemover::REMOVE_SITE_DATA,
175 BrowsingDataHelper::UNPROTECTED_WEB);
178 void EnrollmentScreenHandler::ShowSigninScreen() {
179 ShowStep(kEnrollmentStepSignin);
182 void EnrollmentScreenHandler::ShowEnrollmentSpinnerScreen() {
183 ShowWorking(IDS_ENTERPRISE_ENROLLMENT_WORKING);
186 void EnrollmentScreenHandler::ShowLoginSpinnerScreen() {
187 ShowWorking(IDS_ENTERPRISE_ENROLLMENT_RESUMING_LOGIN);
190 void EnrollmentScreenHandler::ShowAuthError(
191 const GoogleServiceAuthError& error) {
192 switch (error.state()) {
193 case GoogleServiceAuthError::NONE:
194 case GoogleServiceAuthError::CAPTCHA_REQUIRED:
195 case GoogleServiceAuthError::TWO_FACTOR:
196 case GoogleServiceAuthError::HOSTED_NOT_ALLOWED:
197 case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
198 case GoogleServiceAuthError::REQUEST_CANCELED:
199 case GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE:
200 case GoogleServiceAuthError::SERVICE_ERROR:
201 ShowError(IDS_ENTERPRISE_ENROLLMENT_AUTH_FATAL_ERROR, false);
203 case GoogleServiceAuthError::USER_NOT_SIGNED_UP:
204 case GoogleServiceAuthError::ACCOUNT_DELETED:
205 case GoogleServiceAuthError::ACCOUNT_DISABLED:
206 ShowError(IDS_ENTERPRISE_ENROLLMENT_AUTH_ACCOUNT_ERROR, true);
208 case GoogleServiceAuthError::CONNECTION_FAILED:
209 case GoogleServiceAuthError::SERVICE_UNAVAILABLE:
210 ShowError(IDS_ENTERPRISE_ENROLLMENT_AUTH_NETWORK_ERROR, true);
212 case GoogleServiceAuthError::NUM_STATES:
218 void EnrollmentScreenHandler::ShowUIError(UIError error) {
220 case UI_ERROR_DOMAIN_MISMATCH:
221 ShowError(IDS_ENTERPRISE_ENROLLMENT_STATUS_LOCK_WRONG_USER, true);
223 case UI_ERROR_AUTO_ENROLLMENT_BAD_MODE:
224 ShowError(IDS_ENTERPRISE_AUTO_ENROLLMENT_BAD_MODE, true);
227 ShowError(IDS_ENTERPRISE_ENROLLMENT_FATAL_ENROLLMENT_ERROR, true);
233 void EnrollmentScreenHandler::ShowEnrollmentStatus(
234 policy::EnrollmentStatus status) {
235 switch (status.status()) {
236 case policy::EnrollmentStatus::STATUS_SUCCESS:
237 ShowStep(kEnrollmentStepSuccess);
239 case policy::EnrollmentStatus::STATUS_NO_STATE_KEYS:
240 ShowError(IDS_ENTERPRISE_ENROLLMENT_STATUS_NO_STATE_KEYS, false);
242 case policy::EnrollmentStatus::STATUS_REGISTRATION_FAILED:
243 // Some special cases for generating a nicer message that's more helpful.
244 switch (status.client_status()) {
245 case policy::DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED:
246 ShowError(IDS_ENTERPRISE_ENROLLMENT_ACCOUNT_ERROR, true);
248 case policy::DM_STATUS_SERVICE_MISSING_LICENSES:
249 ShowError(IDS_ENTERPRISE_ENROLLMENT_MISSING_LICENSES_ERROR, true);
251 case policy::DM_STATUS_SERVICE_DEPROVISIONED:
252 ShowError(IDS_ENTERPRISE_ENROLLMENT_DEPROVISIONED_ERROR, true);
254 case policy::DM_STATUS_SERVICE_DOMAIN_MISMATCH:
255 ShowError(IDS_ENTERPRISE_ENROLLMENT_DOMAIN_MISMATCH_ERROR, true);
259 l10n_util::GetStringFUTF8(
260 IDS_ENTERPRISE_ENROLLMENT_STATUS_REGISTRATION_FAILED,
261 policy::FormatDeviceManagementStatus(status.client_status())),
265 case policy::EnrollmentStatus::STATUS_ROBOT_AUTH_FETCH_FAILED:
266 ShowError(IDS_ENTERPRISE_ENROLLMENT_ROBOT_AUTH_FETCH_FAILED, true);
268 case policy::EnrollmentStatus::STATUS_ROBOT_REFRESH_FETCH_FAILED:
269 ShowError(IDS_ENTERPRISE_ENROLLMENT_ROBOT_REFRESH_FETCH_FAILED, true);
271 case policy::EnrollmentStatus::STATUS_ROBOT_REFRESH_STORE_FAILED:
272 ShowError(IDS_ENTERPRISE_ENROLLMENT_ROBOT_REFRESH_STORE_FAILED, true);
274 case policy::EnrollmentStatus::STATUS_REGISTRATION_BAD_MODE:
275 ShowError(IDS_ENTERPRISE_ENROLLMENT_STATUS_REGISTRATION_BAD_MODE, false);
277 case policy::EnrollmentStatus::STATUS_POLICY_FETCH_FAILED:
279 l10n_util::GetStringFUTF8(
280 IDS_ENTERPRISE_ENROLLMENT_STATUS_POLICY_FETCH_FAILED,
281 policy::FormatDeviceManagementStatus(status.client_status())),
284 case policy::EnrollmentStatus::STATUS_VALIDATION_FAILED:
286 l10n_util::GetStringFUTF8(
287 IDS_ENTERPRISE_ENROLLMENT_STATUS_VALIDATION_FAILED,
288 policy::FormatValidationStatus(status.validation_status())),
291 case policy::EnrollmentStatus::STATUS_LOCK_ERROR:
292 ShowError(IDS_ENTERPRISE_ENROLLMENT_STATUS_LOCK_ERROR, false);
294 case policy::EnrollmentStatus::STATUS_LOCK_TIMEOUT:
295 ShowError(IDS_ENTERPRISE_ENROLLMENT_STATUS_LOCK_TIMEOUT, false);
297 case policy::EnrollmentStatus::STATUS_LOCK_WRONG_USER:
298 ShowError(IDS_ENTERPRISE_ENROLLMENT_STATUS_LOCK_WRONG_USER, true);
300 case policy::EnrollmentStatus::STATUS_STORE_ERROR:
302 l10n_util::GetStringFUTF8(
303 IDS_ENTERPRISE_ENROLLMENT_STATUS_STORE_ERROR,
304 policy::FormatStoreStatus(status.store_status(),
305 status.validation_status())),
312 // EnrollmentScreenHandler BaseScreenHandler implementation -----
314 void EnrollmentScreenHandler::Initialize() {
317 show_on_init_ = false;
321 void EnrollmentScreenHandler::DeclareLocalizedValues(
322 LocalizedValuesBuilder* builder) {
323 builder->Add("oauthEnrollScreenTitle",
324 IDS_ENTERPRISE_ENROLLMENT_SCREEN_TITLE);
325 builder->Add("oauthEnrollDescription", IDS_ENTERPRISE_ENROLLMENT_DESCRIPTION);
326 builder->Add("oauthEnrollReEnrollmentText",
327 IDS_ENTERPRISE_ENROLLMENT_RE_ENROLLMENT_TEXT);
328 builder->Add("oauthEnrollRetry", IDS_ENTERPRISE_ENROLLMENT_RETRY);
329 builder->Add("oauthEnrollCancel", IDS_ENTERPRISE_ENROLLMENT_CANCEL);
330 builder->Add("oauthEnrollDone", IDS_ENTERPRISE_ENROLLMENT_DONE);
331 builder->Add("oauthEnrollSuccess", IDS_ENTERPRISE_ENROLLMENT_SUCCESS);
332 builder->Add("oauthEnrollExplain", IDS_ENTERPRISE_ENROLLMENT_EXPLAIN);
333 builder->Add("oauthEnrollExplainLink",
334 IDS_ENTERPRISE_ENROLLMENT_EXPLAIN_LINK);
335 builder->Add("oauthEnrollExplainButton",
336 IDS_ENTERPRISE_ENROLLMENT_EXPLAIN_BUTTON);
337 builder->Add("oauthEnrollCancelAutoEnrollmentReally",
338 IDS_ENTERPRISE_ENROLLMENT_CANCEL_AUTO_REALLY);
339 builder->Add("oauthEnrollCancelAutoEnrollmentConfirm",
340 IDS_ENTERPRISE_ENROLLMENT_CANCEL_AUTO_CONFIRM);
341 builder->Add("oauthEnrollCancelAutoEnrollmentGoBack",
342 IDS_ENTERPRISE_ENROLLMENT_CANCEL_AUTO_GO_BACK);
345 void EnrollmentScreenHandler::OnBrowsingDataRemoverDone() {
346 browsing_data_remover_->RemoveObserver(this);
347 browsing_data_remover_ = NULL;
349 std::vector<base::Closure> callbacks_to_run;
350 callbacks_to_run.swap(auth_reset_callbacks_);
351 for (std::vector<base::Closure>::iterator callback(callbacks_to_run.begin());
352 callback != callbacks_to_run.end(); ++callback) {
357 // EnrollmentScreenHandler, private -----------------------------
359 void EnrollmentScreenHandler::HandleRetrieveAuthenticatedUserEmail(
360 double attempt_token) {
361 email_retriever_.reset(new AuthenticatedUserEmailRetriever(
362 base::Bind(&EnrollmentScreenHandler::CallJS<double, std::string>,
363 base::Unretained(this),
364 "setAuthenticatedUserEmail",
366 Profile::FromWebUI(web_ui())->GetRequestContext()));
369 void EnrollmentScreenHandler::HandleClose(const std::string& reason) {
375 if (reason == "cancel" || reason == "autocancel")
376 controller_->OnCancel();
377 else if (reason == "done")
378 controller_->OnConfirmationClosed();
383 void EnrollmentScreenHandler::HandleCompleteLogin(const std::string& user) {
388 controller_->OnLoginDone(gaia::SanitizeEmail(user));
391 void EnrollmentScreenHandler::HandleRetry() {
396 controller_->OnRetry();
399 void EnrollmentScreenHandler::ShowStep(const char* step) {
400 CallJS("showStep", std::string(step));
403 void EnrollmentScreenHandler::ShowError(int message_id, bool retry) {
404 ShowErrorMessage(l10n_util::GetStringUTF8(message_id), retry);
407 void EnrollmentScreenHandler::ShowErrorMessage(const std::string& message,
409 CallJS("showError", message, retry);
412 void EnrollmentScreenHandler::ShowWorking(int message_id) {
413 CallJS("showWorking", l10n_util::GetStringUTF16(message_id));
416 void EnrollmentScreenHandler::OnTokenFetched(
417 const std::string& token,
418 const GoogleServiceAuthError& error) {
422 if (error.state() != GoogleServiceAuthError::NONE)
423 controller_->OnAuthError(error);
425 controller_->OnOAuthTokenAvailable(token);
428 void EnrollmentScreenHandler::DoShow() {
429 base::DictionaryValue screen_data;
430 screen_data.SetString("signin_url", kGaiaExtStartPage);
431 screen_data.SetString("gaiaUrl", GaiaUrls::GetInstance()->gaia_url().spec());
432 screen_data.SetString("enrollment_mode",
433 EnrollmentModeToString(enrollment_mode_));
434 screen_data.SetString("management_domain", management_domain_);
436 ShowScreen(OobeUI::kScreenOobeEnrollment, &screen_data);
439 } // namespace chromeos