summaryrefslogtreecommitdiffstats
path: root/image/test/browser
diff options
context:
space:
mode:
Diffstat (limited to 'image/test/browser')
-rw-r--r--image/test/browser/animated.gifbin0 -> 71479 bytes
-rw-r--r--image/test/browser/animated2.gifbin0 -> 66647 bytes
-rw-r--r--image/test/browser/big.pngbin0 -> 129497 bytes
-rw-r--r--image/test/browser/browser.ini14
-rw-r--r--image/test/browser/browser_bug666317.js140
-rw-r--r--image/test/browser/browser_docshell_type_editor.js92
-rw-r--r--image/test/browser/browser_image.js195
-rw-r--r--image/test/browser/head.js26
-rw-r--r--image/test/browser/image.html24
-rw-r--r--image/test/browser/imageX2.html15
10 files changed, 506 insertions, 0 deletions
diff --git a/image/test/browser/animated.gif b/image/test/browser/animated.gif
new file mode 100644
index 000000000..eb034e150
--- /dev/null
+++ b/image/test/browser/animated.gif
Binary files differ
diff --git a/image/test/browser/animated2.gif b/image/test/browser/animated2.gif
new file mode 100644
index 000000000..053eaae68
--- /dev/null
+++ b/image/test/browser/animated2.gif
Binary files differ
diff --git a/image/test/browser/big.png b/image/test/browser/big.png
new file mode 100644
index 000000000..94e7eb6db
--- /dev/null
+++ b/image/test/browser/big.png
Binary files differ
diff --git a/image/test/browser/browser.ini b/image/test/browser/browser.ini
new file mode 100644
index 000000000..d5e94e575
--- /dev/null
+++ b/image/test/browser/browser.ini
@@ -0,0 +1,14 @@
+[DEFAULT]
+support-files =
+ animated.gif
+ animated2.gif
+ big.png
+ head.js
+ image.html
+ imageX2.html
+
+[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]
diff --git a/image/test/browser/browser_bug666317.js b/image/test/browser/browser_bug666317.js
new file mode 100644
index 000000000..2bd2d0615
--- /dev/null
+++ b/image/test/browser/browser_bug666317.js
@@ -0,0 +1,140 @@
+waitForExplicitFinish();
+
+var pageSource =
+ '<html><body>' +
+ '<img id="testImg" src="' + TESTROOT + 'big.png">' +
+ '</body></html>';
+
+var oldDiscardingPref, oldTab, newTab;
+var prefBranch = Cc["@mozilla.org/preferences-service;1"]
+ .getService(Ci.nsIPrefService)
+ .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');
+ img.QueryInterface(Ci.nsIImageLoadingContent);
+ return img.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
+}
+
+function isImgDecoded() {
+ let request = currentRequest();
+ return request.imageStatus & Ci.imgIRequest.STATUS_DECODE_COMPLETE ? true : false;
+}
+
+// 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, false);
+ aCallback();
+ }
+ }
+
+ window.addEventListener('message', handlePostMessage, false);
+
+ // 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 = gBrowser.addTab('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 = Cc["@mozilla.org/observer-service;1"]
+ .getService(Ci.nsIObserverService);
+ 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 000000000..8ac98924f
--- /dev/null
+++ b/image/test/browser/browser_docshell_type_editor.js
@@ -0,0 +1,92 @@
+
+"use strict";
+
+const Ci = Components.interfaces;
+const SIMPLE_HTML = "data:text/html,<html><head></head><body></body></html>";
+
+// 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://devtools/content/framework/dev-edition-promo/dev-edition-logo.png
+
+add_task(function* () {
+ info("docshell of appType APP_TYPE_EDITOR can access privileged images.");
+
+ yield BrowserTestUtils.withNewTab({
+ gBrowser,
+ url: SIMPLE_HTML
+ }, function* (browser) {
+ yield ContentTask.spawn(browser, null, function* () {
+ let rootDocShell = docShell.QueryInterface(Ci.nsIDocShellTreeItem)
+ .rootTreeItem
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(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://devtools/content/framework/dev-edition-promo/dev-edition-logo.png";
+ });
+ });
+ });
+});
+
+add_task(function* () {
+ info("docshell of appType APP_TYPE_UNKNOWN can *not* access privileged images.");
+
+ yield BrowserTestUtils.withNewTab({
+ gBrowser,
+ url: SIMPLE_HTML
+ }, function* (browser) {
+ yield ContentTask.spawn(browser, null, function* () {
+ let rootDocShell = docShell.QueryInterface(Ci.nsIDocShellTreeItem)
+ .rootTreeItem
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(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 acces 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 acces privileged image");
+ // restore appType of rootDocShell before moving on to the next test
+ rootDocShell.appType = defaultAppType;
+ resolve();
+ }
+ doc.body.appendChild(image);
+ image.src = "chrome://devtools/content/framework/dev-edition-promo/dev-edition-logo.png";
+ });
+ });
+ });
+});
diff --git a/image/test/browser/browser_image.js b/image/test/browser/browser_image.js
new file mode 100644
index 000000000..9527726c3
--- /dev/null
+++ b/image/test/browser/browser_image.js
@@ -0,0 +1,195 @@
+waitForExplicitFinish();
+requestLongerTimeout(2); // see bug 660123 -- this test is slow on Mac.
+
+// A hold on the current timer, so it doens'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
+function testBFCache() {
+ function theTest() {
+ var abort = false;
+ var chances, gImage, gFrames;
+ gBrowser.selectedTab = gBrowser.addTab(TESTROOT + "image.html");
+ gBrowser.selectedBrowser.addEventListener("pageshow", function () {
+ gBrowser.selectedBrowser.removeEventListener("pageshow", arguments.callee, true);
+ 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();
+ }, 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 += '<img src="animated2.gif" id="img3">';
+ 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 = gBrowser.addTab(TESTROOT + "image.html");
+ gBrowser.selectedBrowser.addEventListener("pageshow", function () {
+ gBrowser.selectedBrowser.removeEventListener("pageshow", arguments.callee, true);
+ 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();
+ }, 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 = gBrowser.addTab(TESTROOT + "imageX2.html");
+ gBrowser.selectedBrowser.addEventListener("pageshow", function () {
+ gBrowser.selectedBrowser.removeEventListener("pageshow", arguments.callee, true);
+ [1,2].forEach(function(i) {
+ actOnMozImage(gBrowser.contentDocument, "img"+i, function(image) {
+ gImages[i] = image;
+ });
+ });
+ goer.next();
+ }, 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/head.js b/image/test/browser/head.js
new file mode 100644
index 000000000..91a5f5793
--- /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) {
+ var htmlImg = doc.getElementById(id);
+ return htmlImg.QueryInterface(Ci.nsIImageLoadingContent);
+}
+
+// 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 000000000..298bf1bdc
--- /dev/null
+++ b/image/test/browser/image.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+ <head>
+ <title>Imagelib2 animation tests</title>
+ <style type="text/css">
+ #background_div {
+ border: 1px black solid;
+ height: 200px;
+ width: 200px;
+ margin: 10px;
+ background: url(animated2.gif) center center no-repeat;
+ }
+ </style>
+ </head>
+ </head>
+<body>
+ <p>Page with image</p>
+ <img src="animated.gif" id="img1">
+ <div id="background_div"></div>
+</body>
+</html>
+
diff --git a/image/test/browser/imageX2.html b/image/test/browser/imageX2.html
new file mode 100644
index 000000000..bdacd0888
--- /dev/null
+++ b/image/test/browser/imageX2.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+ <head>
+ <title>Imagelib2 animation tests</title>
+ </head>
+<body>
+ <p>Page with images</p>
+ <img src="animated.gif" id="img1">
+ <br>
+ <img src="animated.gif" id="img2">
+</body>
+</html>
+