blob: 22595ded520007d7c0132b2f985b377e2adfe62b [file] [log] [blame]
<html>
<head>
<script>
var logDiv;
function log(msg, success)
{
logDiv.appendChild(document.createElement('div')).textContent = msg + ': ' + (success ? 'PASS' : 'FAIL');
}
function moveOver(element)
{
if (!window.eventSender)
return;
var x = element.offsetLeft + element.offsetWidth / 2;
var y = element.offsetTop + element.offsetHeight / 2;
eventSender.mouseMoveTo(x, y);
}
function moveOverLeftQuarterOf(element)
{
if (!window.eventSender)
return;
var x = element.offsetLeft + element.offsetWidth / 4;
var y = element.offsetTop + element.offsetHeight / 2;
eventSender.mouseMoveTo(x, y);
}
function moveOverRightQuarterOf(element)
{
if (!window.eventSender)
return;
var x = element.offsetLeft + element.offsetWidth * 3 / 4;
var y = element.offsetTop + element.offsetHeight / 2;
eventSender.mouseMoveTo(x, y);
}
function clickOn(element)
{
moveOver(element);
eventSender.mouseDown();
eventSender.mouseUp();
}
function clickOnLeftQuarterOf(element)
{
if (!window.eventSender)
return;
moveOverLeftQuarterOf(element);
eventSender.mouseDown();
eventSender.mouseUp();
}
function leapForward()
{
if (!window.eventSender)
return;
eventSender.leapForward(1000);
}
var tests = {
mutationEventPropagation: function()
{
var textarea = document.body.appendChild(document.createElement('textarea'));
var mutationEventFired;
textarea.addEventListener('DOMSubtreeModified', function(e)
{
mutationEventFired = true;
}, false);
textarea.value = 'test';
// Trigger style recalc and sadly, the actual mutation of the textarea shadow DOM.
textarea.offsetHeight;
log('Mutation events should not propagate out of the shadow DOM', !mutationEventFired);
textarea.parentNode.removeChild(textarea);
},
selectstartEventPropagation: function()
{
var textInput = document.body.appendChild(document.createElement('input'));
var selectstartEventFired = false;
document.selectstart = function()
{
selectstartEventFired = true;
}
clickOn(textInput);
log('The selectstart event should not propagate out of the shadow DOM', !selectstartEventFired);
textInput.parentNode.removeChild(textInput);
document.selectstart = null;
},
mouseOverAndOutPropagation: function()
{
var count = 0;
var fileInput = document.body.appendChild(document.createElement('input'));
fileInput.setAttribute('type', 'file');
var countEventDispatch = function()
{
count++;
}
moveOverLeftQuarterOf(fileInput);
document.body.addEventListener('mouseover', countEventDispatch, false);
document.body.addEventListener('mouseout', countEventDispatch, false);
moveOverRightQuarterOf(fileInput);
log("The mouseover/mouseout event between two elements inside the same shadow subtree should not propagate out of the shadow DOM", count == 0);
document.body.removeEventListener('mouseover', countEventDispatch, false);
document.body.removeEventListener('mouseout', countEventDispatch, false);
fileInput.parentNode.removeChild(fileInput);
},
relatedTargetAsHost: function()
{
var count = 0;
var relatedTarget = document.createElement('div');
relatedTarget.style.cssText = 'width: 50px; height: 50px; padding-left: 50px;';
document.body.appendChild(relatedTarget);
var target = document.createElement('div');
target.style.cssText = 'width: 50px; height: 50px';
internals.ensureShadowRoot(relatedTarget).appendChild(target);
moveOverLeftQuarterOf(relatedTarget);
var countEventDispatch = function()
{
count++;
}
relatedTarget.addEventListener('mouseover', countEventDispatch, false)
moveOverRightQuarterOf(relatedTarget);
log("The mouseover event in a shadow subtree, where related target is the tree host should not escape out of shadow DOM", count == 0);
relatedTarget.removeEventListener('mouseover', countEventDispatch, false);
document.body.removeChild(relatedTarget);
},
targetAsHost: function()
{
var count = 0;
var target = document.createElement('div');
target.style.cssText = 'width: 50px; height: 50px; padding-left: 50px;';
document.body.appendChild(target);
var relatedTarget = document.createElement('div');
relatedTarget.style.cssText = 'width: 50px; height: 50px';
internals.ensureShadowRoot(target).appendChild(relatedTarget);
moveOverRightQuarterOf(target);
var countEventDispatch = function(evt)
{
count++;
}
target.addEventListener('mouseover', countEventDispatch, false)
moveOverLeftQuarterOf(target);
log("Events with relatedTarget should not escape out of shadow subtree when its host is the target", count == 0);
target.removeEventListener('mouseout', countEventDispatch, false);
document.body.removeChild(target);
},
mouseOverOnHost: function()
{
var count = 0;
var input = document.body.appendChild(document.createElement('input'));
var countEventDispatch = function()
{
count++;
}
moveOver(document.body);
input.addEventListener('mouseover', countEventDispatch, false);
moveOver(input);
log("The mouseover/mouseout event on a shadow subtree host should propagate out of the shadow DOM", count == 1);
document.body.removeEventListener('mouseover', countEventDispatch, false);
input.parentNode.removeChild(input);
},
labelSyntheticClick: function()
{
var count = 0;
var label = document.body.appendChild(document.createElement('label'));
var searchInput = label.appendChild(document.createElement('input'));
searchInput.setAttribute('type', 'search');
searchInput.setAttribute('id', 'baz');
label.setAttribute('for', 'baz');
searchInput.addEventListener('click', function(e)
{
count++;
}, false);
clickOn(searchInput);
log("Label should look beyond shadow boundary to detect if it encloses its associated element", count == 1);
label.parentNode.removeChild(label);
},
/* This subtest started crashing after r89007:
* https://bugs.webkit.org/show_bug.cgi?id=62788
* I'm disabling this test for now while I ask for help understanding the problem.
defaultEventRetargeting: function()
{
var count = 0;
var fileInput = document.body.appendChild(document.createElement('input'));
fileInput.setAttribute('type', 'file');
var counter = function()
{
count++;
}
document.body.addEventListener('DOMActivate', counter, false);
clickOnLeftQuarterOf(fileInput);
log("Events for default event handler should not be retargeted", count == 1);
document.body.removeEventListener('DOMActivate', counter, false);
fileInput.parentNode.removeChild(fileInput);
},
*/
relatedTargetRetargeting: function()
{
var count = 0;
var textInput = document.body.appendChild(document.createElement('input'));
var counter = function(evt)
{
if (evt.relatedTarget && !evt.relatedTarget.parentNode)
count++;
}
moveOver(textInput);
document.body.addEventListener("mouseover", counter, false);
moveOver(document.body);
document.body.removeEventListener("mouseover", counter, false);
log("Event's relatedTarget should be retargeted", count == 0);
textInput.parentNode.removeChild(textInput);
},
eventInProgress: function()
{
var textInput = document.body.appendChild(document.createElement('input'));
textInput.addEventListener('click', function(e)
{
log('Other events should be retargeted', e.target == textInput);
}, false);
clickOn(textInput);
textInput.parentNode.removeChild(textInput);
},
finalEventObject: function()
{
var textInput = document.body.appendChild(document.createElement('input'));
var storedEvent;
textInput.addEventListener('click', function(e)
{
storedEvent = e;
}, false);
clickOn(textInput);
log('After event dispatch, the event object should not reveal shadow DOM', storedEvent && storedEvent.target == textInput);
textInput.parentNode.removeChild(textInput);
},
focusEventPropagation: function()
{
var searchInput = document.body.appendChild(document.createElement('input'));
searchInput.setAttribute('type', 'search');
var count = 0;
searchInput.addEventListener('focus', function(evt)
{
count++;
});
clickOn(searchInput);
leapForward();
clickOn(searchInput);
log('Focusing same shadow DOM element repeatedly should not trigger multiple focus/blur events', count == 1);
searchInput.parentNode.removeChild(searchInput);
}
};
function runTest()
{
if (window.testRunner)
testRunner.dumpAsText();
logDiv = document.getElementById('log');
for(var testName in tests) {
tests[testName]();
}
}
</script>
</head>
<body onload="runTest()">
<p>Tests to ensure that shadow DOM boundary is not crossed during event propagation. Can only run within DRT.
<p>See <a href="https://bugs.webkit.org/show_bug.cgi?id=46015">bug 46015</a> for details.
<div id="log"></div>
</body>
</html>