Home | History | Annotate | Download | only in login
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/chromeos/login/webui_screen_locker.h"
      6 
      7 #include "ash/shell.h"
      8 #include "ash/wm/lock_state_controller.h"
      9 #include "ash/wm/lock_state_observer.h"
     10 #include "base/command_line.h"
     11 #include "base/metrics/histogram.h"
     12 #include "base/strings/utf_string_conversions.h"
     13 #include "base/values.h"
     14 #include "chrome/browser/browser_shutdown.h"
     15 #include "chrome/browser/chrome_notification_types.h"
     16 #include "chrome/browser/chromeos/accessibility/accessibility_util.h"
     17 #include "chrome/browser/chromeos/login/helper.h"
     18 #include "chrome/browser/chromeos/login/screen_locker.h"
     19 #include "chrome/browser/chromeos/login/user_manager.h"
     20 #include "chrome/browser/chromeos/login/webui_login_display.h"
     21 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
     22 #include "chrome/common/url_constants.h"
     23 #include "chromeos/dbus/dbus_thread_manager.h"
     24 #include "content/public/browser/browser_thread.h"
     25 #include "content/public/browser/notification_service.h"
     26 #include "content/public/browser/notification_types.h"
     27 #include "content/public/browser/render_widget_host_view.h"
     28 #include "content/public/browser/web_ui.h"
     29 #include "ui/aura/client/capture_client.h"
     30 #include "ui/base/l10n/l10n_util.h"
     31 #include "ui/base/x/x11_util.h"
     32 #include "ui/gfx/screen.h"
     33 #include "ui/views/controls/webview/webview.h"
     34 
     35 namespace {
     36 
     37 // URL which corresponds to the login WebUI.
     38 const char kLoginURL[] = "chrome://oobe/login#lock";
     39 
     40 }  // namespace
     41 
     42 namespace chromeos {
     43 
     44 ////////////////////////////////////////////////////////////////////////////////
     45 // WebUIScreenLocker implementation.
     46 
     47 WebUIScreenLocker::WebUIScreenLocker(ScreenLocker* screen_locker)
     48     : ScreenLockerDelegate(screen_locker),
     49       lock_ready_(false),
     50       webui_ready_(false),
     51       network_state_helper_(new login::NetworkStateHelper),
     52       weak_factory_(this) {
     53   set_should_emit_login_prompt_visible(false);
     54   ash::Shell::GetInstance()->lock_state_controller()->AddObserver(this);
     55   DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(this);
     56 }
     57 
     58 void WebUIScreenLocker::LockScreen() {
     59   gfx::Rect bounds(ash::Shell::GetScreen()->GetPrimaryDisplay().bounds());
     60 
     61   lock_time_ = base::TimeTicks::Now();
     62   LockWindow* lock_window = LockWindow::Create();
     63   lock_window->set_observer(this);
     64   lock_window_ = lock_window->GetWidget();
     65   lock_window_->AddObserver(this);
     66   WebUILoginView::Init(lock_window_);
     67   lock_window_->SetContentsView(this);
     68   lock_window_->Show();
     69   OnWindowCreated();
     70   LoadURL(GURL(kLoginURL));
     71   lock_window->Grab();
     72 
     73   // Subscribe to crash events.
     74   content::WebContentsObserver::Observe(GetWebContents());
     75 
     76   login_display_.reset(new WebUILoginDisplay(this));
     77   login_display_->set_background_bounds(bounds);
     78   login_display_->set_parent_window(GetNativeWindow());
     79   login_display_->Init(screen_locker()->users(), false, true, false);
     80 
     81   static_cast<OobeUI*>(GetWebUI()->GetController())->ShowSigninScreen(
     82       login_display_.get(), login_display_.get());
     83 
     84   registrar_.Add(this,
     85                  chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED,
     86                  content::NotificationService::AllSources());
     87   registrar_.Add(this,
     88                  chrome::NOTIFICATION_LOCK_WEBUI_READY,
     89                  content::NotificationService::AllSources());
     90   registrar_.Add(this,
     91                  chrome::NOTIFICATION_LOCK_BACKGROUND_DISPLAYED,
     92                  content::NotificationService::AllSources());
     93 }
     94 
     95 void WebUIScreenLocker::ScreenLockReady() {
     96   UMA_HISTOGRAM_TIMES("LockScreen.LockReady",
     97                       base::TimeTicks::Now() - lock_time_);
     98   ScreenLockerDelegate::ScreenLockReady();
     99   SetInputEnabled(true);
    100 }
    101 
    102 void WebUIScreenLocker::OnAuthenticate() {
    103 }
    104 
    105 void WebUIScreenLocker::SetInputEnabled(bool enabled) {
    106   login_display_->SetUIEnabled(enabled);
    107 }
    108 
    109 void WebUIScreenLocker::ShowErrorMessage(
    110     int error_msg_id,
    111     HelpAppLauncher::HelpTopic help_topic_id) {
    112   login_display_->ShowError(error_msg_id,
    113                   0 /* login_attempts */,
    114                   help_topic_id);
    115 }
    116 
    117 void WebUIScreenLocker::AnimateAuthenticationSuccess() {
    118   GetWebUI()->CallJavascriptFunction("cr.ui.Oobe.animateAuthenticationSuccess");
    119 }
    120 
    121 void WebUIScreenLocker::ClearErrors() {
    122   GetWebUI()->CallJavascriptFunction("cr.ui.Oobe.clearErrors");
    123 }
    124 
    125 gfx::NativeWindow WebUIScreenLocker::GetNativeWindow() const {
    126   return lock_window_->GetNativeWindow();
    127 }
    128 
    129 content::WebUI* WebUIScreenLocker::GetAssociatedWebUI() {
    130   return GetWebUI();
    131 }
    132 
    133 void WebUIScreenLocker::FocusUserPod() {
    134   if (!webui_ready_)
    135     return;
    136   webui_login_->RequestFocus();
    137   GetWebUI()->CallJavascriptFunction("cr.ui.Oobe.forceLockedUserPodFocus");
    138 }
    139 
    140 WebUIScreenLocker::~WebUIScreenLocker() {
    141   DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(this);
    142   ash::Shell::GetInstance()->
    143       lock_state_controller()->RemoveObserver(this);
    144   // In case of shutdown, lock_window_ may be deleted before WebUIScreenLocker.
    145   if (lock_window_) {
    146     lock_window_->RemoveObserver(this);
    147     lock_window_->Close();
    148   }
    149   // If LockScreen() was called, we need to clear the signin screen handler
    150   // delegate set in ShowSigninScreen so that it no longer points to us.
    151   if (login_display_.get()) {
    152     static_cast<OobeUI*>(GetWebUI()->GetController())->
    153         ResetSigninScreenHandlerDelegate();
    154   }
    155 }
    156 
    157 ////////////////////////////////////////////////////////////////////////////////
    158 // WebUIScreenLocker, content::NotificationObserver implementation:
    159 
    160 void WebUIScreenLocker::Observe(
    161     int type,
    162     const content::NotificationSource& source,
    163     const content::NotificationDetails& details) {
    164   switch (type) {
    165     case chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED: {
    166       const User& user = *content::Details<User>(details).ptr();
    167       login_display_->OnUserImageChanged(user);
    168       break;
    169     }
    170     case chrome::NOTIFICATION_LOCK_WEBUI_READY: {
    171       VLOG(1) << "WebUI ready; lock window is "
    172               << (lock_ready_ ? "too" : "not");
    173       webui_ready_ = true;
    174       if (lock_ready_)
    175         ScreenLockReady();
    176       break;
    177     }
    178     case chrome::NOTIFICATION_LOCK_BACKGROUND_DISPLAYED: {
    179       UMA_HISTOGRAM_TIMES("LockScreen.BackgroundReady",
    180                           base::TimeTicks::Now() - lock_time_);
    181       break;
    182     }
    183     default:
    184       WebUILoginView::Observe(type, source, details);
    185   }
    186 }
    187 
    188 ////////////////////////////////////////////////////////////////////////////////
    189 // WebUIScreenLocker, LoginDisplay::Delegate implementation:
    190 
    191 void WebUIScreenLocker::CancelPasswordChangedFlow()  {
    192   NOTREACHED();
    193 }
    194 
    195 void WebUIScreenLocker::CreateAccount() {
    196   NOTREACHED();
    197 }
    198 
    199 void WebUIScreenLocker::CompleteLogin(const UserContext& user_context) {
    200   NOTREACHED();
    201 }
    202 
    203 string16 WebUIScreenLocker::GetConnectedNetworkName() {
    204   return network_state_helper_->GetCurrentNetworkName();
    205 }
    206 
    207 bool WebUIScreenLocker::IsSigninInProgress() const {
    208   // The way how screen locker is implemented right now there's no
    209   // GAIA sign in in progress in any case.
    210   return false;
    211 }
    212 
    213 void WebUIScreenLocker::Login(const UserContext& user_context) {
    214   chromeos::ScreenLocker::default_screen_locker()->Authenticate(user_context);
    215 }
    216 
    217 void WebUIScreenLocker::LoginAsRetailModeUser() {
    218   NOTREACHED();
    219 }
    220 
    221 void WebUIScreenLocker::LoginAsGuest() {
    222   NOTREACHED();
    223 }
    224 
    225 void WebUIScreenLocker::MigrateUserData(const std::string& old_password) {
    226   NOTREACHED();
    227 }
    228 
    229 void WebUIScreenLocker::LoginAsPublicAccount(const std::string& username) {
    230   NOTREACHED();
    231 }
    232 
    233 void WebUIScreenLocker::OnSigninScreenReady() {
    234 }
    235 
    236 void WebUIScreenLocker::OnUserSelected(const std::string& username) {
    237 }
    238 
    239 void WebUIScreenLocker::OnStartEnterpriseEnrollment() {
    240   NOTREACHED();
    241 }
    242 
    243 void WebUIScreenLocker::OnStartKioskEnableScreen() {
    244   NOTREACHED();
    245 }
    246 
    247 void WebUIScreenLocker::OnStartDeviceReset() {
    248   NOTREACHED();
    249 }
    250 
    251 void WebUIScreenLocker::OnStartKioskAutolaunchScreen() {
    252   NOTREACHED();
    253 }
    254 
    255 void WebUIScreenLocker::ShowWrongHWIDScreen() {
    256   NOTREACHED();
    257 }
    258 
    259 void WebUIScreenLocker::ResetPublicSessionAutoLoginTimer() {
    260 }
    261 
    262 void WebUIScreenLocker::ResyncUserData() {
    263   NOTREACHED();
    264 }
    265 
    266 void WebUIScreenLocker::SetDisplayEmail(const std::string& email) {
    267   NOTREACHED();
    268 }
    269 
    270 void WebUIScreenLocker::Signout() {
    271   chromeos::ScreenLocker::default_screen_locker()->Signout();
    272 }
    273 
    274 ////////////////////////////////////////////////////////////////////////////////
    275 // LockWindow::Observer implementation:
    276 
    277 void WebUIScreenLocker::OnLockWindowReady() {
    278   VLOG(1) << "Lock window ready; WebUI is " << (webui_ready_ ? "too" : "not");
    279   lock_ready_ = true;
    280   if (webui_ready_)
    281     ScreenLockReady();
    282 }
    283 
    284 ////////////////////////////////////////////////////////////////////////////////
    285 // SessionLockStateObserver override.
    286 
    287 void WebUIScreenLocker::OnLockStateEvent(
    288     ash::LockStateObserver::EventType event) {
    289   if (event == ash::LockStateObserver::EVENT_LOCK_ANIMATION_FINISHED) {
    290     // Release capture if any.
    291     aura::client::GetCaptureClient(GetNativeWindow()->GetRootWindow())->
    292         SetCapture(NULL);
    293     GetWebUI()->CallJavascriptFunction("cr.ui.Oobe.animateOnceFullyDisplayed");
    294   }
    295 }
    296 
    297 ////////////////////////////////////////////////////////////////////////////////
    298 // WidgetObserver override.
    299 
    300 void WebUIScreenLocker::OnWidgetDestroying(views::Widget* widget) {
    301   lock_window_->RemoveObserver(this);
    302   lock_window_ = NULL;
    303 }
    304 
    305 ////////////////////////////////////////////////////////////////////////////////
    306 // PowerManagerClient::Observer overrides.
    307 
    308 void WebUIScreenLocker::LidEventReceived(bool open,
    309                                          const base::TimeTicks& time) {
    310   content::BrowserThread::PostTask(
    311       content::BrowserThread::UI,
    312       FROM_HERE,
    313       base::Bind(&WebUIScreenLocker::FocusUserPod, weak_factory_.GetWeakPtr()));
    314 }
    315 
    316 void WebUIScreenLocker::SystemResumed(const base::TimeDelta& sleep_duration) {
    317   content::BrowserThread::PostTask(
    318       content::BrowserThread::UI,
    319       FROM_HERE,
    320       base::Bind(&WebUIScreenLocker::FocusUserPod, weak_factory_.GetWeakPtr()));
    321 }
    322 
    323 void WebUIScreenLocker::RenderProcessGone(base::TerminationStatus status) {
    324   if (browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID &&
    325       status != base::TERMINATION_STATUS_NORMAL_TERMINATION) {
    326     LOG(ERROR) << "Renderer crash on lock screen";
    327     Signout();
    328   }
    329 }
    330 
    331 }  // namespace chromeos
    332