summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/browser.cc8
-rw-r--r--chrome/browser/browser.h1
-rw-r--r--chrome/browser/browser_focus_uitest.cc106
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc4
-rw-r--r--chrome/browser/renderer_host/render_view_host.h1
-rw-r--r--chrome/browser/renderer_host/render_view_host_delegate.h3
-rw-r--r--chrome/browser/renderer_host/render_widget_host.cc4
-rw-r--r--chrome/browser/renderer_host/render_widget_host.h2
-rw-r--r--chrome/browser/tab_contents/tab_contents.cc7
-rw-r--r--chrome/browser/tab_contents/tab_contents.h1
-rw-r--r--chrome/browser/tab_contents/tab_contents_view_gtk.cc6
11 files changed, 102 insertions, 41 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc
index 88cf354..a8e5469 100644
--- a/chrome/browser/browser.cc
+++ b/chrome/browser/browser.cc
@@ -1999,6 +1999,14 @@ void Browser::TabContentsFocused(TabContents* tab_content) {
window_->TabContentsFocused(tab_content);
}
+bool Browser::TakeFocus(bool reverse) {
+ NotificationService::current()->Notify(
+ NotificationType::FOCUS_RETURNED_TO_BROWSER,
+ Source<Browser>(this),
+ NotificationService::NoDetails());
+ return false;
+}
+
bool Browser::IsApplication() const {
return (type_ & TYPE_APP) != 0;
}
diff --git a/chrome/browser/browser.h b/chrome/browser/browser.h
index 5635c23..f5c1bd6 100644
--- a/chrome/browser/browser.h
+++ b/chrome/browser/browser.h
@@ -515,6 +515,7 @@ class Browser : public TabStripModelDelegate,
virtual void ContentsMouseEvent(TabContents* source, bool motion);
virtual void ContentsZoomChange(bool zoom_in);
virtual void TabContentsFocused(TabContents* tab_content);
+ virtual bool TakeFocus(bool reverse);
virtual bool IsApplication() const;
virtual void ConvertContentsToApplication(TabContents* source);
virtual bool ShouldDisplayURLField();
diff --git a/chrome/browser/browser_focus_uitest.cc b/chrome/browser/browser_focus_uitest.cc
index d2cab01..89abf91 100644
--- a/chrome/browser/browser_focus_uitest.cc
+++ b/chrome/browser/browser_focus_uitest.cc
@@ -147,7 +147,8 @@ class TestInterstitialPage : public InterstitialPage {
public:
TestInterstitialPage(TabContents* tab, bool new_navigation, const GURL& url)
: InterstitialPage(tab, new_navigation, url),
- waiting_for_dom_response_(false) {
+ waiting_for_dom_response_(false),
+ waiting_for_focus_change_(false) {
FilePath file_path;
bool r = PathService::Get(chrome::DIR_TEST_DATA, &file_path);
EXPECT_TRUE(r);
@@ -192,10 +193,25 @@ class TestInterstitialPage : public InterstitialPage {
return render_view_host()->view()->HasFocus();
}
+ void WaitForFocusChange() {
+ waiting_for_focus_change_ = true;
+ ui_test_utils::RunMessageLoop();
+ }
+
+ protected:
+ virtual void FocusedNodeChanged() {
+ if (!waiting_for_focus_change_)
+ return;
+
+ waiting_for_focus_change_= false;
+ MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ }
+
private:
std::string html_contents_;
bool waiting_for_dom_response_;
+ bool waiting_for_focus_change_;
std::string dom_response_;
};
@@ -396,6 +412,10 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, LocationBarLockFocus) {
}
// Focus traversal on a regular page.
+// Note that this test relies on a notification from the renderer that the
+// focus has changed in the page. The notification in the renderer may change
+// at which point this test would fail (see comment in
+// RenderWidget::didFocus()).
IN_PROC_BROWSER_TEST_F(BrowserFocusTest, FocusTraversal) {
HTTPTestServer* server = StartHTTPServer();
@@ -420,7 +440,7 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, FocusTraversal) {
CheckViewHasFocus(VIEW_ID_LOCATION_BAR);
// Now let's press tab to move the focus.
- for (int j = 0; j < 7; ++j) {
+ for (size_t j = 0; j < arraysize(kExpElementIDs); ++j) {
// Let's make sure the focus is on the expected element in the page.
std::string actual;
ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
@@ -430,21 +450,22 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, FocusTraversal) {
&actual));
ASSERT_STREQ(kExpElementIDs[j], actual.c_str());
- ui_controls::SendKeyPressNotifyWhenDone(window, base::VKEY_TAB, false,
- false, false,
- new MessageLoop::QuitTask());
- ui_test_utils::RunMessageLoop();
- // Ideally, we wouldn't sleep here and instead would use the event
- // processed ack notification from the renderer. I am reluctant to create
- // a new notification/callback for that purpose just for this test.
- PlatformThread::Sleep(kActionDelayMs);
+ ASSERT_TRUE(ui_controls::SendKeyPress(window, base::VKEY_TAB,
+ false, false, false));
+
+ if (j < arraysize(kExpElementIDs) - 1) {
+ ui_test_utils::WaitForFocusChange(browser()->GetSelectedTabContents()->
+ render_view_host());
+ } else {
+ // On the last tab key press, the focus returns to the browser.
+ ui_test_utils::WaitForFocusInBrowser(browser());
+ }
}
// At this point the renderer has sent us a message asking to advance the
// focus (as the end of the focus loop was reached in the renderer).
// We need to run the message loop to process it.
- MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
- ui_test_utils::RunMessageLoop();
+ MessageLoop::current()->RunAllPending();
}
// Now let's try reverse focus traversal.
@@ -453,12 +474,17 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, FocusTraversal) {
CheckViewHasFocus(VIEW_ID_LOCATION_BAR);
// Now let's press shift-tab to move the focus in reverse.
- for (int j = 0; j < 7; ++j) {
- ui_controls::SendKeyPressNotifyWhenDone(window, base::VKEY_TAB, false,
- true, false,
- new MessageLoop::QuitTask());
- ui_test_utils::RunMessageLoop();
- PlatformThread::Sleep(kActionDelayMs);
+ for (size_t j = 0; j < 7; ++j) {
+ ASSERT_TRUE(ui_controls::SendKeyPress(window, base::VKEY_TAB,
+ false, true, false));
+
+ if (j < arraysize(kExpElementIDs) - 1) {
+ ui_test_utils::WaitForFocusChange(browser()->GetSelectedTabContents()->
+ render_view_host());
+ } else {
+ // On the last tab key press, the focus returns to the browser.
+ ui_test_utils::WaitForFocusInBrowser(browser());
+ }
// Let's make sure the focus is on the expected element in the page.
std::string actual;
@@ -473,8 +499,7 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, FocusTraversal) {
// At this point the renderer has sent us a message asking to advance the
// focus (as the end of the focus loop was reached in the renderer).
// We need to run the message loop to process it.
- MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
- ui_test_utils::RunMessageLoop();
+ MessageLoop::current()->RunAllPending();
}
}
@@ -517,26 +542,26 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_FocusTraversalOnInterstitial) {
CheckViewHasFocus(VIEW_ID_LOCATION_BAR);
// Now let's press tab to move the focus.
- for (int j = 0; j < 7; ++j) {
+ for (size_t j = 0; j < 7; ++j) {
// Let's make sure the focus is on the expected element in the page.
std::string actual = interstitial_page->GetFocusedElement();
ASSERT_STREQ(kExpElementIDs[j], actual.c_str());
- ui_controls::SendKeyPressNotifyWhenDone(window, base::VKEY_TAB, false,
- false, false,
- new MessageLoop::QuitTask());
- ui_test_utils::RunMessageLoop();
- // Ideally, we wouldn't sleep here and instead would use the event
- // processed ack notification from the renderer. I am reluctant to create
- // a new notification/callback for that purpose just for this test.
- PlatformThread::Sleep(kActionDelayMs);
+ ASSERT_TRUE(ui_controls::SendKeyPress(window, base::VKEY_TAB,
+ false, false, false));
+
+ if (j < arraysize(kExpElementIDs) - 1) {
+ interstitial_page->WaitForFocusChange();
+ } else {
+ // On the last tab key press, the focus returns to the browser.
+ ui_test_utils::WaitForFocusInBrowser(browser());
+ }
}
// At this point the renderer has sent us a message asking to advance the
// focus (as the end of the focus loop was reached in the renderer).
// We need to run the message loop to process it.
- MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
- ui_test_utils::RunMessageLoop();
+ MessageLoop::current()->RunAllPending();
}
// Now let's try reverse focus traversal.
@@ -545,12 +570,16 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_FocusTraversalOnInterstitial) {
CheckViewHasFocus(VIEW_ID_LOCATION_BAR);
// Now let's press shift-tab to move the focus in reverse.
- for (int j = 0; j < 7; ++j) {
- ui_controls::SendKeyPressNotifyWhenDone(window, base::VKEY_TAB, false,
- true, false,
- new MessageLoop::QuitTask());
- ui_test_utils::RunMessageLoop();
- PlatformThread::Sleep(kActionDelayMs);
+ for (size_t j = 0; j < 7; ++j) {
+ ASSERT_TRUE(ui_controls::SendKeyPress(window, base::VKEY_TAB,
+ false, true, false));
+
+ if (j < arraysize(kExpElementIDs) - 1) {
+ interstitial_page->WaitForFocusChange();
+ } else {
+ // On the last tab key press, the focus returns to the browser.
+ ui_test_utils::WaitForFocusInBrowser(browser());
+ }
// Let's make sure the focus is on the expected element in the page.
std::string actual = interstitial_page->GetFocusedElement();
@@ -560,8 +589,7 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_FocusTraversalOnInterstitial) {
// At this point the renderer has sent us a message asking to advance the
// focus (as the end of the focus loop was reached in the renderer).
// We need to run the message loop to process it.
- MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
- ui_test_utils::RunMessageLoop();
+ MessageLoop::current()->RunAllPending();
}
}
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index 932bf89..63cc15e 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -1572,6 +1572,10 @@ void RenderViewHost::NotifyRendererResponsive() {
delegate_->RendererResponsive(this);
}
+void RenderViewHost::OnMsgFocusedNodeChanged() {
+ delegate_->FocusedNodeChanged();
+}
+
gfx::Rect RenderViewHost::GetRootWindowResizerRect() const {
return delegate_->GetRootWindowResizerRect();
}
diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h
index 52a0c10..b7f2d86 100644
--- a/chrome/browser/renderer_host/render_view_host.h
+++ b/chrome/browser/renderer_host/render_view_host.h
@@ -452,6 +452,7 @@ class RenderViewHost : public RenderWidgetHost,
virtual void OnUserGesture();
virtual void NotifyRendererUnresponsive();
virtual void NotifyRendererResponsive();
+ virtual void OnMsgFocusedNodeChanged();
// IPC message handlers.
void OnMsgShowView(int route_id,
diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h
index c1e301c..74dc44e 100644
--- a/chrome/browser/renderer_host/render_view_host_delegate.h
+++ b/chrome/browser/renderer_host/render_view_host_delegate.h
@@ -544,6 +544,9 @@ class RenderViewHostDelegate {
// The RenderView has inserted one css file into page.
virtual void DidInsertCSS() {}
+
+ // A different node in the page got focused.
+ virtual void FocusedNodeChanged() {}
};
#endif // CHROME_BROWSER_RENDERER_HOST_RENDER_VIEW_HOST_DELEGATE_H_
diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc
index 05b90c98..2bdf11c 100644
--- a/chrome/browser/renderer_host/render_widget_host.cc
+++ b/chrome/browser/renderer_host/render_widget_host.cc
@@ -132,6 +132,7 @@ void RenderWidgetHost::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_HandleInputEvent_ACK, OnMsgInputEventAck)
IPC_MESSAGE_HANDLER(ViewHostMsg_Focus, OnMsgFocus)
IPC_MESSAGE_HANDLER(ViewHostMsg_Blur, OnMsgBlur)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeChanged, OnMsgFocusedNodeChanged)
IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnMsgSetCursor)
IPC_MESSAGE_HANDLER(ViewHostMsg_ImeUpdateStatus, OnMsgImeUpdateStatus)
#if defined(OS_LINUX)
@@ -778,6 +779,9 @@ void RenderWidgetHost::OnMsgBlur() {
}
}
+void RenderWidgetHost::OnMsgFocusedNodeChanged() {
+}
+
void RenderWidgetHost::OnMsgSetCursor(const WebCursor& cursor) {
if (!view_) {
return;
diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h
index b76d4c7..a80d1fd 100644
--- a/chrome/browser/renderer_host/render_widget_host.h
+++ b/chrome/browser/renderer_host/render_widget_host.h
@@ -406,6 +406,8 @@ class RenderWidgetHost : public IPC::Channel::Listener,
void OnMsgInputEventAck(const IPC::Message& message);
void OnMsgFocus();
void OnMsgBlur();
+ virtual void OnMsgFocusedNodeChanged();
+
void OnMsgSetCursor(const WebCursor& cursor);
// Using int instead of ViewHostMsg_ImeControl for control's type to avoid
// having to bring in render_messages.h in a header file.
diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc
index c7c1c37..1568790 100644
--- a/chrome/browser/tab_contents/tab_contents.cc
+++ b/chrome/browser/tab_contents/tab_contents.cc
@@ -2410,6 +2410,13 @@ void TabContents::DidInsertCSS() {
// This RVHDelegate function is used for extensions and not us.
}
+void TabContents::FocusedNodeChanged() {
+ NotificationService::current()->Notify(
+ NotificationType::FOCUS_CHANGED_IN_PAGE,
+ Source<RenderViewHost>(render_view_host()),
+ NotificationService::NoDetails());
+}
+
void TabContents::FileSelected(const FilePath& path,
int index, void* params) {
render_view_host()->FileSelected(path);
diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h
index 61404f3..cd8ec58 100644
--- a/chrome/browser/tab_contents/tab_contents.h
+++ b/chrome/browser/tab_contents/tab_contents.h
@@ -897,6 +897,7 @@ class TabContents : public PageNavigator,
virtual void LoadStateChanged(const GURL& url, net::LoadState load_state);
virtual bool IsExternalTabContainer() const;
virtual void DidInsertCSS();
+ virtual void FocusedNodeChanged();
// SelectFileDialog::Listener ------------------------------------------------
diff --git a/chrome/browser/tab_contents/tab_contents_view_gtk.cc b/chrome/browser/tab_contents/tab_contents_view_gtk.cc
index 6326ae1..32ac7cf 100644
--- a/chrome/browser/tab_contents/tab_contents_view_gtk.cc
+++ b/chrome/browser/tab_contents/tab_contents_view_gtk.cc
@@ -549,8 +549,10 @@ void TabContentsViewGtk::GotFocus() {
// This is called when we the renderer asks us to take focus back (i.e., it has
// iterated past the last focusable element on the page).
void TabContentsViewGtk::TakeFocus(bool reverse) {
- gtk_widget_child_focus(GTK_WIDGET(GetTopLevelNativeWindow()),
- reverse ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD);
+ if (!tab_contents()->delegate()->TakeFocus(reverse)) {
+ gtk_widget_child_focus(GTK_WIDGET(GetTopLevelNativeWindow()),
+ reverse ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD);
+ }
}
void TabContentsViewGtk::HandleKeyboardEvent(