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