tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit fd2f344cfcfffe56fe2cc7ad7cbfb683360d837f
parent b8ab0b6ce9c9d312b57414c281df16cd57d9af99
Author: Perry <perryuwang@gmail.com>
Date:   Wed, 15 Oct 2025 08:22:10 +0000

Bug 1992859 [wpt PR 55261] - Save and restore iframe scroll offset when going to/from display:none, a=testonly

Automatic update from web-platform-tests
Save and restore iframe scroll offset when going to/from display:none

When iframe is set to display:none, its scroll offset is clamped to
zero, so it cannot preserve previous scroll offset after returning from
display:none. This CL saves the current scroll offset when iframe was
set to display:none, and restore the scroll offset when it returns from
display:none.

Bug: 41368291
Change-Id: I7440f4198741d7f7bd9bc472d16438e9781260fe
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6999533
Commit-Queue: Perry <perryuwang@gmail.com>
Reviewed-by: Stefan Zager <szager@chromium.org>
Reviewed-by: David Bokan <bokan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1527333}

--

wpt-commits: 9561610dc1096d35ed38080c675accecc97cf13e
wpt-pr: 55261

Diffstat:
Atesting/web-platform/tests/dom/events/scrolling/save-iframe-scroll-offset-when-display-none.html | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atesting/web-platform/tests/dom/events/scrolling/save-iframe-scroll-offset-when-display-none.sub.html | 34++++++++++++++++++++++++++++++++++
2 files changed, 119 insertions(+), 0 deletions(-)

diff --git a/testing/web-platform/tests/dom/events/scrolling/save-iframe-scroll-offset-when-display-none.html b/testing/web-platform/tests/dom/events/scrolling/save-iframe-scroll-offset-when-display-none.html @@ -0,0 +1,85 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Ensure that the scroll position isn't lost when the iframe is set to display:none and shown again</title> +<link rel="author" href="mailto:perryuwang@gmail.com"> +<link rel="help" href="https://issues.chromium.org/issues/41368291"> +<script src="scroll_support.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<div> + <iframe id="frame"></iframe> +</div> + +<script> +const IFRAME_PATH = '/dom/events/scrolling/save-iframe-scroll-offset-when-display-none.sub.html'; + +function waitForFrameLoadAsync(frame) { + return new Promise(async (resolve) => { + frame.addEventListener('load', resolve, { once: true }); + }); +} + +function waitForMessageAsync(expected_frame_id, expected_command) { + return new Promise((resolve) => { + window.addEventListener('message', (event) => { + assert_equals(event.data.command, expected_command); + assert_equals(event.data.frame_id, expected_frame_id); + resolve({scrollX: event.data.scrollX, scrollY: event.data.scrollY}); + }, { once: true }); + }); +} + +function iframeScrollTo(frame, x, y) { + return new Promise(async (resolve) => { + const scroll_ack_waiter = waitForMessageAsync(frame.id, 'scrollTo'); + await frame.contentWindow.postMessage({ + command: 'scrollTo', + frame_id: frame.id, + scrollX: x, + scrollY: y, + }, '*'); + const ret = await scroll_ack_waiter; + resolve(ret); + }); +} + +function iframeGetScroll(frame) { + return new Promise(async (resolve) => { + const scroll_ack_waiter = waitForMessageAsync(frame.id, 'getScroll'); + await frame.contentWindow.postMessage({ + command: 'getScroll', + frame_id: frame.id, + }, '*'); + const ret = await scroll_ack_waiter; + resolve(ret); + }); +} + +async function testIFrame(src) { + const frame = document.getElementById('frame'); + frame.src = src; + await waitForFrameLoadAsync(frame); + let ret = await iframeScrollTo(frame, 1000, 2000); + assert_equals(ret.scrollX, 1000); + assert_equals(ret.scrollY, 2000); + frame.style.display = 'none'; + await waitForCompositorCommit(); + frame.style.display = ''; + await waitForCompositorCommit(); + ret = await iframeGetScroll(frame); + assert_equals(ret.scrollX, 1000); + assert_equals(ret.scrollY, 2000); +} + +window.onload = async () => { + promise_test(async () => { + await testIFrame(IFRAME_PATH); + }, 'Ensure that the scroll position is not lost when the local iframe is set to display:none and shown again.'); + + promise_test(async () => { + await testIFrame(get_host_info().HTTP_NOTSAMESITE_ORIGIN + IFRAME_PATH); + }, 'Ensure that the scroll position is not lost when the remote iframe is set to display:none and shown again.'); +} +</script> diff --git a/testing/web-platform/tests/dom/events/scrolling/save-iframe-scroll-offset-when-display-none.sub.html b/testing/web-platform/tests/dom/events/scrolling/save-iframe-scroll-offset-when-display-none.sub.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<div style="width: 10000px; height: 10000px"> + <!-- Adding <input> is to reproduce scroll offset reset when display:none --> + <input type="text"> +</div> +<script> +function postReplyMessage(target, frame_id, command) { + target.postMessage({ + command: command, + frame_id: frame_id, + scrollX: window.scrollX, + scrollY: window.scrollY + }, "*"); +} + +function handleMessage(event) { + switch (event.data.command) { + case 'scrollTo': + window.scrollTo(event.data.scrollX, event.data.scrollY); + break; + case 'getScroll': + // No-op, just reply with current scroll position. + break; + default: + throw Error(`Unknown command: ${event.data.command}`); + break; + } + requestAnimationFrame(() => { + postReplyMessage(event.source, event.data.frame_id, event.data.command); + }); +} + +window.addEventListener('message', handleMessage); +</script>