From 2aa4a82499d4becd2284cdb482213d541b8804dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 16:29:10 +0200 Subject: Adding upstream version 86.0.1. Signed-off-by: Daniel Baumann --- image/test/browser/animated.gif | Bin 0 -> 71479 bytes image/test/browser/animated2.gif | Bin 0 -> 66647 bytes image/test/browser/big.png | Bin 0 -> 129497 bytes image/test/browser/browser.ini | 18 ++ image/test/browser/browser_bug666317.js | 139 +++++++++++ image/test/browser/browser_docshell_type_editor.js | 134 +++++++++++ .../browser_docshell_type_editor/chrome.manifest | 1 + .../img/privileged.png | Bin 0 -> 90 bytes image/test/browser/browser_image.js | 261 +++++++++++++++++++++ ...ser_offscreen_image_in_out_of_process_iframe.js | 164 +++++++++++++ image/test/browser/empty.html | 2 + image/test/browser/head.js | 26 ++ image/test/browser/image.html | 23 ++ image/test/browser/imageX2.html | 14 ++ 14 files changed, 782 insertions(+) create mode 100644 image/test/browser/animated.gif create mode 100644 image/test/browser/animated2.gif create mode 100644 image/test/browser/big.png create mode 100644 image/test/browser/browser.ini create mode 100644 image/test/browser/browser_bug666317.js create mode 100644 image/test/browser/browser_docshell_type_editor.js create mode 100644 image/test/browser/browser_docshell_type_editor/chrome.manifest create mode 100644 image/test/browser/browser_docshell_type_editor/img/privileged.png create mode 100644 image/test/browser/browser_image.js create mode 100644 image/test/browser/browser_offscreen_image_in_out_of_process_iframe.js create mode 100644 image/test/browser/empty.html create mode 100644 image/test/browser/head.js create mode 100644 image/test/browser/image.html create mode 100644 image/test/browser/imageX2.html (limited to 'image/test/browser') diff --git a/image/test/browser/animated.gif b/image/test/browser/animated.gif new file mode 100644 index 0000000000..eb034e1501 Binary files /dev/null and b/image/test/browser/animated.gif differ diff --git a/image/test/browser/animated2.gif b/image/test/browser/animated2.gif new file mode 100644 index 0000000000..053eaae688 Binary files /dev/null and b/image/test/browser/animated2.gif differ diff --git a/image/test/browser/big.png b/image/test/browser/big.png new file mode 100644 index 0000000000..94e7eb6db2 Binary files /dev/null and b/image/test/browser/big.png differ diff --git a/image/test/browser/browser.ini b/image/test/browser/browser.ini new file mode 100644 index 0000000000..3318120419 --- /dev/null +++ b/image/test/browser/browser.ini @@ -0,0 +1,18 @@ +[DEFAULT] +support-files = + animated.gif + animated2.gif + big.png + head.js + image.html + imageX2.html + browser_docshell_type_editor/** + +[browser_bug666317.js] +skip-if = true || e10s # Bug 1207012 - Permaorange from an uncaught exception that isn't actually turning the suite orange until it hits beta, Bug 948194 - Decoded Images seem to not be discarded on memory-pressure notification with e10s enabled +[browser_image.js] +skip-if = true # Bug 987616 +[browser_docshell_type_editor.js] +[browser_offscreen_image_in_out_of_process_iframe.js] +support-files = + empty.html diff --git a/image/test/browser/browser_bug666317.js b/image/test/browser/browser_bug666317.js new file mode 100644 index 0000000000..ac537c569d --- /dev/null +++ b/image/test/browser/browser_bug666317.js @@ -0,0 +1,139 @@ +waitForExplicitFinish(); +const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); + +var pageSource = + "" + + '' + + ""; + +var oldDiscardingPref, oldTab, newTab; +var prefBranch = Services.prefs.getBranch("image.mem."); + +var gWaitingForDiscard = false; +var gScriptedObserver; +var gClonedRequest; + +function ImageObserver(decodeCallback, discardCallback) { + this.decodeComplete = function onDecodeComplete(aRequest) { + decodeCallback(); + }; + + this.discard = function onDiscard(request) { + if (!gWaitingForDiscard) { + return; + } + + this.synchronous = false; + discardCallback(); + }; + + this.synchronous = true; +} + +function currentRequest() { + let img = gBrowser + .getBrowserForTab(newTab) + .contentWindow.document.getElementById("testImg"); + return img.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST); +} + +function isImgDecoded() { + let request = currentRequest(); + return !!(request.imageStatus & Ci.imgIRequest.STATUS_DECODE_COMPLETE); +} + +// Ensure that the image is decoded by drawing it to a canvas. +function forceDecodeImg() { + let doc = gBrowser.getBrowserForTab(newTab).contentWindow.document; + let img = doc.getElementById("testImg"); + let canvas = doc.createElement("canvas"); + let ctx = canvas.getContext("2d"); + ctx.drawImage(img, 0, 0); +} + +function runAfterAsyncEvents(aCallback) { + function handlePostMessage(aEvent) { + if (aEvent.data == "next") { + window.removeEventListener("message", handlePostMessage); + aCallback(); + } + } + + window.addEventListener("message", handlePostMessage); + + // We'll receive the 'message' event after everything else that's currently in + // the event queue (which is a stronger guarantee than setTimeout, because + // setTimeout events may be coalesced). This lets us ensure that we run + // aCallback *after* any asynchronous events are delivered. + window.postMessage("next", "*"); +} + +function test() { + // Enable the discarding pref. + oldDiscardingPref = prefBranch.getBoolPref("discardable"); + prefBranch.setBoolPref("discardable", true); + + // Create and focus a new tab. + oldTab = gBrowser.selectedTab; + newTab = BrowserTestUtils.addTab(gBrowser, "data:text/html," + pageSource); + gBrowser.selectedTab = newTab; + + // Run step2 after the tab loads. + gBrowser.getBrowserForTab(newTab).addEventListener("pageshow", step2); +} + +function step2() { + // Create the image observer. + var observer = new ImageObserver( + () => runAfterAsyncEvents(step3), // DECODE_COMPLETE + () => runAfterAsyncEvents(step5) + ); // DISCARD + gScriptedObserver = Cc["@mozilla.org/image/tools;1"] + .getService(Ci.imgITools) + .createScriptedObserver(observer); + + // Clone the current imgIRequest with our new observer. + var request = currentRequest(); + gClonedRequest = request.clone(gScriptedObserver); + + // Check that the image is decoded. + forceDecodeImg(); + + // The DECODE_COMPLETE notification is delivered asynchronously. ImageObserver will + // eventually call step3. +} + +function step3() { + ok(isImgDecoded(), "Image should initially be decoded."); + + // Focus the old tab, then fire a memory-pressure notification. This should + // cause the decoded image in the new tab to be discarded. + gBrowser.selectedTab = oldTab; + + // Allow time to process the tab change. + runAfterAsyncEvents(step4); +} + +function step4() { + gWaitingForDiscard = true; + + var os = Services.obs; + os.notifyObservers(null, "memory-pressure", "heap-minimize"); + + // The DISCARD notification is delivered asynchronously. ImageObserver will + // eventually call step5. (Or else, sadly, the test will time out.) +} + +function step5() { + ok(true, "Image should be discarded."); + + // And we're done. + gBrowser.removeTab(newTab); + prefBranch.setBoolPref("discardable", oldDiscardingPref); + + gClonedRequest.cancelAndForgetObserver(0); + + finish(); +} diff --git a/image/test/browser/browser_docshell_type_editor.js b/image/test/browser/browser_docshell_type_editor.js new file mode 100644 index 0000000000..306f4a3fc4 --- /dev/null +++ b/image/test/browser/browser_docshell_type_editor.js @@ -0,0 +1,134 @@ +"use strict"; + +const SIMPLE_HTML = "data:text/html,"; + +/** + * Returns the directory where the chrome.manifest file for the test can be found. + * + * @return nsIFile of the manifest directory + */ +function getManifestDir() { + let path = getTestFilePath("browser_docshell_type_editor"); + let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); + file.initWithPath(path); + return file; +} + +// The following URI is *not* accessible to content, hence loading that URI +// from an unprivileged site should be blocked. If docshell is of appType +// APP_TYPE_EDITOR however the load should be allowed. +// >> chrome://test1/skin/privileged.png + +add_task(async function() { + info("docshell of appType APP_TYPE_EDITOR can access privileged images."); + + // Load a temporary manifest adding a route to a privileged image + let manifestDir = getManifestDir(); + Components.manager.addBootstrappedManifestLocation(manifestDir); + + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: SIMPLE_HTML, + }, + async function(browser) { + await SpecialPowers.spawn(browser, [], async function() { + let rootDocShell = docShell.sameTypeRootTreeItem.QueryInterface( + Ci.nsIDocShell + ); + let defaultAppType = rootDocShell.appType; + + rootDocShell.appType = Ci.nsIDocShell.APP_TYPE_EDITOR; + + is( + rootDocShell.appType, + Ci.nsIDocShell.APP_TYPE_EDITOR, + "sanity check: appType after update should be type editor" + ); + + return new Promise(resolve => { + let doc = content.document; + let image = doc.createElement("img"); + image.onload = function() { + ok(true, "APP_TYPE_EDITOR is allowed to load privileged image"); + // restore appType of rootDocShell before moving on to the next test + rootDocShell.appType = defaultAppType; + resolve(); + }; + image.onerror = function() { + ok(false, "APP_TYPE_EDITOR is allowed to load privileged image"); + // restore appType of rootDocShell before moving on to the next test + rootDocShell.appType = defaultAppType; + resolve(); + }; + doc.body.appendChild(image); + image.src = "chrome://test1/skin/privileged.png"; + }); + }); + } + ); + + Components.manager.removeBootstrappedManifestLocation(manifestDir); +}); + +add_task(async function() { + info( + "docshell of appType APP_TYPE_UNKNOWN can *not* access privileged images." + ); + + // Load a temporary manifest adding a route to a privileged image + let manifestDir = getManifestDir(); + Components.manager.addBootstrappedManifestLocation(manifestDir); + + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: SIMPLE_HTML, + }, + async function(browser) { + await SpecialPowers.spawn(browser, [], async function() { + let rootDocShell = docShell.sameTypeRootTreeItem.QueryInterface( + Ci.nsIDocShell + ); + let defaultAppType = rootDocShell.appType; + + rootDocShell.appType = Ci.nsIDocShell.APP_TYPE_UNKNOWN; + + is( + rootDocShell.appType, + Ci.nsIDocShell.APP_TYPE_UNKNOWN, + "sanity check: appType of docshell should be unknown" + ); + + return new Promise(resolve => { + let doc = content.document; + let image = doc.createElement("img"); + image.onload = function() { + ok( + false, + "APP_TYPE_UNKNOWN is *not* allowed to access privileged image" + ); + // restore appType of rootDocShell before moving on to the next test + rootDocShell.appType = defaultAppType; + resolve(); + }; + image.onerror = function() { + ok( + true, + "APP_TYPE_UNKNOWN is *not* allowed to access privileged image" + ); + // restore appType of rootDocShell before moving on to the next test + rootDocShell.appType = defaultAppType; + resolve(); + }; + doc.body.appendChild(image); + // Set the src via wrappedJSObject so the load is triggered with + // the content page's principal rather than ours. + image.wrappedJSObject.src = "chrome://test1/skin/privileged.png"; + }); + }); + } + ); + + Components.manager.removeBootstrappedManifestLocation(manifestDir); +}); diff --git a/image/test/browser/browser_docshell_type_editor/chrome.manifest b/image/test/browser/browser_docshell_type_editor/chrome.manifest new file mode 100644 index 0000000000..85510a8af9 --- /dev/null +++ b/image/test/browser/browser_docshell_type_editor/chrome.manifest @@ -0,0 +1 @@ +skin test1 test img/ \ No newline at end of file diff --git a/image/test/browser/browser_docshell_type_editor/img/privileged.png b/image/test/browser/browser_docshell_type_editor/img/privileged.png new file mode 100644 index 0000000000..2bf7b7e828 Binary files /dev/null and b/image/test/browser/browser_docshell_type_editor/img/privileged.png differ diff --git a/image/test/browser/browser_image.js b/image/test/browser/browser_image.js new file mode 100644 index 0000000000..afbdb91138 --- /dev/null +++ b/image/test/browser/browser_image.js @@ -0,0 +1,261 @@ +waitForExplicitFinish(); +requestLongerTimeout(2); // see bug 660123 -- this test is slow on Mac. + +// A hold on the current timer, so it doesn't get GCed out from +// under us +var gTimer; + +// Browsing to a new URL - pushing us into the bfcache - should cause +// animations to stop, and resume when we return +/* global yield */ +function testBFCache() { + function theTest() { + var abort = false; + var chances, gImage, gFrames; + gBrowser.selectedTab = BrowserTestUtils.addTab( + gBrowser, + TESTROOT + "image.html" + ); + gBrowser.selectedBrowser.addEventListener( + "pageshow", + function() { + var window = gBrowser.contentWindow; + // If false, we are in an optimized build, and we abort this and + // all further tests + if ( + !actOnMozImage(window.document, "img1", function(image) { + gImage = image; + gFrames = gImage.framesNotified; + }) + ) { + gBrowser.removeCurrentTab(); + abort = true; + } + goer.next(); + }, + { capture: true, once: true } + ); + yield; + if (abort) { + finish(); + yield; // optimized build + } + + // Let animation run for a bit + chances = 120; + do { + gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + gTimer.initWithCallback( + function() { + if (gImage.framesNotified >= 20) { + goer.send(true); + } else { + chances--; + goer.send(chances == 0); // maybe if we wait a bit, it will happen + } + }, + 500, + Ci.nsITimer.TYPE_ONE_SHOT + ); + } while (!yield); + is(chances > 0, true, "Must have animated a few frames so far"); + + // Browse elsewhere; push our animating page into the bfcache + gBrowser.loadURI("about:blank"); + + // Wait a bit for page to fully load, then wait a while and + // see that no animation occurs. + gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + gTimer.initWithCallback( + function() { + gFrames = gImage.framesNotified; + gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + gTimer.initWithCallback( + function() { + // Might have a few stray frames, until other page totally loads + var additionalFrames = gImage.framesNotified - gFrames; + is( + additionalFrames == 0, + true, + "Must have not animated in bfcache! Got " + + additionalFrames + + " additional frames" + ); + goer.next(); + }, + 4000, + Ci.nsITimer.TYPE_ONE_SHOT + ); // 4 seconds - expect 40 frames + }, + 0, + Ci.nsITimer.TYPE_ONE_SHOT + ); // delay of 0 - wait for next event loop + yield; + + // Go back + gBrowser.goBack(); + + chances = 120; + do { + gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + gTimer.initWithCallback( + function() { + if (gImage.framesNotified - gFrames >= 20) { + goer.send(true); + } else { + chances--; + goer.send(chances == 0); // maybe if we wait a bit, it will happen + } + }, + 500, + Ci.nsITimer.TYPE_ONE_SHOT + ); + } while (!yield); + is(chances > 0, true, "Must have animated once out of bfcache!"); + + // Finally, check that the css background image has essentially the same + // # of frames, implying that it animated at the same times as the regular + // image. We can easily retrieve regular images through their HTML image + // elements, which is what we did before. For the background image, we + // create a regular image now, and read the current frame count. + var doc = gBrowser.selectedBrowser.contentWindow.document; + var div = doc.getElementById("background_div"); + div.innerHTML += ''; + actOnMozImage(doc, "img3", function(image) { + is( + Math.abs(image.framesNotified - gImage.framesNotified) / + gImage.framesNotified < + 0.5, + true, + "Must have also animated the background image, and essentially the same # of frames. " + + "Regular image got " + + gImage.framesNotified + + " frames but background image got " + + image.framesNotified + ); + }); + + gBrowser.removeCurrentTab(); + + nextTest(); + } + + var goer = theTest(); + goer.next(); +} + +// Check that imgContainers are shared on the same page and +// between tabs +function testSharedContainers() { + function theTest() { + var gImages = []; + var gFrames; + + gBrowser.selectedTab = BrowserTestUtils.addTab( + gBrowser, + TESTROOT + "image.html" + ); + gBrowser.selectedBrowser.addEventListener( + "pageshow", + function() { + actOnMozImage(gBrowser.contentDocument, "img1", function(image) { + gImages[0] = image; + gFrames = image.framesNotified; // May in theory have frames from last test + // in this counter - so subtract them out + }); + goer.next(); + }, + { capture: true, once: true } + ); + yield; + + // Load next tab somewhat later + gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + gTimer.initWithCallback( + function() { + goer.next(); + }, + 1500, + Ci.nsITimer.TYPE_ONE_SHOT + ); + yield; + + gBrowser.selectedTab = BrowserTestUtils.addTab( + gBrowser, + TESTROOT + "imageX2.html" + ); + gBrowser.selectedBrowser.addEventListener( + "pageshow", + function() { + [1, 2].forEach(function(i) { + actOnMozImage(gBrowser.contentDocument, "img" + i, function(image) { + gImages[i] = image; + }); + }); + goer.next(); + }, + { capture: true, once: true } + ); + yield; + + var chances = 120; + do { + gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + gTimer.initWithCallback( + function() { + if (gImages[0].framesNotified - gFrames >= 10) { + goer.send(true); + } else { + chances--; + goer.send(chances == 0); // maybe if we wait a bit, it will happen + } + }, + 500, + Ci.nsITimer.TYPE_ONE_SHOT + ); + } while (!yield); + is( + chances > 0, + true, + "Must have been animating while showing several images" + ); + + // Check they all have the same frame counts + var theFrames = null; + [0, 1, 2].forEach(function(i) { + var frames = gImages[i].framesNotified; + if (theFrames == null) { + theFrames = frames; + } else { + is( + theFrames, + frames, + "Sharing the same imgContainer means *exactly* the same frame counts!" + ); + } + }); + + gBrowser.removeCurrentTab(); + gBrowser.removeCurrentTab(); + + nextTest(); + } + + var goer = theTest(); + goer.next(); +} + +var tests = [testBFCache, testSharedContainers]; + +function nextTest() { + if (tests.length == 0) { + finish(); + return; + } + tests.shift()(); +} + +function test() { + ignoreAllUncaughtExceptions(); + nextTest(); +} diff --git a/image/test/browser/browser_offscreen_image_in_out_of_process_iframe.js b/image/test/browser/browser_offscreen_image_in_out_of_process_iframe.js new file mode 100644 index 0000000000..d55edd1d4e --- /dev/null +++ b/image/test/browser/browser_offscreen_image_in_out_of_process_iframe.js @@ -0,0 +1,164 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const DIRPATH = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content/", + "" +); +const parentPATH = DIRPATH + "empty.html"; +const iframePATH = DIRPATH + "empty.html"; + +const parentURL = `http://example.com/${parentPATH}`; +const iframeURL = `http://example.org/${iframePATH}`; + +add_task(async function setup_pref() { + await SpecialPowers.pushPrefEnv({ + set: [ + // To avoid throttling requestAnimationFrame callbacks in invisible + // iframes + ["layout.throttled_frame_rate", 60], + ], + }); +}); + +add_task(async function() { + const win = await BrowserTestUtils.openNewBrowserWindow({ + fission: true, + }); + + try { + const browser = win.gBrowser.selectedTab.linkedBrowser; + + BrowserTestUtils.loadURI(browser, parentURL); + await BrowserTestUtils.browserLoaded(browser, false, parentURL); + + async function setup(url) { + const scroller = content.document.createElement("div"); + scroller.style = "width: 300px; height: 300px; overflow: scroll;"; + scroller.setAttribute("id", "scroller"); + content.document.body.appendChild(scroller); + + // Make a space bigger than display port. + const spacer = content.document.createElement("div"); + spacer.style = "width: 100%; height: 10000px;"; + scroller.appendChild(spacer); + + const iframe = content.document.createElement("iframe"); + scroller.appendChild(iframe); + + iframe.contentWindow.location = url; + await new Promise(resolve => { + iframe.addEventListener("load", resolve, { once: true }); + }); + + return iframe.browsingContext; + } + + async function setupImage() { + const img = content.document.createElement("img"); + // This GIF is a 100ms interval animation. + img.setAttribute("src", "animated.gif"); + img.setAttribute("id", "img"); + content.document.body.appendChild(img); + + const spacer = content.document.createElement("div"); + spacer.style = "width: 100%; height: 10000px;"; + content.document.body.appendChild(spacer); + await new Promise(resolve => { + img.addEventListener("load", resolve, { once: true }); + }); + } + + // Returns the count of frameUpdate during |time| (in ms) period. + async function observeFrameUpdate(time) { + function ImageDecoderObserverStub() { + this.sizeAvailable = function sizeAvailable(aRequest) {}; + this.frameComplete = function frameComplete(aRequest) {}; + this.decodeComplete = function decodeComplete(aRequest) {}; + this.loadComplete = function loadComplete(aRequest) {}; + this.frameUpdate = function frameUpdate(aRequest) {}; + this.discard = function discard(aRequest) {}; + this.isAnimated = function isAnimated(aRequest) {}; + this.hasTransparency = function hasTransparency(aRequest) {}; + } + + // Start from the callback of setTimeout. + await new Promise(resolve => content.window.setTimeout(resolve, 0)); + + let frameCount = 0; + const observer = new ImageDecoderObserverStub(); + observer.frameUpdate = () => { + frameCount++; + }; + observer.loadComplete = () => { + // Ignore the frameUpdate callback along with loadComplete. It seems + // a frameUpdate sometimes happens with a loadComplete when attatching + // observer in fission world. + frameCount--; + }; + + const gObserver = SpecialPowers.Cc["@mozilla.org/image/tools;1"] + .getService(SpecialPowers.Ci.imgITools) + .createScriptedObserver(observer); + const img = content.document.getElementById("img"); + + SpecialPowers.wrap(img).addObserver(gObserver); + await new Promise(resolve => content.window.setTimeout(resolve, time)); + SpecialPowers.wrap(img).removeObserver(gObserver); + + return frameCount; + } + + // Setup an iframe which is initially scrolled out. + const iframe = await SpecialPowers.spawn(browser, [iframeURL], setup); + + // Setup a 100ms interval animated GIF image in the iframe. + await SpecialPowers.spawn(iframe, [], setupImage); + + let frameCount = await SpecialPowers.spawn( + iframe, + [1000], + observeFrameUpdate + ); + // Bug 1577084. + if (frameCount == 0) { + is(frameCount, 0, "no frameupdates"); + } else { + todo_is(frameCount, 0, "no frameupdates"); + } + + // Scroll the iframe into view. + await SpecialPowers.spawn(browser, [], async () => { + const scroller = content.document.getElementById("scroller"); + scroller.scrollTo({ left: 0, top: 9800, behavior: "smooth" }); + await new Promise(resolve => content.window.setTimeout(resolve, 1000)); + }); + + await new Promise(resolve => requestAnimationFrame(resolve)); + + frameCount = await SpecialPowers.spawn(iframe, [1000], observeFrameUpdate); + ok(frameCount > 0, "There should be frameUpdate(s)"); + + await new Promise(resolve => requestAnimationFrame(resolve)); + + await SpecialPowers.spawn(iframe, [], async () => { + const img = content.document.getElementById("img"); + // Move the image outside of the scroll port. 'position: absolute' causes + // a relow on the image element. + img.style = "position: absolute; top: 9000px;"; + await new Promise(resolve => + content.window.requestAnimationFrame(resolve) + ); + }); + + await new Promise(resolve => requestAnimationFrame(resolve)); + + frameCount = await SpecialPowers.spawn(iframe, [1000], observeFrameUpdate); + is(frameCount, 0, "No frameUpdate should happen"); + } finally { + await BrowserTestUtils.closeWindow(win); + } +}); diff --git a/image/test/browser/empty.html b/image/test/browser/empty.html new file mode 100644 index 0000000000..a31dad3630 --- /dev/null +++ b/image/test/browser/empty.html @@ -0,0 +1,2 @@ + + diff --git a/image/test/browser/head.js b/image/test/browser/head.js new file mode 100644 index 0000000000..020c8bd35f --- /dev/null +++ b/image/test/browser/head.js @@ -0,0 +1,26 @@ +const RELATIVE_DIR = "image/test/browser/"; +const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR; +const TESTROOT2 = "http://example.org/browser/" + RELATIVE_DIR; + +var chrome_root = getRootDirectory(gTestPath); +const CHROMEROOT = chrome_root; + +function getImageLoading(doc, id) { + return doc.getElementById(id); +} + +// Tries to get the Moz debug image, imgIContainerDebug. Only works +// in a debug build. If we succeed, we call func(). +function actOnMozImage(doc, id, func) { + var imgContainer = getImageLoading(doc, id).getRequest( + Ci.nsIImageLoadingContent.CURRENT_REQUEST + ).image; + var mozImage; + try { + mozImage = imgContainer.QueryInterface(Ci.imgIContainerDebug); + } catch (e) { + return false; + } + func(mozImage); + return true; +} diff --git a/image/test/browser/image.html b/image/test/browser/image.html new file mode 100644 index 0000000000..3831ab68a4 --- /dev/null +++ b/image/test/browser/image.html @@ -0,0 +1,23 @@ + + + + + Imagelib2 animation tests + + + + +

Page with image

+ +
+ + diff --git a/image/test/browser/imageX2.html b/image/test/browser/imageX2.html new file mode 100644 index 0000000000..4ce953bfac --- /dev/null +++ b/image/test/browser/imageX2.html @@ -0,0 +1,14 @@ + + + + + Imagelib2 animation tests + + +

Page with images

+ +
+ + + -- cgit v1.2.3