1 // Copyright 2013 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/gaia_screen_handler.h"
7 #include "ash/system/chromeos/devicetype_utils.h"
10 #include "base/logging.h"
11 #include "base/metrics/histogram.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/values.h"
15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/browser_shutdown.h"
17 #include "chrome/browser/chromeos/input_method/input_method_util.h"
18 #include "chrome/browser/chromeos/language_preferences.h"
19 #include "chrome/browser/chromeos/login/screens/network_error.h"
20 #include "chrome/browser/chromeos/login/startup_utils.h"
21 #include "chrome/browser/chromeos/login/ui/user_adding_screen.h"
22 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
23 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
24 #include "chrome/browser/chromeos/policy/consumer_management_service.h"
25 #include "chrome/browser/chromeos/policy/consumer_management_stage.h"
26 #include "chrome/browser/chromeos/profiles/profile_helper.h"
27 #include "chrome/browser/chromeos/settings/cros_settings.h"
28 #include "chrome/browser/io_thread.h"
29 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
30 #include "chrome/browser/ui/webui/signin/inline_login_ui.h"
31 #include "chrome/common/channel_info.h"
32 #include "chrome/common/pref_names.h"
33 #include "chrome/grit/generated_resources.h"
34 #include "chromeos/chromeos_switches.h"
35 #include "chromeos/login/auth/user_context.h"
36 #include "chromeos/settings/cros_settings_names.h"
37 #include "chromeos/system/devicetype.h"
38 #include "chromeos/system/version_loader.h"
39 #include "components/login/localized_values_builder.h"
40 #include "components/user_manager/user_manager.h"
41 #include "components/version_info/version_info.h"
42 #include "content/public/browser/browser_thread.h"
43 #include "content/public/browser/render_frame_host.h"
44 #include "google_apis/gaia/gaia_auth_util.h"
45 #include "google_apis/gaia/gaia_switches.h"
46 #include "google_apis/gaia/gaia_urls.h"
47 #include "ui/base/ime/chromeos/input_method_manager.h"
48 #include "ui/base/l10n/l10n_util.h"
50 using content::BrowserThread
;
56 const char kJsScreenPath
[] = "login.GaiaSigninScreen";
57 const char kAuthIframeParentName
[] = "signin-frame";
58 const char kAuthIframeParentOrigin
[] =
59 "chrome-extension://mfffpogegjflfpflabcdkioaeobkgjik/";
61 const char kGaiaSandboxUrlSwitch
[] = "gaia-sandbox-url";
62 const char kEndpointGen
[] = "1.0";
64 std::string
GetChromeType() {
65 switch (chromeos::GetDeviceType()) {
66 case chromeos::DeviceType::kChromebox
:
68 case chromeos::DeviceType::kChromebase
:
70 case chromeos::DeviceType::kChromebit
:
72 case chromeos::DeviceType::kChromebook
:
75 return "chromedevice";
79 void UpdateAuthParams(base::DictionaryValue
* params
,
81 bool is_enrolling_consumer_management
) {
82 CrosSettings
* cros_settings
= CrosSettings::Get();
83 bool allow_new_user
= true;
84 cros_settings
->GetBoolean(kAccountsPrefAllowNewUser
, &allow_new_user
);
85 bool allow_guest
= true;
86 cros_settings
->GetBoolean(kAccountsPrefAllowGuest
, &allow_guest
);
87 // Account creation depends on Guest sign-in (http://crosbug.com/24570).
88 params
->SetBoolean("createAccount", allow_new_user
&& allow_guest
);
89 params
->SetBoolean("guestSignin", allow_guest
);
91 // nosignup flow if new users are not allowed.
92 if (!allow_new_user
&& StartupUtils::IsWebviewSigninEnabled())
93 params
->SetString("flow", "nosignup");
95 // Allow supervised user creation only if:
96 // 1. Enterprise managed device > is allowed by policy.
97 // 2. Consumer device > owner exists.
98 // 3. New users are allowed by owner.
99 // 4. Supervised users are allowed by owner.
100 bool supervised_users_allowed
=
101 user_manager::UserManager::Get()->AreSupervisedUsersAllowed();
102 bool supervised_users_can_create
= true;
105 supervised_users_can_create
= false;
106 message_id
= IDS_CREATE_SUPERVISED_USER_NO_MANAGER_TEXT
;
108 if (!allow_new_user
|| !supervised_users_allowed
) {
109 supervised_users_can_create
= false;
110 message_id
= IDS_CREATE_SUPERVISED_USER_CREATION_RESTRICTED_TEXT
;
112 if (supervised_users_can_create
&&
113 ChromeUserManager::Get()
114 ->GetUsersAllowedForSupervisedUsersCreation()
116 supervised_users_can_create
= false;
117 message_id
= IDS_CREATE_SUPERVISED_USER_NO_MANAGER_EXCEPT_KIDS_TEXT
;
120 params
->SetBoolean("supervisedUsersEnabled", supervised_users_allowed
);
121 params
->SetBoolean("supervisedUsersCanCreate", supervised_users_can_create
);
122 if (!supervised_users_can_create
) {
123 params
->SetString("supervisedUsersRestrictionReason",
124 l10n_util::GetStringUTF16(message_id
));
127 // Now check whether we're in multi-profiles user adding scenario and
128 // disable GAIA right panel features if that's the case.
129 // For consumer management enrollment, we also hide all right panel components
130 // and show only an enrollment message.
131 if (UserAddingScreen::Get()->IsRunning() ||
132 is_enrolling_consumer_management
) {
133 params
->SetBoolean("createAccount", false);
134 params
->SetBoolean("guestSignin", false);
135 params
->SetBoolean("supervisedUsersEnabled", false);
139 void RecordSAMLScrapingVerificationResultInHistogram(bool success
) {
140 UMA_HISTOGRAM_BOOLEAN("ChromeOS.SAML.Scraping.VerificationResult", success
);
143 void RecordGAIAFlowTypeHistogram() {
144 UMA_HISTOGRAM_BOOLEAN("ChromeOS.GAIA.WebViewFlow",
145 StartupUtils::IsWebviewSigninEnabled());
148 // The Task posted to PostTaskAndReply in StartClearingDnsCache on the IO
150 void ClearDnsCache(IOThread
* io_thread
) {
151 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
152 if (browser_shutdown::IsTryingToQuit())
155 io_thread
->ClearHostCache();
158 void PushFrontIMIfNotExists(const std::string
& input_method
,
159 std::vector
<std::string
>* input_methods
) {
160 if (input_method
.empty())
163 if (std::find(input_methods
->begin(), input_methods
->end(), input_method
) ==
164 input_methods
->end())
165 input_methods
->insert(input_methods
->begin(), input_method
);
170 GaiaContext::GaiaContext()
171 : force_reload(false),
178 GaiaScreenHandler::GaiaScreenHandler(
179 CoreOobeActor
* core_oobe_actor
,
180 const scoped_refptr
<NetworkStateInformer
>& network_state_informer
,
181 policy::ConsumerManagementService
* consumer_management
)
182 : BaseScreenHandler(kJsScreenPath
),
183 frame_state_(FRAME_STATE_UNKNOWN
),
184 frame_error_(net::OK
),
185 network_state_informer_(network_state_informer
),
186 consumer_management_(consumer_management
),
187 core_oobe_actor_(core_oobe_actor
),
189 dns_clear_task_running_(false),
190 cookies_cleared_(false),
191 show_when_dns_and_cookies_cleared_(false),
192 gaia_silent_load_(false),
193 using_saml_api_(false),
194 is_enrolling_consumer_management_(false),
195 test_expects_complete_login_(false),
196 use_easy_bootstrap_(false),
197 signin_screen_handler_(NULL
),
198 weak_factory_(this) {
199 DCHECK(network_state_informer_
.get());
202 GaiaScreenHandler::~GaiaScreenHandler() {
205 void GaiaScreenHandler::LoadGaia(const GaiaContext
& context
) {
206 if (StartupUtils::IsWebviewSigninEnabled()) {
207 base::PostTaskAndReplyWithResult(
208 content::BrowserThread::GetBlockingPool(), FROM_HERE
,
209 base::Bind(&version_loader::GetVersion
, version_loader::VERSION_SHORT
),
210 base::Bind(&GaiaScreenHandler::LoadGaiaWithVersion
,
211 weak_factory_
.GetWeakPtr(), context
));
213 LoadGaiaWithVersion(context
, "");
217 void GaiaScreenHandler::LoadGaiaWithVersion(
218 const GaiaContext
& context
,
219 const std::string
& platform_version
) {
220 if (!auth_extension_
) {
221 Profile
* signin_profile
= ProfileHelper::GetSigninProfile();
222 auth_extension_
.reset(new ScopedGaiaAuthExtension(signin_profile
));
225 base::DictionaryValue params
;
226 const bool is_enrolling_consumer_management
=
227 context
.is_enrolling_consumer_management
;
229 params
.SetBoolean("forceReload", context
.force_reload
);
230 params
.SetBoolean("isLocal", context
.is_local
);
231 params
.SetBoolean("isShowUsers", context
.show_users
);
232 params
.SetBoolean("useOffline", context
.use_offline
);
233 params
.SetString("gaiaId", context
.gaia_id
);
234 params
.SetString("email", context
.email
);
235 params
.SetBoolean("isEnrollingConsumerManagement",
236 is_enrolling_consumer_management
);
237 params
.SetString("gapsCookie", context
.gaps_cookie
);
239 UpdateAuthParams(¶ms
,
241 is_enrolling_consumer_management
);
243 if (!context
.use_offline
) {
244 const std::string app_locale
= g_browser_process
->GetApplicationLocale();
245 if (!app_locale
.empty())
246 params
.SetString("hl", app_locale
);
248 base::DictionaryValue
* localized_strings
= new base::DictionaryValue();
249 if (StartupUtils::IsWebviewSigninEnabled()) {
250 policy::BrowserPolicyConnectorChromeOS
* connector
=
251 g_browser_process
->platform_part()
252 ->browser_policy_connector_chromeos();
253 std::string
enterprise_domain(connector
->GetEnterpriseDomain());
254 if (!enterprise_domain
.empty()) {
255 localized_strings
->SetString(
256 "stringEnterpriseInfo",
257 l10n_util::GetStringFUTF16(
258 IDS_NEWGAIA_OFFLINE_DEVICE_MANAGED_BY_NOTICE
,
259 base::UTF8ToUTF16(enterprise_domain
)));
262 localized_strings
->SetString(
263 "stringEmail", l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_EMAIL
));
264 localized_strings
->SetString(
266 l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_PASSWORD
));
267 localized_strings
->SetString(
268 "stringSignIn", l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_SIGNIN
));
269 localized_strings
->SetString(
271 l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_EMPTY_EMAIL
));
272 localized_strings
->SetString(
273 "stringEmptyPassword",
274 l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_EMPTY_PASSWORD
));
275 localized_strings
->SetString(
276 "stringError", l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_ERROR
));
278 params
.Set("localizedStrings", localized_strings
);
281 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
283 if (StartupUtils::IsWebviewSigninEnabled()) {
284 params
.SetBoolean("useNewGaiaFlow", true);
286 policy::BrowserPolicyConnectorChromeOS
* connector
=
287 g_browser_process
->platform_part()->browser_policy_connector_chromeos();
288 std::string
enterprise_domain(connector
->GetEnterpriseDomain());
289 if (!enterprise_domain
.empty())
290 params
.SetString("enterpriseDomain", enterprise_domain
);
292 params
.SetString("chromeType", GetChromeType());
293 params
.SetString("clientId",
294 GaiaUrls::GetInstance()->oauth2_chrome_client_id());
295 params
.SetString("clientVersion", version_info::GetVersionNumber());
296 if (!platform_version
.empty())
297 params
.SetString("platformVersion", platform_version
);
298 params
.SetString("releaseChannel", chrome::GetChannelString());
299 params
.SetString("endpointGen", kEndpointGen
);
301 std::string email_domain
;
302 if (CrosSettings::Get()->GetString(
303 kAccountsPrefLoginScreenDomainAutoComplete
, &email_domain
) &&
304 !email_domain
.empty()) {
305 params
.SetString("emailDomain", email_domain
);
308 params
.SetBoolean("useNewGaiaFlow", false);
311 if (!command_line
->HasSwitch(::switches::kGaiaUrl
) &&
312 command_line
->HasSwitch(kGaiaSandboxUrlSwitch
) &&
313 StartupUtils::IsWebviewSigninEnabled()) {
314 // We can't use switch --gaia-url in this case cause we need get
315 // auth_code from staging gaia and make all the other auths against prod
316 // gaia so user could use all the google services.
317 // Default to production Gaia for MM unless --gaia-url or --gaia-sandbox-url
319 // TODO(dpolukhin): crbug.com/462204
320 const GURL gaia_url
=
321 GURL(command_line
->GetSwitchValueASCII(kGaiaSandboxUrlSwitch
));
322 params
.SetString("gaiaUrl", gaia_url
.spec());
324 const GURL gaia_url
=
325 command_line
->HasSwitch(::switches::kGaiaUrl
)
326 ? GURL(command_line
->GetSwitchValueASCII(::switches::kGaiaUrl
))
327 : GaiaUrls::GetInstance()->gaia_url();
328 params
.SetString("gaiaUrl", gaia_url
.spec());
331 if (use_easy_bootstrap_
) {
332 params
.SetBoolean("useEafe", true);
333 // Easy login overrides.
334 std::string eafe_url
= "https://easylogin.corp.google.com/";
335 if (command_line
->HasSwitch(switches::kEafeUrl
))
336 eafe_url
= command_line
->GetSwitchValueASCII(switches::kEafeUrl
);
337 std::string eafe_path
= "planters/cbaudioChrome";
338 if (command_line
->HasSwitch(switches::kEafePath
))
339 eafe_path
= command_line
->GetSwitchValueASCII(switches::kEafePath
);
341 params
.SetString("gaiaUrl", eafe_url
);
342 params
.SetString("gaiaPath", eafe_path
);
343 params
.SetString("clientId",
344 GaiaUrls::GetInstance()->oauth2_chrome_client_id());
347 frame_state_
= FRAME_STATE_LOADING
;
348 CallJS("loadAuthExtension", params
);
351 void GaiaScreenHandler::UpdateGaia(const GaiaContext
& context
) {
352 base::DictionaryValue params
;
353 UpdateAuthParams(¶ms
, context
.has_users
,
354 context
.is_enrolling_consumer_management
);
355 CallJS("updateAuthExtension", params
);
358 void GaiaScreenHandler::ReloadGaia(bool force_reload
) {
359 if (frame_state_
== FRAME_STATE_LOADING
&& !force_reload
) {
360 VLOG(1) << "Skipping reloading of Gaia since gaia is loading.";
363 NetworkStateInformer::State state
= network_state_informer_
->state();
364 if (state
!= NetworkStateInformer::ONLINE
) {
365 VLOG(1) << "Skipping reloading of Gaia since network state="
366 << NetworkStateInformer::StatusString(state
);
369 VLOG(1) << "Reloading Gaia.";
370 frame_state_
= FRAME_STATE_LOADING
;
374 void GaiaScreenHandler::MonitorOfflineIdle(bool is_online
) {
375 CallJS("monitorOfflineIdle", is_online
);
378 void GaiaScreenHandler::DeclareLocalizedValues(
379 ::login::LocalizedValuesBuilder
* builder
) {
380 builder
->Add("signinScreenTitle", IDS_SIGNIN_SCREEN_TITLE_TAB_PROMPT
);
381 builder
->Add("createAccount", IDS_CREATE_ACCOUNT_HTML
);
382 builder
->Add("guestSignin", IDS_BROWSE_WITHOUT_SIGNING_IN_HTML
);
383 builder
->Add("createSupervisedUser",
384 IDS_CREATE_SUPERVISED_USER_HTML
);
385 builder
->Add("createSupervisedUserFeatureName",
386 IDS_CREATE_SUPERVISED_USER_FEATURE_NAME
);
387 builder
->Add("consumerManagementEnrollmentSigninMessage",
388 IDS_LOGIN_CONSUMER_MANAGEMENT_ENROLLMENT
);
389 builder
->Add("backButton", IDS_ACCNAME_BACK
);
390 builder
->Add("closeButton", IDS_CLOSE
);
391 builder
->Add("whitelistErrorConsumer", IDS_LOGIN_ERROR_WHITELIST
);
392 builder
->Add("whitelistErrorEnterprise",
393 IDS_ENTERPRISE_LOGIN_ERROR_WHITELIST
);
394 builder
->Add("tryAgainButton", IDS_WHITELIST_ERROR_TRY_AGAIN_BUTTON
);
395 builder
->Add("learnMoreButton", IDS_WHITELIST_ERROR_LEARN_MORE_BUTTON
);
396 builder
->Add("gaiaLoadingNewGaia", IDS_LOGIN_GAIA_LOADING_MESSAGE
);
398 // Strings used by the SAML fatal error dialog.
399 builder
->Add("fatalErrorMessageNoAccountDetails",
400 IDS_LOGIN_FATAL_ERROR_NO_ACCOUNT_DETAILS
);
401 builder
->Add("fatalErrorMessageNoPassword",
402 IDS_LOGIN_FATAL_ERROR_NO_PASSWORD
);
403 builder
->Add("fatalErrorMessageVerificationFailed",
404 IDS_LOGIN_FATAL_ERROR_PASSWORD_VERIFICATION
);
405 builder
->Add("fatalErrorMessageInsecureURL",
406 IDS_LOGIN_FATAL_ERROR_TEXT_INSECURE_URL
);
407 builder
->Add("fatalErrorDismissButton", IDS_OK
);
408 builder
->Add("fatalErrorDoneButton", IDS_DONE
);
409 builder
->Add("fatalErrorTryAgainButton",
410 IDS_LOGIN_FATAL_ERROR_TRY_AGAIN_BUTTON
);
412 builder
->AddF("offlineLoginWelcome", IDS_NEWGAIA_OFFLINE_WELCOME
,
413 ash::GetChromeOSDeviceTypeResourceId());
414 builder
->Add("offlineLoginEmail", IDS_NEWGAIA_OFFLINE_EMAIL
);
415 builder
->Add("offlineLoginPassword", IDS_NEWGAIA_OFFLINE_PASSWORD
);
416 builder
->Add("offlineLoginInvalidEmail", IDS_NEWGAIA_OFFLINE_INVALID_EMAIL
);
417 builder
->Add("offlineLoginInvalidPassword",
418 IDS_NEWGAIA_OFFLINE_INVALID_PASSWORD
);
419 builder
->Add("offlineLoginNextBtn", IDS_NEWGAIA_OFFLINE_NEXT_BUTTON_TEXT
);
420 builder
->Add("offlineLoginForgotPasswordBtn",
421 IDS_NEWGAIA_OFFLINE_FORGOT_PASSWORD_BUTTON_TEXT
);
422 builder
->Add("offlineLoginForgotPasswordDlg",
423 IDS_NEWGAIA_OFFLINE_FORGOT_PASSWORD_DIALOG_TEXT
);
424 builder
->Add("offlineLoginCloseBtn", IDS_NEWGAIA_OFFLINE_CLOSE_BUTTON_TEXT
);
427 void GaiaScreenHandler::GetAdditionalParameters(base::DictionaryValue
* dict
) {
428 dict
->SetBoolean("isWebviewSignin", StartupUtils::IsWebviewSigninEnabled());
431 void GaiaScreenHandler::Initialize() {
434 void GaiaScreenHandler::RegisterMessages() {
435 AddCallback("frameLoadingCompleted",
436 &GaiaScreenHandler::HandleFrameLoadingCompleted
);
437 AddCallback("webviewLoadAborted",
438 &GaiaScreenHandler::HandleWebviewLoadAborted
);
439 AddCallback("completeLogin", &GaiaScreenHandler::HandleCompleteLogin
);
440 AddCallback("completeAuthentication",
441 &GaiaScreenHandler::HandleCompleteAuthentication
);
442 AddCallback("completeAuthenticationAuthCodeOnly",
443 &GaiaScreenHandler::HandleCompleteAuthenticationAuthCodeOnly
);
444 AddCallback("usingSAMLAPI", &GaiaScreenHandler::HandleUsingSAMLAPI
);
445 AddCallback("scrapedPasswordCount",
446 &GaiaScreenHandler::HandleScrapedPasswordCount
);
447 AddCallback("scrapedPasswordVerificationFailed",
448 &GaiaScreenHandler::HandleScrapedPasswordVerificationFailed
);
449 AddCallback("loginWebuiReady", &GaiaScreenHandler::HandleGaiaUIReady
);
450 AddCallback("toggleEasyBootstrap",
451 &GaiaScreenHandler::HandleToggleEasyBootstrap
);
452 AddCallback("identifierEntered", &GaiaScreenHandler::HandleIdentifierEntered
);
455 void GaiaScreenHandler::HandleIdentifierEntered(
456 const std::string
& account_identifier
) {
457 if (!Delegate()->IsUserWhitelisted(account_identifier
))
458 ShowWhitelistCheckFailedError();
461 void GaiaScreenHandler::HandleFrameLoadingCompleted(int status
) {
462 const net::Error frame_error
= static_cast<net::Error
>(-status
);
463 if (frame_error
== net::ERR_ABORTED
) {
464 LOG(WARNING
) << "Ignoring Gaia frame error: " << frame_error
;
467 frame_error_
= frame_error
;
468 if (frame_error
== net::OK
) {
469 VLOG(1) << "Gaia is loaded";
470 frame_state_
= FRAME_STATE_LOADED
;
472 LOG(WARNING
) << "Gaia frame error: " << frame_error_
;
473 frame_state_
= FRAME_STATE_ERROR
;
476 if (network_state_informer_
->state() != NetworkStateInformer::ONLINE
)
478 if (frame_state_
== FRAME_STATE_LOADED
)
479 UpdateState(NetworkError::ERROR_REASON_UPDATE
);
480 else if (frame_state_
== FRAME_STATE_ERROR
)
481 UpdateState(NetworkError::ERROR_REASON_FRAME_ERROR
);
484 void GaiaScreenHandler::HandleWebviewLoadAborted(
485 const std::string
& error_reason_str
) {
486 // TODO(nkostylev): Switch to int code once webview supports that.
487 // http://crbug.com/470483
488 if (error_reason_str
== "ERR_ABORTED") {
489 LOG(WARNING
) << "Ignoring Gaia webview error: " << error_reason_str
;
493 // TODO(nkostylev): Switch to int code once webview supports that.
494 // http://crbug.com/470483
495 // Extract some common codes used by SigninScreenHandler for now.
496 if (error_reason_str
== "ERR_NAME_NOT_RESOLVED")
497 frame_error_
= net::ERR_NAME_NOT_RESOLVED
;
498 else if (error_reason_str
== "ERR_INTERNET_DISCONNECTED")
499 frame_error_
= net::ERR_INTERNET_DISCONNECTED
;
500 else if (error_reason_str
== "ERR_NETWORK_CHANGED")
501 frame_error_
= net::ERR_NETWORK_CHANGED
;
502 else if (error_reason_str
== "ERR_INTERNET_DISCONNECTED")
503 frame_error_
= net::ERR_INTERNET_DISCONNECTED
;
504 else if (error_reason_str
== "ERR_PROXY_CONNECTION_FAILED")
505 frame_error_
= net::ERR_PROXY_CONNECTION_FAILED
;
506 else if (error_reason_str
== "ERR_TUNNEL_CONNECTION_FAILED")
507 frame_error_
= net::ERR_TUNNEL_CONNECTION_FAILED
;
509 frame_error_
= net::ERR_INTERNET_DISCONNECTED
;
511 LOG(ERROR
) << "Gaia webview error: " << error_reason_str
;
512 NetworkError::ErrorReason error_reason
=
513 NetworkError::ERROR_REASON_FRAME_ERROR
;
514 frame_state_
= FRAME_STATE_ERROR
;
515 UpdateState(error_reason
);
518 void GaiaScreenHandler::HandleCompleteAuthentication(
519 const std::string
& gaia_id
,
520 const std::string
& email
,
521 const std::string
& password
,
522 const std::string
& auth_code
,
524 const std::string
& gaps_cookie
) {
528 RecordGAIAFlowTypeHistogram();
530 DCHECK(!email
.empty());
531 DCHECK(!gaia_id
.empty());
532 const std::string sanitized_email
= gaia::SanitizeEmail(email
);
533 Delegate()->SetDisplayEmail(sanitized_email
);
534 UserContext
user_context(sanitized_email
);
535 user_context
.SetGaiaID(gaia_id
);
536 user_context
.SetKey(Key(password
));
537 user_context
.SetAuthCode(auth_code
);
538 user_context
.SetAuthFlow(using_saml
539 ? UserContext::AUTH_FLOW_GAIA_WITH_SAML
540 : UserContext::AUTH_FLOW_GAIA_WITHOUT_SAML
);
541 user_context
.SetGAPSCookie(gaps_cookie
);
542 Delegate()->CompleteLogin(user_context
);
545 void GaiaScreenHandler::HandleCompleteAuthenticationAuthCodeOnly(
546 const std::string
& auth_code
) {
550 RecordGAIAFlowTypeHistogram();
552 UserContext user_context
;
553 user_context
.SetAuthFlow(UserContext::AUTH_FLOW_EASY_BOOTSTRAP
);
554 user_context
.SetAuthCode(auth_code
);
555 Delegate()->CompleteLogin(user_context
);
558 void GaiaScreenHandler::HandleCompleteLogin(const std::string
& gaia_id
,
559 const std::string
& typed_email
,
560 const std::string
& password
,
562 if (!is_enrolling_consumer_management_
) {
563 DoCompleteLogin(gaia_id
, typed_email
, password
, using_saml
);
567 // Consumer management enrollment is in progress.
568 const std::string owner_email
=
569 user_manager::UserManager::Get()->GetOwnerEmail();
570 if (typed_email
!= owner_email
) {
571 // Show Gaia sign-in screen again, since we only allow the owner to sign
573 populated_email_
= owner_email
;
574 ShowGaiaAsync(is_enrolling_consumer_management_
);
578 CHECK(consumer_management_
);
579 consumer_management_
->SetOwner(owner_email
,
580 base::Bind(&GaiaScreenHandler::OnSetOwnerDone
,
581 weak_factory_
.GetWeakPtr(),
588 void GaiaScreenHandler::HandleUsingSAMLAPI() {
589 SetSAMLPrincipalsAPIUsed(true);
592 void GaiaScreenHandler::HandleScrapedPasswordCount(int password_count
) {
593 SetSAMLPrincipalsAPIUsed(false);
594 // Use a histogram that has 11 buckets, one for each of the values in [0, 9]
595 // and an overflow bucket at the end.
596 UMA_HISTOGRAM_ENUMERATION(
597 "ChromeOS.SAML.Scraping.PasswordCount", std::min(password_count
, 10), 11);
598 if (password_count
== 0)
599 HandleScrapedPasswordVerificationFailed();
602 void GaiaScreenHandler::HandleScrapedPasswordVerificationFailed() {
603 RecordSAMLScrapingVerificationResultInHistogram(false);
606 void GaiaScreenHandler::HandleToggleEasyBootstrap() {
607 use_easy_bootstrap_
= !use_easy_bootstrap_
;
608 const bool kForceReload
= true;
609 const bool kSilentLoad
= true;
610 const bool kNoOfflineUI
= false;
611 LoadAuthExtension(kForceReload
, kSilentLoad
, kNoOfflineUI
);
614 void GaiaScreenHandler::HandleGaiaUIReady() {
615 // As we could miss and window.onload could already be called, restore
616 // focus to current pod (see crbug/175243).
617 if (gaia_silent_load_
)
618 signin_screen_handler_
->RefocusCurrentPod();
620 HandleFrameLoadingCompleted(0);
622 if (test_expects_complete_login_
)
623 SubmitLoginFormForTest();
626 void GaiaScreenHandler::OnSetOwnerDone(const std::string
& gaia_id
,
627 const std::string
& typed_email
,
628 const std::string
& password
,
631 CHECK(consumer_management_
);
633 consumer_management_
->SetStage(
634 policy::ConsumerManagementStage::EnrollmentOwnerStored());
636 LOG(ERROR
) << "Failed to write owner e-mail to boot lockbox.";
637 consumer_management_
->SetStage(
638 policy::ConsumerManagementStage::EnrollmentBootLockboxFailed());
639 // We should continue logging in the user, as there's not much we can do
642 DoCompleteLogin(gaia_id
, typed_email
, password
, using_saml
);
645 void GaiaScreenHandler::DoCompleteLogin(const std::string
& gaia_id
,
646 const std::string
& typed_email
,
647 const std::string
& password
,
652 if (using_saml
&& !using_saml_api_
)
653 RecordSAMLScrapingVerificationResultInHistogram(true);
654 RecordGAIAFlowTypeHistogram();
656 DCHECK(!typed_email
.empty());
657 DCHECK(!gaia_id
.empty());
658 const std::string sanitized_email
= gaia::SanitizeEmail(typed_email
);
659 Delegate()->SetDisplayEmail(sanitized_email
);
660 UserContext
user_context(sanitized_email
);
661 user_context
.SetGaiaID(gaia_id
);
662 user_context
.SetKey(Key(password
));
663 user_context
.SetAuthFlow(using_saml
664 ? UserContext::AUTH_FLOW_GAIA_WITH_SAML
665 : UserContext::AUTH_FLOW_GAIA_WITHOUT_SAML
);
666 Delegate()->CompleteLogin(user_context
);
668 if (test_expects_complete_login_
) {
669 VLOG(2) << "Complete test login for " << typed_email
670 << ", requested=" << test_user_
;
672 test_expects_complete_login_
= false;
678 void GaiaScreenHandler::PopulateEmail(const std::string
& user_id
) {
679 populated_email_
= user_id
;
682 void GaiaScreenHandler::StartClearingDnsCache() {
683 if (dns_clear_task_running_
|| !g_browser_process
->io_thread())
686 dns_cleared_
= false;
687 BrowserThread::PostTaskAndReply(
690 base::Bind(&ClearDnsCache
, g_browser_process
->io_thread()),
691 base::Bind(&GaiaScreenHandler::OnDnsCleared
, weak_factory_
.GetWeakPtr()));
692 dns_clear_task_running_
= true;
695 void GaiaScreenHandler::OnDnsCleared() {
696 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
697 dns_clear_task_running_
= false;
699 ShowGaiaScreenIfReady();
702 void GaiaScreenHandler::StartClearingCookies(
703 const base::Closure
& on_clear_callback
) {
704 cookies_cleared_
= false;
705 ProfileHelper
* profile_helper
= ProfileHelper::Get();
706 LOG_ASSERT(Profile::FromWebUI(web_ui()) ==
707 profile_helper
->GetSigninProfile());
708 profile_helper
->ClearSigninProfile(
709 base::Bind(&GaiaScreenHandler::OnCookiesCleared
,
710 weak_factory_
.GetWeakPtr(), on_clear_callback
));
713 void GaiaScreenHandler::OnCookiesCleared(
714 const base::Closure
& on_clear_callback
) {
715 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
716 cookies_cleared_
= true;
717 on_clear_callback
.Run();
720 void GaiaScreenHandler::ShowSigninScreenForCreds(const std::string
& username
,
721 const std::string
& password
) {
722 VLOG(2) << "ShowSigninScreenForCreds for user " << username
723 << ", frame_state=" << frame_state();
725 test_user_
= username
;
726 test_pass_
= password
;
727 test_expects_complete_login_
= true;
729 // Submit login form for test if gaia is ready. If gaia is loading, login
730 // will be attempted in HandleLoginWebuiReady after gaia is ready. Otherwise,
731 // reload gaia then follow the loading case.
732 if (frame_state() == GaiaScreenHandler::FRAME_STATE_LOADED
) {
733 SubmitLoginFormForTest();
734 } else if (frame_state() != GaiaScreenHandler::FRAME_STATE_LOADING
) {
735 DCHECK(signin_screen_handler_
);
736 signin_screen_handler_
->OnShowAddUser();
740 void GaiaScreenHandler::SubmitLoginFormForTest() {
741 VLOG(2) << "Submit login form for test, user=" << test_user_
;
743 content::RenderFrameHost
* frame
= InlineLoginUI::GetAuthFrame(
744 web_ui()->GetWebContents(),
745 GURL(kAuthIframeParentOrigin
),
746 kAuthIframeParentName
);
748 if (!StartupUtils::IsWebviewSigninEnabled()) {
750 code
+= "document.getElementById('Email').value = '" + test_user_
+ "';";
751 code
+= "document.getElementById('Passwd').value = '" + test_pass_
+ "';";
752 code
+= "document.getElementById('signIn').click();";
754 frame
->ExecuteJavaScriptForTests(base::ASCIIToUTF16(code
));
759 "document.getElementById('identifier').value = '" + test_user_
+ "';";
760 code
+= "document.getElementById('nextButton').click();";
761 frame
->ExecuteJavaScriptForTests(base::ASCIIToUTF16(code
));
763 if (!test_pass_
.empty()) {
765 "document.getElementById('password').value = '" + test_pass_
+ "';";
766 code
+= "document.getElementById('nextButton').click();";
767 frame
->ExecuteJavaScriptForTests(base::ASCIIToUTF16(code
));
771 // Test properties are cleared in HandleCompleteLogin because the form
772 // submission might fail and login will not be attempted after reloading
773 // if they are cleared here.
776 void GaiaScreenHandler::SetSAMLPrincipalsAPIUsed(bool api_used
) {
777 using_saml_api_
= api_used
;
778 UMA_HISTOGRAM_BOOLEAN("ChromeOS.SAML.APIUsed", api_used
);
781 void GaiaScreenHandler::ShowGaiaAsync(bool is_enrolling_consumer_management
) {
782 is_enrolling_consumer_management_
= is_enrolling_consumer_management
;
783 show_when_dns_and_cookies_cleared_
= true;
784 if (gaia_silent_load_
&& populated_email_
.empty()) {
786 cookies_cleared_
= true;
787 ShowGaiaScreenIfReady();
789 StartClearingDnsCache();
790 StartClearingCookies(base::Bind(&GaiaScreenHandler::ShowGaiaScreenIfReady
,
791 weak_factory_
.GetWeakPtr()));
795 void GaiaScreenHandler::CancelShowGaiaAsync() {
796 show_when_dns_and_cookies_cleared_
= false;
799 void GaiaScreenHandler::ShowGaiaScreenIfReady() {
802 !show_when_dns_and_cookies_cleared_
||
807 std::string active_network_path
= network_state_informer_
->network_path();
808 if (gaia_silent_load_
&&
809 (network_state_informer_
->state() != NetworkStateInformer::ONLINE
||
810 gaia_silent_load_network_
!= active_network_path
)) {
811 // Network has changed. Force Gaia reload.
812 gaia_silent_load_
= false;
815 // Note that LoadAuthExtension clears |populated_email_|.
816 if (populated_email_
.empty())
817 Delegate()->LoadSigninWallpaper();
819 Delegate()->LoadWallpaper(populated_email_
);
821 input_method::InputMethodManager
* imm
=
822 input_method::InputMethodManager::Get();
824 scoped_refptr
<input_method::InputMethodManager::State
> gaia_ime_state
=
825 imm
->GetActiveIMEState()->Clone();
826 imm
->SetState(gaia_ime_state
);
828 // Set Least Recently Used input method for the user.
829 if (!populated_email_
.empty()) {
830 SigninScreenHandler::SetUserInputMethod(populated_email_
,
831 gaia_ime_state
.get());
833 std::vector
<std::string
> input_methods
=
834 imm
->GetInputMethodUtil()->GetHardwareLoginInputMethodIds();
835 const std::string owner_im
= SigninScreenHandler::GetUserLRUInputMethod(
836 user_manager::UserManager::Get()->GetOwnerEmail());
837 const std::string system_im
= g_browser_process
->local_state()->GetString(
838 language_prefs::kPreferredKeyboardLayout
);
840 PushFrontIMIfNotExists(owner_im
, &input_methods
);
841 PushFrontIMIfNotExists(system_im
, &input_methods
);
843 gaia_ime_state
->EnableLoginLayouts(
844 g_browser_process
->GetApplicationLocale(), input_methods
);
846 if (!system_im
.empty()) {
847 gaia_ime_state
->ChangeInputMethod(system_im
, false /* show_message */);
848 } else if (!owner_im
.empty()) {
849 gaia_ime_state
->ChangeInputMethod(owner_im
, false /* show_message */);
853 LoadAuthExtension(!gaia_silent_load_
, false, false);
854 signin_screen_handler_
->UpdateUIState(
855 SigninScreenHandler::UI_STATE_GAIA_SIGNIN
, NULL
);
857 if (gaia_silent_load_
) {
858 // The variable is assigned to false because silently loaded Gaia page was
860 gaia_silent_load_
= false;
862 signin_screen_handler_
->UpdateState(NetworkError::ERROR_REASON_UPDATE
);
864 if (core_oobe_actor_
) {
865 PrefService
* prefs
= g_browser_process
->local_state();
866 if (prefs
->GetBoolean(prefs::kFactoryResetRequested
)) {
867 core_oobe_actor_
->ShowDeviceResetScreen();
868 } else if (prefs
->GetBoolean(prefs::kDebuggingFeaturesRequested
)) {
869 core_oobe_actor_
->ShowEnableDebuggingScreen();
874 void GaiaScreenHandler::MaybePreloadAuthExtension() {
875 VLOG(1) << "MaybePreloadAuthExtension() call.";
877 // If cookies clearing was initiated or |dns_clear_task_running_| then auth
878 // extension showing has already been initiated and preloading is senseless.
879 if (signin_screen_handler_
->ShouldLoadGaia() &&
880 !gaia_silent_load_
&&
882 !dns_clear_task_running_
&&
883 network_state_informer_
->state() == NetworkStateInformer::ONLINE
) {
884 gaia_silent_load_
= true;
885 gaia_silent_load_network_
= network_state_informer_
->network_path();
886 LoadAuthExtension(true, true, false);
890 void GaiaScreenHandler::ShowWhitelistCheckFailedError() {
891 base::DictionaryValue params
;
892 params
.SetBoolean("enterpriseManaged",
893 g_browser_process
->platform_part()
894 ->browser_policy_connector_chromeos()
895 ->IsEnterpriseManaged());
896 CallJS("showWhitelistCheckFailedError", true, params
);
899 void GaiaScreenHandler::LoadAuthExtension(bool force
,
903 context
.force_reload
= force
;
904 context
.is_local
= offline
;
905 context
.use_offline
= offline
;
906 context
.email
= populated_email_
;
907 context
.is_enrolling_consumer_management
= is_enrolling_consumer_management_
;
910 if (user_manager::UserManager::Get()->FindGaiaID(context
.email
, &gaia_id
))
911 context
.gaia_id
= gaia_id
;
914 context
.show_users
= Delegate()->IsShowUsers();
915 context
.has_users
= !Delegate()->GetUsers().empty();
918 if (!context
.email
.empty()) {
919 context
.gaps_cookie
=
920 user_manager::UserManager::Get()->GetKnownUserGAPSCookie(
921 gaia::CanonicalizeEmail(context
.email
));
924 populated_email_
.clear();
929 void GaiaScreenHandler::UpdateState(NetworkError::ErrorReason reason
) {
930 if (signin_screen_handler_
)
931 signin_screen_handler_
->UpdateState(reason
);
934 SigninScreenHandlerDelegate
* GaiaScreenHandler::Delegate() {
935 DCHECK(signin_screen_handler_
);
936 return signin_screen_handler_
->delegate_
;
939 void GaiaScreenHandler::SetSigninScreenHandler(SigninScreenHandler
* handler
) {
940 signin_screen_handler_
= handler
;
943 } // namespace chromeos