diff options
Diffstat (limited to 'image/test/browser/browser_bug666317.js')
-rw-r--r-- | image/test/browser/browser_bug666317.js | 138 |
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(); +} |