diff options
author | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-05 07:18:27 +0000 |
---|---|---|
committer | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-05 07:18:27 +0000 |
commit | ab2bd2c2bf7136b153e54f7a4e0ec6777a3c32b3 (patch) | |
tree | 3918a228670d2562968215356dea52dcd36d3c44 /chrome/browser | |
parent | 2d3a1d8c35f7b1a8611aa97569101cff6f5767ae (diff) | |
download | chromium_src-ab2bd2c2bf7136b153e54f7a4e0ec6777a3c32b3.zip chromium_src-ab2bd2c2bf7136b153e54f7a4e0ec6777a3c32b3.tar.gz chromium_src-ab2bd2c2bf7136b153e54f7a4e0ec6777a3c32b3.tar.bz2 |
Screen Locker: 1st step
* ScreenLocker screen currently reuses Background from Login screen.
* GrabWidget is created to grab keyboard/mouse events.
* Modified StubAuthentiator to fail when an empty password is entered.
* Changed UserManager to explicitly remember the currently logged in user.
UI is not hooked yet.
BUG=43131, http://crosbug.com/2914
TEST=none
Review URL: http://codereview.chromium.org/1897001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@46442 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/chromeos/login/authenticator.h | 22 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/screen_lock_view.cc | 186 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/screen_lock_view.h | 75 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/screen_locker.cc | 142 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/screen_locker.h | 81 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/user_controller.cc | 4 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/user_manager.cc | 6 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/user_manager.h | 8 |
8 files changed, 513 insertions, 11 deletions
diff --git a/chrome/browser/chromeos/login/authenticator.h b/chrome/browser/chromeos/login/authenticator.h index cf6531e..26ea871 100644 --- a/chrome/browser/chromeos/login/authenticator.h +++ b/chrome/browser/chromeos/login/authenticator.h @@ -58,11 +58,19 @@ class StubAuthenticator : public Authenticator { const std::string& username, const std::string& password) { username_ = username; - ChromeThread::PostTask( - ChromeThread::UI, FROM_HERE, - NewRunnableMethod(this, - &StubAuthenticator::OnLoginSuccess, - std::string())); + if (password == "fail") { + ChromeThread::PostTask( + ChromeThread::UI, FROM_HERE, + NewRunnableMethod(this, + &StubAuthenticator::OnLoginFailure, + std::string())); + } else { + ChromeThread::PostTask( + ChromeThread::UI, FROM_HERE, + NewRunnableMethod(this, + &StubAuthenticator::OnLoginSuccess, + std::string())); + } return true; } @@ -70,7 +78,9 @@ class StubAuthenticator : public Authenticator { consumer_->OnLoginSuccess(username_, credentials); } - void OnLoginFailure(const std::string& data) {} + void OnLoginFailure(const std::string& data) { + consumer_->OnLoginFailure(data); + } private: std::string username_; diff --git a/chrome/browser/chromeos/login/screen_lock_view.cc b/chrome/browser/chromeos/login/screen_lock_view.cc new file mode 100644 index 0000000..1aa7bca --- /dev/null +++ b/chrome/browser/chromeos/login/screen_lock_view.cc @@ -0,0 +1,186 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/login/screen_lock_view.h" + +#include "app/l10n_util.h" +#include "app/resource_bundle.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/chromeos/login/screen_locker.h" +#include "chrome/browser/chromeos/login/user_manager.h" +#include "chrome/common/notification_service.h" +#include "grit/generated_resources.h" +#include "grit/theme_resources.h" +#include "views/controls/image_view.h" +#include "views/controls/label.h" +#include "views/grid_layout.h" + +namespace { + +// Max image size. +const int kMaxImageSize = 260; + +// Gap between edge and image view, and image view and controls. +const int kBorderSize = 30; + +// Background color. +const SkColor kBackgroundColor = SK_ColorWHITE; + +// Text color. +const SkColor kTextColor = SK_ColorWHITE; + +} // namespace + +namespace chromeos { + +using views::GridLayout; + +ScreenLockView::ScreenLockView(ScreenLocker* screen_locker) + : image_view_(NULL), + password_field_(NULL), + unlock_button_(NULL), + screen_locker_(screen_locker) { + DCHECK(screen_locker_); +} + +void ScreenLockView::Init() { + registrar_.Add(this, + NotificationType::LOGIN_USER_IMAGE_CHANGED, + NotificationService::AllSources()); + + views::View* main = new views::View(); + main->set_background( + views::Background::CreateSolidBackground(kBackgroundColor)); + + // Password field. + password_field_ = new views::Textfield(views::Textfield::STYLE_PASSWORD); + password_field_->set_text_to_display_when_empty( + l10n_util::GetStringUTF16(IDS_LOGIN_EMPTY_PASSWORD_TEXT)); + password_field_->SetController(this); + + // Unlock button. + // TODO(sky|oshima): change ids + unlock_button_ = new views::TextButton( + this, l10n_util::GetString(IDS_LOGIN_BUTTON)); + + // User icon. + image_view_ = new views::ImageView(); + UserManager::User user = screen_locker_->user(); + SetImage(user.image(), user.image().width(), user.image().height()); + + // User name. + std::wstring text = UTF8ToWide(user.GetDisplayName()); + views::Label* label = new views::Label(text); + label->SetColor(kTextColor); + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + const gfx::Font& font = + rb.GetFont(ResourceBundle::LargeFont).DeriveFont(0, gfx::Font::BOLD); + label->SetFont(font); + + // Layouts image, textfield and button components. + GridLayout* layout = new GridLayout(main); + main->SetLayoutManager(layout); + views::ColumnSet* column_set = layout->AddColumnSet(0); + column_set->AddPaddingColumn(0, kBorderSize); + column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, + GridLayout::USE_PREF, 0, 0); + column_set->AddPaddingColumn(0, kBorderSize); + + column_set = layout->AddColumnSet(1); + column_set->AddPaddingColumn(0, 5); + column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, + GridLayout::USE_PREF, 0, 0); + column_set->AddPaddingColumn(0, 5); + column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 0, + GridLayout::USE_PREF, 0, 0); + column_set->AddPaddingColumn(0, 5); + + layout->AddPaddingRow(0, kBorderSize); + layout->StartRow(0, 0); + layout->AddView(image_view_); + layout->AddPaddingRow(0, kBorderSize); + layout->StartRow(0, 1); + layout->AddView(password_field_); + layout->AddView(unlock_button_); + layout->AddPaddingRow(0, 5); + + unlock_button_->SetFocusable(true); + + // Layouts the main view and the account label. + layout = new GridLayout(this); + SetLayoutManager(layout); + column_set = layout->AddColumnSet(0); + column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, + GridLayout::USE_PREF, 0, 0); + + column_set = layout->AddColumnSet(1); + column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1, + GridLayout::USE_PREF, 0, 0); + + layout->StartRow(0, 0); + layout->AddView(main); + layout->StartRow(0, 1); + layout->AddView(label); +} + +void ScreenLockView::ClearAndSetFocusToPassword() { + password_field_->RequestFocus(); + password_field_->SetText(string16()); +} + +void ScreenLockView::SetEnabled(bool enabled) { + views::View::SetEnabled(enabled); + + // TODO(oshima): Re-enabling does not move the focus to the view + // that had a focus (issue http://crbug.com/43131). + // Move the focus to other field as a workaround. + if (!enabled) + unlock_button_->RequestFocus(); + unlock_button_->SetEnabled(enabled); + password_field_->SetEnabled(enabled); +} + +void ScreenLockView::ButtonPressed(views::Button* sender, + const views::Event& event) { + screen_locker_->Authenticate(password_field_->text()); +} + +bool ScreenLockView::HandleKeystroke( + views::Textfield* sender, + const views::Textfield::Keystroke& keystroke) { + if (keystroke.GetKeyboardCode() == base::VKEY_RETURN) { + screen_locker_->Authenticate(password_field_->text()); + return true; + } + return false; +} + +void ScreenLockView::Observe( + NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + if (type != NotificationType::LOGIN_USER_IMAGE_CHANGED || !image_view_) + return; + + UserManager::User* user = Details<UserManager::User>(details).ptr(); + if (screen_locker_->user().email() != user->email()) + return; + + SetImage(user->image(), user->image().width(), user->image().height()); + image_view_->SchedulePaint(); +} + +////////////////////////////////////////////////////////////////////////// +// private: + +void ScreenLockView::SetImage(const SkBitmap& image, + int desired_width, + int desired_height) { + image_view_->SetImage(image); + image_view_->SetImageSize(gfx::Size(std::min(desired_width, kMaxImageSize), + std::min(desired_height, kMaxImageSize))); +} + +} // namespace chromeos + diff --git a/chrome/browser/chromeos/login/screen_lock_view.h b/chrome/browser/chromeos/login/screen_lock_view.h new file mode 100644 index 0000000..9d94cfb --- /dev/null +++ b/chrome/browser/chromeos/login/screen_lock_view.h @@ -0,0 +1,75 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREEN_LOCK_VIEW_H_ +#define CHROME_BROWSER_CHROMEOS_LOGIN_SCREEN_LOCK_VIEW_H_ + +#include "chrome/common/notification_observer.h" +#include "chrome/common/notification_registrar.h" +#include "views/controls/button/text_button.h" +#include "views/controls/textfield/textfield.h" +#include "views/view.h" + +namespace views { +class ImageView; +} // namespace views + +namespace chromeos { + +class ScreenLocker; + +// ScreenLockView creates view components necessary to authenticate +// a user to unlock the screen. +class ScreenLockView : public views::View, + public views::ButtonListener, + public views::Textfield::Controller, + public NotificationObserver { + public: + explicit ScreenLockView(ScreenLocker* screen_locker); + virtual ~ScreenLockView() {} + + void Init(); + + // Clears and sets the focus to the password field. + void ClearAndSetFocusToPassword(); + + // views::View implementation: + virtual void SetEnabled(bool enabled); + + // NotificationObserver implementation: + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + // views::ButtonListener implmeentation: + virtual void ButtonPressed(views::Button* sender, const views::Event& event); + + // views::Textfield::Controller implementation: + virtual void ContentsChanged(views::Textfield* sender, + const string16& new_contents) {} + virtual bool HandleKeystroke(views::Textfield* sender, + const views::Textfield::Keystroke& keystroke); + + private: + // Set the user's image. + void SetImage(const SkBitmap& image, + int desired_width, + int desired_height); + + // For editing the password. + views::ImageView* image_view_; + views::Textfield* password_field_; + views::TextButton* unlock_button_; + + // ScreenLocker is owned by itself. + ScreenLocker* screen_locker_; + + NotificationRegistrar registrar_; + + DISALLOW_COPY_AND_ASSIGN(ScreenLockView); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_LOGIN_SCREEN_LOCK_VIEW_H_ diff --git a/chrome/browser/chromeos/login/screen_locker.cc b/chrome/browser/chromeos/login/screen_locker.cc new file mode 100644 index 0000000..906de77 --- /dev/null +++ b/chrome/browser/chromeos/login/screen_locker.cc @@ -0,0 +1,142 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/login/screen_locker.h" + +#include "app/l10n_util.h" +#include "app/resource_bundle.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/chromeos/login/authenticator.h" +#include "chrome/browser/chromeos/login/background_view.h" +#include "chrome/browser/chromeos/login/login_utils.h" +#include "chrome/browser/chromeos/login/screen_lock_view.h" +#include "views/screen.h" +#include "views/widget/widget_gtk.h" + +namespace { + +// A child widget that grabs both keyboard and pointer input. +// TODO(oshima): catch grab-broke event and quit if it ever happenes. +class GrabWidget : public views::WidgetGtk { + public: + GrabWidget() : views::WidgetGtk(views::WidgetGtk::TYPE_CHILD) { + } + + virtual void Show() { + views::WidgetGtk::Show(); + + GtkWidget* current_grab_window = gtk_grab_get_current(); + if (current_grab_window) + gtk_grab_remove(current_grab_window); + + DoGrab(); + GdkGrabStatus kbd_status = + gdk_keyboard_grab(window_contents()->window, FALSE, + GDK_CURRENT_TIME); + CHECK_EQ(kbd_status, GDK_GRAB_SUCCESS) << "Failed to grab keyboard input"; + GdkGrabStatus ptr_status = + gdk_pointer_grab(window_contents()->window, + FALSE, + static_cast<GdkEventMask>( + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | + GDK_POINTER_MOTION_MASK), + NULL, + NULL, + GDK_CURRENT_TIME); + CHECK_EQ(ptr_status, GDK_GRAB_SUCCESS) << "Failed to grab pointer input"; + } + + private: + DISALLOW_COPY_AND_ASSIGN(GrabWidget); +}; + +} // namespace + +namespace chromeos { + +ScreenLocker::ScreenLocker(const UserManager::User& user, Profile* profile) + : lock_window_(NULL), + lock_widget_(NULL), + screen_lock_view_(NULL), + user_(user), + profile_(profile) { +} + +ScreenLocker::~ScreenLocker() { + DCHECK(lock_window_); + lock_window_->Close(); + // lock_widget_ will be deleted by gtk's destroy signal. +} + +void ScreenLocker::Init(const gfx::Rect& bounds) { + // TODO(oshima): Figure out which UI to keep and remove in the background. + views::View* screen = new chromeos::BackgroundView(); + lock_window_ = new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW); + lock_window_->Init(NULL, bounds); + lock_window_->SetContentsView(screen); + lock_window_->Show(); + lock_window_->MoveAbove(NULL); + + authenticator_ = + LoginUtils::Get()->CreateAuthenticator(this); + screen_lock_view_ = new ScreenLockView(this); + screen_lock_view_->Init(); + + gfx::Size size = screen_lock_view_->GetPreferredSize(); + + lock_widget_ = new GrabWidget(); + lock_widget_->Init(lock_window_->window_contents(), + gfx::Rect((bounds.width() - size.width()) /2, + (bounds.height() - size.width()) /2, + size.width(), + size.height())); + lock_widget_->SetContentsView(screen_lock_view_); + lock_widget_->Show(); + screen_lock_view_->ClearAndSetFocusToPassword(); +} + +void ScreenLocker::SetAuthenticator(Authenticator* authenticator) { + authenticator_ = authenticator; +} + +void ScreenLocker::OnLoginFailure(const std::string& error) { + DLOG(INFO) << "OnLoginFailure"; + screen_lock_view_->SetEnabled(true); + screen_lock_view_->ClearAndSetFocusToPassword(); +} + +void ScreenLocker::OnLoginSuccess(const std::string& username, + const std::string& credentials) { + DLOG(INFO) << "OnLoginSuccess"; + gdk_keyboard_ungrab(GDK_CURRENT_TIME); + gdk_pointer_ungrab(GDK_CURRENT_TIME); + MessageLoop::current()->DeleteSoon(FROM_HERE, this); +} + +void ScreenLocker::Authenticate(const string16& password) { + screen_lock_view_->SetEnabled(false); + ChromeThread::PostTask( + ChromeThread::FILE, FROM_HERE, + NewRunnableMethod(authenticator_.get(), + &Authenticator::Authenticate, + profile_, + user_.email(), + UTF16ToUTF8(password))); +} + +} // namespace chromeos + +namespace browser { + +void ShowScreenLock(Profile* profile) { + DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI); + gfx::Rect bounds(views::Screen::GetMonitorWorkAreaNearestWindow(NULL)); + + chromeos::ScreenLocker* locker = + new chromeos::ScreenLocker(chromeos::UserManager::Get()->logged_in_user(), + profile); + locker->Init(bounds); +} + +} // namespace browser diff --git a/chrome/browser/chromeos/login/screen_locker.h b/chrome/browser/chromeos/login/screen_locker.h new file mode 100644 index 0000000..d8d8108 --- /dev/null +++ b/chrome/browser/chromeos/login/screen_locker.h @@ -0,0 +1,81 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREEN_LOCKER_H_ +#define CHROME_BROWSER_CHROMEOS_LOGIN_SCREEN_LOCKER_H_ + +#include <string> + +#include "base/task.h" +#include "chrome/browser/chromeos/login/login_status_consumer.h" +#include "chrome/browser/chromeos/login/user_manager.h" + +class Profile; + +namespace gfx { +class Rect; +} // namespace gfx + +namespace views { +class WidgetGtk; +} // namespace views + +namespace chromeos { + +class Authenticator; +class ScreenLockView; + +// ScreenLocker creates a background view as well as ScreenLockView to +// authenticate the user. ScreenLocker manages its life cycle and will +// delete itself when it's unlocked. +class ScreenLocker : public LoginStatusConsumer { + public: + ScreenLocker(const UserManager::User& user, Profile* profile); + + // Initialize and show the screen locker with given |bounds|. + void Init(const gfx::Rect& bounds); + + // LoginStatusConsumer implements: + virtual void OnLoginFailure(const std::string& error); + virtual void OnLoginSuccess(const std::string& username, + const std::string& credentials); + + // Authenticates the user with given |password| and authenticator. + void Authenticate(const string16& password); + + // Sets the authenticator. + void SetAuthenticator(Authenticator* authenticator); + + // Returns the user to authenticate. + const UserManager::User& user() const { + return user_; + } + + private: + friend class DeleteTask<ScreenLocker>; + + virtual ~ScreenLocker(); + + // The screen locker window. + views::WidgetGtk* lock_window_; + + // TYPE_CHILD widget to grab the keyboard/mouse input. + views::WidgetGtk* lock_widget_; + + // A view that accepts password. + ScreenLockView* screen_lock_view_; + + // Logged in user and its profile. + UserManager::User user_; + Profile* profile_; + + // Used for logging in. + scoped_refptr<Authenticator> authenticator_; + + DISALLOW_COPY_AND_ASSIGN(ScreenLocker); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_LOGIN_SCREEN_LOCKER_H_ diff --git a/chrome/browser/chromeos/login/user_controller.cc b/chrome/browser/chromeos/login/user_controller.cc index a833492..6506ba9 100644 --- a/chrome/browser/chromeos/login/user_controller.cc +++ b/chrome/browser/chromeos/login/user_controller.cc @@ -99,10 +99,6 @@ UserController::~UserController() { border_window_->Close(); label_window_->Close(); unselected_label_window_->Close(); - registrar_.Remove( - this, - NotificationType::LOGIN_USER_IMAGE_CHANGED, - NotificationService::AllSources()); } void UserController::Init(int index, int total_user_count) { diff --git a/chrome/browser/chromeos/login/user_manager.cc b/chrome/browser/chromeos/login/user_manager.cc index 50bf852..b018829 100644 --- a/chrome/browser/chromeos/login/user_manager.cc +++ b/chrome/browser/chromeos/login/user_manager.cc @@ -104,6 +104,8 @@ void UserManager::UserLoggedIn(const std::string& email) { ListValue* prefs_users = prefs->GetMutableList(kLoggedInUsers); prefs_users->Clear(); + logged_in_user_.set_email(email); + // Make sure this user is first. prefs_users->Append(Value::CreateStringValue(email)); for (std::vector<User>::iterator it = users.begin(); @@ -113,6 +115,8 @@ void UserManager::UserLoggedIn(const std::string& email) { // Skip the most recent user. if (email != user_email) { prefs_users->Append(Value::CreateStringValue(user_email)); + } else { + logged_in_user_ = *it; } } prefs->ScheduleSavePersistentPrefs(); @@ -121,7 +125,7 @@ void UserManager::UserLoggedIn(const std::string& email) { NotificationService::current()->Notify( NotificationType::LOGIN_USER_CHANGED, Source<UserManager>(this), - Details<const User>(&user)); + Details<const User>(&logged_in_user_)); } void UserManager::DownloadUserImage(const std::string& username) { diff --git a/chrome/browser/chromeos/login/user_manager.h b/chrome/browser/chromeos/login/user_manager.h index 16b5b69..d7f4907 100644 --- a/chrome/browser/chromeos/login/user_manager.h +++ b/chrome/browser/chromeos/login/user_manager.h @@ -61,6 +61,11 @@ class UserManager : public UserImageLoader::Delegate { // The persistent list will be updated accordingly. void UserLoggedIn(const std::string& email); + // Returns the logged-in user. + const User& logged_in_user() { + return logged_in_user_; + } + // Downloads user image and stores it to use on subsequent login. // Call it after user's cookies have been set. void DownloadUserImage(const std::string& username); @@ -87,6 +92,9 @@ class UserManager : public UserImageLoader::Delegate { typedef base::hash_map<std::string, SkBitmap> UserImages; mutable UserImages user_images_; + // The logged-in user. + User logged_in_user_; + DISALLOW_COPY_AND_ASSIGN(UserManager); }; |