Index: chrome/browser/chromeos/login/lock_window_gtk.cc |
diff --git a/chrome/browser/chromeos/login/webui_screen_locker.cc b/chrome/browser/chromeos/login/lock_window_gtk.cc |
similarity index 56% |
copy from chrome/browser/chromeos/login/webui_screen_locker.cc |
copy to chrome/browser/chromeos/login/lock_window_gtk.cc |
index 4294eebde7ec2ff6f1ce5d192798880296cfb24d..37e2ba470392ba358765451356b2e4c891b75174 100644 |
--- a/chrome/browser/chromeos/login/webui_screen_locker.cc |
+++ b/chrome/browser/chromeos/login/lock_window_gtk.cc |
@@ -2,7 +2,7 @@ |
// 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/webui_screen_locker.h" |
+#include "chrome/browser/chromeos/login/lock_window_gtk.h" |
#include <X11/extensions/XTest.h> |
#include <X11/keysym.h> |
@@ -34,12 +34,10 @@ |
#include "ui/base/x/x11_util.h" |
#include "ui/gfx/screen.h" |
#include "ui/views/widget/native_widget_gtk.h" |
+#include "ui/views/widget/widget.h" |
namespace { |
-// URL which corresponds to the login WebUI. |
-const char kLoginURL[] = "chrome://oobe/login"; |
- |
// The maximum duration for which locker should try to grab the keyboard and |
// mouse and its interval for regrabbing on failure. |
const int kMaxGrabFailureSec = 30; |
@@ -49,57 +47,6 @@ const int64 kRetryGrabIntervalMs = 500; |
// giving up. If we hit the limit, Chrome exits and the session is terminated. |
const int kMaxGrabFailures = kMaxGrabFailureSec * 1000 / kRetryGrabIntervalMs; |
-// A ScreenLock window that covers entire screen to keep the keyboard |
-// focus/events inside the grab widget. |
-class LockWindow : public views::NativeWidgetGtk { |
- public: |
- explicit LockWindow(chromeos::WebUIScreenLocker* webui_screen_locker) |
- : views::NativeWidgetGtk(new views::Widget), |
- toplevel_focus_widget_(NULL), |
- webui_screen_locker_(webui_screen_locker) { |
- EnableDoubleBuffer(true); |
- } |
- |
- virtual gboolean OnButtonPress(GtkWidget* widget, |
- GdkEventButton* event) OVERRIDE { |
- // Never propagate mouse events to parent. |
- return true; |
- } |
- |
- virtual void OnDestroy(GtkWidget* object) OVERRIDE { |
- VLOG(1) << "OnDestroy: LockWindow destroyed"; |
- views::NativeWidgetGtk::OnDestroy(object); |
- } |
- |
- virtual void ClearNativeFocus() OVERRIDE { |
- DCHECK(toplevel_focus_widget_); |
- gtk_widget_grab_focus(toplevel_focus_widget_); |
- } |
- |
- virtual void HandleGtkGrabBroke() OVERRIDE { |
- webui_screen_locker_->HandleGtkGrabBroke(); |
- } |
- |
- // Sets the widget to move the focus to when clearning the native |
- // widget's focus. |
- void set_toplevel_focus_widget(GtkWidget* widget) { |
- gtk_widget_set_can_focus(widget, TRUE); |
- toplevel_focus_widget_ = widget; |
- } |
- |
- private: |
- // The widget we set focus to when clearning the focus on native |
- // widget. Gdk input is grabbed in WebUIScreenLocker, and resetting the focus |
- // by using gtk_window_set_focus seems to confuse gtk and doesn't let focus |
- // move to native widget under this. |
- GtkWidget* toplevel_focus_widget_; |
- |
- // The WebUI screen locker. |
- chromeos::WebUIScreenLocker* webui_screen_locker_; |
- |
- DISALLOW_COPY_AND_ASSIGN(LockWindow); |
-}; |
- |
// Define separate methods for each error code so that stack trace |
// will tell which error the grab failed with. |
void FailedWithGrabAlreadyGrabbed() { |
@@ -122,30 +69,86 @@ void FailedWithUnknownError() { |
namespace chromeos { |
+LockWindow* LockWindow::Create() { |
+ LockWindowGtk* window = new LockWindowGtk(); |
+ return window; |
+} |
+ |
//////////////////////////////////////////////////////////////////////////////// |
-// WebUIScreenLocker implementation. |
+// LockWindowGtk implementation. |
-WebUIScreenLocker::WebUIScreenLocker(ScreenLocker* screen_locker) |
- : ScreenLockerDelegate(screen_locker), |
+LockWindowGtk::LockWindowGtk() |
+ : views::NativeWidgetGtk(new views::Widget), |
+ lock_window_(NULL), |
+ grab_widget_(NULL), |
drawn_(false), |
input_grabbed_(false), |
ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
grab_failure_count_(0), |
kbd_grab_status_(GDK_GRAB_INVALID_TIME), |
mouse_grab_status_(GDK_GRAB_INVALID_TIME) { |
+ Init(); |
} |
-void WebUIScreenLocker::LockScreen(bool unlock_on_input) { |
+void LockWindowGtk::SetContentsView(views::View* content) { |
+ lock_window_->SetContentsView(content); |
+} |
+ |
+void LockWindowGtk::Show(DOMView* dom_view) { |
+ lock_window_->Show(); |
+ // Grab on the RenderWidgetHostView hosting the WebUI login screen. |
+ grab_widget_ = dom_view->dom_contents()->tab_contents()-> |
+ GetRenderWidgetHostView()->GetNativeView(); |
+ ClearGtkGrab(); |
+ |
+ // Call this after lock_window_->Show(); otherwise the 1st invocation |
+ // of gdk_xxx_grab() will always fail. |
+ TryGrabAllInputs(); |
+ |
+ // Add the window to its own group so that its grab won't be stolen if |
+ // gtk_grab_add() gets called on behalf on a non-screen-locker widget (e.g. |
+ // a modal dialog) -- see http://crosbug.com/8999. We intentionally do this |
+ // after calling ClearGtkGrab(), as want to be in the default window group |
+ // then so we can break any existing GTK grabs. |
+ GtkWindowGroup* window_group = gtk_window_group_new(); |
+ gtk_window_group_add_window(window_group, |
+ GTK_WINDOW(lock_window_->GetNativeView())); |
+ g_object_unref(window_group); |
+} |
+ |
+views::Widget* LockWindowGtk::GetWidget() { |
+ return views::NativeWidgetGtk::GetWidget(); |
+} |
+ |
+gboolean LockWindowGtk::OnButtonPress(GtkWidget* widget, |
+ GdkEventButton* event) { |
+ // Never propagate mouse events to parent. |
+ return true; |
+} |
+ |
+void LockWindowGtk::OnDestroy(GtkWidget* object) { |
+ VLOG(1) << "OnDestroy: LockWindow destroyed"; |
+ views::NativeWidgetGtk::OnDestroy(object); |
+} |
+ |
+void LockWindowGtk::ClearNativeFocus() { |
+ gtk_widget_grab_focus(window_contents()); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// LockWindowGtk private: |
+ |
+void LockWindowGtk::Init() { |
static const GdkColor kGdkBlack = {0, 0, 0, 0}; |
+ EnableDoubleBuffer(true); |
gfx::Rect bounds(gfx::Screen::GetMonitorAreaNearestWindow(NULL)); |
- LockWindow* lock_window = new LockWindow(this); |
- lock_window_ = lock_window->GetWidget(); |
+ lock_window_ = GetWidget(); |
views::Widget::InitParams params( |
views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); |
params.bounds = bounds; |
- params.native_widget = lock_window; |
+ params.native_widget = this; |
lock_window_->Init(params); |
gtk_widget_modify_bg( |
lock_window_->GetNativeView(), GTK_STATE_NORMAL, &kGdkBlack); |
@@ -153,76 +156,32 @@ void WebUIScreenLocker::LockScreen(bool unlock_on_input) { |
g_signal_connect(lock_window_->GetNativeView(), "client-event", |
G_CALLBACK(OnClientEventThunk), this); |
- // TODO(flackr): Obscure the screen with black / a screensaver if |
- // unlock_on_input. |
DCHECK(GTK_WIDGET_REALIZED(lock_window_->GetNativeView())); |
WmIpc::instance()->SetWindowType( |
lock_window_->GetNativeView(), |
WM_IPC_WINDOW_CHROME_SCREEN_LOCKER, |
NULL); |
- |
- WebUILoginView::Init(lock_window_); |
- lock_window_->SetContentsView(this); |
- lock_window_->Show(); |
- OnWindowCreated(); |
- LoadURL(GURL(kLoginURL)); |
- // User list consisting of a single logged-in user. |
- UserList users(1, &chromeos::UserManager::Get()->logged_in_user()); |
- login_display_.reset(new WebUILoginDisplay(this)); |
- login_display_->set_background_bounds(bounds); |
- login_display_->set_parent_window( |
- GTK_WINDOW(lock_window_->GetNativeView())); |
- login_display_->Init(users, false, false); |
- |
- static_cast<OobeUI*>(GetWebUI())->ShowSigninScreen(login_display_.get()); |
- |
- registrar_.Add(this, |
- chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED, |
- content::NotificationService::AllSources()); |
- |
- ClearGtkGrab(); |
- |
- // Call this after lock_window_->Show(); otherwise the 1st invocation |
- // of gdk_xxx_grab() will always fail. |
- TryGrabAllInputs(); |
- |
- // Add the window to its own group so that its grab won't be stolen if |
- // gtk_grab_add() gets called on behalf on a non-screen-locker widget (e.g. |
- // a modal dialog) -- see http://crosbug.com/8999. We intentionally do this |
- // after calling ClearGtkGrab(), as want to be in the default window group |
- // then so we can break any existing GTK grabs. |
- GtkWindowGroup* window_group = gtk_window_group_new(); |
- gtk_window_group_add_window(window_group, |
- GTK_WINDOW(lock_window_->GetNativeView())); |
- g_object_unref(window_group); |
- |
- lock_window->set_toplevel_focus_widget(lock_window->window_contents()); |
} |
-void WebUIScreenLocker::OnGrabInputs() { |
+void LockWindowGtk::OnGrabInputs() { |
DVLOG(1) << "OnGrabInputs"; |
input_grabbed_ = true; |
- if (drawn_) |
- ScreenLockReady(); |
+ if (drawn_ && observer_) |
+ observer_->OnLockWindowReady(); |
} |
-void WebUIScreenLocker::OnWindowManagerReady() { |
+void LockWindowGtk::OnWindowManagerReady() { |
DVLOG(1) << "OnClientEvent: drawn for lock"; |
drawn_ = true; |
- if (input_grabbed_) |
- ScreenLockReady(); |
+ if (input_grabbed_ && observer_) |
+ observer_->OnLockWindowReady(); |
} |
-void WebUIScreenLocker::ScreenLockReady() { |
- ScreenLockerDelegate::ScreenLockReady(); |
- SetInputEnabled(true); |
-} |
- |
-void WebUIScreenLocker::ClearGtkGrab() { |
+void LockWindowGtk::ClearGtkGrab() { |
GtkWidget* current_grab_window; |
// Grab gtk input first so that the menu holding gtk grab will |
// close itself. |
- gtk_grab_add(webui_login_->native_view()); |
+ gtk_grab_add(grab_widget_); |
// Make sure there is no gtk grab widget so that gtk simply propagates |
// an event. GTK maintains grab widgets in a linked-list, so we need to |
@@ -231,19 +190,18 @@ void WebUIScreenLocker::ClearGtkGrab() { |
gtk_grab_remove(current_grab_window); |
} |
-void WebUIScreenLocker::TryGrabAllInputs() { |
- // Grab on the RenderWidgetHostView hosting the WebUI login screen. |
- GdkWindow* grab_widget = webui_login_->dom_contents()->tab_contents()-> |
- GetRenderWidgetHostView()->GetNativeView()->window; |
+void LockWindowGtk::TryGrabAllInputs() { |
// Grab x server so that we can atomically grab and take |
// action when grab fails. |
gdk_x11_grab_server(); |
- gtk_grab_add(webui_login_->native_view()); |
+ gtk_grab_add(grab_widget_); |
if (kbd_grab_status_ != GDK_GRAB_SUCCESS) |
- kbd_grab_status_ = gdk_keyboard_grab(grab_widget, FALSE, GDK_CURRENT_TIME); |
+ kbd_grab_status_ = gdk_keyboard_grab(grab_widget_->window, |
+ FALSE, |
+ GDK_CURRENT_TIME); |
if (mouse_grab_status_ != GDK_GRAB_SUCCESS) { |
mouse_grab_status_ = |
- gdk_pointer_grab(grab_widget, |
+ gdk_pointer_grab(grab_widget_->window, |
FALSE, |
static_cast<GdkEventMask>( |
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | |
@@ -262,7 +220,7 @@ void WebUIScreenLocker::TryGrabAllInputs() { |
gdk_x11_ungrab_server(); |
MessageLoop::current()->PostDelayedTask( |
FROM_HERE, |
- base::Bind(&WebUIScreenLocker::TryGrabAllInputs, |
+ base::Bind(&LockWindowGtk::TryGrabAllInputs, |
weak_factory_.GetWeakPtr()), |
kRetryGrabIntervalMs); |
} else { |
@@ -295,7 +253,7 @@ void WebUIScreenLocker::TryGrabAllInputs() { |
} |
} |
-void WebUIScreenLocker::TryUngrabOtherClients() { |
+void LockWindowGtk::TryUngrabOtherClients() { |
#if !defined(NDEBUG) |
{ |
int event_base, error_base; |
@@ -321,7 +279,6 @@ void WebUIScreenLocker::TryUngrabOtherClients() { |
unsigned int mask; |
XQueryPointer(display, |
ui::GetX11WindowFromGtkWidget( |
- static_cast<LockWindow*>(lock_window_->native_widget())-> |
window_contents()), |
&root, &child, &root_x, &root_y, |
&win_x, &winy, &mask); |
@@ -345,7 +302,7 @@ void WebUIScreenLocker::TryUngrabOtherClients() { |
} |
} |
-void WebUIScreenLocker::HandleGtkGrabBroke() { |
+void LockWindowGtk::HandleGtkGrabBroke() { |
// Input should never be stolen from ScreenLocker once it's |
// grabbed. If this happens, it's a bug and has to be fixed. We |
// let chrome crash to get a crash report and dump, and |
@@ -354,107 +311,11 @@ void WebUIScreenLocker::HandleGtkGrabBroke() { |
CHECK_NE(GDK_GRAB_SUCCESS, mouse_grab_status_); |
} |
-void WebUIScreenLocker::OnAuthenticate() { |
-} |
- |
-void WebUIScreenLocker::SetInputEnabled(bool enabled) { |
- login_display_->SetUIEnabled(enabled); |
- SetStatusAreaEnabled(enabled); |
-} |
- |
-void WebUIScreenLocker::SetSignoutEnabled(bool enabled) { |
- // TODO(flackr): Implement (crbug.com/105267). |
- NOTIMPLEMENTED(); |
-} |
- |
-void WebUIScreenLocker::ShowErrorMessage(const string16& message, |
- bool sign_out_only) { |
- // TODO(flackr): Use login_display_ to show error message (requires either |
- // adding a method to display error strings or strictly passing error ids: |
- // crbug.com/105267). |
- base::FundamentalValue login_attempts_value(0); |
- base::StringValue error_message(message); |
- base::StringValue help_link(""); |
- base::FundamentalValue help_id(0); |
- GetWebUI()->CallJavascriptFunction("cr.ui.Oobe.showSignInError", |
- login_attempts_value, |
- error_message, |
- help_link, |
- help_id); |
-} |
- |
-void WebUIScreenLocker::ShowCaptchaAndErrorMessage(const GURL& captcha_url, |
- const string16& message) { |
- ShowErrorMessage(message, true); |
-} |
- |
-void WebUIScreenLocker::ClearErrors() { |
- GetWebUI()->CallJavascriptFunction("cr.ui.Oobe.clearErrors"); |
-} |
- |
-WebUIScreenLocker::~WebUIScreenLocker() { |
- DCHECK(lock_window_); |
- lock_window_->Close(); |
-} |
- |
-void WebUIScreenLocker::OnClientEvent(GtkWidget* widge, GdkEventClient* event) { |
+void LockWindowGtk::OnClientEvent(GtkWidget* widge, GdkEventClient* event) { |
WmIpc::Message msg; |
WmIpc::instance()->DecodeMessage(*event, &msg); |
if (msg.type() == WM_IPC_MESSAGE_CHROME_NOTIFY_SCREEN_REDRAWN_FOR_LOCK) |
OnWindowManagerReady(); |
} |
-//////////////////////////////////////////////////////////////////////////////// |
-// WebUIScreenLocker, content::NotificationObserver implementation: |
- |
-void WebUIScreenLocker::Observe( |
- int type, |
- const content::NotificationSource& source, |
- const content::NotificationDetails& details) { |
- if (type != chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED) |
- return; |
- |
- const User& user = *content::Details<User>(details).ptr(); |
- login_display_->OnUserImageChanged(user); |
-} |
- |
-//////////////////////////////////////////////////////////////////////////////// |
-// WebUIScreenLocker, LoginDisplay::Delegate implementation: |
- |
-void WebUIScreenLocker::CreateAccount() { |
- NOTREACHED(); |
-} |
- |
-string16 WebUIScreenLocker::GetConnectedNetworkName() { |
- return GetCurrentNetworkName(CrosLibrary::Get()->GetNetworkLibrary()); |
-} |
- |
-void WebUIScreenLocker::FixCaptivePortal() { |
- NOTREACHED(); |
-} |
- |
-void WebUIScreenLocker::CompleteLogin(const std::string& username, |
- const std::string& password) { |
- NOTREACHED(); |
-} |
- |
-void WebUIScreenLocker::Login(const std::string& username, |
- const std::string& password) { |
- DCHECK(username == chromeos::UserManager::Get()->logged_in_user().email()); |
- |
- chromeos::ScreenLocker::default_screen_locker()->Authenticate( |
- ASCIIToUTF16(password)); |
-} |
- |
-void WebUIScreenLocker::LoginAsGuest() { |
- NOTREACHED(); |
-} |
- |
-void WebUIScreenLocker::OnUserSelected(const std::string& username) { |
-} |
- |
-void WebUIScreenLocker::OnStartEnterpriseEnrollment() { |
- NOTREACHED(); |
-} |
- |
} // namespace chromeos |