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