Commit 6a539b43 authored by avallee's avatar avallee Committed by Commit bot

OOPIF: Enable TabAndMouseFocusNavigation.

When advancing focus into an iframe, allow the frame to focus itself
after deciding which element will be focused. This prevents sending a
focus event to the previous element in that frame only to blur it
immediately. Non-oopifs simply fire a focus event to the new element,
the previously focused element in that frame received a blur event when
another frame was focused.

The test ensures a consistent state when mixing tab and clicking
navigation. In specific cases, focus would early out when the element to
advance to was previously focused, and never cleared when the mouse is
clicked in another frame.

BUG=702330
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:linux_site_isolation

Review-Url: https://codereview.chromium.org/2796533002
Cr-Commit-Position: refs/heads/master@{#463006}
parent c1dcea6b
...@@ -302,11 +302,12 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessInteractiveBrowserTest, ...@@ -302,11 +302,12 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessInteractiveBrowserTest,
EXPECT_EQ(main_frame, web_contents->GetFocusedFrame()); EXPECT_EQ(main_frame, web_contents->GetFocusedFrame());
} }
// TODO(https://crbug.com/702330): Enable this test. #if (defined(OS_LINUX) && !defined(USE_OZONE)) || defined(OS_WIN)
// Ensures that renderers know to advance focus to sibling frames and parent // Ensures that renderers know to advance focus to sibling frames and parent
// frames in the presence of mouse click initiated focus changes. // frames in the presence of mouse click initiated focus changes.
// Verifies against regression of https://crbug.com/702330
IN_PROC_BROWSER_TEST_F(SitePerProcessInteractiveBrowserTest, IN_PROC_BROWSER_TEST_F(SitePerProcessInteractiveBrowserTest,
DISABLED_TabAndMouseFocusNavigation) { TabAndMouseFocusNavigation) {
GURL main_url(embedded_test_server()->GetURL( GURL main_url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b,c)")); "a.com", "/cross_site_iframe_factory.html?a(b,c)"));
ui_test_utils::NavigateToURL(browser(), main_url); ui_test_utils::NavigateToURL(browser(), main_url);
...@@ -336,7 +337,6 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessInteractiveBrowserTest, ...@@ -336,7 +337,6 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessInteractiveBrowserTest,
// iframe: 55,18;55,67 // iframe: 55,18;55,67
std::string script = std::string script =
"function onFocus(e) {" "function onFocus(e) {"
" console.log(window.name+'-focused-'+ e.target.id);"
" domAutomationController.setAutomationId(0);" " domAutomationController.setAutomationId(0);"
" domAutomationController.send(window.name + '-focused-' + e.target.id);" " domAutomationController.send(window.name + '-focused-' + e.target.id);"
"}" "}"
...@@ -433,47 +433,59 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessInteractiveBrowserTest, ...@@ -433,47 +433,59 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessInteractiveBrowserTest,
EXPECT_EQ("\"root-focused-input1\"", EXPECT_EQ("\"root-focused-input1\"",
click_element_and_wait_for_message(main_frame_input_coords[0])); click_element_and_wait_for_message(main_frame_input_coords[0]));
EXPECT_EQ(main_frame, web_contents->GetFocusedFrame()); EXPECT_EQ(main_frame, web_contents->GetFocusedFrame());
auto frame_focused = base::MakeUnique<content::FrameFocusedObserver>(child1);
EXPECT_EQ("\"child1-focused-input1\"", EXPECT_EQ("\"child1-focused-input1\"",
click_element_and_wait_for_message(child1_input_coords[0])); click_element_and_wait_for_message(child1_input_coords[0]));
EXPECT_EQ(child1, web_contents->GetFocusedFrame()); frame_focused->Wait();
frame_focused = base::MakeUnique<content::FrameFocusedObserver>(main_frame);
EXPECT_EQ("\"root-focused-input1\"", press_tab_and_wait_for_message(true)); EXPECT_EQ("\"root-focused-input1\"", press_tab_and_wait_for_message(true));
EXPECT_EQ(main_frame, web_contents->GetFocusedFrame()); frame_focused->Wait();
// Tab from child2 forward to root. // Tab from child2 forward to root.
EXPECT_EQ("\"root-focused-input2\"", EXPECT_EQ("\"root-focused-input2\"",
click_element_and_wait_for_message(main_frame_input_coords[1])); click_element_and_wait_for_message(main_frame_input_coords[1]));
EXPECT_EQ(main_frame, web_contents->GetFocusedFrame()); EXPECT_EQ(main_frame, web_contents->GetFocusedFrame());
frame_focused = base::MakeUnique<content::FrameFocusedObserver>(child2);
EXPECT_EQ("\"child2-focused-input2\"", EXPECT_EQ("\"child2-focused-input2\"",
click_element_and_wait_for_message(child2_input_coords[1])); click_element_and_wait_for_message(child2_input_coords[1]));
EXPECT_EQ(child2, web_contents->GetFocusedFrame()); frame_focused->Wait();
frame_focused = base::MakeUnique<content::FrameFocusedObserver>(main_frame);
EXPECT_EQ("\"root-focused-input2\"", press_tab_and_wait_for_message(false)); EXPECT_EQ("\"root-focused-input2\"", press_tab_and_wait_for_message(false));
EXPECT_EQ(main_frame, web_contents->GetFocusedFrame()); frame_focused->Wait();
// Tab forward from child1 to child2. // Tab forward from child1 to child2.
frame_focused = base::MakeUnique<content::FrameFocusedObserver>(child2);
EXPECT_EQ("\"child2-focused-input1\"", EXPECT_EQ("\"child2-focused-input1\"",
click_element_and_wait_for_message(child2_input_coords[0])); click_element_and_wait_for_message(child2_input_coords[0]));
EXPECT_EQ(child2, web_contents->GetFocusedFrame()); frame_focused->Wait();
frame_focused = base::MakeUnique<content::FrameFocusedObserver>(child1);
EXPECT_EQ("\"child1-focused-input2\"", EXPECT_EQ("\"child1-focused-input2\"",
click_element_and_wait_for_message(child1_input_coords[1])); click_element_and_wait_for_message(child1_input_coords[1]));
EXPECT_EQ(child1, web_contents->GetFocusedFrame()); frame_focused->Wait();
frame_focused = base::MakeUnique<content::FrameFocusedObserver>(child2);
EXPECT_EQ("\"child2-focused-input1\"", press_tab_and_wait_for_message(false)); EXPECT_EQ("\"child2-focused-input1\"", press_tab_and_wait_for_message(false));
EXPECT_EQ(child2, web_contents->GetFocusedFrame()); frame_focused->Wait();
// Tab backward from child2 to child1. // Tab backward from child2 to child1.
frame_focused = base::MakeUnique<content::FrameFocusedObserver>(child1);
EXPECT_EQ("\"child1-focused-input2\"", EXPECT_EQ("\"child1-focused-input2\"",
click_element_and_wait_for_message(child1_input_coords[1])); click_element_and_wait_for_message(child1_input_coords[1]));
EXPECT_EQ(child1, web_contents->GetFocusedFrame()); frame_focused->Wait();
frame_focused = base::MakeUnique<content::FrameFocusedObserver>(child2);
EXPECT_EQ("\"child2-focused-input1\"", EXPECT_EQ("\"child2-focused-input1\"",
click_element_and_wait_for_message(child2_input_coords[0])); click_element_and_wait_for_message(child2_input_coords[0]));
EXPECT_EQ(child2, web_contents->GetFocusedFrame()); frame_focused->Wait();
frame_focused = base::MakeUnique<content::FrameFocusedObserver>(child1);
EXPECT_EQ("\"child1-focused-input2\"", press_tab_and_wait_for_message(true)); EXPECT_EQ("\"child1-focused-input2\"", press_tab_and_wait_for_message(true));
EXPECT_EQ(child1, web_contents->GetFocusedFrame()); // EXPECT_EQ(child1, web_contents->GetFocusedFrame());
frame_focused->Wait();
// Ensure there are no pending focus events after tabbing. // Ensure there are no pending focus events after tabbing.
EXPECT_EQ("\"root-focused-input1\"", EXPECT_EQ("\"root-focused-input1\"",
click_element_and_wait_for_message(main_frame_input_coords[0])) click_element_and_wait_for_message(main_frame_input_coords[0]))
<< "Unexpected extra focus events."; << "Unexpected extra focus events.";
} }
#endif
namespace { namespace {
......
...@@ -933,7 +933,11 @@ bool FocusController::advanceFocusAcrossFrames( ...@@ -933,7 +933,11 @@ bool FocusController::advanceFocusAcrossFrames(
start = toHTMLFrameOwnerElement(from->owner()); start = toHTMLFrameOwnerElement(from->owner());
} }
return advanceFocusInDocumentOrder(to, start, type, false, // If we're coming from a parent frame, we need to restart from the first or
// last focusable element.
bool initialFocus = to->tree().parent() == from;
return advanceFocusInDocumentOrder(to, start, type, initialFocus,
sourceCapabilities); sourceCapabilities);
} }
...@@ -998,7 +1002,11 @@ bool FocusController::advanceFocusInDocumentOrder( ...@@ -998,7 +1002,11 @@ bool FocusController::advanceFocusInDocumentOrder(
} }
if (element == document->focusedElement()) { if (element == document->focusedElement()) {
// Focus wrapped around to the same element. // Focus is either coming from a remote frame or has wrapped around.
if (focusedFrame() != document->frame()) {
setFocusedFrame(document->frame());
dispatchFocusEvent(*document, *element);
}
return true; return true;
} }
...@@ -1012,14 +1020,17 @@ bool FocusController::advanceFocusInDocumentOrder( ...@@ -1012,14 +1020,17 @@ bool FocusController::advanceFocusInDocumentOrder(
return false; return false;
document->clearFocusedElement(); document->clearFocusedElement();
setFocusedFrame(owner->contentFrame());
// If contentFrame is remote, continue the search for focusable // If contentFrame is remote, continue the search for focusable elements in
// elements in that frame's process. // that frame's process. The target contentFrame's process will grab focus
// clearFocusedElement() fires events that might detach the // from inside advanceFocusInDocumentOrder().
// contentFrame, hence the need to null-check it again. //
// clearFocusedElement() fires events that might detach the contentFrame,
// hence the need to null-check it again.
if (owner->contentFrame() && owner->contentFrame()->isRemoteFrame()) if (owner->contentFrame() && owner->contentFrame()->isRemoteFrame())
toRemoteFrame(owner->contentFrame())->advanceFocus(type, frame); toRemoteFrame(owner->contentFrame())->advanceFocus(type, frame);
else
setFocusedFrame(owner->contentFrame());
return true; return true;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment