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