Skip to content

Commit dc499a8

Browse files
Yoav Weisschromium-wpt-export-bot
Yoav Weiss
authored andcommitted
Reland: [soft navigations] Enable keyboard shortcuts as soft navigation triggers
Following the discussion on issue #3 [1], this CL adds support to soft navigations triggered by keyboard shortcuts, by adding unfocused keydown events to the events that can trigger the soft navigation heuristic. This is a reland of [2], rebased and which fixes the unguarded ScriptState access in event_dispatcher, which caused a crash. [1] WICG/soft-navigations#3 [2] https://chromium-review.googlesource.com/c/chromium/src/+/4839506 Bug: 1478772, 1480047 Change-Id: I6428e0635222366d880dd908f04f2273b6bf8b44 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4900577 Reviewed-by: Ian Clelland <[email protected]> Commit-Queue: Yoav Weiss <[email protected]> Cr-Commit-Position: refs/heads/main@{#1203903}
1 parent 7e2b1ea commit dc499a8

4 files changed

+54
-18
lines changed

soft-navigation-heuristics/image-lcp-followed-by-two-image-softnavs-lcp.tentative.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
const first_click_paint_promise = waitOnPaintEntriesPromise();
3333

34-
click(link);
34+
interact(link);
3535
await new Promise(resolve => {
3636
(new PerformanceObserver(resolve)).observe({
3737
type: 'soft-navigation'
@@ -54,7 +54,7 @@
5454

5555
const second_click_paint_promise = waitOnPaintEntriesPromise();
5656
const preClickLcp2 = await getLcpEntries();
57-
click(link);
57+
interact(link);
5858
await new Promise(resolve => {
5959
(new PerformanceObserver(() => resolve())).observe({
6060
type: 'soft-navigation'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<!DOCTYPE HTML>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Detect hashchange event.</title>
6+
<script src="/resources/testharness.js"></script>
7+
<script src="/resources/testharnessreport.js"></script>
8+
<script src="/resources/testdriver.js"></script>
9+
<script src="/resources/testdriver-vendor.js"></script>
10+
<script src="resources/soft-navigation-helper.js"></script>
11+
</head>
12+
<!-- Not including a body element to ensure the keydown heuristic works on
13+
malformed HTML -->
14+
<main id=main>
15+
<div>
16+
First LCP!
17+
</div>
18+
</main>
19+
<script>
20+
testSoftNavigation({
21+
addContent: () => {
22+
addTextToDivOnMain();
23+
},
24+
link: document.body,
25+
interactionType: "keydown",
26+
eventType: "keydown",
27+
test: "Keydown on body triggers SoftNavigationHeuristics"});
28+
</script>
29+
</html>
30+

soft-navigation-heuristics/navigate-child.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
await new Promise(r => t.step_timeout(r, 10));
2121
}
2222
const link = document.getElementById("link");
23-
click(link);
23+
interact(link);
2424
while (!child.location.href.includes("2")) {
2525
await new Promise(r => t.step_timeout(r, 10));
2626
}

soft-navigation-heuristics/resources/soft-navigation-helper.js

+21-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
var counter = 0;
2-
var clicked;
2+
var interacted;
33
var timestamps = []
44
const MAX_CLICKS = 50;
55
// Entries for one hard navigation + 50 soft navigations.
@@ -20,6 +20,7 @@ const testSoftNavigation =
2020
const testName = options.testName;
2121
const pushUrl = readValue(options.pushUrl, true);
2222
const eventType = readValue(options.eventType, "click");
23+
const interactionType = readValue(options.interactionType, 'click');
2324
const expectLCP = options.validate != 'no-lcp';
2425
const eventPrepWork = options.eventPrepWork;
2526
promise_test(async t => {
@@ -30,8 +31,8 @@ const testSoftNavigation =
3031
const firstClick = (i === 0);
3132
let paint_entries_promise =
3233
waitOnPaintEntriesPromise(expectLCP && firstClick);
33-
clicked = false;
34-
click(link);
34+
interacted = false;
35+
interact(link, interactionType);
3536

3637
await new Promise(resolve => {
3738
(new PerformanceObserver(() => resolve())).observe({
@@ -62,7 +63,7 @@ const testNavigationApi = (testName, navigateEventHandler, link) => {
6263
await waitInitialLCP();
6364
const preClickLcp = await getLcpEntries();
6465
let paint_entries_promise = waitOnPaintEntriesPromise();
65-
click(link);
66+
interact(link);
6667
await new Promise(resolve => {
6768
(new PerformanceObserver(() => resolve())).observe({
6869
type: 'soft-navigation'
@@ -81,7 +82,7 @@ const testSoftNavigationNotDetected = options => {
8182
promise_test(async t => {
8283
const preClickLcp = await getLcpEntries();
8384
options.eventTarget.addEventListener(options.eventName, options.eventHandler);
84-
click(options.link);
85+
interact(options.link);
8586
await new Promise((resolve, reject) => {
8687
(new PerformanceObserver(() =>
8788
reject("Soft navigation should not be triggered"))).observe({
@@ -129,16 +130,21 @@ const runEntryValidations =
129130
}
130131
};
131132

132-
const click = link => {
133-
if (test_driver) {
134-
test_driver.click(link);
135-
timestamps[counter] = {"syncPostClick": performance.now()};
136-
}
137-
}
133+
const interact =
134+
(link, interactionType = 'click') => {
135+
if (test_driver) {
136+
if (interactionType == 'click') {
137+
test_driver.click(link);
138+
} else {
139+
test_driver.send_keys(link, 'j');
140+
}
141+
timestamps[counter] = {"syncPostInteraction": performance.now()};
142+
}
143+
}
138144

139145
const setEvent = (t, button, pushState, addContent, pushUrl, eventType, prepWork) => {
140-
const eventObject = (eventType == "click") ? button : window;
141-
146+
const eventObject =
147+
(eventType == 'click' || eventType == 'keydown') ? button : window;
142148
eventObject.addEventListener(eventType, async e => {
143149
if (prepWork &&!prepWork(t)) {
144150
return;
@@ -163,7 +169,7 @@ const setEvent = (t, button, pushState, addContent, pushUrl, eventType, prepWork
163169
await addContent(url);
164170
++counter;
165171

166-
clicked = true;
172+
interacted = true;
167173
});
168174
};
169175

@@ -183,7 +189,7 @@ const validateSoftNavigationEntry = async (clicks, extraValidations,
183189
assert_true(entry.name.includes(pushUrl ? URL : document.location.href),
184190
"The soft navigation name is properly set");
185191
const entryTimestamp = entry.startTime;
186-
assert_less_than_equal(timestamps[i]["syncPostClick"], entryTimestamp);
192+
assert_less_than_equal(timestamps[i]["syncPostInteraction"], entryTimestamp);
187193
assert_greater_than_equal(
188194
timestamps[i]['eventStart'], entryTimestamp,
189195
'Event start timestamp matches');

0 commit comments

Comments
 (0)