summaryrefslogtreecommitdiffstats
path: root/image/test/browser/browser_bug666317.js
diff options
context:
space:
mode:
Diffstat (limited to 'image/test/browser/browser_bug666317.js')
-rw-r--r--image/test/browser/browser_bug666317.js138
1 files changed, 138 insertions, 0 deletions
diff --git a/image/test/browser/browser_bug666317.js b/image/test/browser/browser_bug666317.js
new file mode 100644
index 0000000000..7f58c61c56
--- /dev/null
+++ b/image/test/browser/browser_bug666317.js
@@ -0,0 +1,138 @@
+waitForExplicitFinish();
+
+var pageSource =
+ "<html><body>" +
+ '<img id="testImg" src="' +
+ TESTROOT +
+ 'big.png">' +
+ "</body></html>";
+
+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();
+}