From db5d37f1677e740dc7af2534523cc7103bfd9095 Mon Sep 17 00:00:00 2001 From: Mingyu Lei Date: Thu, 1 Jun 2023 01:28:26 -0700 Subject: [PATCH] Add BFCache WPT for pages with WebSocket/WebTransport/WebRTC This CL adds some missing WPT for BFCache interaction with WebSocket, WebTransport and WebRTC. The page should not be BFCached if there is open connection correspondingly. After the connection is closed, the page should be eligible for BFCache again. Bug: 1446619 Change-Id: Id0b70afed08d3b2520767d09513b6a6c56afb744 --- ...h-closed-webrtc-connection.https.window.js | 19 +++++ ...ith-open-webrtc-connection.https.window.js | 20 +++++ webrtc/resources/webrtc-test-helpers.sub.js | 79 +++++++++++++++++++ ...with-closed-websocket-connection.window.js | 20 +++++ ...e-with-open-websocket-connection.window.js | 21 +++++ .../resources/websockets-test-helpers.sub.js | 25 ++++++ ...ed-webtransport-connection.https.window.js | 20 +++++ ...en-webtransport-connection.https.window.js | 25 ++++++ .../webtransport-test-helpers.sub.js | 21 +++++ 9 files changed, 250 insertions(+) create mode 100644 webrtc/back-forward-cache-with-closed-webrtc-connection.https.window.js create mode 100644 webrtc/back-forward-cache-with-open-webrtc-connection.https.window.js create mode 100644 webrtc/resources/webrtc-test-helpers.sub.js create mode 100644 websockets/back-forward-cache-with-closed-websocket-connection.window.js create mode 100644 websockets/back-forward-cache-with-open-websocket-connection.window.js create mode 100644 websockets/resources/websockets-test-helpers.sub.js create mode 100644 webtransport/back-forward-cache-with-closed-webtransport-connection.https.window.js create mode 100644 webtransport/back-forward-cache-with-open-webtransport-connection.https.window.js diff --git a/webrtc/back-forward-cache-with-closed-webrtc-connection.https.window.js b/webrtc/back-forward-cache-with-closed-webrtc-connection.https.window.js new file mode 100644 index 000000000000000..320803adec29361 --- /dev/null +++ b/webrtc/back-forward-cache-with-closed-webrtc-connection.https.window.js @@ -0,0 +1,19 @@ +// META: title=Testing BFCache support for page with closed WebRTC connection. +// META: script=/common/dispatcher/dispatcher.js +// META: script=/common/utils.js +// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js +// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js +// META: script=resources/webrtc-test-helpers.sub.js + +'use strict'; + +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + + // Open a window with noopener so that BFCache will work. + const rc1 = await rcHelper.addWindow( + /*config=*/ null, /*options=*/ { features: 'noopener' }); + await openThenCloseWebRTC(rc1); + // The page should be eligible for BFCache because the WebRTC connection is closed. + await assertBFCacheEligibility(rc1, /*shouldRestoreFromBFCache=*/ true); +}); diff --git a/webrtc/back-forward-cache-with-open-webrtc-connection.https.window.js b/webrtc/back-forward-cache-with-open-webrtc-connection.https.window.js new file mode 100644 index 000000000000000..4a4807d5141123c --- /dev/null +++ b/webrtc/back-forward-cache-with-open-webrtc-connection.https.window.js @@ -0,0 +1,20 @@ +// META: title=Testing BFCache support for page with open WebRTC connection. +// META: script=/common/dispatcher/dispatcher.js +// META: script=/common/utils.js +// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js +// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js +// META: script=resources/webrtc-test-helpers.sub.js + +'use strict'; + +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + + // Open a window with noopener so that BFCache will work. + const rc1 = await rcHelper.addWindow( + /*config=*/ null, /*options=*/ { features: 'noopener' }); + await openWebRTC(rc1); + // The page should not be eligible for BFCache because of open WebRTC connection. + await assertBFCacheEligibility(rc1, /*shouldRestoreFromBFCache=*/ false); + await assertNotRestoredFromBFCache(rc1, ['WebRTC']); +}); diff --git a/webrtc/resources/webrtc-test-helpers.sub.js b/webrtc/resources/webrtc-test-helpers.sub.js new file mode 100644 index 000000000000000..48882b30ccc263c --- /dev/null +++ b/webrtc/resources/webrtc-test-helpers.sub.js @@ -0,0 +1,79 @@ +// SDP copied from JSEP Example 7.1 +// It contains two media streams with different ufrags +// to test if candidate is added to the correct stream +const sdp = `v=0 +o=- 4962303333179871722 1 IN IP4 0.0.0.0 +s=- +t=0 0 +a=ice-options:trickle +a=group:BUNDLE a1 v1 +a=group:LS a1 v1 +m=audio 10100 UDP/TLS/RTP/SAVPF 96 0 8 97 98 +c=IN IP4 203.0.113.100 +a=mid:a1 +a=sendrecv +a=rtpmap:96 opus/48000/2 +a=rtpmap:0 PCMU/8000 +a=rtpmap:8 PCMA/8000 +a=rtpmap:97 telephone-event/8000 +a=rtpmap:98 telephone-event/48000 +a=maxptime:120 +a=extmap:1 urn:ietf:params:rtp-hdrext:sdes:mid +a=extmap:2 urn:ietf:params:rtp-hdrext:ssrc-audio-level +a=msid:47017fee-b6c1-4162-929c-a25110252400 f83006c5-a0ff-4e0a-9ed9-d3e6747be7d9 +a=ice-ufrag:ETEn +a=ice-pwd:OtSK0WpNtpUjkY4+86js7ZQl +a=fingerprint:sha-256 19:E2:1C:3B:4B:9F:81:E6:B8:5C:F4:A5:A8:D8:73:04:BB:05:2F:70:9F:04:A9:0E:05:E9:26:33:E8:70:88:A2 +a=setup:actpass +a=dtls-id:1 +a=rtcp:10101 IN IP4 203.0.113.100 +a=rtcp-mux +a=rtcp-rsize +m=video 10102 UDP/TLS/RTP/SAVPF 100 101 +c=IN IP4 203.0.113.100 +a=mid:v1 +a=sendrecv +a=rtpmap:100 VP8/90000 +a=rtpmap:101 rtx/90000 +a=fmtp:101 apt=100 +a=extmap:1 urn:ietf:params:rtp-hdrext:sdes:mid +a=rtcp-fb:100 ccm fir +a=rtcp-fb:100 nack +a=rtcp-fb:100 nack pli +a=msid:47017fee-b6c1-4162-929c-a25110252400 f30bdb4a-5db8-49b5-bcdc-e0c9a23172e0 +a=ice-ufrag:BGKk +a=ice-pwd:mqyWsAjvtKwTGnvhPztQ9mIf +a=fingerprint:sha-256 19:E2:1C:3B:4B:9F:81:E6:B8:5C:F4:A5:A8:D8:73:04:BB:05:2F:70:9F:04:A9:0E:05:E9:26:33:E8:70:88:A2 +a=setup:actpass +a=dtls-id:1 +a=rtcp:10103 IN IP4 203.0.113.100 +a=rtcp-mux +a=rtcp-rsize +`; + +const sessionDesc = { type: 'offer', sdp }; +const candidate = { + candidate: 'candidate:1 1 udp 2113929471 203.0.113.100 10100 typ host', + sdpMid: 'a1', + sdpMLineIndex: 0, + usernameFragment: 'ETEn' +}; + +// Opens a new WebRTC connection. +async function openWebRTC(remoteContextHelper) { + await remoteContextHelper.executeScript(async (sessionDesc, candidate) => { + const testRTCPeerConnection = new RTCPeerConnection(); + await testRTCPeerConnection.setRemoteDescription(sessionDesc); + await testRTCPeerConnection.addIceCandidate(candidate); + }, [sessionDesc, candidate]); +} + +// Opens a new WebRTC connection and then close it. +async function openThenCloseWebRTC(remoteContextHelper) { + await remoteContextHelper.executeScript(async (sessionDesc, candidate) => { + const testRTCPeerConnection = new RTCPeerConnection(); + await testRTCPeerConnection.setRemoteDescription(sessionDesc); + await testRTCPeerConnection.addIceCandidate(candidate); + testRTCPeerConnection.close(); + }, [sessionDesc, candidate]); +} diff --git a/websockets/back-forward-cache-with-closed-websocket-connection.window.js b/websockets/back-forward-cache-with-closed-websocket-connection.window.js new file mode 100644 index 000000000000000..30b8e63a2cd595d --- /dev/null +++ b/websockets/back-forward-cache-with-closed-websocket-connection.window.js @@ -0,0 +1,20 @@ +// META: title=Testing BFCache support for page with closed WebSocket connection. +// META: script=/common/dispatcher/dispatcher.js +// META: script=/common/utils.js +// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js +// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js +// META: script=/websockets/constants.sub.js +// META: script=resources/websockets-test-helpers.sub.js + +'use strict'; + +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + + // Open a window with noopener so that BFCache will work. + const rc1 = await rcHelper.addWindow( + /*config=*/ null, /*options=*/ { features: 'noopener' }); + await openThenCloseWebSocket(rc1); + // The page should be eligible for BFCache because the WebSocket connection has been closed. + await assertBFCacheEligibility(rc1, /*shouldRestoreFromBFCache=*/ true); +}); diff --git a/websockets/back-forward-cache-with-open-websocket-connection.window.js b/websockets/back-forward-cache-with-open-websocket-connection.window.js new file mode 100644 index 000000000000000..2baf38f303c3dfd --- /dev/null +++ b/websockets/back-forward-cache-with-open-websocket-connection.window.js @@ -0,0 +1,21 @@ +// META: title=Testing BFCache support for page with open WebSocket connection. +// META: script=/common/dispatcher/dispatcher.js +// META: script=/common/utils.js +// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js +// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js +// META: script=/websockets/constants.sub.js +// META: script=resources/websockets-test-helpers.sub.js + +'use strict'; + +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + + // Open a window with noopener so that BFCache will work. + const rc1 = await rcHelper.addWindow( + /*config=*/ null, /*options=*/ { features: 'noopener' }); + await openWebSocket(rc1); + // The page should not be eligible for BFCache because of open WebSocket connection. + await assertBFCacheEligibility(rc1, /*shouldRestoreFromBFCache=*/ false); + await assertNotRestoredFromBFCache(rc1, ['WebSocket']); +}); diff --git a/websockets/resources/websockets-test-helpers.sub.js b/websockets/resources/websockets-test-helpers.sub.js new file mode 100644 index 000000000000000..2680670cc691b14 --- /dev/null +++ b/websockets/resources/websockets-test-helpers.sub.js @@ -0,0 +1,25 @@ +// The file including this must also include `/websockets/constants.sub.js to +// pick up the necessary constants. + +// Opens a new WebSocket connection. +async function openWebSocket(remoteContextHelper) { + let return_value = await remoteContextHelper.executeScript((domain) => { + return new Promise((resolve) => { + var webSocketInNotRestoredReasonsTests = new WebSocket(domain + '/echo'); + webSocketInNotRestoredReasonsTests.onopen = () => { resolve(42); }; + }); + }, [SCHEME_DOMAIN_PORT]); + assert_equals(return_value, 42); +} + +// Opens a new WebSocket connection and then close it. +async function openThenCloseWebSocket(remoteContextHelper) { + let return_value = await remoteContextHelper.executeScript((domain) => { + return new Promise((resolve) => { + var testWebSocket = new WebSocket(domain + '/echo'); + testWebSocket.onopen = () => { testWebSocket.close() }; + testWebSocket.onclose = () => { resolve(42) }; + }); + }, [SCHEME_DOMAIN_PORT]); + assert_equals(return_value, 42); +} diff --git a/webtransport/back-forward-cache-with-closed-webtransport-connection.https.window.js b/webtransport/back-forward-cache-with-closed-webtransport-connection.https.window.js new file mode 100644 index 000000000000000..5cc7e93a2e14d54 --- /dev/null +++ b/webtransport/back-forward-cache-with-closed-webtransport-connection.https.window.js @@ -0,0 +1,20 @@ +// META: title=Testing BFCache support for page with closed WebTransport connection. +// META: script=/common/dispatcher/dispatcher.js +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js +// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js +// META: script=resources/webtransport-test-helpers.sub.js + +'use strict'; + +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + + // Open a window with noopener so that BFCache will work. + const rc1 = await rcHelper.addWindow( + /*config=*/ null, /*options=*/ { features: 'noopener' }); + await openThenCloseWebTransport(rc1); + // The page should be eligible for BFCache because the WebTransport connection is closed. + await assertBFCacheEligibility(rc1, /*shouldRestoreFromBFCache=*/ true); +}); diff --git a/webtransport/back-forward-cache-with-open-webtransport-connection.https.window.js b/webtransport/back-forward-cache-with-open-webtransport-connection.https.window.js new file mode 100644 index 000000000000000..5d5143ae1a47811 --- /dev/null +++ b/webtransport/back-forward-cache-with-open-webtransport-connection.https.window.js @@ -0,0 +1,25 @@ +// META: title=Testing BFCache support for page with open WebTransport connection. +// META: script=/common/dispatcher/dispatcher.js +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js +// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js +// META: script=resources/webtransport-test-helpers.sub.js + +'use strict'; + +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + + // Open a window with noopener so that BFCache will work. + const rc1 = await rcHelper.addWindow( + /*config=*/ null, /*options=*/ { features: 'noopener' }); + await openWebTransport(rc1); + // The page should be eligible for BFCache and the WebTransport connection + // should be closed. + await assertBFCacheEligibility(rc1, /*shouldRestoreFromBFCache=*/ true); + await rc1.executeScript(async () => { + assert_false(window.testWebTransport === undefined); + await window.testWebTransport.closed; + }); +}); diff --git a/webtransport/resources/webtransport-test-helpers.sub.js b/webtransport/resources/webtransport-test-helpers.sub.js index 9f9127b22f96da1..36788699e8bbbef 100644 --- a/webtransport/resources/webtransport-test-helpers.sub.js +++ b/webtransport/resources/webtransport-test-helpers.sub.js @@ -110,3 +110,24 @@ async function readInto(reader, buffer) { return buffer; } + +// Opens a new WebTransport connection. +async function openWebTransport(remoteContextHelper) { + const url = webtransport_url('custom-response.py?:status=200'); + await remoteContextHelper.executeScript((url) => { + window.testWebTransport = new WebTransport(url); + return window.testWebTransport.ready; + }, [url]); +} + +// Opens a new WebTransport connection and then close it. +async function openThenCloseWebTransport(remoteContextHelper) { + const url = webtransport_url('custom-response.py?:status=200'); + await remoteContextHelper.executeScript((url) => { + window.testWebTransport = new WebTransport(url); + return window.testWebTransport.ready.then(async () => { + window.testWebTransport.close(); + await window.testWebTransport.closed; + }); + }, [url]); +}