<!DOCTYPE html>
<html>
<head>
<link rel="help" href="http://www.w3.org/TR/DOM-Level-3-Events/#events-WheelEvent">
<script src="../../resources/js-test-pre.js"></script>
<script>
var wheelCount = 0;
function onScrollWheel(evt) {
    wheelCount = wheelCount + 1;
}

function onLoad() {
    document.addEventListener("mousewheel", onScrollWheel);
    window.addEventListener("scroll", onPageScroll);
}
</script>
</head>
<body onload="onLoad();">
<script>

var iframeTarget;
var pageScrollPositionBefore;
var iFrameScrollPositionBefore;
var continueCount = 5;

function onPageScroll()
{
    if (document.scrollingElement.scrollTop >= 70)
        checkForScroll();
}

function checkForScroll()
{
    // The IFrame should not have scrolled at all.
    var pageScrollPositionAfter = document.scrollingElement.scrollTop;
    var iFrameScrollPositionAfter = window.frames['target'].document.scrollingElement.scrollTop;

    if (iFrameScrollPositionBefore != iFrameScrollPositionAfter)
        testFailed("IFrame consumed wheel events.");
    else
        testPassed("IFrame did not receive wheel events.");

    if (window.internals) {
        document.getElementById('layers').innerText = internals.layerTreeAsText(document,
            internals.LAYER_TREE_INCLUDES_VISIBLE_RECTS | internals.LAYER_TREE_INCLUDES_TILE_CACHES);
    }

    testRunner.notifyDone();
}

function scrollTest()
{
    pageScrollPositionBefore = document.scrollingElement.scrollTop;
    iFrameScrollPositionBefore = window.frames['target'].document.scrollingElement.scrollTop;

    iframeTarget = document.getElementById('target');

    // Scroll the #source until we reach the #target.
    var startPosX = Math.round(iframeTarget.offsetLeft) + 20;
    var startPosY = Math.round(iframeTarget.offsetTop) - 42; // Slightly more than one wheel scroll away from the IFrame
    eventSender.mouseMoveTo(startPosX, startPosY);
    //debug("Mouse moved to (" + startPosX + ", " + startPosY + ")");
    eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'began', 'none');
    eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'changed', 'none');
    eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'changed', 'none');
    eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, 'ended', 'none');
    eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'none', 'begin');
    eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -4, 'none', 'continue');
    eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, 'none', 'end');
    eventSender.callAfterScrollingCompletes(checkForScroll);

    // We should finish via the scroll event; this will fire in the case of failure when the page doesn't scroll.
}

function setupTopLevel()
{
    if (window.eventSender) {
        testRunner.dumpAsText();
        testRunner.waitUntilDone();

        eventSender.monitorWheelEvents();
        setTimeout(scrollTest, 0);
    } else {
        var messageLocation = document.getElementById('parent');
        var message = document.createElement('div');
        message.innerHTML = "<p>This test is better run under DumpRenderTree. To manually test it, place the mouse pointer<br/>"
            + "at the top of the page, and then use the mouse wheel or a two-finger swipe to scroll the<br/>"
            + "down past the IFrame.<br/><br/>"
            + "You should not see the row of END labels if this test is successful.</p>";
        messageLocation.appendChild(message);
    }
}

</script>
<div id="parent" style="height: 2000px;">
    <div id="source" style="height: 100px">
        Put mouse here and flick downwards
    </div>
    <iframe id="target" name="target" style="border:solid 1px green; height: 300px; width: 500px;" 
     src= "data:text/html,
     <div id='notToBeScrolled' style='height: 1000px; width: 1000px;'>
     TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP<br/><br/>
     This should still be visible inside the frame after you scroll down
     <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
     <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
     <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
     This should NOT be visible inside the frame after you scroll down<br/>
     <br/>
     END END END END END END END END END END END END END
     </div>
     "
     onload="setupTopLevel();"
     >
    </iframe>
</div>
<div id="console"></div>
<script>
description("Tests that iframe doesn't consume wheel events when scroll ");
</script>
<pre id="layers">Layer tree goes here</p>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>
