OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/command_line.h" | 5 #include "base/command_line.h" |
6 #include "base/strings/string_number_conversions.h" | 6 #include "base/strings/string_number_conversions.h" |
7 #include "chrome/browser/renderer_context_menu/render_view_context_menu_browsert est_util.h" | 7 #include "chrome/browser/renderer_context_menu/render_view_context_menu_browsert est_util.h" |
8 #include "chrome/browser/ui/browser.h" | 8 #include "chrome/browser/ui/browser.h" |
9 #include "chrome/browser/ui/browser_window.h" | 9 #include "chrome/browser/ui/browser_window.h" |
10 #include "chrome/browser/ui/exclusive_access/fullscreen_controller_test.h" | 10 #include "chrome/browser/ui/exclusive_access/fullscreen_controller_test.h" |
11 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 11 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
12 #include "chrome/test/base/in_process_browser_test.h" | 12 #include "chrome/test/base/in_process_browser_test.h" |
13 #include "chrome/test/base/interactive_test_utils.h" | 13 #include "chrome/test/base/interactive_test_utils.h" |
14 #include "chrome/test/base/ui_test_utils.h" | 14 #include "chrome/test/base/ui_test_utils.h" |
15 #include "components/guest_view/browser/guest_view_manager_delegate.h" | 15 #include "components/guest_view/browser/guest_view_manager_delegate.h" |
16 #include "components/guest_view/browser/test_guest_view_manager.h" | 16 #include "components/guest_view/browser/test_guest_view_manager.h" |
17 #include "content/public/browser/navigation_handle.h" | 17 #include "content/public/browser/navigation_handle.h" |
18 #include "content/public/browser/render_frame_host.h" | 18 #include "content/public/browser/render_frame_host.h" |
19 #include "content/public/browser/render_widget_host.h" | 19 #include "content/public/browser/render_widget_host.h" |
20 #include "content/public/browser/render_widget_host_view.h" | 20 #include "content/public/browser/render_widget_host_view.h" |
21 #include "content/public/browser/web_contents.h" | 21 #include "content/public/browser/web_contents.h" |
22 #include "content/public/test/browser_test_utils.h" | 22 #include "content/public/test/browser_test_utils.h" |
23 #include "content/public/test/content_browser_test_utils.h" | 23 #include "content/public/test/content_browser_test_utils.h" |
24 #include "content/public/test/test_navigation_observer.h" | 24 #include "content/public/test/test_navigation_observer.h" |
25 #include "content/public/test/test_utils.h" | 25 #include "content/public/test/test_utils.h" |
26 #include "extensions/browser/api/extensions_api_client.h" | 26 #include "extensions/browser/api/extensions_api_client.h" |
27 #include "extensions/common/constants.h" | 27 #include "extensions/common/constants.h" |
28 #include "net/dns/mock_host_resolver.h" | 28 #include "net/dns/mock_host_resolver.h" |
29 #include "net/test/embedded_test_server/embedded_test_server.h" | 29 #include "net/test/embedded_test_server/embedded_test_server.h" |
30 #include "ui/base/test/ui_controls.h" | |
30 #include "ui/display/display.h" | 31 #include "ui/display/display.h" |
31 #include "ui/display/screen.h" | 32 #include "ui/display/screen.h" |
32 #include "url/gurl.h" | 33 #include "url/gurl.h" |
33 | 34 |
34 class SitePerProcessInteractiveBrowserTest : public InProcessBrowserTest { | 35 class SitePerProcessInteractiveBrowserTest : public InProcessBrowserTest { |
35 public: | 36 public: |
36 SitePerProcessInteractiveBrowserTest() {} | 37 SitePerProcessInteractiveBrowserTest() {} |
37 ~SitePerProcessInteractiveBrowserTest() override {} | 38 ~SitePerProcessInteractiveBrowserTest() override {} |
38 | 39 |
39 void SetUpCommandLine(base::CommandLine* command_line) override { | 40 void SetUpCommandLine(base::CommandLine* command_line) override { |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
273 EXPECT_EQ("\"child2-focused-input2\"", press_tab_and_wait_for_message(true)); | 274 EXPECT_EQ("\"child2-focused-input2\"", press_tab_and_wait_for_message(true)); |
274 EXPECT_EQ(child2, web_contents->GetFocusedFrame()); | 275 EXPECT_EQ(child2, web_contents->GetFocusedFrame()); |
275 EXPECT_EQ("\"child2-focused-input1\"", press_tab_and_wait_for_message(true)); | 276 EXPECT_EQ("\"child2-focused-input1\"", press_tab_and_wait_for_message(true)); |
276 EXPECT_EQ("\"child1-focused-input2\"", press_tab_and_wait_for_message(true)); | 277 EXPECT_EQ("\"child1-focused-input2\"", press_tab_and_wait_for_message(true)); |
277 EXPECT_EQ(child1, web_contents->GetFocusedFrame()); | 278 EXPECT_EQ(child1, web_contents->GetFocusedFrame()); |
278 EXPECT_EQ("\"child1-focused-input1\"", press_tab_and_wait_for_message(true)); | 279 EXPECT_EQ("\"child1-focused-input1\"", press_tab_and_wait_for_message(true)); |
279 EXPECT_EQ("\"root-focused-input1\"", press_tab_and_wait_for_message(true)); | 280 EXPECT_EQ("\"root-focused-input1\"", press_tab_and_wait_for_message(true)); |
280 EXPECT_EQ(main_frame, web_contents->GetFocusedFrame()); | 281 EXPECT_EQ(main_frame, web_contents->GetFocusedFrame()); |
281 } | 282 } |
282 | 283 |
284 // TODO(http://crbug.com/702330): Enable this test. | |
alexmos
2017/03/24 23:55:39
nit: https
avallee
2017/03/27 19:54:24
Done.
| |
285 // Ensures that renderers know to advance focus to sibling frames and parent | |
286 // frames in the presence of mouse click initiated focus changes. | |
287 IN_PROC_BROWSER_TEST_F(SitePerProcessInteractiveBrowserTest, | |
288 DISABLED_TabAndMouseFocusNavigation) { | |
289 GURL main_url(embedded_test_server()->GetURL( | |
290 "a.com", "/cross_site_iframe_factory.html?a(b,c)")); | |
291 ui_test_utils::NavigateToURL(browser(), main_url); | |
292 | |
293 content::WebContents* web_contents = | |
294 browser()->tab_strip_model()->GetActiveWebContents(); | |
295 | |
296 content::RenderFrameHost* main_frame = web_contents->GetMainFrame(); | |
297 content::RenderFrameHost* child1 = ChildFrameAt(main_frame, 0); | |
298 ASSERT_NE(nullptr, child1); | |
299 content::RenderFrameHost* child2 = ChildFrameAt(main_frame, 1); | |
300 ASSERT_NE(nullptr, child2); | |
301 | |
302 // Assign a name to each frame. This will be sent along in test messages | |
303 // from focus events. | |
304 EXPECT_TRUE(ExecuteScript(main_frame, "window.name = 'root';")); | |
305 EXPECT_TRUE(ExecuteScript(child1, "window.name = 'child1';")); | |
306 EXPECT_TRUE(ExecuteScript(child2, "window.name = 'child2';")); | |
307 | |
308 // This script will insert two <input> fields in the document, one at the | |
309 // beginning and one at the end. For root frame, this means that we will | |
310 // have an <input>, then two <iframe> elements, then another <input>. | |
alexmos
2017/03/24 23:55:39
Perhaps also mention what it sends back. It's kin
avallee
2017/03/27 19:54:24
Done.
| |
311 std::string script = | |
312 "function onFocus(e) {" | |
313 " console.log(window.name+'-focused-'+ e.target.id);" | |
314 " domAutomationController.setAutomationId(0);" | |
315 " domAutomationController.send(window.name + '-focused-' + e.target.id);" | |
316 "}" | |
317 "" | |
318 "function getElementCoords(element) {" | |
319 " var rect = element.getBoundingClientRect();" | |
320 " return Math.floor(rect.left + 0.5 * rect.width) +','+" | |
321 " Math.floor(rect.top + 0.5 * rect.height);" | |
322 "}" | |
323 "function getIframeCoords(element) {" | |
324 " var rect = element.getBoundingClientRect();" | |
325 " return Math.floor(rect.left) +','+" | |
326 " Math.floor(rect.top);" | |
327 "}" | |
328 "" | |
329 "document.styleSheets[0].insertRule('input {width:100%;margin:0;}', 1);" | |
330 "document.styleSheets[0].insertRule('h2 {margin:0;}', 1);" | |
331 "var input1 = document.createElement('input');" | |
332 "input1.id = 'input1';" | |
333 "input1.addEventListener('focus', onFocus, false);" | |
334 "var input2 = document.createElement('input');" | |
335 "input2.id = 'input2';" | |
336 "input2.addEventListener('focus', onFocus, false);" | |
337 "document.body.insertBefore(input1, document.body.firstChild);" | |
338 "document.body.appendChild(input2);" | |
339 "" | |
340 "var frames = document.querySelectorAll('iframe');" | |
341 "frames = Array.prototype.map.call(frames, getIframeCoords).join(';');" | |
342 "var inputCoords = [input1, input2].map(getElementCoords).join(';');" | |
343 "if (frames) {" | |
344 " inputCoords = inputCoords + ':' + frames;" | |
345 "}" | |
346 "domAutomationController.send(inputCoords);"; | |
347 | |
348 auto parse_points = [](const std::string& input, const gfx::Point& offset) { | |
349 base::StringPairs pieces; | |
350 base::SplitStringIntoKeyValuePairs(input, ',', ';', &pieces); | |
351 std::vector<gfx::Point> points; | |
352 for (const auto& piece : pieces) { | |
353 int x, y; | |
354 EXPECT_TRUE(base::StringToInt(piece.first, &x)); | |
355 EXPECT_TRUE(base::StringToInt(piece.second, &y)); | |
356 points.push_back(gfx::Point(x + offset.x(), y + offset.y())); | |
357 } | |
358 return points; | |
359 }; | |
360 auto parse_points_and_offsets = [parse_points](const std::string& input) { | |
361 auto pieces = base::SplitString(input, ":", base::TRIM_WHITESPACE, | |
362 base::SPLIT_WANT_NONEMPTY); | |
363 gfx::Point origin; | |
alexmos
2017/03/24 23:55:39
is there a better name? I'm thinking of the docum
avallee
2017/03/27 19:54:24
Well both the input points and the offset points f
alexmos
2017/03/27 23:09:28
Yes, either one of those sounds fine.
| |
364 return make_pair(parse_points(pieces[0], origin), | |
365 parse_points(pieces[1], origin)); | |
366 }; | |
367 | |
368 // Add two input fields to each of the three frames. | |
369 std::string result; | |
370 EXPECT_TRUE(ExecuteScriptAndExtractString(main_frame, script, &result)); | |
371 auto parsed = parse_points_and_offsets(result); | |
372 auto main_points = parsed.first; | |
alexmos
2017/03/24 23:55:39
nit: I'd rename to something like main_frame_input
avallee
2017/03/27 19:54:24
Done.
| |
373 | |
374 EXPECT_TRUE(ExecuteScriptAndExtractString(child1, script, &result)); | |
375 auto child1_points = parse_points(result, parsed.second[0]); | |
376 EXPECT_TRUE(ExecuteScriptAndExtractString(child2, script, &result)); | |
377 auto child2_points = parse_points(result, parsed.second[1]); | |
378 | |
379 // Helper to simulate a tab press and wait for a focus message. | |
380 auto press_tab_and_wait_for_message = [web_contents](bool reverse) { | |
381 content::DOMMessageQueue msg_queue; | |
382 std::string reply; | |
383 LOG(ERROR) << "SimulateKeyPress"; | |
alexmos
2017/03/24 23:55:39
Did you want to leave these and the console.log()
avallee
2017/03/27 19:54:25
nope, missed a couple.
| |
384 SimulateKeyPress(web_contents, ui::DomKey::TAB, ui::DomCode::TAB, | |
385 ui::VKEY_TAB, false, reverse /* shift */, false, false); | |
386 EXPECT_TRUE(msg_queue.WaitForMessage(&reply)); | |
387 LOG(ERROR) << "the reply is: " << reply; | |
388 return reply; | |
389 }; | |
390 | |
391 auto click_element_and_wait_for_message = | |
392 [web_contents](const gfx::Point& point) { | |
393 content::DOMMessageQueue msg_queue{web_contents}; | |
alexmos
2017/03/24 23:55:39
Why the {} and not just ()? And do you need it at
avallee
2017/03/27 19:54:24
Gone, this was trying to fix the failure that I di
| |
394 | |
395 auto content_bounds = web_contents->GetContainerBounds(); | |
396 ui_controls::SendMouseMove(point.x() + content_bounds.x(), | |
397 point.y() + content_bounds.y()); | |
398 ui_controls::SendMouseClick(ui_controls::LEFT); | |
399 | |
400 std::string reply; | |
401 EXPECT_TRUE(msg_queue.WaitForMessage(&reply)); | |
402 return reply; | |
403 }; | |
404 | |
405 // Tab from child1 back to root. | |
406 EXPECT_EQ("\"root-focused-input1\"", | |
407 click_element_and_wait_for_message(main_points[0])); | |
408 EXPECT_EQ(main_frame, web_contents->GetFocusedFrame()); | |
409 EXPECT_EQ("\"child1-focused-input1\"", | |
410 click_element_and_wait_for_message(child1_points[0])); | |
411 EXPECT_EQ(child1, web_contents->GetFocusedFrame()); | |
412 EXPECT_EQ("\"root-focused-input1\"", press_tab_and_wait_for_message(true)); | |
413 EXPECT_EQ(main_frame, web_contents->GetFocusedFrame()); | |
414 | |
415 // Tab from child2 forward to root. | |
416 EXPECT_EQ("\"root-focused-input2\"", | |
417 click_element_and_wait_for_message(main_points[1])); | |
418 EXPECT_EQ(main_frame, web_contents->GetFocusedFrame()); | |
419 EXPECT_EQ("\"child2-focused-input2\"", | |
420 click_element_and_wait_for_message(child2_points[1])); | |
421 EXPECT_EQ(child2, web_contents->GetFocusedFrame()); | |
422 EXPECT_EQ("\"root-focused-input2\"", press_tab_and_wait_for_message(false)); | |
423 EXPECT_EQ(main_frame, web_contents->GetFocusedFrame()); | |
424 | |
425 // Tab forward from child1 to child2. | |
426 EXPECT_EQ("\"child2-focused-input1\"", | |
427 click_element_and_wait_for_message(child2_points[0])); | |
428 EXPECT_EQ(child2, web_contents->GetFocusedFrame()); | |
429 EXPECT_EQ("\"child1-focused-input2\"", | |
430 click_element_and_wait_for_message(child1_points[1])); | |
431 EXPECT_EQ(child1, web_contents->GetFocusedFrame()); | |
432 LOG(ERROR) << "before fail"; | |
alexmos
2017/03/24 23:55:39
remove? (also below)
avallee
2017/03/27 19:54:24
Done.
| |
433 EXPECT_EQ("\"child2-focused-input1\"", press_tab_and_wait_for_message(false)); | |
434 LOG(ERROR) << "after fail"; | |
435 EXPECT_EQ(child2, web_contents->GetFocusedFrame()); | |
436 | |
437 // Tab backward from child2 to child1. | |
438 EXPECT_EQ("\"child1-focused-input2\"", | |
439 click_element_and_wait_for_message(child1_points[1])); | |
440 EXPECT_EQ(child1, web_contents->GetFocusedFrame()); | |
441 EXPECT_EQ("\"child2-focused-input1\"", | |
442 click_element_and_wait_for_message(child2_points[0])); | |
443 EXPECT_EQ(child2, web_contents->GetFocusedFrame()); | |
444 EXPECT_EQ("\"child1-focused-input2\"", press_tab_and_wait_for_message(true)); | |
445 EXPECT_EQ(child1, web_contents->GetFocusedFrame()); | |
446 | |
447 // Ensure there are no pending focus events after tabbing. | |
448 EXPECT_EQ("\"root-focused-input1\"", | |
449 click_element_and_wait_for_message(main_points[0])) | |
450 << "Unexpected extra focus events."; | |
451 } | |
452 | |
283 namespace { | 453 namespace { |
284 | 454 |
285 // Helper to retrieve the frame's (window.innerWidth, window.innerHeight). | 455 // Helper to retrieve the frame's (window.innerWidth, window.innerHeight). |
286 gfx::Size GetFrameSize(content::RenderFrameHost* frame) { | 456 gfx::Size GetFrameSize(content::RenderFrameHost* frame) { |
287 int width = 0; | 457 int width = 0; |
288 EXPECT_TRUE(ExecuteScriptAndExtractInt( | 458 EXPECT_TRUE(ExecuteScriptAndExtractInt( |
289 frame, "domAutomationController.send(window.innerWidth);", &width)); | 459 frame, "domAutomationController.send(window.innerWidth);", &width)); |
290 | 460 |
291 int height = 0; | 461 int height = 0; |
292 EXPECT_TRUE(ExecuteScriptAndExtractInt( | 462 EXPECT_TRUE(ExecuteScriptAndExtractInt( |
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
917 send_right_mouse_event(child_view->GetRenderWidgetHost(), 10, 20, | 1087 send_right_mouse_event(child_view->GetRenderWidgetHost(), 10, 20, |
918 blink::WebInputEvent::MouseUp); | 1088 blink::WebInputEvent::MouseUp); |
919 menu_waiter.WaitForMenuOpenAndClose(); | 1089 menu_waiter.WaitForMenuOpenAndClose(); |
920 | 1090 |
921 gfx::Point point_in_root_window = | 1091 gfx::Point point_in_root_window = |
922 child_view->TransformPointToRootCoordSpace(gfx::Point(10, 20)); | 1092 child_view->TransformPointToRootCoordSpace(gfx::Point(10, 20)); |
923 | 1093 |
924 EXPECT_EQ(point_in_root_window.x(), menu_waiter.params().x); | 1094 EXPECT_EQ(point_in_root_window.x(), menu_waiter.params().x); |
925 EXPECT_EQ(point_in_root_window.y(), menu_waiter.params().y); | 1095 EXPECT_EQ(point_in_root_window.y(), menu_waiter.params().y); |
926 } | 1096 } |
OLD | NEW |