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 "core/dom/ClientRect.h" | 5 #include "core/dom/ClientRect.h" |
6 #include "core/frame/BrowserControls.h" | 6 #include "core/frame/BrowserControls.h" |
7 #include "core/frame/FrameHost.h" | 7 #include "core/frame/FrameHost.h" |
8 #include "core/frame/FrameView.h" | 8 #include "core/frame/FrameView.h" |
9 #include "core/frame/RootFrameViewport.h" | 9 #include "core/frame/RootFrameViewport.h" |
10 #include "core/frame/VisualViewport.h" | 10 #include "core/frame/VisualViewport.h" |
11 #include "core/html/HTMLFrameOwnerElement.h" | 11 #include "core/html/HTMLFrameOwnerElement.h" |
12 #include "core/layout/LayoutBox.h" | 12 #include "core/layout/LayoutBox.h" |
13 #include "core/layout/api/LayoutViewItem.h" | 13 #include "core/layout/api/LayoutViewItem.h" |
14 #include "core/layout/compositing/CompositedLayerMapping.h" | 14 #include "core/layout/compositing/CompositedLayerMapping.h" |
15 #include "core/layout/compositing/PaintLayerCompositor.h" | 15 #include "core/layout/compositing/PaintLayerCompositor.h" |
16 #include "core/page/Page.h" | 16 #include "core/page/Page.h" |
17 #include "core/page/scrolling/RootScrollerController.h" | 17 #include "core/page/scrolling/RootScrollerController.h" |
18 #include "core/page/scrolling/TopDocumentRootScrollerController.h" | 18 #include "core/page/scrolling/TopDocumentRootScrollerController.h" |
19 #include "core/paint/PaintLayer.h" | 19 #include "core/paint/PaintLayer.h" |
20 #include "core/paint/PaintLayerScrollableArea.h" | 20 #include "core/paint/PaintLayerScrollableArea.h" |
21 #include "platform/testing/URLTestHelpers.h" | 21 #include "platform/testing/URLTestHelpers.h" |
22 #include "platform/testing/UnitTestHelpers.h" | 22 #include "platform/testing/UnitTestHelpers.h" |
23 #include "public/platform/Platform.h" | 23 #include "public/platform/Platform.h" |
24 #include "public/platform/WebURLLoaderMockFactory.h" | 24 #include "public/platform/WebURLLoaderMockFactory.h" |
25 #include "public/web/WebCache.h" | 25 #include "public/web/WebCache.h" |
26 #include "public/web/WebConsoleMessage.h" | 26 #include "public/web/WebConsoleMessage.h" |
| 27 #include "public/web/WebHitTestResult.h" |
27 #include "public/web/WebRemoteFrame.h" | 28 #include "public/web/WebRemoteFrame.h" |
28 #include "public/web/WebScriptSource.h" | 29 #include "public/web/WebScriptSource.h" |
29 #include "public/web/WebSettings.h" | 30 #include "public/web/WebSettings.h" |
30 #include "testing/gtest/include/gtest/gtest.h" | 31 #include "testing/gtest/include/gtest/gtest.h" |
31 #include "web/WebLocalFrameImpl.h" | 32 #include "web/WebLocalFrameImpl.h" |
32 #include "web/WebRemoteFrameImpl.h" | 33 #include "web/WebRemoteFrameImpl.h" |
33 #include "web/tests/FrameTestHelpers.h" | 34 #include "web/tests/FrameTestHelpers.h" |
34 #include "wtf/Vector.h" | 35 #include "wtf/Vector.h" |
35 | 36 |
36 using blink::testing::runPendingTasks; | 37 using blink::testing::runPendingTasks; |
(...skipping 1272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1309 &mainFrameView()->getRootFrameViewport()->layoutViewport()); | 1310 &mainFrameView()->getRootFrameViewport()->layoutViewport()); |
1310 | 1311 |
1311 // Remove the <iframe> and make sure the layout viewport reverts to the | 1312 // Remove the <iframe> and make sure the layout viewport reverts to the |
1312 // FrameView without a layout. | 1313 // FrameView without a layout. |
1313 iframe->remove(); | 1314 iframe->remove(); |
1314 | 1315 |
1315 EXPECT_EQ(mainFrameView()->layoutViewportScrollableArea(), | 1316 EXPECT_EQ(mainFrameView()->layoutViewportScrollableArea(), |
1316 &mainFrameView()->getRootFrameViewport()->layoutViewport()); | 1317 &mainFrameView()->getRootFrameViewport()->layoutViewport()); |
1317 } | 1318 } |
1318 | 1319 |
| 1320 class RootScrollerHitTest : public RootScrollerTest { |
| 1321 public: |
| 1322 void checkHitTestAtBottomOfScreen() { |
| 1323 // Hide the top controls and scroll down maximally. |
| 1324 { |
| 1325 webViewImpl()->handleInputEvent( |
| 1326 generateTouchGestureEvent(WebInputEvent::GestureScrollBegin)); |
| 1327 ASSERT_EQ(1, browserControls().shownRatio()); |
| 1328 webViewImpl()->handleInputEvent(generateTouchGestureEvent( |
| 1329 WebInputEvent::GestureScrollUpdate, 0, -browserControls().height())); |
| 1330 ASSERT_EQ(0, browserControls().shownRatio()); |
| 1331 webViewImpl()->handleInputEvent(generateTouchGestureEvent( |
| 1332 WebInputEvent::GestureScrollUpdate, 0, -3000)); |
| 1333 webViewImpl()->handleInputEvent( |
| 1334 generateTouchGestureEvent(WebInputEvent::GestureScrollEnd)); |
| 1335 webViewImpl()->resizeWithBrowserControls(IntSize(400, 450), 50, false); |
| 1336 } |
| 1337 |
| 1338 mainFrameView()->updateAllLifecyclePhases(); |
| 1339 |
| 1340 // Do a hit test at the very bottom of the screen. This should be outside |
| 1341 // the |
| 1342 // root scroller's LayoutBox since inert top controls won't resize the ICB |
| 1343 // but, |
| 1344 // since we expaned the clip, we should still be able to hit the target. |
| 1345 WebPoint point(200, 445); |
| 1346 WebSize tapArea(20, 20); |
| 1347 WebHitTestResult result = |
| 1348 webViewImpl()->hitTestResultForTap(point, tapArea); |
| 1349 |
| 1350 ASSERT_TRUE(result.node()); |
| 1351 EXPECT_EQ("target", |
| 1352 result.node().to<WebElement>().getAttribute("id").utf8()); |
| 1353 } |
| 1354 }; |
| 1355 |
| 1356 // Test that hit testing in the area revealed at the bottom of the screen |
| 1357 // revealed by hiding the URL bar works properly when using a root scroller |
| 1358 // when the target and scroller are in the same PaintLayer. |
| 1359 TEST_F(RootScrollerHitTest, HitTestInAreaRevealedByURLBarSameLayer) { |
| 1360 bool oldInertTopControls = RuntimeEnabledFeatures::inertTopControlsEnabled(); |
| 1361 RuntimeEnabledFeatures::setInertTopControlsEnabled(true); |
| 1362 |
| 1363 // Add a target at the bottom of the root scroller that's the size of the url |
| 1364 // bar. We'll test that hiding the URL bar appropriately adjusts clipping so |
| 1365 // that we can hit this target. |
| 1366 initialize("root-scroller.html"); |
| 1367 executeScript( |
| 1368 "var target = document.createElement('div');" |
| 1369 "target.style.width = '100%';" |
| 1370 "target.style.height = '50px';" |
| 1371 "target.id = 'target';" |
| 1372 "document.getElementById('container').appendChild(target);"); |
| 1373 |
| 1374 Document* document = mainFrame()->document(); |
| 1375 Element* container = document->getElementById("container"); |
| 1376 Element* target = document->getElementById("target"); |
| 1377 DummyExceptionStateForTesting exceptionState; |
| 1378 document->setRootScroller(container, exceptionState); |
| 1379 |
| 1380 // This test checks hit testing while the target is in the same PaintLayer as |
| 1381 // the root scroller. |
| 1382 ASSERT_EQ(toLayoutBox(target->layoutObject())->enclosingLayer(), |
| 1383 toLayoutBox(container->layoutObject())->layer()); |
| 1384 |
| 1385 checkHitTestAtBottomOfScreen(); |
| 1386 |
| 1387 RuntimeEnabledFeatures::setInertTopControlsEnabled(oldInertTopControls); |
| 1388 } |
| 1389 |
| 1390 // Test that hit testing in the area revealed at the bottom of the screen |
| 1391 // revealed by hiding the URL bar works properly when using a root scroller |
| 1392 // when the target and scroller are in different PaintLayers. |
| 1393 TEST_F(RootScrollerHitTest, HitTestInAreaRevealedByURLBarDifferentLayer) { |
| 1394 bool oldInertTopControls = RuntimeEnabledFeatures::inertTopControlsEnabled(); |
| 1395 RuntimeEnabledFeatures::setInertTopControlsEnabled(true); |
| 1396 |
| 1397 // Add a target at the bottom of the root scroller that's the size of the url |
| 1398 // bar. We'll test that hiding the URL bar appropriately adjusts clipping so |
| 1399 // that we can hit this target. |
| 1400 initialize("root-scroller.html"); |
| 1401 executeScript( |
| 1402 "var target = document.createElement('div');" |
| 1403 "target.style.width = '100%';" |
| 1404 "target.style.height = '50px';" |
| 1405 "target.style.willChange = 'transform';" |
| 1406 "target.id = 'target';" |
| 1407 "document.getElementById('container').appendChild(target);"); |
| 1408 |
| 1409 Document* document = mainFrame()->document(); |
| 1410 Element* container = document->getElementById("container"); |
| 1411 Element* target = document->getElementById("target"); |
| 1412 DummyExceptionStateForTesting exceptionState; |
| 1413 document->setRootScroller(container, exceptionState); |
| 1414 |
| 1415 // Ensure the target and container weren't put into the same layer. |
| 1416 ASSERT_NE(toLayoutBox(target->layoutObject())->enclosingLayer(), |
| 1417 toLayoutBox(container->layoutObject())->layer()); |
| 1418 |
| 1419 checkHitTestAtBottomOfScreen(); |
| 1420 |
| 1421 RuntimeEnabledFeatures::setInertTopControlsEnabled(oldInertTopControls); |
| 1422 } |
| 1423 |
| 1424 // Test that hit testing in the area revealed at the bottom of the screen |
| 1425 // revealed by hiding the URL bar works properly when using a root scroller |
| 1426 // inside an iframe and the target is in the same paint layer as the scroller. |
| 1427 TEST_F(RootScrollerHitTest, HitTestInAreaRevealedByURLBarIframeSameLayer) { |
| 1428 bool oldInertTopControls = RuntimeEnabledFeatures::inertTopControlsEnabled(); |
| 1429 RuntimeEnabledFeatures::setInertTopControlsEnabled(true); |
| 1430 |
| 1431 // Add a target at the bottom of the root scroller that's the size of the url |
| 1432 // bar. We'll test that hiding the URL bar appropriately adjusts clipping so |
| 1433 // that we can hit this target. |
| 1434 initialize("root-scroller-iframe.html"); |
| 1435 WebLocalFrame* childWebFrame = |
| 1436 mainWebFrame()->firstChild()->toWebLocalFrame(); |
| 1437 executeScript( |
| 1438 "var target = document.createElement('div');" |
| 1439 "target.style.width = '100%';" |
| 1440 "target.style.height = '50px';" |
| 1441 "target.id = 'target';" |
| 1442 "document.getElementById('container').appendChild(target);", |
| 1443 *childWebFrame); |
| 1444 |
| 1445 Element* iframe = mainFrame()->document()->getElementById("iframe"); |
| 1446 LocalFrame* childFrame = |
| 1447 toLocalFrame(toHTMLFrameOwnerElement(iframe)->contentFrame()); |
| 1448 |
| 1449 Document* childDocument = childFrame->document(); |
| 1450 Element* container = childDocument->getElementById("container"); |
| 1451 Element* target = childDocument->getElementById("target"); |
| 1452 DummyExceptionStateForTesting exceptionState; |
| 1453 childDocument->setRootScroller(container, exceptionState); |
| 1454 mainFrame()->document()->setRootScroller(iframe, exceptionState); |
| 1455 |
| 1456 // This test checks hit testing while the target is in the same PaintLayer as |
| 1457 // the root scroller. |
| 1458 ASSERT_EQ(toLayoutBox(target->layoutObject())->enclosingLayer(), |
| 1459 toLayoutBox(container->layoutObject())->layer()); |
| 1460 |
| 1461 checkHitTestAtBottomOfScreen(); |
| 1462 |
| 1463 RuntimeEnabledFeatures::setInertTopControlsEnabled(oldInertTopControls); |
| 1464 } |
| 1465 |
| 1466 // Test that hit testing in the area revealed at the bottom of the screen |
| 1467 // revealed by hiding the URL bar works properly when using a root scroller |
| 1468 // inside an iframe and the target is in a different PaintLayer as the scroller. |
| 1469 TEST_F(RootScrollerHitTest, HitTestInAreaRevealedByURLBarIframeDifferentLayer) { |
| 1470 bool oldInertTopControls = RuntimeEnabledFeatures::inertTopControlsEnabled(); |
| 1471 RuntimeEnabledFeatures::setInertTopControlsEnabled(true); |
| 1472 |
| 1473 // Add a target at the bottom of the root scroller that's the size of the url |
| 1474 // bar. We'll test that hiding the URL bar appropriately adjusts clipping so |
| 1475 // that we can hit this target. |
| 1476 initialize("root-scroller-iframe.html"); |
| 1477 WebLocalFrame* childWebFrame = |
| 1478 mainWebFrame()->firstChild()->toWebLocalFrame(); |
| 1479 executeScript( |
| 1480 "var target = document.createElement('div');" |
| 1481 "target.style.width = '100%';" |
| 1482 "target.style.height = '50px';" |
| 1483 "target.style.willChange = 'transform';" |
| 1484 "target.id = 'target';" |
| 1485 "document.getElementById('container').appendChild(target);", |
| 1486 *childWebFrame); |
| 1487 |
| 1488 Element* iframe = mainFrame()->document()->getElementById("iframe"); |
| 1489 LocalFrame* childFrame = |
| 1490 toLocalFrame(toHTMLFrameOwnerElement(iframe)->contentFrame()); |
| 1491 |
| 1492 Document* childDocument = childFrame->document(); |
| 1493 Element* container = childDocument->getElementById("container"); |
| 1494 Element* target = childDocument->getElementById("target"); |
| 1495 DummyExceptionStateForTesting exceptionState; |
| 1496 childDocument->setRootScroller(container, exceptionState); |
| 1497 mainFrame()->document()->setRootScroller(iframe, exceptionState); |
| 1498 |
| 1499 // This test checks hit testing while the target is in a different PaintLayer |
| 1500 // as the root scroller (ensured by will-change style). |
| 1501 ASSERT_NE(toLayoutBox(target->layoutObject())->enclosingLayer(), |
| 1502 toLayoutBox(container->layoutObject())->layer()); |
| 1503 |
| 1504 checkHitTestAtBottomOfScreen(); |
| 1505 |
| 1506 RuntimeEnabledFeatures::setInertTopControlsEnabled(oldInertTopControls); |
| 1507 } |
| 1508 |
| 1509 // Test that hit testing in the area revealed at the bottom of the screen |
| 1510 // revealed by hiding the URL bar works properly when using a iframe itself as |
| 1511 // the root scroller. |
| 1512 TEST_F(RootScrollerHitTest, HitTestInAreaRevealedByURLBarIframeRootScroller) { |
| 1513 bool oldInertTopControls = RuntimeEnabledFeatures::inertTopControlsEnabled(); |
| 1514 RuntimeEnabledFeatures::setInertTopControlsEnabled(true); |
| 1515 |
| 1516 // Add a target at the bottom of the root scroller that's the size of the url |
| 1517 // bar. We'll test that hiding the URL bar appropriately adjusts clipping so |
| 1518 // that we can hit this target. |
| 1519 initialize("root-scroller-iframe.html"); |
| 1520 WebLocalFrame* childWebFrame = |
| 1521 mainWebFrame()->firstChild()->toWebLocalFrame(); |
| 1522 executeScript( |
| 1523 "var target = document.createElement('div');" |
| 1524 "target.style.width = '100%';" |
| 1525 "target.style.height = '50px';" |
| 1526 "target.id = 'target';" |
| 1527 "document.getElementById('container').innerHTML = '';" |
| 1528 "document.getElementById('container').style.height = '200%';" |
| 1529 "document.body.appendChild(target);", |
| 1530 *childWebFrame); |
| 1531 |
| 1532 Element* iframe = mainFrame()->document()->getElementById("iframe"); |
| 1533 |
| 1534 DummyExceptionStateForTesting exceptionState; |
| 1535 mainFrame()->document()->setRootScroller(iframe, exceptionState); |
| 1536 |
| 1537 checkHitTestAtBottomOfScreen(); |
| 1538 |
| 1539 RuntimeEnabledFeatures::setInertTopControlsEnabled(oldInertTopControls); |
| 1540 } |
| 1541 |
1319 } // namespace | 1542 } // namespace |
1320 | 1543 |
1321 } // namespace blink | 1544 } // namespace blink |
OLD | NEW |