From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- ...er_target_configuration_command_touch_events.js | 264 +++++++++++++++++++++ 1 file changed, 264 insertions(+) create mode 100644 devtools/shared/commands/target-configuration/tests/browser_target_configuration_command_touch_events.js (limited to 'devtools/shared/commands/target-configuration/tests/browser_target_configuration_command_touch_events.js') diff --git a/devtools/shared/commands/target-configuration/tests/browser_target_configuration_command_touch_events.js b/devtools/shared/commands/target-configuration/tests/browser_target_configuration_command_touch_events.js new file mode 100644 index 0000000000..55a0d198ce --- /dev/null +++ b/devtools/shared/commands/target-configuration/tests/browser_target_configuration_command_touch_events.js @@ -0,0 +1,264 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test touch event simulation. +const TEST_DOCUMENT = "target_configuration_test_doc.sjs"; +const TEST_URI = URL_ROOT_COM_SSL + TEST_DOCUMENT; + +add_task(async function () { + // Disable click hold and double tap zooming as it might interfere with the test + await pushPref("ui.click_hold_context_menus", false); + await pushPref("apz.allow_double_tap_zooming", false); + + const tab = await addTab(TEST_URI); + + info("Create commands for the tab"); + const commands = await CommandsFactory.forTab(tab); + + const targetConfigurationCommand = commands.targetConfigurationCommand; + const targetCommand = commands.targetCommand; + await targetCommand.startListening(); + + info("Touch simulation is disabled at the beginning"); + await checkTopLevelDocumentTouchSimulation({ enabled: false }); + await checkIframeTouchSimulation({ + enabled: false, + }); + + info("Enable touch simulation"); + await targetConfigurationCommand.updateConfiguration({ + touchEventsOverride: "enabled", + }); + await checkTopLevelDocumentTouchSimulation({ enabled: true }); + await checkIframeTouchSimulation({ + enabled: true, + }); + + info("Reload the page"); + await BrowserTestUtils.reloadTab(tab, /* includeSubFrames */ true); + + is( + await topLevelDocumentMatchesCoarsePointerAtStartup(), + true, + "The touch simulation was enabled in the content page when it loaded after reloading" + ); + await checkTopLevelDocumentTouchSimulation({ enabled: true }); + + is( + await iframeMatchesCoarsePointerAtStartup(), + true, + "The touch simulation was enabled in the iframe when it loaded after reloading" + ); + await checkIframeTouchSimulation({ + enabled: true, + }); + + info( + "Create another commands instance and check that destroying it won't reset the touch simulation" + ); + const otherCommands = await CommandsFactory.forTab(tab); + const otherTargetConfigurationCommand = + otherCommands.targetConfigurationCommand; + const otherTargetCommand = otherCommands.targetCommand; + + await otherTargetCommand.startListening(); + // Watch targets so we wait for server communication to settle (e.g. attach calls), as + // this could cause intermittent failures. + await otherTargetCommand.watchTargets({ + types: [otherTargetCommand.TYPES.FRAME], + onAvailable: () => {}, + }); + + // Let's update the configuration with this commands instance to make sure we hit the TargetConfigurationActor + await otherTargetConfigurationCommand.updateConfiguration({ + colorSchemeSimulation: "dark", + }); + + otherTargetCommand.destroy(); + await otherCommands.destroy(); + + await checkTopLevelDocumentTouchSimulation({ enabled: true }); + await checkIframeTouchSimulation({ + enabled: true, + }); + + const previousBrowsingContextId = gBrowser.selectedBrowser.browsingContext.id; + info( + "Check that navigating to a page that forces the creation of a new browsing context keep the simulation enabled" + ); + + const onBrowserLoaded = BrowserTestUtils.browserLoaded( + gBrowser.selectedBrowser, + true + ); + BrowserTestUtils.loadURIString( + gBrowser.selectedBrowser, + URL_ROOT_ORG_SSL + TEST_DOCUMENT + "?crossOriginIsolated=true" + ); + await onBrowserLoaded; + + isnot( + gBrowser.selectedBrowser.browsingContext.id, + previousBrowsingContextId, + "A new browsing context was created" + ); + + is( + await topLevelDocumentMatchesCoarsePointerAtStartup(), + true, + "The touch simulation was enabled in the content page when it loaded after navigating to a new browsing context" + ); + await checkTopLevelDocumentTouchSimulation({ + enabled: true, + }); + + is( + await iframeMatchesCoarsePointerAtStartup(), + true, + "The touch simulation was enabled in the iframe when it loaded after navigating to a new browsing context" + ); + await checkIframeTouchSimulation({ + enabled: true, + }); + + info( + "Check that destroying the commands we enabled the simulation in will disable the simulation" + ); + targetCommand.destroy(); + await commands.destroy(); + + await checkTopLevelDocumentTouchSimulation({ enabled: false }); + await checkIframeTouchSimulation({ + enabled: false, + }); +}); + +function matchesCoarsePointer(browserOrBrowsingContext) { + return SpecialPowers.spawn( + browserOrBrowsingContext, + [], + () => content.matchMedia("(pointer: coarse)").matches + ); +} + +function matchesCoarsePointerAtStartup(browserOrBrowsingContext) { + return SpecialPowers.spawn( + browserOrBrowsingContext, + [], + () => content.wrappedJSObject.initialMatchesCoarsePointer + ); +} + +async function isTouchEventEmitted(browserOrBrowsingContext) { + const onTimeout = wait(1000).then(() => "TIMEOUT"); + const onTouchEvent = SpecialPowers.spawn( + browserOrBrowsingContext, + [], + async () => { + content.touchStartController = new content.AbortController(); + const el = content.document.querySelector("button"); + + let gotTouchEndEvent = false; + + const promise = new Promise(resolve => { + el.addEventListener( + "touchend", + () => { + gotTouchEndEvent = true; + resolve(); + }, + { + signal: content.touchStartController.signal, + once: true, + } + ); + }); + + // For some reason, it might happen that the event is properly registered and transformed + // in the touch simulator, but not received by the event listener we set up just before. + // So here let's try to "tap" 3 times to give us more chance to catch the event. + for (let i = 0; i < 3; i++) { + if (gotTouchEndEvent) { + break; + } + + // Simulate a "tap" with mousedown and then mouseup. + EventUtils.synthesizeMouseAtCenter( + el, + { type: "mousedown", isSynthesized: false }, + content + ); + + await new Promise(res => content.setTimeout(res, 10)); + EventUtils.synthesizeMouseAtCenter( + el, + { type: "mouseup", isSynthesized: false }, + content + ); + await new Promise(res => content.setTimeout(res, 50)); + } + + return promise; + } + ); + + const result = await Promise.race([onTimeout, onTouchEvent]); + + // Remove the event listener + await SpecialPowers.spawn(browserOrBrowsingContext, [], () => { + content.touchStartController.abort(); + delete content.touchStartController; + }); + + return result !== "TIMEOUT"; +} + +async function checkTopLevelDocumentTouchSimulation({ enabled }) { + is( + await matchesCoarsePointer(gBrowser.selectedBrowser), + enabled, + `The touch simulation is ${ + enabled ? "enabled" : "disabled" + } on the top level document` + ); + + is( + await isTouchEventEmitted(gBrowser.selectedBrowser), + enabled, + `touch events are ${enabled ? "" : "not "}emitted on the top level document` + ); +} + +function topLevelDocumentMatchesCoarsePointerAtStartup() { + return matchesCoarsePointerAtStartup(gBrowser.selectedBrowser); +} + +function getIframeBrowsingContext() { + return SpecialPowers.spawn( + gBrowser.selectedBrowser, + [], + () => content.document.querySelector("iframe").browsingContext + ); +} + +async function checkIframeTouchSimulation({ enabled }) { + const iframeBC = await getIframeBrowsingContext(); + is( + await matchesCoarsePointer(iframeBC), + enabled, + `The touch simulation is ${enabled ? "enabled" : "disabled"} on the iframe` + ); + + is( + await isTouchEventEmitted(iframeBC), + enabled, + `touch events are ${enabled ? "" : "not "}emitted on the iframe` + ); +} + +async function iframeMatchesCoarsePointerAtStartup() { + const iframeBC = await getIframeBrowsingContext(); + return matchesCoarsePointerAtStartup(iframeBC); +} -- cgit v1.2.3