Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / ui / webui / chromeos / login / gaia_screen_handler.cc
blob34c61120f6cc61fb28641bd50aa29d52c23725ff
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"
8 #include "base/bind.h"
9 #include "base/guid.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;
52 namespace chromeos {
54 namespace {
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:
67 return "chromebox";
68 case chromeos::DeviceType::kChromebase:
69 return "chromebase";
70 case chromeos::DeviceType::kChromebit:
71 return "chromebit";
72 case chromeos::DeviceType::kChromebook:
73 return "chromebook";
74 default:
75 return "chromedevice";
79 void UpdateAuthParams(base::DictionaryValue* params,
80 bool has_users,
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;
103 int message_id = -1;
104 if (!has_users) {
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()
115 .empty()) {
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
149 // thread.
150 void ClearDnsCache(IOThread* io_thread) {
151 DCHECK_CURRENTLY_ON(BrowserThread::IO);
152 if (browser_shutdown::IsTryingToQuit())
153 return;
155 io_thread->ClearHostCache();
158 void PushFrontIMIfNotExists(const std::string& input_method,
159 std::vector<std::string>* input_methods) {
160 if (input_method.empty())
161 return;
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);
168 } // namespace
170 GaiaContext::GaiaContext()
171 : force_reload(false),
172 is_local(false),
173 show_users(false),
174 use_offline(false),
175 has_users(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),
188 dns_cleared_(false),
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));
212 } else {
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(&params,
240 context.has_users,
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);
247 } else {
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)));
261 } else {
262 localized_strings->SetString(
263 "stringEmail", l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_EMAIL));
264 localized_strings->SetString(
265 "stringPassword",
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(
270 "stringEmptyEmail",
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);
307 } else {
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
318 // is specified.
319 // TODO(dpolukhin): crbug.com/462204
320 const GURL gaia_url =
321 GURL(command_line->GetSwitchValueASCII(kGaiaSandboxUrlSwitch));
322 params.SetString("gaiaUrl", gaia_url.spec());
323 } else {
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(&params, 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.";
361 return;
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);
367 return;
369 VLOG(1) << "Reloading Gaia.";
370 frame_state_ = FRAME_STATE_LOADING;
371 CallJS("doReload");
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;
465 return;
467 frame_error_ = frame_error;
468 if (frame_error == net::OK) {
469 VLOG(1) << "Gaia is loaded";
470 frame_state_ = FRAME_STATE_LOADED;
471 } else {
472 LOG(WARNING) << "Gaia frame error: " << frame_error_;
473 frame_state_ = FRAME_STATE_ERROR;
476 if (network_state_informer_->state() != NetworkStateInformer::ONLINE)
477 return;
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;
490 return;
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;
508 else
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,
523 bool using_saml,
524 const std::string& gaps_cookie) {
525 if (!Delegate())
526 return;
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) {
547 if (!Delegate())
548 return;
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,
561 bool using_saml) {
562 if (!is_enrolling_consumer_management_) {
563 DoCompleteLogin(gaia_id, typed_email, password, using_saml);
564 return;
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
572 // in.
573 populated_email_ = owner_email;
574 ShowGaiaAsync(is_enrolling_consumer_management_);
575 return;
578 CHECK(consumer_management_);
579 consumer_management_->SetOwner(owner_email,
580 base::Bind(&GaiaScreenHandler::OnSetOwnerDone,
581 weak_factory_.GetWeakPtr(),
582 gaia_id,
583 typed_email,
584 password,
585 using_saml));
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,
629 bool using_saml,
630 bool success) {
631 CHECK(consumer_management_);
632 if (success) {
633 consumer_management_->SetStage(
634 policy::ConsumerManagementStage::EnrollmentOwnerStored());
635 } else {
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
640 // here.
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,
648 bool using_saml) {
649 if (!Delegate())
650 return;
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;
673 test_user_.clear();
674 test_pass_.clear();
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())
684 return;
686 dns_cleared_ = false;
687 BrowserThread::PostTaskAndReply(
688 BrowserThread::IO,
689 FROM_HERE,
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;
698 dns_cleared_ = true;
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()) {
749 std::string code;
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));
755 } else {
756 std::string code;
758 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()) {
764 code =
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()) {
785 dns_cleared_ = true;
786 cookies_cleared_ = true;
787 ShowGaiaScreenIfReady();
788 } else {
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() {
800 if (!dns_cleared_ ||
801 !cookies_cleared_ ||
802 !show_when_dns_and_cookies_cleared_ ||
803 !Delegate()) {
804 return;
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();
818 else
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());
832 } else {
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
859 // used.
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_ &&
881 !cookies_cleared_ &&
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,
900 bool silent_load,
901 bool offline) {
902 GaiaContext context;
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_;
909 std::string gaia_id;
910 if (user_manager::UserManager::Get()->FindGaiaID(context.email, &gaia_id))
911 context.gaia_id = gaia_id;
913 if (Delegate()) {
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();
926 LoadGaia(context);
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