зеркало из https://github.com/mozilla/gecko-dev.git
141 строка
4.1 KiB
JavaScript
141 строка
4.1 KiB
JavaScript
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);
|
|
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 = 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();
|
|
}
|