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 --- gfx/tests/browser/browser.ini | 13 +++ .../browser/browser_native_font_cache_macos.js | 115 +++++++++++++++++++++ gfx/tests/browser/browser_omta_tearoff_tab.js | 39 +++++++ ...browser_partial_prerender_animation_in_popup.js | 90 ++++++++++++++++ .../browser_windowless_troubleshoot_crash.js | 54 ++++++++++ .../browser/file_native_font_cache_macos.html | 15 +++ 6 files changed, 326 insertions(+) create mode 100644 gfx/tests/browser/browser.ini create mode 100644 gfx/tests/browser/browser_native_font_cache_macos.js create mode 100644 gfx/tests/browser/browser_omta_tearoff_tab.js create mode 100644 gfx/tests/browser/browser_partial_prerender_animation_in_popup.js create mode 100644 gfx/tests/browser/browser_windowless_troubleshoot_crash.js create mode 100644 gfx/tests/browser/file_native_font_cache_macos.html (limited to 'gfx/tests/browser') diff --git a/gfx/tests/browser/browser.ini b/gfx/tests/browser/browser.ini new file mode 100644 index 0000000000..c66e65e96d --- /dev/null +++ b/gfx/tests/browser/browser.ini @@ -0,0 +1,13 @@ +[DEFAULT] +support-files = + +[browser_native_font_cache_macos.js] +support-files = + file_native_font_cache_macos.html +skip-if = (os != 'mac') +[browser_omta_tearoff_tab.js] +[browser_partial_prerender_animation_in_popup.js] +support-files = + !/dom/animation/test/testcommon.js +skip-if = (os == 'mac') # on Mac popup windows use basic layers so animation can't be run on the compositor +[browser_windowless_troubleshoot_crash.js] diff --git a/gfx/tests/browser/browser_native_font_cache_macos.js b/gfx/tests/browser/browser_native_font_cache_macos.js new file mode 100644 index 0000000000..919a5c7a72 --- /dev/null +++ b/gfx/tests/browser/browser_native_font_cache_macos.js @@ -0,0 +1,115 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_task(async () => { + // Create a tab that loads a system font. + const CROSS_ORIGIN_DOMAIN = "https://example.com"; + const TARGET_URL = `${CROSS_ORIGIN_DOMAIN}/browser/gfx/tests/browser/file_native_font_cache_macos.html`; + await BrowserTestUtils.withNewTab( + { gBrowser, url: TARGET_URL }, + async browser => { + await SpecialPowers.spawn(browser, [], async () => { + // Capture a snapshot of the tab, which will load the system font in the + // parent process. + const TARGET_WIDTH = 200; + const TARGET_HEIGHT = 100; + + const rect = new content.window.DOMRect( + 0, + 0, + TARGET_WIDTH, + TARGET_HEIGHT + ); + await SpecialPowers.snapshotContext(content.window, rect, "white"); + }); + } + ); + + // Now create a tab that shows the memory reporter. + await BrowserTestUtils.withNewTab( + { gBrowser, url: "about:memory" }, + async browser => { + // Click the "Measure" button. + await SpecialPowers.spawn(browser, [], () => { + let measureButton = content.document.getElementById("measureButton"); + measureButton.click(); + }); + + // Copy the page text and check for an expected start with string. + let copiedText = await new Promise(resolve => { + const REPORT_TIMEOUT_MS = 15 * 1e3; + const EXPECTED_START_WITH = "Main Process"; + let mostRecentTextOnClipboard = ""; + + SimpleTest.waitForClipboard( + textOnClipboard => { + mostRecentTextOnClipboard = textOnClipboard; + const gotExpected = textOnClipboard.startsWith(EXPECTED_START_WITH); + if (!gotExpected) { + // Try copying again. + EventUtils.synthesizeKey("A", { accelKey: true }); + EventUtils.synthesizeKey("C", { accelKey: true }); + } + return gotExpected; + }, + () => { + EventUtils.synthesizeKey("A", { accelKey: true }); + EventUtils.synthesizeKey("C", { accelKey: true }); + }, + () => { + resolve(mostRecentTextOnClipboard); + }, + () => { + info(`Didn't find expected text within ${REPORT_TIMEOUT_MS}ms.`); + dump("*******ACTUAL*******\n"); + dump("<<<" + mostRecentTextOnClipboard + ">>>\n"); + dump("********************\n"); + resolve(""); + }, + "text/plain", + REPORT_TIMEOUT_MS + ); + }); + + isnot(copiedText, "", "Got some text from clipboard."); + + // Search the copied text for our desired pattern. Initially, check for + // a line with "native-font-resource-mac". If that exists, ensure that it + // has less than a maximum MB. If that doesn't exist, check instead for + // a line with "gfx" before the "Other Measurements" section. If that + // exists, it is tested against the same MB limit. If it doesn't exist, + // that is an indication that "gfx" doesn't occur in the first section + // "Explicit Allocations', and therefore isn't holding memory at all. + const MB_EXCLUSIVE_MAX = 20; + const nfrm_line = /^.*?(\d+)\.\d+ MB.*-- native-font-resource-mac/m; + const nfrm_match = nfrm_line.exec(copiedText); + if (nfrm_match) { + const nfrm_mb = nfrm_match[1]; + ok( + nfrm_mb < MB_EXCLUSIVE_MAX, + `native-font-resource-mac ${nfrm_mb} MB should be less than ${MB_EXCLUSIVE_MAX} MB.` + ); + } else { + // Figure out where the "Other Measurements" section begins. + const om_line = /^Other Measurements$/m; + const om_match = om_line.exec(copiedText); + + // Find the first gfx line, and if it occurs before the "Other + // Measurements" section, check its size. + const gfx_line = /^.*?(\d+)\.\d+ MB.*-- gfx/m; + const gfx_match = gfx_line.exec(copiedText); + if (gfx_match && gfx_match.index < om_match.index) { + const gfx_mb = gfx_match[1]; + ok( + gfx_mb < MB_EXCLUSIVE_MAX, + `Explicit Allocations gfx ${gfx_mb} MB should be less than ${MB_EXCLUSIVE_MAX} MB.` + ); + } else { + ok(true, "Explicit Allocations gfx is not listed."); + } + } + } + ); +}); diff --git a/gfx/tests/browser/browser_omta_tearoff_tab.js b/gfx/tests/browser/browser_omta_tearoff_tab.js new file mode 100644 index 0000000000..3dd65a78c6 --- /dev/null +++ b/gfx/tests/browser/browser_omta_tearoff_tab.js @@ -0,0 +1,39 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +var testPage = + "data:text/html,Text"; + +add_task(async function test() { + let tab = BrowserTestUtils.addTab(gBrowser, testPage, { + skipAnimation: true, + }); + await BrowserTestUtils.browserLoaded(tab.linkedBrowser); + await BrowserTestUtils.switchTab(gBrowser, tab); + + await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { + const anim = content.document.getAnimations()[0]; + await anim.ready; + ok(SpecialPowers.wrap(anim).isRunningOnCompositor); + }); + + let promiseWin = BrowserTestUtils.waitForNewWindow(); + let newWin = gBrowser.replaceTabWithWindow(tab); + await promiseWin; + Assert.ok( + ChromeUtils.vsyncEnabled(), + "vsync should be enabled as we have a tab with an animation" + ); + + newWin.close(); + await TestUtils.waitForCondition( + () => !ChromeUtils.vsyncEnabled(), + "wait for vsync to be disabled" + ); + Assert.ok( + !ChromeUtils.vsyncEnabled(), + "vsync should be disabled after closing window that contained an animated tab" + ); +}); diff --git a/gfx/tests/browser/browser_partial_prerender_animation_in_popup.js b/gfx/tests/browser/browser_partial_prerender_animation_in_popup.js new file mode 100644 index 0000000000..2e68b9cdde --- /dev/null +++ b/gfx/tests/browser/browser_partial_prerender_animation_in_popup.js @@ -0,0 +1,90 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/* import-globals-from ../../../dom/animation/test/testcommon.js */ +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/tests/dom/animation/test/testcommon.js", + this +); + +add_task(async () => { + await SpecialPowers.pushPrefEnv({ + set: [ + ["layout.animation.prerender.partial", true], + ["layout.animation.prerender.viewport-ratio-limit", 1.125], + ], + }); + + let navBar = document.getElementById("nav-bar"); + + const anchor = document.createXULElement("toolbarbutton"); + anchor.classList.add("toolbarbutton-1", "chromeclass-toolbar-additional"); + navBar.appendChild(anchor); + + // Prepare a popup panel. + const panel = document.createXULElement("panel"); + panel.setAttribute("noautohide", true); + navBar.appendChild(panel); + + // Add a overflow:scroll container to avoid expanding the popup window size. + const container = document.createElement("div"); + container.style = "width: 100px; height: 100px; overflow: scroll;"; + + // Looks like in popup window wider elements in the overflow:scroll container + // are still affecting the viewport size of the popup content, for example, + // if we specify "witdh: 800px" here, this element is not going to be partial- + // prerendered, it will be fully prerendered, so we use vertically overflowed + // element here. + const target = document.createElement("div"); + target.style = "width: 100px; height: 800px;"; + + container.appendChild(target); + panel.appendChild(container); + + registerCleanupFunction(() => { + panel.remove(); + anchor.remove(); + }); + + panel.openPopup(anchor); + + // Start a transform transition with a 1s delay step-start function so that + // we can ensure that + // 1) when the target element is initially composited on the compositor the + // transition hasn't yet started, thus no jank happens + // 2) when the transition starts on the compositor thread, it causes a jank + // so that it will report back to the main-thread + target.style.transition = "transform 100s step-start 1s"; + getComputedStyle(target); + const startTransition = new Promise(resolve => { + target.addEventListener("transitionstart", resolve); + }); + target.style.transform = "translateY(-130px)"; + const transition = target.getAnimations()[0]; + + // Wait for the transition start. + await startTransition; + + // Make sure it's running on the compositor. + Assert.ok( + transition.isRunningOnCompositor, + "The transition should be running on the compositor thread" + ); + + // Collect restyling markers in 5 frames. + const markers = await observeStylingInTargetWindow(panel.ownerGlobal, 5); + + // On non WebRender we observe two restyling markers because we get the second + // jank report from the compositor thread before a new pre-rendered result, + // which was triggered by the first jank report, reached to the compositor + // thread. So we allow one or two makers here. + // NOTE: Since we wrap the target element in overflow:scroll container, we + // might see an additional restyling marker triggered by + // KeyframeEffect::OverflowRegionRefreshInterval (200ms) on very slow + // platforms (e.g. TSAN builds), if it happens we should allow the additional + // restyling here. + Assert.greaterOrEqual(markers.length, 1); + Assert.lessOrEqual(markers.length, 2); +}); diff --git a/gfx/tests/browser/browser_windowless_troubleshoot_crash.js b/gfx/tests/browser/browser_windowless_troubleshoot_crash.js new file mode 100644 index 0000000000..44fc50e2f8 --- /dev/null +++ b/gfx/tests/browser/browser_windowless_troubleshoot_crash.js @@ -0,0 +1,54 @@ +add_task(async function test_windowlessBrowserTroubleshootCrash() { + let webNav = Services.appShell.createWindowlessBrowser(false); + + let onLoaded = new Promise((resolve, reject) => { + let docShell = webNav.docShell; + let listener = { + observe(contentWindow, topic, data) { + let observedDocShell = + contentWindow.docShell.sameTypeRootTreeItem.QueryInterface( + Ci.nsIDocShell + ); + if (docShell === observedDocShell) { + Services.obs.removeObserver( + listener, + "content-document-global-created" + ); + resolve(); + } + }, + }; + Services.obs.addObserver(listener, "content-document-global-created"); + }); + let loadURIOptions = { + triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({}), + }; + webNav.loadURI(Services.io.newURI("about:blank"), loadURIOptions); + + await onLoaded; + + let winUtils = webNav.document.defaultView.windowUtils; + try { + let layerManager = winUtils.layerManagerType; + ok( + layerManager == "Basic" || layerManager == "WebRender (Software)", + "windowless browser's layerManagerType should be 'Basic' or 'WebRender (Software)'" + ); + } catch (e) { + // The windowless browser may not have a layermanager at all yet, and that's ok. + // The troubleshooting code similarly skips over windows with no layer managers. + } + ok(true, "not crashed"); + + var { Troubleshoot } = ChromeUtils.importESModule( + "resource://gre/modules/Troubleshoot.sys.mjs" + ); + var data = await Troubleshoot.snapshot(); + + ok( + data.graphics.windowLayerManagerType !== "None", + "windowless browser window should not set windowLayerManagerType to 'None'" + ); + + webNav.close(); +}); diff --git a/gfx/tests/browser/file_native_font_cache_macos.html b/gfx/tests/browser/file_native_font_cache_macos.html new file mode 100644 index 0000000000..84692a4ca7 --- /dev/null +++ b/gfx/tests/browser/file_native_font_cache_macos.html @@ -0,0 +1,15 @@ + + + + + + + +🔍🍔🔥 + + -- cgit v1.2.3