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.
4
5#include "chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h"
6
7#include "base/bind.h"
8#include "base/logging.h"
9#include "base/metrics/histogram.h"
10#include "base/prefs/pref_service.h"
11#include "base/strings/utf_string_conversions.h"
12#include "base/values.h"
13#include "chrome/browser/browser_process.h"
14#include "chrome/browser/browser_shutdown.h"
15#include "chrome/browser/chromeos/input_method/input_method_util.h"
16#include "chrome/browser/chromeos/language_preferences.h"
17#include "chrome/browser/chromeos/login/ui/user_adding_screen.h"
18#include "chrome/browser/chromeos/policy/consumer_management_service.h"
19#include "chrome/browser/chromeos/profiles/profile_helper.h"
20#include "chrome/browser/chromeos/settings/cros_settings.h"
21#include "chrome/browser/io_thread.h"
22#include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
23#include "chrome/browser/ui/webui/signin/inline_login_ui.h"
24#include "chrome/common/pref_names.h"
25#include "chrome/grit/generated_resources.h"
26#include "chromeos/chromeos_switches.h"
27#include "chromeos/ime/input_method_manager.h"
28#include "chromeos/settings/cros_settings_names.h"
29#include "components/user_manager/user_manager.h"
30#include "content/public/browser/browser_thread.h"
31#include "content/public/browser/render_frame_host.h"
32#include "google_apis/gaia/gaia_auth_util.h"
33#include "google_apis/gaia/gaia_switches.h"
34#include "google_apis/gaia/gaia_urls.h"
35#include "ui/base/l10n/l10n_util.h"
36
37using content::BrowserThread;
38
39namespace chromeos {
40
41namespace {
42
43const char kJsScreenPath[] = "login.GaiaSigninScreen";
44const char kAuthIframeParentName[] = "signin-frame";
45const char kAuthIframeParentOrigin[] =
46    "chrome-extension://mfffpogegjflfpflabcdkioaeobkgjik/";
47
48void UpdateAuthParams(base::DictionaryValue* params,
49                      bool has_users,
50                      bool is_enrolling_consumer_management) {
51  CrosSettings* cros_settings = CrosSettings::Get();
52  bool allow_new_user = true;
53  cros_settings->GetBoolean(kAccountsPrefAllowNewUser, &allow_new_user);
54  bool allow_guest = true;
55  cros_settings->GetBoolean(kAccountsPrefAllowGuest, &allow_guest);
56  // Account creation depends on Guest sign-in (http://crosbug.com/24570).
57  params->SetBoolean("createAccount", allow_new_user && allow_guest);
58  params->SetBoolean("guestSignin", allow_guest);
59
60  // Allow supervised user creation only if:
61  // 1. Enterprise managed device > is allowed by policy.
62  // 2. Consumer device > owner exists.
63  // 3. New users are allowed by owner.
64  // 4. Supervised users are allowed by owner.
65  bool supervised_users_allowed =
66      user_manager::UserManager::Get()->AreSupervisedUsersAllowed();
67  bool supervised_users_can_create = true;
68  int message_id = -1;
69  if (!has_users) {
70    supervised_users_can_create = false;
71    message_id = IDS_CREATE_SUPERVISED_USER_NO_MANAGER_TEXT;
72  }
73  if (!allow_new_user || !supervised_users_allowed) {
74    supervised_users_can_create = false;
75    message_id = IDS_CREATE_SUPERVISED_USER_CREATION_RESTRICTED_TEXT;
76  }
77
78  params->SetBoolean("supervisedUsersEnabled", supervised_users_allowed);
79  params->SetBoolean("supervisedUsersCanCreate", supervised_users_can_create);
80  if (!supervised_users_can_create) {
81    params->SetString("supervisedUsersRestrictionReason",
82                      l10n_util::GetStringUTF16(message_id));
83  }
84
85  // Now check whether we're in multi-profiles user adding scenario and
86  // disable GAIA right panel features if that's the case.
87  // For consumer management enrollment, we also hide all right panel components
88  // and show only an enrollment message.
89  if (UserAddingScreen::Get()->IsRunning() ||
90      is_enrolling_consumer_management) {
91    params->SetBoolean("createAccount", false);
92    params->SetBoolean("guestSignin", false);
93    params->SetBoolean("supervisedUsersEnabled", false);
94  }
95}
96
97void RecordSAMLScrapingVerificationResultInHistogram(bool success) {
98  UMA_HISTOGRAM_BOOLEAN("ChromeOS.SAML.Scraping.VerificationResult", success);
99}
100
101// The Task posted to PostTaskAndReply in StartClearingDnsCache on the IO
102// thread.
103void ClearDnsCache(IOThread* io_thread) {
104  DCHECK_CURRENTLY_ON(BrowserThread::IO);
105  if (browser_shutdown::IsTryingToQuit())
106    return;
107
108  io_thread->ClearHostCache();
109}
110
111void PushFrontIMIfNotExists(const std::string& input_method,
112                            std::vector<std::string>* input_methods) {
113  if (input_method.empty())
114    return;
115
116  if (std::find(input_methods->begin(), input_methods->end(), input_method) ==
117      input_methods->end())
118    input_methods->insert(input_methods->begin(), input_method);
119}
120
121}  // namespace
122
123GaiaContext::GaiaContext()
124    : force_reload(false),
125      is_local(false),
126      password_changed(false),
127      show_users(false),
128      use_offline(false),
129      has_users(false) {}
130
131GaiaScreenHandler::GaiaScreenHandler(
132    CoreOobeActor* core_oobe_actor,
133    const scoped_refptr<NetworkStateInformer>& network_state_informer,
134    policy::ConsumerManagementService* consumer_management)
135    : BaseScreenHandler(kJsScreenPath),
136      frame_state_(FRAME_STATE_UNKNOWN),
137      frame_error_(net::OK),
138      network_state_informer_(network_state_informer),
139      consumer_management_(consumer_management),
140      core_oobe_actor_(core_oobe_actor),
141      dns_cleared_(false),
142      dns_clear_task_running_(false),
143      cookies_cleared_(false),
144      focus_stolen_(false),
145      gaia_silent_load_(false),
146      using_saml_api_(false),
147      is_enrolling_consumer_management_(false),
148      test_expects_complete_login_(false),
149      signin_screen_handler_(NULL),
150      weak_factory_(this) {
151  DCHECK(network_state_informer_.get());
152}
153
154GaiaScreenHandler::~GaiaScreenHandler() {
155}
156
157void GaiaScreenHandler::LoadGaia(const GaiaContext& context) {
158  base::DictionaryValue params;
159  const bool is_enrolling_consumer_management =
160      context.is_enrolling_consumer_management;
161
162  params.SetBoolean("forceReload", context.force_reload);
163  params.SetBoolean("isLocal", context.is_local);
164  params.SetBoolean("passwordChanged", context.password_changed);
165  params.SetBoolean("isShowUsers", context.show_users);
166  params.SetBoolean("useOffline", context.use_offline);
167  params.SetString("email", context.email);
168  params.SetBoolean("isEnrollingConsumerManagement",
169                    is_enrolling_consumer_management);
170
171  UpdateAuthParams(&params,
172                   context.has_users,
173                   is_enrolling_consumer_management);
174
175  if (!context.use_offline) {
176    const std::string app_locale = g_browser_process->GetApplicationLocale();
177    if (!app_locale.empty())
178      params.SetString("hl", app_locale);
179  } else {
180    base::DictionaryValue* localized_strings = new base::DictionaryValue();
181    localized_strings->SetString(
182        "stringEmail", l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_EMAIL));
183    localized_strings->SetString(
184        "stringPassword",
185        l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_PASSWORD));
186    localized_strings->SetString(
187        "stringSignIn", l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_SIGNIN));
188    localized_strings->SetString(
189        "stringEmptyEmail",
190        l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_EMPTY_EMAIL));
191    localized_strings->SetString(
192        "stringEmptyPassword",
193        l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_EMPTY_PASSWORD));
194    localized_strings->SetString(
195        "stringError", l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_ERROR));
196    params.Set("localizedStrings", localized_strings);
197  }
198
199  CommandLine* command_line = CommandLine::ForCurrentProcess();
200
201  const GURL gaia_url =
202      command_line->HasSwitch(::switches::kGaiaUrl)
203          ? GURL(command_line->GetSwitchValueASCII(::switches::kGaiaUrl))
204          : GaiaUrls::GetInstance()->gaia_url();
205  params.SetString("gaiaUrl", gaia_url.spec());
206
207  if (command_line->HasSwitch(chromeos::switches::kEnableEmbeddedSignin))
208    params.SetBoolean("useEmbedded", true);
209
210  frame_state_ = FRAME_STATE_LOADING;
211  CallJS("loadAuthExtension", params);
212}
213
214void GaiaScreenHandler::UpdateGaia(const GaiaContext& context) {
215  base::DictionaryValue params;
216  UpdateAuthParams(&params, context.has_users,
217                   context.is_enrolling_consumer_management);
218  CallJS("updateAuthExtension", params);
219}
220
221void GaiaScreenHandler::ReloadGaia(bool force_reload) {
222  if (frame_state_ == FRAME_STATE_LOADING && !force_reload) {
223    VLOG(1) << "Skipping reloading of Gaia since gaia is loading.";
224    return;
225  }
226  NetworkStateInformer::State state = network_state_informer_->state();
227  if (state != NetworkStateInformer::ONLINE) {
228    VLOG(1) << "Skipping reloading of Gaia since network state="
229            << NetworkStateInformer::StatusString(state);
230    return;
231  }
232  VLOG(1) << "Reloading Gaia.";
233  frame_state_ = FRAME_STATE_LOADING;
234  CallJS("doReload");
235}
236
237void GaiaScreenHandler::DeclareLocalizedValues(
238    LocalizedValuesBuilder* builder) {
239  builder->Add("signinScreenTitle", IDS_SIGNIN_SCREEN_TITLE);
240  builder->Add("signinScreenPasswordChanged",
241               IDS_SIGNIN_SCREEN_PASSWORD_CHANGED);
242  builder->Add("createAccount", IDS_CREATE_ACCOUNT_HTML);
243  builder->Add("guestSignin", IDS_BROWSE_WITHOUT_SIGNING_IN_HTML);
244  builder->Add("createSupervisedUser",
245               IDS_CREATE_SUPERVISED_USER_HTML);
246  builder->Add("createSupervisedUserFeatureName",
247               IDS_CREATE_SUPERVISED_USER_FEATURE_NAME);
248  builder->Add("consumerManagementEnrollmentSigninMessage",
249               IDS_LOGIN_CONSUMER_MANAGEMENT_ENROLLMENT);
250
251  // Strings used by the SAML fatal error dialog.
252  builder->Add("fatalErrorMessageNoEmail", IDS_LOGIN_FATAL_ERROR_NO_EMAIL);
253  builder->Add("fatalErrorMessageNoPassword",
254               IDS_LOGIN_FATAL_ERROR_NO_PASSWORD);
255  builder->Add("fatalErrorMessageVerificationFailed",
256               IDS_LOGIN_FATAL_ERROR_PASSWORD_VERIFICATION);
257  builder->Add("fatalErrorMessageInsecureURL",
258               IDS_LOGIN_FATAL_ERROR_TEXT_INSECURE_URL);
259  builder->Add("fatalErrorInstructions", IDS_LOGIN_FATAL_ERROR_INSTRUCTIONS);
260  builder->Add("fatalErrorDismissButton", IDS_OK);
261}
262
263void GaiaScreenHandler::Initialize() {
264}
265
266void GaiaScreenHandler::RegisterMessages() {
267  AddCallback("frameLoadingCompleted",
268              &GaiaScreenHandler::HandleFrameLoadingCompleted);
269  AddCallback("completeLogin", &GaiaScreenHandler::HandleCompleteLogin);
270  AddCallback("completeAuthentication",
271              &GaiaScreenHandler::HandleCompleteAuthentication);
272  AddCallback("usingSAMLAPI", &GaiaScreenHandler::HandleUsingSAMLAPI);
273  AddCallback("scrapedPasswordCount",
274              &GaiaScreenHandler::HandleScrapedPasswordCount);
275  AddCallback("scrapedPasswordVerificationFailed",
276              &GaiaScreenHandler::HandleScrapedPasswordVerificationFailed);
277  AddCallback("loginWebuiReady", &GaiaScreenHandler::HandleGaiaUIReady);
278}
279
280void GaiaScreenHandler::HandleFrameLoadingCompleted(int status) {
281  const net::Error frame_error = static_cast<net::Error>(-status);
282  if (frame_error == net::ERR_ABORTED) {
283    LOG(WARNING) << "Ignoring Gaia frame error: " << frame_error;
284    return;
285  }
286  frame_error_ = frame_error;
287  if (frame_error == net::OK) {
288    VLOG(1) << "Gaia is loaded";
289    frame_state_ = FRAME_STATE_LOADED;
290  } else {
291    LOG(WARNING) << "Gaia frame error: " << frame_error_;
292    frame_state_ = FRAME_STATE_ERROR;
293  }
294
295  if (network_state_informer_->state() != NetworkStateInformer::ONLINE)
296    return;
297  if (frame_state_ == FRAME_STATE_LOADED)
298    UpdateState(ErrorScreenActor::ERROR_REASON_UPDATE);
299  else if (frame_state_ == FRAME_STATE_ERROR)
300    UpdateState(ErrorScreenActor::ERROR_REASON_FRAME_ERROR);
301}
302
303void GaiaScreenHandler::HandleCompleteAuthentication(
304    const std::string& email,
305    const std::string& password,
306    const std::string& auth_code) {
307  if (!Delegate())
308    return;
309  Delegate()->SetDisplayEmail(gaia::SanitizeEmail(email));
310  UserContext user_context(email);
311  user_context.SetKey(Key(password));
312  user_context.SetAuthCode(auth_code);
313  Delegate()->CompleteLogin(user_context);
314}
315
316void GaiaScreenHandler::HandleCompleteLogin(const std::string& typed_email,
317                                            const std::string& password,
318                                            bool using_saml) {
319  if (!is_enrolling_consumer_management_) {
320    DoCompleteLogin(typed_email, password, using_saml);
321    return;
322  }
323
324  // Consumer management enrollment is in progress.
325  const std::string owner_email =
326      user_manager::UserManager::Get()->GetOwnerEmail();
327  if (typed_email != owner_email) {
328    // Show Gaia sign-in screen again, since we only allow the owner to sign
329    // in.
330    populated_email_ = owner_email;
331    ShowGaia(is_enrolling_consumer_management_);
332    return;
333  }
334
335  CHECK(consumer_management_);
336  consumer_management_->SetOwner(owner_email,
337                                 base::Bind(&GaiaScreenHandler::OnSetOwnerDone,
338                                            weak_factory_.GetWeakPtr(),
339                                            typed_email,
340                                            password,
341                                            using_saml));
342}
343
344void GaiaScreenHandler::HandleUsingSAMLAPI() {
345  SetSAMLPrincipalsAPIUsed(true);
346}
347
348void GaiaScreenHandler::HandleScrapedPasswordCount(int password_count) {
349  SetSAMLPrincipalsAPIUsed(false);
350  // Use a histogram that has 11 buckets, one for each of the values in [0, 9]
351  // and an overflow bucket at the end.
352  UMA_HISTOGRAM_ENUMERATION(
353      "ChromeOS.SAML.Scraping.PasswordCount", std::min(password_count, 10), 11);
354  if (password_count == 0)
355    HandleScrapedPasswordVerificationFailed();
356}
357
358void GaiaScreenHandler::HandleScrapedPasswordVerificationFailed() {
359  RecordSAMLScrapingVerificationResultInHistogram(false);
360}
361
362void GaiaScreenHandler::HandleGaiaUIReady() {
363  if (focus_stolen_) {
364    // Set focus to the Gaia page.
365    // TODO(altimofeev): temporary solution, until focus parameters are
366    // implemented on the Gaia side.
367    // Do this only once. Any subsequent call would relod GAIA frame.
368    focus_stolen_ = false;
369    const char code[] =
370        "if (typeof gWindowOnLoad != 'undefined') gWindowOnLoad();";
371    content::RenderFrameHost* frame = InlineLoginUI::GetAuthIframe(
372        web_ui()->GetWebContents(),
373        GURL(kAuthIframeParentOrigin),
374        kAuthIframeParentName);
375    frame->ExecuteJavaScript(base::ASCIIToUTF16(code));
376  }
377  if (gaia_silent_load_) {
378    focus_stolen_ = true;
379    // Prevent focus stealing by the Gaia page.
380    // TODO(altimofeev): temporary solution, until focus parameters are
381    // implemented on the Gaia side.
382    const char code[] =
383        "var gWindowOnLoad = window.onload; "
384        "window.onload=function() {};";
385    content::RenderFrameHost* frame = InlineLoginUI::GetAuthIframe(
386        web_ui()->GetWebContents(),
387        GURL(kAuthIframeParentOrigin),
388        kAuthIframeParentName);
389    frame->ExecuteJavaScript(base::ASCIIToUTF16(code));
390
391    // As we could miss and window.onload could already be called, restore
392    // focus to current pod (see crbug/175243).
393    DCHECK(signin_screen_handler_);
394    signin_screen_handler_->RefocusCurrentPod();
395  }
396  HandleFrameLoadingCompleted(0);
397
398  if (test_expects_complete_login_)
399    SubmitLoginFormForTest();
400}
401
402void GaiaScreenHandler::OnSetOwnerDone(const std::string& typed_email,
403                                       const std::string& password,
404                                       bool using_saml,
405                                       bool success) {
406  CHECK(consumer_management_);
407  if (success) {
408    consumer_management_->SetEnrollmentStage(
409        policy::ConsumerManagementService::ENROLLMENT_STAGE_OWNER_STORED);
410  } else {
411    LOG(ERROR) << "Failed to write owner e-mail to boot lockbox.";
412    consumer_management_->SetEnrollmentStage(
413        policy::ConsumerManagementService::
414            ENROLLMENT_STAGE_BOOT_LOCKBOX_FAILED);
415    // We should continue logging in the user, as there's not much we can do
416    // here.
417  }
418  DoCompleteLogin(typed_email, password, using_saml);
419}
420
421void GaiaScreenHandler::DoCompleteLogin(const std::string& typed_email,
422                                        const std::string& password,
423                                        bool using_saml) {
424  if (!Delegate())
425    return;
426
427  if (using_saml && !using_saml_api_)
428    RecordSAMLScrapingVerificationResultInHistogram(true);
429
430  const std::string sanitized_email = gaia::SanitizeEmail(typed_email);
431  Delegate()->SetDisplayEmail(sanitized_email);
432  UserContext user_context(sanitized_email);
433  user_context.SetKey(Key(password));
434  user_context.SetAuthFlow(using_saml
435                               ? UserContext::AUTH_FLOW_GAIA_WITH_SAML
436                               : UserContext::AUTH_FLOW_GAIA_WITHOUT_SAML);
437  Delegate()->CompleteLogin(user_context);
438
439  if (test_expects_complete_login_) {
440    VLOG(2) << "Complete test login for " << typed_email
441            << ", requested=" << test_user_;
442
443    test_expects_complete_login_ = false;
444    test_user_.clear();
445    test_pass_.clear();
446  }
447}
448
449void GaiaScreenHandler::PopulateEmail(const std::string& user_id) {
450  populated_email_ = user_id;
451}
452
453void GaiaScreenHandler::PasswordChangedFor(const std::string& user_id) {
454  password_changed_for_.insert(user_id);
455}
456
457void GaiaScreenHandler::StartClearingDnsCache() {
458  if (dns_clear_task_running_ || !g_browser_process->io_thread())
459    return;
460
461  dns_cleared_ = false;
462  BrowserThread::PostTaskAndReply(
463      BrowserThread::IO,
464      FROM_HERE,
465      base::Bind(&ClearDnsCache, g_browser_process->io_thread()),
466      base::Bind(&GaiaScreenHandler::OnDnsCleared, weak_factory_.GetWeakPtr()));
467  dns_clear_task_running_ = true;
468}
469
470void GaiaScreenHandler::OnDnsCleared() {
471  DCHECK_CURRENTLY_ON(BrowserThread::UI);
472  dns_clear_task_running_ = false;
473  dns_cleared_ = true;
474  ShowGaiaScreenIfReady();
475}
476
477void GaiaScreenHandler::StartClearingCookies(
478    const base::Closure& on_clear_callback) {
479  cookies_cleared_ = false;
480  ProfileHelper* profile_helper = ProfileHelper::Get();
481  LOG_ASSERT(Profile::FromWebUI(web_ui()) ==
482             profile_helper->GetSigninProfile());
483  profile_helper->ClearSigninProfile(
484      base::Bind(&GaiaScreenHandler::OnCookiesCleared,
485                 weak_factory_.GetWeakPtr(),
486                 on_clear_callback));
487}
488
489void GaiaScreenHandler::OnCookiesCleared(
490    const base::Closure& on_clear_callback) {
491  DCHECK_CURRENTLY_ON(BrowserThread::UI);
492  cookies_cleared_ = true;
493  on_clear_callback.Run();
494}
495
496void GaiaScreenHandler::ShowSigninScreenForCreds(const std::string& username,
497                                                 const std::string& password) {
498  VLOG(2) << "ShowSigninScreenForCreds  for user " << username
499          << ", frame_state=" << frame_state();
500
501  test_user_ = username;
502  test_pass_ = password;
503  test_expects_complete_login_ = true;
504
505  // Submit login form for test if gaia is ready. If gaia is loading, login
506  // will be attempted in HandleLoginWebuiReady after gaia is ready. Otherwise,
507  // reload gaia then follow the loading case.
508  if (frame_state() == GaiaScreenHandler::FRAME_STATE_LOADED) {
509    SubmitLoginFormForTest();
510  } else if (frame_state() != GaiaScreenHandler::FRAME_STATE_LOADING) {
511    DCHECK(signin_screen_handler_);
512    signin_screen_handler_->OnShowAddUser();
513  }
514}
515
516void GaiaScreenHandler::SubmitLoginFormForTest() {
517  VLOG(2) << "Submit login form for test, user=" << test_user_;
518
519  std::string code;
520  code += "document.getElementById('Email').value = '" + test_user_ + "';";
521  code += "document.getElementById('Passwd').value = '" + test_pass_ + "';";
522  code += "document.getElementById('signIn').click();";
523
524  content::RenderFrameHost* frame = InlineLoginUI::GetAuthIframe(
525      web_ui()->GetWebContents(),
526      GURL(kAuthIframeParentOrigin),
527      kAuthIframeParentName);
528  frame->ExecuteJavaScript(base::ASCIIToUTF16(code));
529
530  // Test properties are cleared in HandleCompleteLogin because the form
531  // submission might fail and login will not be attempted after reloading
532  // if they are cleared here.
533}
534
535void GaiaScreenHandler::SetSAMLPrincipalsAPIUsed(bool api_used) {
536  using_saml_api_ = api_used;
537  UMA_HISTOGRAM_BOOLEAN("ChromeOS.SAML.APIUsed", api_used);
538}
539
540void GaiaScreenHandler::ShowGaia(bool is_enrolling_consumer_management) {
541  is_enrolling_consumer_management_ = is_enrolling_consumer_management;
542  if (gaia_silent_load_ && populated_email_.empty()) {
543    dns_cleared_ = true;
544    cookies_cleared_ = true;
545    ShowGaiaScreenIfReady();
546  } else {
547    StartClearingDnsCache();
548    StartClearingCookies(base::Bind(&GaiaScreenHandler::ShowGaiaScreenIfReady,
549                                    weak_factory_.GetWeakPtr()));
550  }
551}
552
553void GaiaScreenHandler::ShowGaiaScreenIfReady() {
554  if (!dns_cleared_ || !cookies_cleared_ || !Delegate())
555    return;
556
557  std::string active_network_path = network_state_informer_->network_path();
558  if (gaia_silent_load_ &&
559      (network_state_informer_->state() != NetworkStateInformer::ONLINE ||
560       gaia_silent_load_network_ != active_network_path)) {
561    // Network has changed. Force Gaia reload.
562    gaia_silent_load_ = false;
563    // Gaia page will be realoded, so focus isn't stolen anymore.
564    focus_stolen_ = false;
565  }
566
567  // Note that LoadAuthExtension clears |populated_email_|.
568  if (populated_email_.empty())
569    Delegate()->LoadSigninWallpaper();
570  else
571    Delegate()->LoadWallpaper(populated_email_);
572
573  input_method::InputMethodManager* imm =
574      input_method::InputMethodManager::Get();
575
576  scoped_refptr<input_method::InputMethodManager::State> gaia_ime_state =
577      imm->GetActiveIMEState()->Clone();
578  imm->SetState(gaia_ime_state);
579
580  // Set Least Recently Used input method for the user.
581  if (!populated_email_.empty()) {
582    signin_screen_handler_->SetUserInputMethod(populated_email_,
583                                               gaia_ime_state.get());
584  } else {
585    std::vector<std::string> input_methods =
586        imm->GetInputMethodUtil()->GetHardwareLoginInputMethodIds();
587    const std::string owner_im = signin_screen_handler_->GetUserLRUInputMethod(
588        user_manager::UserManager::Get()->GetOwnerEmail());
589    const std::string system_im = g_browser_process->local_state()->GetString(
590        language_prefs::kPreferredKeyboardLayout);
591
592    PushFrontIMIfNotExists(owner_im, &input_methods);
593    PushFrontIMIfNotExists(system_im, &input_methods);
594
595    gaia_ime_state->EnableLoginLayouts(
596        g_browser_process->GetApplicationLocale(), input_methods);
597
598    if (!system_im.empty()) {
599      gaia_ime_state->ChangeInputMethod(system_im, false /* show_message */);
600    } else if (!owner_im.empty()) {
601      gaia_ime_state->ChangeInputMethod(owner_im, false /* show_message */);
602    }
603  }
604
605  LoadAuthExtension(!gaia_silent_load_, false, false);
606  signin_screen_handler_->UpdateUIState(
607      SigninScreenHandler::UI_STATE_GAIA_SIGNIN, NULL);
608
609  if (gaia_silent_load_) {
610    // The variable is assigned to false because silently loaded Gaia page was
611    // used.
612    gaia_silent_load_ = false;
613    if (focus_stolen_)
614      HandleGaiaUIReady();
615  }
616  signin_screen_handler_->UpdateState(ErrorScreenActor::ERROR_REASON_UPDATE);
617
618  PrefService* prefs = g_browser_process->local_state();
619  if (prefs->GetBoolean(prefs::kFactoryResetRequested)) {
620    if (core_oobe_actor_)
621      core_oobe_actor_->ShowDeviceResetScreen();
622  }
623}
624
625void GaiaScreenHandler::MaybePreloadAuthExtension() {
626  VLOG(1) << "MaybePreloadAuthExtension() call.";
627
628  // If cookies clearing was initiated or |dns_clear_task_running_| then auth
629  // extension showing has already been initiated and preloading is senseless.
630  if (signin_screen_handler_->ShouldLoadGaia() &&
631      !gaia_silent_load_ &&
632      !cookies_cleared_ &&
633      !dns_clear_task_running_ &&
634      network_state_informer_->state() == NetworkStateInformer::ONLINE) {
635    gaia_silent_load_ = true;
636    gaia_silent_load_network_ = network_state_informer_->network_path();
637    LoadAuthExtension(true, true, false);
638  }
639}
640
641void GaiaScreenHandler::LoadAuthExtension(bool force,
642                                          bool silent_load,
643                                          bool offline) {
644  GaiaContext context;
645  context.force_reload = force;
646  context.is_local = offline;
647  context.password_changed = !populated_email_.empty() &&
648                             password_changed_for_.count(populated_email_);
649  context.use_offline = offline;
650  context.email = populated_email_;
651  context.is_enrolling_consumer_management = is_enrolling_consumer_management_;
652  if (Delegate()) {
653    context.show_users = Delegate()->IsShowUsers();
654    context.has_users = !Delegate()->GetUsers().empty();
655  }
656
657  populated_email_.clear();
658
659  LoadGaia(context);
660}
661
662void GaiaScreenHandler::UpdateState(ErrorScreenActor::ErrorReason reason) {
663  if (signin_screen_handler_)
664    signin_screen_handler_->UpdateState(reason);
665}
666
667SigninScreenHandlerDelegate* GaiaScreenHandler::Delegate() {
668  DCHECK(signin_screen_handler_);
669  return signin_screen_handler_->delegate_;
670}
671
672void GaiaScreenHandler::SetSigninScreenHandler(SigninScreenHandler* handler) {
673  signin_screen_handler_ = handler;
674}
675}  // namespace chromeos
676