Commit d75fede5 authored by Nicolás Peña Moreno's avatar Nicolás Peña Moreno Committed by Commit Bot

[EventTiming] Fix crossiframe test

This CL does the following fixes to crossiframe.html test:
* Remove slow-image and onload, which are obsolete assumptions.
Instead, rely solely on PerformanceObserver.
* Use awaits where needed to make the test logic more sequential.
* Use coordinates and test_driver.Actions() to target the iframe. Using
the test_driver.click directly won't work for elements in iframes.
* Updates the test to check reasonable values for the frame and iframe
entries and check that they don't receive each other's entries.

This CL also:
* Removes unneeded variables from the clickAndBlockMain().
* Removes manual test, which is no longer needed.

Bug: 831729
Change-Id: Iff50035a216b21f67cd71796023af4f934573086
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1972249
Commit-Queue: Nicolás Peña Moreno <npm@chromium.org>
Reviewed-by: default avatarAnnie Sullivan <sullivan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#726422}
parent 4d23d568
...@@ -2426,9 +2426,6 @@ crbug.com/705125 fast/mediacapturefromelement/CanvasCaptureMediaStream-capture-o ...@@ -2426,9 +2426,6 @@ crbug.com/705125 fast/mediacapturefromelement/CanvasCaptureMediaStream-capture-o
crbug.com/763830 http/tests/security/cors-rfc1918/external-to-internal-fetch.php [ Skip ] crbug.com/763830 http/tests/security/cors-rfc1918/external-to-internal-fetch.php [ Skip ]
crbug.com/763830 http/tests/security/cors-rfc1918/external-to-internal-xhr.php [ Skip ] crbug.com/763830 http/tests/security/cors-rfc1918/external-to-internal-xhr.php [ Skip ]
crbug.com/831729 external/wpt/event-timing/crossiframe.html [ Timeout ]
crbug.com/831729 external/wpt/event-timing/observer-manual.html [ Skip ]
# Working on getting the CSP tests going: # Working on getting the CSP tests going:
crbug.com/694525 external/wpt/content-security-policy/connect-src/worker-from-guid.sub.html [ Skip ] crbug.com/694525 external/wpt/content-security-policy/connect-src/worker-from-guid.sub.html [ Skip ]
crbug.com/694525 external/wpt/content-security-policy/connect-src/worker-connect-src-blocked.sub.html [ Skip ] crbug.com/694525 external/wpt/content-security-policy/connect-src/worker-connect-src-blocked.sub.html [ Skip ]
......
...@@ -12,80 +12,79 @@ ...@@ -12,80 +12,79 @@
<script src=/resources/testharness.js></script> <script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script> <script src=/resources/testharnessreport.js></script>
<script src=/resources/testdriver.js></script> <script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-actions.js></script>
<script src=/resources/testdriver-vendor.js></script> <script src=/resources/testdriver-vendor.js></script>
<script src=resources/event-timing-test-utils.js></script> <script src=resources/event-timing-test-utils.js></script>
<img src=./resources/slow-image.py> <iframe id='iframe' src=resources/crossiframe-childframe.html></iframe>
<iframe src=resources/crossiframe-childframe.html></iframe>
<script> <script>
let clickTimeMin; let clickTimeMin;
let processingStartMin; let clickDone;
let onloadStart;
function validateEntries() { function validateEntries(entries) {
const entries = performance.getEntriesByName('mousedown', 'event'); assert_equals(entries.length, 1, "Only 1 entry should be received");
assert_equals(entries.length, 1,
"Observer of main frames should only capture main-frame event-timing entries."
);
const entry = entries[0]; const entry = entries[0];
verifyClickEvent(entry, true); verifyClickEvent(entry, true);
assert_greater_than(entry.processingStart, processingStartMin, assert_less_than(entry.processingStart, clickDone,
"The entry's processing start should be later than processingStartMin."); "The entry's processing start should be before clickDone.");
assert_greater_than(onloadStart, entry.processingStart,
"onload should occur later than the entry's processing start.");
assert_greater_than(entry.startTime, clickTimeMin, assert_greater_than(entry.startTime, clickTimeMin,
"The entry's start time should be later than clickTimeMin."); "The entry's start time should be later than clickTimeMin.");
assert_greater_than(onloadStart, entry.startTime,
"onload should occur later than the entry's start time.");
} }
function validateChildFrameEntries(childFrameData) { function validateChildFrameEntries(childFrameData) {
assert_equals(childFrameData.bufferedEntries.length, 1, if (childFrameData === "failed") {
"Event Timing of child frames should only capture child-frame event-timing entries." assert_unreached("Did not receive exactly one entry from child as expected");
); }
const entry = entries[0]; // |childFrameData| has properties with the same names as its
verifyClickEvent(entry); // PerformanceEventTiming counterpart.
verifyClickEvent(childFrameData);
assert_greater_than(entry.processingStart, childFrameData.processingStartMin, assert_less_than(childFrameData.processingStart, childFrameData.clickDone,
"The entry's processing start should be later than the child frame's processingStartMin."); "The entry's processing start should be before than the child frame's clickDone.");
assert_greater_than(childFrameData.onloadStart, entry.processingStart, assert_greater_than(childFrameData.startTime, childFrameData.clickTimeMin,
"Child frame's onload should occur later than the entry's processing \
start.");
assert_greater_than(entry.startTime, childFrameData.clickTimeMin,
"The entry's start time should be later than the child frame's \ "The entry's start time should be later than the child frame's \
clickTimeMin."); clickTimeMin.");
assert_greater_than(childFrameData.onloadStart, entry.startTime,
"Child frame's onload should be later than the entry's start time.");
assert_array_equals(childFrameData.observedEntries,
childFrameData.bufferedEntries,
"The child frame's observed entries should be buffered as well.");
} }
async_test(function(t) { async_test(async function(t) {
if (!window.PerformanceEventTiming) assert_precondition(window.PerformanceEventTiming,
assert_unreached("PerformanceEventTiming is not supported"); "PerformanceEventTiming is not supported");
clickTimeMin = performance.now(); clickTimeMin = performance.now();
clickAndBlockMain('button'); let observedEntries = false;
processingStartMin = performance.now(); const observerPromise = new Promise(resolve => {
const childFrameEntriesPromise = new Promise((resolve, reject) => { new PerformanceObserver(t.step_func(entries => {
assert_false(observedEntries,
"Observer of main frames should only capture main-frame event-timing entries");
validateEntries(entries.getEntriesByName('mousedown'));
observedEntries = true;
resolve();
})).observe({type: 'event'});
});
await clickAndBlockMain('button');
clickDone = performance.now();
await observerPromise;
const childFrameEntriesPromise = new Promise(resolve => {
window.addEventListener("message", (event) => { window.addEventListener("message", (event) => {
resolve(event.data); resolve(event.data);
}, false); }, false);
}); });
on_event(window, 'load', e => {
onloadStart = performance.now(); let iframe = document.getElementById('iframe');
childFrameEntriesPromise.then((entries) => { const iframeX = document.getElementById('iframe').offsetLeft;
t.step(() => { const iframeY = document.getElementById('iframe').offsetTop;
validateChildFrameEntries(entries); // Tap on the iframe, with an offset of 10 to target the div inside it.
validateEntries(); const actions = new test_driver.Actions()
}); .pointerMove(iframeX + 10, iframeY + 10)
t.done(); .pointerDown()
}); .pointerUp()
actions.send();
const childFrameData = await childFrameEntriesPromise;
t.step(() => {
validateChildFrameEntries(childFrameData);
}); });
t.done();
}, "Event Timing: entries should only be observable by its own frame."); }, "Event Timing: entries should only be observable by its own frame.");
</script> </script>
......
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Event Timing: entries should be observable by its own frame.
</title>
<script src=./resources/event-timing-test-utils.js></script>
</head>
<body>
<h2>Description:</h2>
<p>
<div>
The goal of this manual test is to verify that observers that have
registered "event" entry type can observe the long-latency input events,
and verify the same behavior within iframe and in cross-frame scenario.
</div>
</p>
<h2>Manual test steps:</h2>
<p>
<div>
Step 1: Click the "make busy" button to make main-thread busy for 2 seconds.</span>
</div>
<div>
Step 2: do several clicks on "click while busy" while busy to generate long-latency inputs.
</div>
<div>
Step 3: observe in the "timeline" section that the long-latency clicks are captured by the observer.
</div>
<div>
Step 4: do step 1 to step 3 for the iframe. Observe that the observers only observe input events within its frame.
</div>
</p>
<div>
<h2>Actions:</h2>
<button id='busy_button' onclick='onMakeBusy()'>make busy</button>
<button id='click_input_button' onclick='1'> click while busy </button>
</div>
<h2>iframe:</h2>
<div>
<iframe name='childframe' width="100%" height="30%" src=./resources/observer-manual-childframe.html></iframe>
</div>
<h2>Timeline:</h2>
<p id='timeline'></p>
</body>
<script>
function log(message) {
const timestamp = performance.now();
const elem = document.createElement('div');
elem.innerHTML = `${timestamp.toFixed(1)}: ${message}`;
const timeline = document.getElementById('timeline');
timeline.appendChild(elem);
}
function onMakeBusy() {
log("busy start");
step_timeout(()=>{
mainThreadBusy(2000);
log("busy end");
}, 0);
}
document.body.onload = () => {
new PerformanceObserver((entryList) => {
entryList.getEntries().forEach(e => {
log(`entry observed: ${JSON.stringify(e)}`);
});
}).observe({ entryTypes: ['event'] });
log("observer registered");
};
window.onmessage = (msg) => {
log("received msg: " + msg.data);
if (msg.data === 'CHILD_FRAME_IS_READY') {
// TODO(crbug/831729): automate clicks on iframe when testdriver support
// clicking in iframe.
}
};
</script>
</html>
<!DOCType html> <!DOCType html>
<html> <html>
<body>
<script src=event-timing-test-utils.js></script> <script src=event-timing-test-utils.js></script>
<button id='button_child_frame'>Generate a 'click' event</button> <div style="width: 300px; height: 300px" onmousedown="mainThreadBusy(120)">
<script> <script>
(async () => {
const clickTimeMin = performance.now(); const clickTimeMin = performance.now();
clickAndBlockMain('button_child_frame'); const observerPromise = new Promise(resolve => {
const processingStartMin = performance.now(); new PerformanceObserver(entryList => {
const observerPromise = new Promise((resolve, reject) => {
new PerformanceObserver((entryList) => {
resolve(entryList.getEntries().filter(entry => entry.name === 'mousedown')); resolve(entryList.getEntries().filter(entry => entry.name === 'mousedown'));
}).observe({ type:'event', buffered: true }); }).observe({ type:'event' });
});
window.addEventListener('load', e => {
observerPromise.then((observedEntries) => {
const onloadStart = performance.now();
const bufferedEntries = performance.getEntriesByType('event');
top.postMessage({
"bufferedEntries" : bufferedEntries,
"observedEntries": observedEntries,
"clickTimeMin": clickTimeMin,
"processingStartMin" : processingStartMin,
"onloadStart" : onloadStart,
}, '*');
});
}); });
const entries = await observerPromise;
const clickDone = performance.now();
if (entries.length !== 1) {
top.postMessage("failed", "*");
return;
}
const entry = entries[0];
top.postMessage({
// Entry values (|entry| itself is not clonable)
"name": entry.name,
"cancelable": entry.cancelable,
"entryType": entry.entryType,
"startTime": entry.startTime,
"processingStart": entry.processingStart,
"processingEnd": entry.processingEnd,
"duration": entry.duration,
// Other values
"clickTimeMin": clickTimeMin,
"clickDone" : clickDone,
}, '*');
}) ();
</script> </script>
</body>
</html> </html>
...@@ -3,10 +3,6 @@ ...@@ -3,10 +3,6 @@
// where appropriate. Calls |callback| during event handler. // where appropriate. Calls |callback| during event handler.
function clickOnElement(id, callback) { function clickOnElement(id, callback) {
const element = document.getElementById(id); const element = document.getElementById(id);
const rect = element.getBoundingClientRect();
const xCenter = rect.x + rect.width / 2;
const yCenter = rect.y + rect.height / 2;
const leftButton = 0;
const clickHandler = () => { const clickHandler = () => {
mainThreadBusy(120); mainThreadBusy(120);
if (callback) if (callback)
......
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
</head>
<script src=./event-timing-test-utils.js></script>
<script>
function log(message) {
const timestamp = performance.now();
const elem = document.createElement('div');
elem.innerHTML = `${timestamp.toFixed(1)}: ${message}`;
const timeline = document.getElementById('timeline');
timeline.appendChild(elem);
}
function run() {
new PerformanceObserver((entryList) => {
entryList.getEntries().forEach(e => {
log(`entry observed: ${JSON.stringify(e)}`);
});
}).observe({ entryTypes: ['event'] });
log("observer registered");
top.postMessage('CHILD_FRAME_IS_READY', "*");
}
function onMakeBusy() {
log("busy start");
step_timeout(()=>{
mainThreadBusy(2000);
log("busy end");
}, 0);
}
</script>
<body onload='run()'>
<h3>Actions:</h3>
<p>
<button id='busy_button' onclick='onMakeBusy()'>Make busy</button>
<button id='click_input_button' onclick='1'> click while busy </button>
</p>
<h3>Timeline:</h3>
<p id='timeline'></p>
</body>
</html>
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