зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1561435 - Format image/, a=automatic-formatting
# ignore-this-changeset Differential Revision: https://phabricator.services.mozilla.com/D35906 --HG-- extra : source : a224e9d645e49dd7a343f88bd95c0da61aff0f6a
This commit is contained in:
Родитель
054a393a76
Коммит
06e7696b74
|
@ -45,7 +45,6 @@ module.exports = {
|
||||||
"overrides": [{
|
"overrides": [{
|
||||||
"files": [
|
"files": [
|
||||||
"devtools/**",
|
"devtools/**",
|
||||||
"image/**",
|
|
||||||
"intl/**",
|
"intl/**",
|
||||||
"ipc/**",
|
"ipc/**",
|
||||||
"js/**",
|
"js/**",
|
||||||
|
|
|
@ -40,7 +40,6 @@ toolkit/components/telemetry/datareporting-prefs.js
|
||||||
toolkit/components/telemetry/healthreport-prefs.js
|
toolkit/components/telemetry/healthreport-prefs.js
|
||||||
|
|
||||||
# Ignore all top-level directories for now.
|
# Ignore all top-level directories for now.
|
||||||
image/**
|
|
||||||
intl/**
|
intl/**
|
||||||
ipc/**
|
ipc/**
|
||||||
js/**
|
js/**
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
waitForExplicitFinish();
|
waitForExplicitFinish();
|
||||||
|
|
||||||
var pageSource =
|
var pageSource =
|
||||||
'<html><body>' +
|
"<html><body>" +
|
||||||
'<img id="testImg" src="' + TESTROOT + 'big.png">' +
|
'<img id="testImg" src="' +
|
||||||
'</body></html>';
|
TESTROOT +
|
||||||
|
'big.png">' +
|
||||||
|
"</body></html>";
|
||||||
|
|
||||||
var oldDiscardingPref, oldTab, newTab;
|
var oldDiscardingPref, oldTab, newTab;
|
||||||
var prefBranch = Cc["@mozilla.org/preferences-service;1"]
|
var prefBranch = Cc["@mozilla.org/preferences-service;1"]
|
||||||
.getService(Ci.nsIPrefService)
|
.getService(Ci.nsIPrefService)
|
||||||
.getBranch('image.mem.');
|
.getBranch("image.mem.");
|
||||||
|
|
||||||
var gWaitingForDiscard = false;
|
var gWaitingForDiscard = false;
|
||||||
var gScriptedObserver;
|
var gScriptedObserver;
|
||||||
|
@ -17,81 +19,83 @@ var gClonedRequest;
|
||||||
function ImageObserver(decodeCallback, discardCallback) {
|
function ImageObserver(decodeCallback, discardCallback) {
|
||||||
this.decodeComplete = function onDecodeComplete(aRequest) {
|
this.decodeComplete = function onDecodeComplete(aRequest) {
|
||||||
decodeCallback();
|
decodeCallback();
|
||||||
}
|
};
|
||||||
|
|
||||||
this.discard = function onDiscard(request)
|
this.discard = function onDiscard(request) {
|
||||||
{
|
|
||||||
if (!gWaitingForDiscard) {
|
if (!gWaitingForDiscard) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.synchronous = false;
|
this.synchronous = false;
|
||||||
discardCallback();
|
discardCallback();
|
||||||
}
|
};
|
||||||
|
|
||||||
this.synchronous = true;
|
this.synchronous = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function currentRequest() {
|
function currentRequest() {
|
||||||
let img = gBrowser.getBrowserForTab(newTab).contentWindow
|
let img = gBrowser
|
||||||
.document.getElementById('testImg');
|
.getBrowserForTab(newTab)
|
||||||
|
.contentWindow.document.getElementById("testImg");
|
||||||
return img.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
|
return img.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isImgDecoded() {
|
function isImgDecoded() {
|
||||||
let request = currentRequest();
|
let request = currentRequest();
|
||||||
return request.imageStatus & Ci.imgIRequest.STATUS_DECODE_COMPLETE ? true : false;
|
return request.imageStatus & Ci.imgIRequest.STATUS_DECODE_COMPLETE
|
||||||
|
? true
|
||||||
|
: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the image is decoded by drawing it to a canvas.
|
// Ensure that the image is decoded by drawing it to a canvas.
|
||||||
function forceDecodeImg() {
|
function forceDecodeImg() {
|
||||||
let doc = gBrowser.getBrowserForTab(newTab).contentWindow.document;
|
let doc = gBrowser.getBrowserForTab(newTab).contentWindow.document;
|
||||||
let img = doc.getElementById('testImg');
|
let img = doc.getElementById("testImg");
|
||||||
let canvas = doc.createElement('canvas');
|
let canvas = doc.createElement("canvas");
|
||||||
let ctx = canvas.getContext('2d');
|
let ctx = canvas.getContext("2d");
|
||||||
ctx.drawImage(img, 0, 0);
|
ctx.drawImage(img, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function runAfterAsyncEvents(aCallback) {
|
function runAfterAsyncEvents(aCallback) {
|
||||||
function handlePostMessage(aEvent) {
|
function handlePostMessage(aEvent) {
|
||||||
if (aEvent.data == 'next') {
|
if (aEvent.data == "next") {
|
||||||
window.removeEventListener('message', handlePostMessage);
|
window.removeEventListener("message", handlePostMessage);
|
||||||
aCallback();
|
aCallback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('message', handlePostMessage);
|
window.addEventListener("message", handlePostMessage);
|
||||||
|
|
||||||
// We'll receive the 'message' event after everything else that's currently in
|
// We'll receive the 'message' event after everything else that's currently in
|
||||||
// the event queue (which is a stronger guarantee than setTimeout, because
|
// the event queue (which is a stronger guarantee than setTimeout, because
|
||||||
// setTimeout events may be coalesced). This lets us ensure that we run
|
// setTimeout events may be coalesced). This lets us ensure that we run
|
||||||
// aCallback *after* any asynchronous events are delivered.
|
// aCallback *after* any asynchronous events are delivered.
|
||||||
window.postMessage('next', '*');
|
window.postMessage("next", "*");
|
||||||
}
|
}
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
// Enable the discarding pref.
|
// Enable the discarding pref.
|
||||||
oldDiscardingPref = prefBranch.getBoolPref('discardable');
|
oldDiscardingPref = prefBranch.getBoolPref("discardable");
|
||||||
prefBranch.setBoolPref('discardable', true);
|
prefBranch.setBoolPref("discardable", true);
|
||||||
|
|
||||||
// Create and focus a new tab.
|
// Create and focus a new tab.
|
||||||
oldTab = gBrowser.selectedTab;
|
oldTab = gBrowser.selectedTab;
|
||||||
newTab = BrowserTestUtils.addTab(gBrowser, 'data:text/html,' + pageSource);
|
newTab = BrowserTestUtils.addTab(gBrowser, "data:text/html," + pageSource);
|
||||||
gBrowser.selectedTab = newTab;
|
gBrowser.selectedTab = newTab;
|
||||||
|
|
||||||
// Run step2 after the tab loads.
|
// Run step2 after the tab loads.
|
||||||
gBrowser.getBrowserForTab(newTab)
|
gBrowser.getBrowserForTab(newTab).addEventListener("pageshow", step2);
|
||||||
.addEventListener("pageshow", step2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function step2() {
|
function step2() {
|
||||||
// Create the image observer.
|
// Create the image observer.
|
||||||
var observer =
|
var observer = new ImageObserver(
|
||||||
new ImageObserver(() => runAfterAsyncEvents(step3), // DECODE_COMPLETE
|
() => runAfterAsyncEvents(step3), // DECODE_COMPLETE
|
||||||
() => runAfterAsyncEvents(step5)); // DISCARD
|
() => runAfterAsyncEvents(step5)
|
||||||
|
); // DISCARD
|
||||||
gScriptedObserver = Cc["@mozilla.org/image/tools;1"]
|
gScriptedObserver = Cc["@mozilla.org/image/tools;1"]
|
||||||
.getService(Ci.imgITools)
|
.getService(Ci.imgITools)
|
||||||
.createScriptedObserver(observer);
|
.createScriptedObserver(observer);
|
||||||
|
|
||||||
// Clone the current imgIRequest with our new observer.
|
// Clone the current imgIRequest with our new observer.
|
||||||
var request = currentRequest();
|
var request = currentRequest();
|
||||||
|
@ -105,7 +109,7 @@ function step2() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function step3() {
|
function step3() {
|
||||||
ok(isImgDecoded(), 'Image should initially be decoded.');
|
ok(isImgDecoded(), "Image should initially be decoded.");
|
||||||
|
|
||||||
// Focus the old tab, then fire a memory-pressure notification. This should
|
// Focus the old tab, then fire a memory-pressure notification. This should
|
||||||
// cause the decoded image in the new tab to be discarded.
|
// cause the decoded image in the new tab to be discarded.
|
||||||
|
@ -118,20 +122,21 @@ function step3() {
|
||||||
function step4() {
|
function step4() {
|
||||||
gWaitingForDiscard = true;
|
gWaitingForDiscard = true;
|
||||||
|
|
||||||
var os = Cc["@mozilla.org/observer-service;1"]
|
var os = Cc["@mozilla.org/observer-service;1"].getService(
|
||||||
.getService(Ci.nsIObserverService);
|
Ci.nsIObserverService
|
||||||
os.notifyObservers(null, 'memory-pressure', 'heap-minimize');
|
);
|
||||||
|
os.notifyObservers(null, "memory-pressure", "heap-minimize");
|
||||||
|
|
||||||
// The DISCARD notification is delivered asynchronously. ImageObserver will
|
// The DISCARD notification is delivered asynchronously. ImageObserver will
|
||||||
// eventually call step5. (Or else, sadly, the test will time out.)
|
// eventually call step5. (Or else, sadly, the test will time out.)
|
||||||
}
|
}
|
||||||
|
|
||||||
function step5() {
|
function step5() {
|
||||||
ok(true, 'Image should be discarded.');
|
ok(true, "Image should be discarded.");
|
||||||
|
|
||||||
// And we're done.
|
// And we're done.
|
||||||
gBrowser.removeTab(newTab);
|
gBrowser.removeTab(newTab);
|
||||||
prefBranch.setBoolPref('discardable', oldDiscardingPref);
|
prefBranch.setBoolPref("discardable", oldDiscardingPref);
|
||||||
|
|
||||||
gClonedRequest.cancelAndForgetObserver(0);
|
gClonedRequest.cancelAndForgetObserver(0);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const SIMPLE_HTML = "data:text/html,<html><head></head><body></body></html>";
|
const SIMPLE_HTML = "data:text/html,<html><head></head><body></body></html>";
|
||||||
|
@ -10,8 +9,7 @@ const SIMPLE_HTML = "data:text/html,<html><head></head><body></body></html>";
|
||||||
*/
|
*/
|
||||||
function getManifestDir() {
|
function getManifestDir() {
|
||||||
let path = getTestFilePath("browser_docshell_type_editor");
|
let path = getTestFilePath("browser_docshell_type_editor");
|
||||||
let file = Cc["@mozilla.org/file/local;1"]
|
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
||||||
.createInstance(Ci.nsIFile);
|
|
||||||
file.initWithPath(path);
|
file.initWithPath(path);
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
@ -28,92 +26,111 @@ add_task(async function() {
|
||||||
let manifestDir = getManifestDir();
|
let manifestDir = getManifestDir();
|
||||||
Components.manager.addBootstrappedManifestLocation(manifestDir);
|
Components.manager.addBootstrappedManifestLocation(manifestDir);
|
||||||
|
|
||||||
await BrowserTestUtils.withNewTab({
|
await BrowserTestUtils.withNewTab(
|
||||||
gBrowser,
|
{
|
||||||
url: SIMPLE_HTML
|
gBrowser,
|
||||||
}, async function(browser) {
|
url: SIMPLE_HTML,
|
||||||
await ContentTask.spawn(browser, null, async function() {
|
},
|
||||||
let rootDocShell = docShell.QueryInterface(Ci.nsIDocShellTreeItem)
|
async function(browser) {
|
||||||
.rootTreeItem
|
await ContentTask.spawn(browser, null, async function() {
|
||||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
let rootDocShell = docShell
|
||||||
.getInterface(Ci.nsIDocShell);
|
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||||
let defaultAppType = rootDocShell.appType;
|
.rootTreeItem.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIDocShell);
|
||||||
|
let defaultAppType = rootDocShell.appType;
|
||||||
|
|
||||||
rootDocShell.appType = Ci.nsIDocShell.APP_TYPE_EDITOR;
|
rootDocShell.appType = Ci.nsIDocShell.APP_TYPE_EDITOR;
|
||||||
|
|
||||||
is(rootDocShell.appType, Ci.nsIDocShell.APP_TYPE_EDITOR,
|
is(
|
||||||
"sanity check: appType after update should be type editor");
|
rootDocShell.appType,
|
||||||
|
Ci.nsIDocShell.APP_TYPE_EDITOR,
|
||||||
|
"sanity check: appType after update should be type editor"
|
||||||
|
);
|
||||||
|
|
||||||
|
return new Promise(resolve => {
|
||||||
return new Promise(resolve => {
|
let doc = content.document;
|
||||||
let doc = content.document;
|
let image = doc.createElement("img");
|
||||||
let image = doc.createElement("img");
|
image.onload = function() {
|
||||||
image.onload = function() {
|
ok(true, "APP_TYPE_EDITOR is allowed to load privileged image");
|
||||||
ok(true, "APP_TYPE_EDITOR is allowed to load privileged image");
|
// restore appType of rootDocShell before moving on to the next test
|
||||||
// restore appType of rootDocShell before moving on to the next test
|
rootDocShell.appType = defaultAppType;
|
||||||
rootDocShell.appType = defaultAppType;
|
resolve();
|
||||||
resolve();
|
};
|
||||||
}
|
image.onerror = function() {
|
||||||
image.onerror = function() {
|
ok(false, "APP_TYPE_EDITOR is allowed to load privileged image");
|
||||||
ok(false, "APP_TYPE_EDITOR is allowed to load privileged image");
|
// restore appType of rootDocShell before moving on to the next test
|
||||||
// restore appType of rootDocShell before moving on to the next test
|
rootDocShell.appType = defaultAppType;
|
||||||
rootDocShell.appType = defaultAppType;
|
resolve();
|
||||||
resolve();
|
};
|
||||||
}
|
doc.body.appendChild(image);
|
||||||
doc.body.appendChild(image);
|
image.src = "chrome://test1/skin/privileged.png";
|
||||||
image.src = "chrome://test1/skin/privileged.png";
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
});
|
);
|
||||||
|
|
||||||
Components.manager.removeBootstrappedManifestLocation(manifestDir);
|
Components.manager.removeBootstrappedManifestLocation(manifestDir);
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function() {
|
add_task(async function() {
|
||||||
info("docshell of appType APP_TYPE_UNKNOWN can *not* access privileged images.");
|
info(
|
||||||
|
"docshell of appType APP_TYPE_UNKNOWN can *not* access privileged images."
|
||||||
|
);
|
||||||
|
|
||||||
// Load a temporary manifest adding a route to a privileged image
|
// Load a temporary manifest adding a route to a privileged image
|
||||||
let manifestDir = getManifestDir();
|
let manifestDir = getManifestDir();
|
||||||
Components.manager.addBootstrappedManifestLocation(manifestDir);
|
Components.manager.addBootstrappedManifestLocation(manifestDir);
|
||||||
|
|
||||||
await BrowserTestUtils.withNewTab({
|
await BrowserTestUtils.withNewTab(
|
||||||
gBrowser,
|
{
|
||||||
url: SIMPLE_HTML
|
gBrowser,
|
||||||
}, async function(browser) {
|
url: SIMPLE_HTML,
|
||||||
await ContentTask.spawn(browser, null, async function() {
|
},
|
||||||
let rootDocShell = docShell.QueryInterface(Ci.nsIDocShellTreeItem)
|
async function(browser) {
|
||||||
.rootTreeItem
|
await ContentTask.spawn(browser, null, async function() {
|
||||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
let rootDocShell = docShell
|
||||||
.getInterface(Ci.nsIDocShell);
|
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||||
let defaultAppType = rootDocShell.appType;
|
.rootTreeItem.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIDocShell);
|
||||||
|
let defaultAppType = rootDocShell.appType;
|
||||||
|
|
||||||
rootDocShell.appType = Ci.nsIDocShell.APP_TYPE_UNKNOWN;
|
rootDocShell.appType = Ci.nsIDocShell.APP_TYPE_UNKNOWN;
|
||||||
|
|
||||||
is(rootDocShell.appType, Ci.nsIDocShell.APP_TYPE_UNKNOWN,
|
is(
|
||||||
"sanity check: appType of docshell should be unknown");
|
rootDocShell.appType,
|
||||||
|
Ci.nsIDocShell.APP_TYPE_UNKNOWN,
|
||||||
|
"sanity check: appType of docshell should be unknown"
|
||||||
|
);
|
||||||
|
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
let doc = content.document;
|
let doc = content.document;
|
||||||
let image = doc.createElement("img");
|
let image = doc.createElement("img");
|
||||||
image.onload = function() {
|
image.onload = function() {
|
||||||
ok(false, "APP_TYPE_UNKNOWN is *not* allowed to acces privileged image");
|
ok(
|
||||||
// restore appType of rootDocShell before moving on to the next test
|
false,
|
||||||
rootDocShell.appType = defaultAppType;
|
"APP_TYPE_UNKNOWN is *not* allowed to acces privileged image"
|
||||||
resolve();
|
);
|
||||||
}
|
// restore appType of rootDocShell before moving on to the next test
|
||||||
image.onerror = function() {
|
rootDocShell.appType = defaultAppType;
|
||||||
ok(true, "APP_TYPE_UNKNOWN is *not* allowed to acces privileged image");
|
resolve();
|
||||||
// restore appType of rootDocShell before moving on to the next test
|
};
|
||||||
rootDocShell.appType = defaultAppType;
|
image.onerror = function() {
|
||||||
resolve();
|
ok(
|
||||||
}
|
true,
|
||||||
doc.body.appendChild(image);
|
"APP_TYPE_UNKNOWN is *not* allowed to acces privileged image"
|
||||||
// Set the src via wrappedJSObject so the load is triggered with
|
);
|
||||||
// the content page's principal rather than ours.
|
// restore appType of rootDocShell before moving on to the next test
|
||||||
image.wrappedJSObject.src = "chrome://test1/skin/privileged.png";
|
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);
|
Components.manager.removeBootstrappedManifestLocation(manifestDir);
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,20 +11,29 @@ function testBFCache() {
|
||||||
function theTest() {
|
function theTest() {
|
||||||
var abort = false;
|
var abort = false;
|
||||||
var chances, gImage, gFrames;
|
var chances, gImage, gFrames;
|
||||||
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, TESTROOT + "image.html");
|
gBrowser.selectedTab = BrowserTestUtils.addTab(
|
||||||
gBrowser.selectedBrowser.addEventListener("pageshow", function () {
|
gBrowser,
|
||||||
var window = gBrowser.contentWindow;
|
TESTROOT + "image.html"
|
||||||
// If false, we are in an optimized build, and we abort this and
|
);
|
||||||
// all further tests
|
gBrowser.selectedBrowser.addEventListener(
|
||||||
if (!actOnMozImage(window.document, "img1", function(image) {
|
"pageshow",
|
||||||
gImage = image;
|
function() {
|
||||||
gFrames = gImage.framesNotified;
|
var window = gBrowser.contentWindow;
|
||||||
})) {
|
// If false, we are in an optimized build, and we abort this and
|
||||||
gBrowser.removeCurrentTab();
|
// all further tests
|
||||||
abort = true;
|
if (
|
||||||
}
|
!actOnMozImage(window.document, "img1", function(image) {
|
||||||
goer.next();
|
gImage = image;
|
||||||
}, {capture: true, once: true});
|
gFrames = gImage.framesNotified;
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
gBrowser.removeCurrentTab();
|
||||||
|
abort = true;
|
||||||
|
}
|
||||||
|
goer.next();
|
||||||
|
},
|
||||||
|
{ capture: true, once: true }
|
||||||
|
);
|
||||||
yield;
|
yield;
|
||||||
if (abort) {
|
if (abort) {
|
||||||
finish();
|
finish();
|
||||||
|
@ -35,15 +44,19 @@ function testBFCache() {
|
||||||
chances = 120;
|
chances = 120;
|
||||||
do {
|
do {
|
||||||
gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||||
gTimer.initWithCallback(function() {
|
gTimer.initWithCallback(
|
||||||
if (gImage.framesNotified >= 20) {
|
function() {
|
||||||
goer.send(true);
|
if (gImage.framesNotified >= 20) {
|
||||||
} else {
|
goer.send(true);
|
||||||
chances--;
|
} else {
|
||||||
goer.send(chances == 0); // maybe if we wait a bit, it will happen
|
chances--;
|
||||||
}
|
goer.send(chances == 0); // maybe if we wait a bit, it will happen
|
||||||
}, 500, Ci.nsITimer.TYPE_ONE_SHOT);
|
}
|
||||||
} while (!(yield));
|
},
|
||||||
|
500,
|
||||||
|
Ci.nsITimer.TYPE_ONE_SHOT
|
||||||
|
);
|
||||||
|
} while (!yield);
|
||||||
is(chances > 0, true, "Must have animated a few frames so far");
|
is(chances > 0, true, "Must have animated a few frames so far");
|
||||||
|
|
||||||
// Browse elsewhere; push our animating page into the bfcache
|
// Browse elsewhere; push our animating page into the bfcache
|
||||||
|
@ -52,16 +65,30 @@ function testBFCache() {
|
||||||
// Wait a bit for page to fully load, then wait a while and
|
// Wait a bit for page to fully load, then wait a while and
|
||||||
// see that no animation occurs.
|
// see that no animation occurs.
|
||||||
gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||||
gTimer.initWithCallback(function() {
|
gTimer.initWithCallback(
|
||||||
gFrames = gImage.framesNotified;
|
function() {
|
||||||
gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
gFrames = gImage.framesNotified;
|
||||||
gTimer.initWithCallback(function() {
|
gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||||
// Might have a few stray frames, until other page totally loads
|
gTimer.initWithCallback(
|
||||||
var additionalFrames = gImage.framesNotified - gFrames;
|
function() {
|
||||||
is(additionalFrames == 0, true, "Must have not animated in bfcache! Got " + additionalFrames + " additional frames");
|
// Might have a few stray frames, until other page totally loads
|
||||||
goer.next();
|
var additionalFrames = gImage.framesNotified - gFrames;
|
||||||
}, 4000, Ci.nsITimer.TYPE_ONE_SHOT); // 4 seconds - expect 40 frames
|
is(
|
||||||
}, 0, Ci.nsITimer.TYPE_ONE_SHOT); // delay of 0 - wait for next event loop
|
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;
|
yield;
|
||||||
|
|
||||||
// Go back
|
// Go back
|
||||||
|
@ -70,15 +97,19 @@ function testBFCache() {
|
||||||
chances = 120;
|
chances = 120;
|
||||||
do {
|
do {
|
||||||
gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||||
gTimer.initWithCallback(function() {
|
gTimer.initWithCallback(
|
||||||
if (gImage.framesNotified - gFrames >= 20) {
|
function() {
|
||||||
goer.send(true);
|
if (gImage.framesNotified - gFrames >= 20) {
|
||||||
} else {
|
goer.send(true);
|
||||||
chances--;
|
} else {
|
||||||
goer.send(chances == 0); // maybe if we wait a bit, it will happen
|
chances--;
|
||||||
}
|
goer.send(chances == 0); // maybe if we wait a bit, it will happen
|
||||||
}, 500, Ci.nsITimer.TYPE_ONE_SHOT);
|
}
|
||||||
} while (!(yield));
|
},
|
||||||
|
500,
|
||||||
|
Ci.nsITimer.TYPE_ONE_SHOT
|
||||||
|
);
|
||||||
|
} while (!yield);
|
||||||
is(chances > 0, true, "Must have animated once out of bfcache!");
|
is(chances > 0, true, "Must have animated once out of bfcache!");
|
||||||
|
|
||||||
// Finally, check that the css background image has essentially the same
|
// Finally, check that the css background image has essentially the same
|
||||||
|
@ -90,9 +121,17 @@ function testBFCache() {
|
||||||
var div = doc.getElementById("background_div");
|
var div = doc.getElementById("background_div");
|
||||||
div.innerHTML += '<img src="animated2.gif" id="img3">';
|
div.innerHTML += '<img src="animated2.gif" id="img3">';
|
||||||
actOnMozImage(doc, "img3", function(image) {
|
actOnMozImage(doc, "img3", function(image) {
|
||||||
is(Math.abs(image.framesNotified - gImage.framesNotified)/gImage.framesNotified < 0.5, true,
|
is(
|
||||||
"Must have also animated the background image, and essentially the same # of frames. " +
|
Math.abs(image.framesNotified - gImage.framesNotified) /
|
||||||
"Regular image got " + gImage.framesNotified + " frames but background image got " + image.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();
|
gBrowser.removeCurrentTab();
|
||||||
|
@ -111,57 +150,87 @@ function testSharedContainers() {
|
||||||
var gImages = [];
|
var gImages = [];
|
||||||
var gFrames;
|
var gFrames;
|
||||||
|
|
||||||
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, TESTROOT + "image.html");
|
gBrowser.selectedTab = BrowserTestUtils.addTab(
|
||||||
gBrowser.selectedBrowser.addEventListener("pageshow", function () {
|
gBrowser,
|
||||||
actOnMozImage(gBrowser.contentDocument, "img1", function(image) {
|
TESTROOT + "image.html"
|
||||||
gImages[0] = image;
|
);
|
||||||
gFrames = image.framesNotified; // May in theory have frames from last test
|
gBrowser.selectedBrowser.addEventListener(
|
||||||
// in this counter - so subtract them out
|
"pageshow",
|
||||||
});
|
function() {
|
||||||
goer.next();
|
actOnMozImage(gBrowser.contentDocument, "img1", function(image) {
|
||||||
}, {capture: true, once: true});
|
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;
|
yield;
|
||||||
|
|
||||||
// Load next tab somewhat later
|
// Load next tab somewhat later
|
||||||
gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||||
gTimer.initWithCallback(function() {
|
gTimer.initWithCallback(
|
||||||
goer.next();
|
function() {
|
||||||
}, 1500, Ci.nsITimer.TYPE_ONE_SHOT);
|
goer.next();
|
||||||
|
},
|
||||||
|
1500,
|
||||||
|
Ci.nsITimer.TYPE_ONE_SHOT
|
||||||
|
);
|
||||||
yield;
|
yield;
|
||||||
|
|
||||||
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, TESTROOT + "imageX2.html");
|
gBrowser.selectedTab = BrowserTestUtils.addTab(
|
||||||
gBrowser.selectedBrowser.addEventListener("pageshow", function () {
|
gBrowser,
|
||||||
[1,2].forEach(function(i) {
|
TESTROOT + "imageX2.html"
|
||||||
actOnMozImage(gBrowser.contentDocument, "img"+i, function(image) {
|
);
|
||||||
gImages[i] = image;
|
gBrowser.selectedBrowser.addEventListener(
|
||||||
|
"pageshow",
|
||||||
|
function() {
|
||||||
|
[1, 2].forEach(function(i) {
|
||||||
|
actOnMozImage(gBrowser.contentDocument, "img" + i, function(image) {
|
||||||
|
gImages[i] = image;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
goer.next();
|
||||||
goer.next();
|
},
|
||||||
}, {capture: true, once: true});
|
{ capture: true, once: true }
|
||||||
|
);
|
||||||
yield;
|
yield;
|
||||||
|
|
||||||
var chances = 120;
|
var chances = 120;
|
||||||
do {
|
do {
|
||||||
gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||||
gTimer.initWithCallback(function() {
|
gTimer.initWithCallback(
|
||||||
if (gImages[0].framesNotified - gFrames >= 10) {
|
function() {
|
||||||
goer.send(true);
|
if (gImages[0].framesNotified - gFrames >= 10) {
|
||||||
} else {
|
goer.send(true);
|
||||||
chances--;
|
} else {
|
||||||
goer.send(chances == 0); // maybe if we wait a bit, it will happen
|
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");
|
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
|
// Check they all have the same frame counts
|
||||||
var theFrames = null;
|
var theFrames = null;
|
||||||
[0,1,2].forEach(function(i) {
|
[0, 1, 2].forEach(function(i) {
|
||||||
var frames = gImages[i].framesNotified;
|
var frames = gImages[i].framesNotified;
|
||||||
if (theFrames == null) {
|
if (theFrames == null) {
|
||||||
theFrames = frames;
|
theFrames = frames;
|
||||||
} else {
|
} else {
|
||||||
is(theFrames, frames, "Sharing the same imgContainer means *exactly* the same frame counts!");
|
is(
|
||||||
|
theFrames,
|
||||||
|
frames,
|
||||||
|
"Sharing the same imgContainer means *exactly* the same frame counts!"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -189,4 +258,3 @@ function test() {
|
||||||
ignoreAllUncaughtExceptions();
|
ignoreAllUncaughtExceptions();
|
||||||
nextTest();
|
nextTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,12 +12,13 @@ function getImageLoading(doc, id) {
|
||||||
// Tries to get the Moz debug image, imgIContainerDebug. Only works
|
// Tries to get the Moz debug image, imgIContainerDebug. Only works
|
||||||
// in a debug build. If we succeed, we call func().
|
// in a debug build. If we succeed, we call func().
|
||||||
function actOnMozImage(doc, id, func) {
|
function actOnMozImage(doc, id, func) {
|
||||||
var imgContainer = getImageLoading(doc, id).getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST).image;
|
var imgContainer = getImageLoading(doc, id).getRequest(
|
||||||
|
Ci.nsIImageLoadingContent.CURRENT_REQUEST
|
||||||
|
).image;
|
||||||
var mozImage;
|
var mozImage;
|
||||||
try {
|
try {
|
||||||
mozImage = imgContainer.QueryInterface(Ci.imgIContainerDebug);
|
mozImage = imgContainer.QueryInterface(Ci.imgIContainerDebug);
|
||||||
}
|
} catch (e) {
|
||||||
catch (e) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
func(mozImage);
|
func(mozImage);
|
||||||
|
|
|
@ -3,49 +3,56 @@ var currentTest;
|
||||||
var gIsRefImageLoaded = false;
|
var gIsRefImageLoaded = false;
|
||||||
const gShouldOutputDebugInfo = false;
|
const gShouldOutputDebugInfo = false;
|
||||||
|
|
||||||
function pollForSuccess()
|
function pollForSuccess() {
|
||||||
{
|
|
||||||
if (!currentTest.isTestFinished) {
|
if (!currentTest.isTestFinished) {
|
||||||
if (!currentTest.reusingReferenceImage || (currentTest.reusingReferenceImage
|
if (
|
||||||
&& gRefImageLoaded)) {
|
!currentTest.reusingReferenceImage ||
|
||||||
|
(currentTest.reusingReferenceImage && gRefImageLoaded)
|
||||||
|
) {
|
||||||
currentTest.checkImage();
|
currentTest.checkImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(pollForSuccess, currentTest.pollFreq);
|
setTimeout(pollForSuccess, currentTest.pollFreq);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
function referencePoller()
|
function referencePoller() {
|
||||||
{
|
|
||||||
currentTest.takeReferenceSnapshot();
|
currentTest.takeReferenceSnapshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
function reuseImageCallback()
|
function reuseImageCallback() {
|
||||||
{
|
|
||||||
gIsRefImageLoaded = true;
|
gIsRefImageLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function failTest()
|
function failTest() {
|
||||||
{
|
|
||||||
if (currentTest.isTestFinished || currentTest.closeFunc) {
|
if (currentTest.isTestFinished || currentTest.closeFunc) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ok(false, "timing out after " + currentTest.timeout + "ms. "
|
ok(
|
||||||
+ "Animated image still doesn't look correct, after poll #"
|
false,
|
||||||
+ currentTest.pollCounter);
|
"timing out after " +
|
||||||
|
currentTest.timeout +
|
||||||
|
"ms. " +
|
||||||
|
"Animated image still doesn't look correct, after poll #" +
|
||||||
|
currentTest.pollCounter
|
||||||
|
);
|
||||||
currentTest.wereFailures = true;
|
currentTest.wereFailures = true;
|
||||||
|
|
||||||
if (currentTest.currentSnapshotDataURI) {
|
if (currentTest.currentSnapshotDataURI) {
|
||||||
currentTest.outputDebugInfo("Snapshot #" + currentTest.pollCounter,
|
currentTest.outputDebugInfo(
|
||||||
"snapNum" + currentTest.pollCounter,
|
"Snapshot #" + currentTest.pollCounter,
|
||||||
currentTest.currentSnapshotDataURI);
|
"snapNum" + currentTest.pollCounter,
|
||||||
|
currentTest.currentSnapshotDataURI
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentTest.enableDisplay(document.getElementById(currentTest.debugElementId));
|
currentTest.enableDisplay(
|
||||||
|
document.getElementById(currentTest.debugElementId)
|
||||||
|
);
|
||||||
|
|
||||||
currentTest.cleanUpAndFinish();
|
currentTest.cleanUpAndFinish();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new AnimationTest object.
|
* Create a new AnimationTest object.
|
||||||
|
@ -75,9 +82,17 @@ function failTest()
|
||||||
* chain tests together, so they are all finished exactly once.
|
* chain tests together, so they are all finished exactly once.
|
||||||
* @returns {AnimationTest}
|
* @returns {AnimationTest}
|
||||||
*/
|
*/
|
||||||
function AnimationTest(pollFreq, timeout, referenceElementId, imageElementId,
|
function AnimationTest(
|
||||||
debugElementId, cleanId, srcAttr, xulTest, closeFunc)
|
pollFreq,
|
||||||
{
|
timeout,
|
||||||
|
referenceElementId,
|
||||||
|
imageElementId,
|
||||||
|
debugElementId,
|
||||||
|
cleanId,
|
||||||
|
srcAttr,
|
||||||
|
xulTest,
|
||||||
|
closeFunc
|
||||||
|
) {
|
||||||
// We want to test the cold loading behavior, so clear cache in case an
|
// We want to test the cold loading behavior, so clear cache in case an
|
||||||
// earlier test got our image in there already.
|
// earlier test got our image in there already.
|
||||||
clearAllImageCaches();
|
clearAllImageCaches();
|
||||||
|
@ -103,24 +118,24 @@ function AnimationTest(pollFreq, timeout, referenceElementId, imageElementId,
|
||||||
this.numRefsTaken = 0;
|
this.numRefsTaken = 0;
|
||||||
this.blankWaitTime = 0;
|
this.blankWaitTime = 0;
|
||||||
|
|
||||||
this.cleanId = cleanId ? cleanId : '';
|
this.cleanId = cleanId ? cleanId : "";
|
||||||
this.xulTest = xulTest ? xulTest : '';
|
this.xulTest = xulTest ? xulTest : "";
|
||||||
this.closeFunc = closeFunc ? closeFunc : '';
|
this.closeFunc = closeFunc ? closeFunc : "";
|
||||||
};
|
}
|
||||||
|
|
||||||
AnimationTest.prototype.preloadImage = function()
|
AnimationTest.prototype.preloadImage = function() {
|
||||||
{
|
|
||||||
if (this.srcAttr) {
|
if (this.srcAttr) {
|
||||||
this.myImage = new Image();
|
this.myImage = new Image();
|
||||||
this.myImage.onload = function() { currentTest.continueTest(); };
|
this.myImage.onload = function() {
|
||||||
|
currentTest.continueTest();
|
||||||
|
};
|
||||||
this.myImage.src = this.srcAttr;
|
this.myImage.src = this.srcAttr;
|
||||||
} else {
|
} else {
|
||||||
this.continueTest();
|
this.continueTest();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
AnimationTest.prototype.outputDebugInfo = function(message, id, dataUri)
|
AnimationTest.prototype.outputDebugInfo = function(message, id, dataUri) {
|
||||||
{
|
|
||||||
if (!gShouldOutputDebugInfo) {
|
if (!gShouldOutputDebugInfo) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -135,13 +150,11 @@ AnimationTest.prototype.outputDebugInfo = function(message, id, dataUri)
|
||||||
todo(false, "Debug (" + id + "): " + message + " " + dataUri);
|
todo(false, "Debug (" + id + "): " + message + " " + dataUri);
|
||||||
};
|
};
|
||||||
|
|
||||||
AnimationTest.prototype.isFinished = function()
|
AnimationTest.prototype.isFinished = function() {
|
||||||
{
|
|
||||||
return this.isTestFinished;
|
return this.isTestFinished;
|
||||||
};
|
};
|
||||||
|
|
||||||
AnimationTest.prototype.takeCleanSnapshot = function()
|
AnimationTest.prototype.takeCleanSnapshot = function() {
|
||||||
{
|
|
||||||
var cleanElement;
|
var cleanElement;
|
||||||
if (this.cleanId) {
|
if (this.cleanId) {
|
||||||
cleanElement = document.getElementById(this.cleanId);
|
cleanElement = document.getElementById(this.cleanId);
|
||||||
|
@ -161,18 +174,23 @@ AnimationTest.prototype.takeCleanSnapshot = function()
|
||||||
}
|
}
|
||||||
|
|
||||||
var dataString1 = "Clean Snapshot";
|
var dataString1 = "Clean Snapshot";
|
||||||
this.outputDebugInfo(dataString1, 'cleanSnap',
|
this.outputDebugInfo(
|
||||||
this.cleanSnapshot.toDataURL());
|
dataString1,
|
||||||
|
"cleanSnap",
|
||||||
|
this.cleanSnapshot.toDataURL()
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
AnimationTest.prototype.takeBlankSnapshot = function()
|
AnimationTest.prototype.takeBlankSnapshot = function() {
|
||||||
{
|
|
||||||
// Take a snapshot of the initial (essentially blank) page
|
// Take a snapshot of the initial (essentially blank) page
|
||||||
this.blankSnapshot = snapshotWindow(window, false);
|
this.blankSnapshot = snapshotWindow(window, false);
|
||||||
|
|
||||||
var dataString1 = "Initial Blank Snapshot";
|
var dataString1 = "Initial Blank Snapshot";
|
||||||
this.outputDebugInfo(dataString1, 'blank1Snap',
|
this.outputDebugInfo(
|
||||||
this.blankSnapshot.toDataURL());
|
dataString1,
|
||||||
|
"blank1Snap",
|
||||||
|
this.blankSnapshot.toDataURL()
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -182,8 +200,7 @@ AnimationTest.prototype.takeBlankSnapshot = function()
|
||||||
* image, if applicable, and then asynchronously call continueTest(), or if not
|
* image, if applicable, and then asynchronously call continueTest(), or if not
|
||||||
* applicable, synchronously trigger a call to continueTest().
|
* applicable, synchronously trigger a call to continueTest().
|
||||||
*/
|
*/
|
||||||
AnimationTest.prototype.beginTest = function()
|
AnimationTest.prototype.beginTest = function() {
|
||||||
{
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
SimpleTest.waitForExplicitFinish();
|
||||||
SimpleTest.requestFlakyTimeout("untriaged");
|
SimpleTest.requestFlakyTimeout("untriaged");
|
||||||
|
|
||||||
|
@ -196,8 +213,7 @@ AnimationTest.prototype.beginTest = function()
|
||||||
* beginTest() either synchronously or asynchronously, as an image load
|
* beginTest() either synchronously or asynchronously, as an image load
|
||||||
* callback.
|
* callback.
|
||||||
*/
|
*/
|
||||||
AnimationTest.prototype.continueTest = function()
|
AnimationTest.prototype.continueTest = function() {
|
||||||
{
|
|
||||||
// In case something goes wrong, fail earlier than mochitest timeout,
|
// In case something goes wrong, fail earlier than mochitest timeout,
|
||||||
// and with more information.
|
// and with more information.
|
||||||
setTimeout(failTest, this.timeout);
|
setTimeout(failTest, this.timeout);
|
||||||
|
@ -211,34 +227,35 @@ AnimationTest.prototype.continueTest = function()
|
||||||
SimpleTest.executeSoon(pollForSuccess);
|
SimpleTest.executeSoon(pollForSuccess);
|
||||||
};
|
};
|
||||||
|
|
||||||
AnimationTest.prototype.setupPolledImage = function ()
|
AnimationTest.prototype.setupPolledImage = function() {
|
||||||
{
|
|
||||||
// Make sure the image is visible
|
// Make sure the image is visible
|
||||||
if (!this.reusingImageAsReference) {
|
if (!this.reusingImageAsReference) {
|
||||||
this.enableDisplay(document.getElementById(this.imageElementId));
|
this.enableDisplay(document.getElementById(this.imageElementId));
|
||||||
var currentSnapshot = snapshotWindow(window, false);
|
var currentSnapshot = snapshotWindow(window, false);
|
||||||
var result = compareSnapshots(currentSnapshot,
|
var result = compareSnapshots(
|
||||||
this.referenceSnapshot, true);
|
currentSnapshot,
|
||||||
|
this.referenceSnapshot,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
this.currentSnapshotDataURI = currentSnapshot.toDataURL();
|
this.currentSnapshotDataURI = currentSnapshot.toDataURL();
|
||||||
|
|
||||||
if (result[0]) {
|
if (result[0]) {
|
||||||
// SUCCESS!
|
// SUCCESS!
|
||||||
ok(true, "Animated image looks correct, at poll #"
|
ok(true, "Animated image looks correct, at poll #" + this.pollCounter);
|
||||||
+ this.pollCounter);
|
|
||||||
|
|
||||||
this.cleanUpAndFinish();
|
this.cleanUpAndFinish();
|
||||||
}
|
}
|
||||||
} else if (!gIsRefImageLoaded) {
|
} else if (!gIsRefImageLoaded) {
|
||||||
this.myImage = new Image();
|
this.myImage = new Image();
|
||||||
this.myImage.onload = reuseImageCallback;
|
this.myImage.onload = reuseImageCallback;
|
||||||
document.getElementById(this.imageElementId).setAttribute('src',
|
document
|
||||||
this.referenceElementId);
|
.getElementById(this.imageElementId)
|
||||||
}
|
.setAttribute("src", this.referenceElementId);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
AnimationTest.prototype.checkImage = function ()
|
AnimationTest.prototype.checkImage = function() {
|
||||||
{
|
|
||||||
if (this.isTestFinished) {
|
if (this.isTestFinished) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -258,15 +275,13 @@ AnimationTest.prototype.checkImage = function ()
|
||||||
|
|
||||||
if (result[0]) {
|
if (result[0]) {
|
||||||
// SUCCESS!
|
// SUCCESS!
|
||||||
ok(true, "Animated image looks correct, at poll #"
|
ok(true, "Animated image looks correct, at poll #" + this.pollCounter);
|
||||||
+ this.pollCounter);
|
|
||||||
|
|
||||||
this.cleanUpAndFinish();
|
this.cleanUpAndFinish();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
AnimationTest.prototype.takeReferenceSnapshot = function ()
|
AnimationTest.prototype.takeReferenceSnapshot = function() {
|
||||||
{
|
|
||||||
this.numRefsTaken++;
|
this.numRefsTaken++;
|
||||||
|
|
||||||
// Test to make sure the reference image doesn't match a clean snapshot
|
// Test to make sure the reference image doesn't match a clean snapshot
|
||||||
|
@ -286,15 +301,20 @@ AnimationTest.prototype.takeReferenceSnapshot = function ()
|
||||||
|
|
||||||
this.referenceSnapshot = snapshotWindow(window, false);
|
this.referenceSnapshot = snapshotWindow(window, false);
|
||||||
|
|
||||||
var snapResult = compareSnapshots(this.cleanSnapshot,
|
var snapResult = compareSnapshots(
|
||||||
this.referenceSnapshot, false);
|
this.cleanSnapshot,
|
||||||
|
this.referenceSnapshot,
|
||||||
|
false
|
||||||
|
);
|
||||||
if (!snapResult[0]) {
|
if (!snapResult[0]) {
|
||||||
if (this.blankWaitTime > 2000) {
|
if (this.blankWaitTime > 2000) {
|
||||||
// if it took longer than two seconds to load the image, we probably
|
// if it took longer than two seconds to load the image, we probably
|
||||||
// have a problem.
|
// have a problem.
|
||||||
this.wereFailures = true;
|
this.wereFailures = true;
|
||||||
ok(snapResult[0],
|
ok(
|
||||||
"Reference snapshot shouldn't match clean (non-image) snapshot");
|
snapResult[0],
|
||||||
|
"Reference snapshot shouldn't match clean (non-image) snapshot"
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this.blankWaitTime += currentTest.pollFreq;
|
this.blankWaitTime += currentTest.pollFreq;
|
||||||
// let's wait a bit and see if it clears up
|
// let's wait a bit and see if it clears up
|
||||||
|
@ -303,12 +323,17 @@ AnimationTest.prototype.takeReferenceSnapshot = function ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ok(snapResult[0],
|
ok(
|
||||||
"Reference snapshot shouldn't match clean (non-image) snapshot");
|
snapResult[0],
|
||||||
|
"Reference snapshot shouldn't match clean (non-image) snapshot"
|
||||||
|
);
|
||||||
|
|
||||||
var dataString = "Reference Snapshot #" + this.numRefsTaken;
|
var dataString = "Reference Snapshot #" + this.numRefsTaken;
|
||||||
this.outputDebugInfo(dataString, 'refSnapId',
|
this.outputDebugInfo(
|
||||||
this.referenceSnapshot.toDataURL());
|
dataString,
|
||||||
|
"refSnapId",
|
||||||
|
this.referenceSnapshot.toDataURL()
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// Make sure the animation section is hidden
|
// Make sure the animation section is hidden
|
||||||
this.disableDisplay(document.getElementById(this.imageElementId));
|
this.disableDisplay(document.getElementById(this.imageElementId));
|
||||||
|
@ -318,15 +343,20 @@ AnimationTest.prototype.takeReferenceSnapshot = function ()
|
||||||
this.enableDisplay(referenceDiv);
|
this.enableDisplay(referenceDiv);
|
||||||
|
|
||||||
this.referenceSnapshot = snapshotWindow(window, false);
|
this.referenceSnapshot = snapshotWindow(window, false);
|
||||||
var snapResult = compareSnapshots(this.cleanSnapshot,
|
var snapResult = compareSnapshots(
|
||||||
this.referenceSnapshot, false);
|
this.cleanSnapshot,
|
||||||
|
this.referenceSnapshot,
|
||||||
|
false
|
||||||
|
);
|
||||||
if (!snapResult[0]) {
|
if (!snapResult[0]) {
|
||||||
if (this.blankWaitTime > 2000) {
|
if (this.blankWaitTime > 2000) {
|
||||||
// if it took longer than two seconds to load the image, we probably
|
// if it took longer than two seconds to load the image, we probably
|
||||||
// have a problem.
|
// have a problem.
|
||||||
this.wereFailures = true;
|
this.wereFailures = true;
|
||||||
ok(snapResult[0],
|
ok(
|
||||||
"Reference snapshot shouldn't match clean (non-image) snapshot");
|
snapResult[0],
|
||||||
|
"Reference snapshot shouldn't match clean (non-image) snapshot"
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this.blankWaitTime += 20;
|
this.blankWaitTime += 20;
|
||||||
// let's wait a bit and see if it clears up
|
// let's wait a bit and see if it clears up
|
||||||
|
@ -335,12 +365,17 @@ AnimationTest.prototype.takeReferenceSnapshot = function ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ok(snapResult[0],
|
ok(
|
||||||
"Reference snapshot shouldn't match clean (non-image) snapshot");
|
snapResult[0],
|
||||||
|
"Reference snapshot shouldn't match clean (non-image) snapshot"
|
||||||
|
);
|
||||||
|
|
||||||
var dataString = "Reference Snapshot #" + this.numRefsTaken;
|
var dataString = "Reference Snapshot #" + this.numRefsTaken;
|
||||||
this.outputDebugInfo(dataString, 'refSnapId',
|
this.outputDebugInfo(
|
||||||
this.referenceSnapshot.toDataURL());
|
dataString,
|
||||||
|
"refSnapId",
|
||||||
|
this.referenceSnapshot.toDataURL()
|
||||||
|
);
|
||||||
|
|
||||||
// Re-hide reference div, and take another snapshot to be sure it's gone
|
// Re-hide reference div, and take another snapshot to be sure it's gone
|
||||||
this.disableDisplay(referenceDiv);
|
this.disableDisplay(referenceDiv);
|
||||||
|
@ -348,47 +383,46 @@ AnimationTest.prototype.takeReferenceSnapshot = function ()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
AnimationTest.prototype.enableDisplay = function(element)
|
AnimationTest.prototype.enableDisplay = function(element) {
|
||||||
{
|
|
||||||
if (!element) {
|
if (!element) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.xulTest) {
|
if (!this.xulTest) {
|
||||||
element.style.display = '';
|
element.style.display = "";
|
||||||
} else {
|
} else {
|
||||||
element.setAttribute('hidden', 'false');
|
element.setAttribute("hidden", "false");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
AnimationTest.prototype.disableDisplay = function(element)
|
AnimationTest.prototype.disableDisplay = function(element) {
|
||||||
{
|
|
||||||
if (!element) {
|
if (!element) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.xulTest) {
|
if (!this.xulTest) {
|
||||||
element.style.display = 'none';
|
element.style.display = "none";
|
||||||
} else {
|
} else {
|
||||||
element.setAttribute('hidden', 'true');
|
element.setAttribute("hidden", "true");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
AnimationTest.prototype.testBlankCameBack = function()
|
AnimationTest.prototype.testBlankCameBack = function() {
|
||||||
{
|
|
||||||
var blankSnapshot2 = snapshotWindow(window, false);
|
var blankSnapshot2 = snapshotWindow(window, false);
|
||||||
var result = compareSnapshots(this.blankSnapshot, blankSnapshot2, true);
|
var result = compareSnapshots(this.blankSnapshot, blankSnapshot2, true);
|
||||||
ok(result[0], "Reference image should disappear when it becomes display:none");
|
ok(
|
||||||
|
result[0],
|
||||||
|
"Reference image should disappear when it becomes display:none"
|
||||||
|
);
|
||||||
|
|
||||||
if (!result[0]) {
|
if (!result[0]) {
|
||||||
this.wereFailures = true;
|
this.wereFailures = true;
|
||||||
var dataString = "Second Blank Snapshot";
|
var dataString = "Second Blank Snapshot";
|
||||||
this.outputDebugInfo(dataString, 'blank2SnapId', result[2]);
|
this.outputDebugInfo(dataString, "blank2SnapId", result[2]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
AnimationTest.prototype.cleanUpAndFinish = function ()
|
AnimationTest.prototype.cleanUpAndFinish = function() {
|
||||||
{
|
|
||||||
// On the off chance that failTest and checkImage are triggered
|
// On the off chance that failTest and checkImage are triggered
|
||||||
// back-to-back, use a flag to prevent multiple calls to SimpleTest.finish.
|
// back-to-back, use a flag to prevent multiple calls to SimpleTest.finish.
|
||||||
if (this.isTestFinished) {
|
if (this.isTestFinished) {
|
||||||
|
@ -404,7 +438,7 @@ AnimationTest.prototype.cleanUpAndFinish = function ()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.wereFailures) {
|
if (this.wereFailures) {
|
||||||
document.getElementById(this.debugElementId).style.display = 'block';
|
document.getElementById(this.debugElementId).style.display = "block";
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
|
|
|
@ -1,54 +1,51 @@
|
||||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||||
// Helper file for shared image functionality
|
// Helper file for shared image functionality
|
||||||
//
|
//
|
||||||
// Note that this is use by tests elsewhere in the source tree. When in doubt,
|
// Note that this is use by tests elsewhere in the source tree. When in doubt,
|
||||||
// check mxr before removing or changing functionality.
|
// check mxr before removing or changing functionality.
|
||||||
|
|
||||||
// Helper function to clear both the content and chrome image caches
|
// Helper function to clear both the content and chrome image caches
|
||||||
function clearAllImageCaches()
|
function clearAllImageCaches() {
|
||||||
{
|
var tools = SpecialPowers.Cc["@mozilla.org/image/tools;1"].getService(
|
||||||
var tools = SpecialPowers.Cc["@mozilla.org/image/tools;1"]
|
SpecialPowers.Ci.imgITools
|
||||||
.getService(SpecialPowers.Ci.imgITools);
|
);
|
||||||
var imageCache = tools.getImgCacheForDocument(window.document);
|
var imageCache = tools.getImgCacheForDocument(window.document);
|
||||||
imageCache.clearCache(true); // true=chrome
|
imageCache.clearCache(true); // true=chrome
|
||||||
imageCache.clearCache(false); // false=content
|
imageCache.clearCache(false); // false=content
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to clear the image cache of content images
|
// Helper function to clear the image cache of content images
|
||||||
function clearImageCache()
|
function clearImageCache() {
|
||||||
{
|
var tools = SpecialPowers.Cc["@mozilla.org/image/tools;1"].getService(
|
||||||
var tools = SpecialPowers.Cc["@mozilla.org/image/tools;1"]
|
SpecialPowers.Ci.imgITools
|
||||||
.getService(SpecialPowers.Ci.imgITools);
|
);
|
||||||
var imageCache = tools.getImgCacheForDocument(window.document);
|
var imageCache = tools.getImgCacheForDocument(window.document);
|
||||||
imageCache.clearCache(false); // true=chrome, false=content
|
imageCache.clearCache(false); // true=chrome, false=content
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to determine if the frame is decoded for a given image id
|
// Helper function to determine if the frame is decoded for a given image id
|
||||||
function isFrameDecoded(id)
|
function isFrameDecoded(id) {
|
||||||
{
|
return getImageStatus(id) & SpecialPowers.Ci.imgIRequest.STATUS_FRAME_COMPLETE
|
||||||
return (getImageStatus(id) &
|
? true
|
||||||
SpecialPowers.Ci.imgIRequest.STATUS_FRAME_COMPLETE)
|
: false;
|
||||||
? true : false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to determine if the image is loaded for a given image id
|
// Helper function to determine if the image is loaded for a given image id
|
||||||
function isImageLoaded(id)
|
function isImageLoaded(id) {
|
||||||
{
|
return getImageStatus(id) & SpecialPowers.Ci.imgIRequest.STATUS_LOAD_COMPLETE
|
||||||
return (getImageStatus(id) &
|
? true
|
||||||
SpecialPowers.Ci.imgIRequest.STATUS_LOAD_COMPLETE)
|
: false;
|
||||||
? true : false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to get the status flags of an image
|
// Helper function to get the status flags of an image
|
||||||
function getImageStatus(id)
|
function getImageStatus(id) {
|
||||||
{
|
|
||||||
// Get the image
|
// Get the image
|
||||||
var img = SpecialPowers.wrap(document.getElementById(id));
|
var img = SpecialPowers.wrap(document.getElementById(id));
|
||||||
|
|
||||||
// Get the request
|
// Get the request
|
||||||
var request = img.getRequest(SpecialPowers.Ci
|
var request = img.getRequest(
|
||||||
.nsIImageLoadingContent
|
SpecialPowers.Ci.nsIImageLoadingContent.CURRENT_REQUEST
|
||||||
.CURRENT_REQUEST);
|
);
|
||||||
|
|
||||||
// Return the status
|
// Return the status
|
||||||
return request.imageStatus;
|
return request.imageStatus;
|
||||||
|
@ -56,8 +53,7 @@ function getImageStatus(id)
|
||||||
|
|
||||||
// Forces a synchronous decode of an image by drawing it to a canvas. Only
|
// Forces a synchronous decode of an image by drawing it to a canvas. Only
|
||||||
// really meaningful if the image is fully loaded first
|
// really meaningful if the image is fully loaded first
|
||||||
function forceDecode(id)
|
function forceDecode(id) {
|
||||||
{
|
|
||||||
// Get the image
|
// Get the image
|
||||||
var img = document.getElementById(id);
|
var img = document.getElementById(id);
|
||||||
|
|
||||||
|
@ -69,25 +65,36 @@ function forceDecode(id)
|
||||||
ctx.drawImage(img, 0, 0);
|
ctx.drawImage(img, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Functions to facilitate getting/setting various image-related prefs
|
// Functions to facilitate getting/setting various image-related prefs
|
||||||
//
|
//
|
||||||
// If you change a pref in a mochitest, Don't forget to reset it to its
|
// If you change a pref in a mochitest, Don't forget to reset it to its
|
||||||
// original value!
|
// original value!
|
||||||
//
|
//
|
||||||
// Null indicates no pref set
|
// Null indicates no pref set
|
||||||
|
|
||||||
const DISCARD_ENABLED_PREF = {name: "discardable", branch: "image.mem.", type: "bool"};
|
const DISCARD_ENABLED_PREF = {
|
||||||
const DECODEONDRAW_ENABLED_PREF = {name: "decodeondraw", branch: "image.mem.", type: "bool"};
|
name: "discardable",
|
||||||
const DISCARD_TIMEOUT_PREF = {name: "min_discard_timeout_ms", branch: "image.mem.", type: "int"};
|
branch: "image.mem.",
|
||||||
|
type: "bool",
|
||||||
|
};
|
||||||
|
const DECODEONDRAW_ENABLED_PREF = {
|
||||||
|
name: "decodeondraw",
|
||||||
|
branch: "image.mem.",
|
||||||
|
type: "bool",
|
||||||
|
};
|
||||||
|
const DISCARD_TIMEOUT_PREF = {
|
||||||
|
name: "min_discard_timeout_ms",
|
||||||
|
branch: "image.mem.",
|
||||||
|
type: "int",
|
||||||
|
};
|
||||||
|
|
||||||
function setImagePref(pref, val)
|
function setImagePref(pref, val) {
|
||||||
{
|
var prefService = SpecialPowers.Cc[
|
||||||
var prefService = SpecialPowers.Cc["@mozilla.org/preferences-service;1"]
|
"@mozilla.org/preferences-service;1"
|
||||||
.getService(SpecialPowers.Ci.nsIPrefService);
|
].getService(SpecialPowers.Ci.nsIPrefService);
|
||||||
var branch = prefService.getBranch(pref.branch);
|
var branch = prefService.getBranch(pref.branch);
|
||||||
if (val != null) {
|
if (val != null) {
|
||||||
switch(pref.type) {
|
switch (pref.type) {
|
||||||
case "bool":
|
case "bool":
|
||||||
branch.setBoolPref(pref.name, val);
|
branch.setBoolPref(pref.name, val);
|
||||||
break;
|
break;
|
||||||
|
@ -97,15 +104,15 @@ function setImagePref(pref, val)
|
||||||
default:
|
default:
|
||||||
throw new Error("Unknown pref type");
|
throw new Error("Unknown pref type");
|
||||||
}
|
}
|
||||||
}
|
} else if (branch.prefHasUserValue(pref.name)) {
|
||||||
else if (branch.prefHasUserValue(pref.name))
|
|
||||||
branch.clearUserPref(pref.name);
|
branch.clearUserPref(pref.name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getImagePref(pref)
|
function getImagePref(pref) {
|
||||||
{
|
var prefService = SpecialPowers.Cc[
|
||||||
var prefService = SpecialPowers.Cc["@mozilla.org/preferences-service;1"]
|
"@mozilla.org/preferences-service;1"
|
||||||
.getService(SpecialPowers.Ci.nsIPrefService);
|
].getService(SpecialPowers.Ci.nsIPrefService);
|
||||||
var branch = prefService.getBranch(pref.branch);
|
var branch = prefService.getBranch(pref.branch);
|
||||||
if (branch.prefHasUserValue(pref.name)) {
|
if (branch.prefHasUserValue(pref.name)) {
|
||||||
switch (pref.type) {
|
switch (pref.type) {
|
||||||
|
@ -116,20 +123,19 @@ function getImagePref(pref)
|
||||||
default:
|
default:
|
||||||
throw new Error("Unknown pref type");
|
throw new Error("Unknown pref type");
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// JS implementation of imgIScriptedNotificationObserver with stubs for all of its methods.
|
// JS implementation of imgIScriptedNotificationObserver with stubs for all of its methods.
|
||||||
function ImageDecoderObserverStub()
|
function ImageDecoderObserverStub() {
|
||||||
{
|
this.sizeAvailable = function sizeAvailable(aRequest) {};
|
||||||
this.sizeAvailable = function sizeAvailable(aRequest) {}
|
this.frameComplete = function frameComplete(aRequest) {};
|
||||||
this.frameComplete = function frameComplete(aRequest) {}
|
this.decodeComplete = function decodeComplete(aRequest) {};
|
||||||
this.decodeComplete = function decodeComplete(aRequest) {}
|
this.loadComplete = function loadComplete(aRequest) {};
|
||||||
this.loadComplete = function loadComplete(aRequest) {}
|
this.frameUpdate = function frameUpdate(aRequest) {};
|
||||||
this.frameUpdate = function frameUpdate(aRequest) {}
|
this.discard = function discard(aRequest) {};
|
||||||
this.discard = function discard(aRequest) {}
|
this.isAnimated = function isAnimated(aRequest) {};
|
||||||
this.isAnimated = function isAnimated(aRequest) {}
|
this.hasTransparency = function hasTransparency(aRequest) {};
|
||||||
this.hasTransparency = function hasTransparency(aRequest) {}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,23 +6,21 @@
|
||||||
* var uri.
|
* var uri.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
|
const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
|
||||||
const {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
|
const { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
|
||||||
|
|
||||||
var server = new HttpServer();
|
var server = new HttpServer();
|
||||||
server.registerDirectory("/", do_get_file(''));
|
server.registerDirectory("/", do_get_file(""));
|
||||||
server.registerContentType("sjs", "sjs");
|
server.registerContentType("sjs", "sjs");
|
||||||
server.start(-1);
|
server.start(-1);
|
||||||
|
|
||||||
|
load("image_load_helpers.js");
|
||||||
load('image_load_helpers.js');
|
|
||||||
|
|
||||||
var requests = [];
|
var requests = [];
|
||||||
|
|
||||||
// Return a closure that holds on to the listener from the original
|
// Return a closure that holds on to the listener from the original
|
||||||
// imgIRequest, and compares its results to the cloned one.
|
// imgIRequest, and compares its results to the cloned one.
|
||||||
function getCloneStopCallback(original_listener)
|
function getCloneStopCallback(original_listener) {
|
||||||
{
|
|
||||||
return function cloneStop(listener) {
|
return function cloneStop(listener) {
|
||||||
Assert.equal(original_listener.state, listener.state);
|
Assert.equal(original_listener.state, listener.state);
|
||||||
|
|
||||||
|
@ -30,35 +28,38 @@ function getCloneStopCallback(original_listener)
|
||||||
// twice.
|
// twice.
|
||||||
Assert.notEqual(original_listener, listener);
|
Assert.notEqual(original_listener, listener);
|
||||||
do_test_finished();
|
do_test_finished();
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure that cloned requests get all the same callbacks as the original,
|
// Make sure that cloned requests get all the same callbacks as the original,
|
||||||
// but they aren't synchronous right now.
|
// but they aren't synchronous right now.
|
||||||
function checkClone(other_listener, aRequest)
|
function checkClone(other_listener, aRequest) {
|
||||||
{
|
|
||||||
do_test_pending();
|
do_test_pending();
|
||||||
|
|
||||||
// For as long as clone notification is synchronous, we can't test the clone state reliably.
|
// For as long as clone notification is synchronous, we can't test the clone state reliably.
|
||||||
var listener = new ImageListener(null, function(foo, bar) { do_test_finished(); } /* getCloneStopCallback(other_listener)*/);
|
var listener = new ImageListener(
|
||||||
|
null,
|
||||||
|
function(foo, bar) {
|
||||||
|
do_test_finished();
|
||||||
|
} /* getCloneStopCallback(other_listener)*/
|
||||||
|
);
|
||||||
listener.synchronous = false;
|
listener.synchronous = false;
|
||||||
var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
|
var outer = Cc["@mozilla.org/image/tools;1"]
|
||||||
.createScriptedObserver(listener);
|
.getService(Ci.imgITools)
|
||||||
|
.createScriptedObserver(listener);
|
||||||
var clone = aRequest.clone(outer);
|
var clone = aRequest.clone(outer);
|
||||||
requests.push({ request: clone, locked: false });
|
requests.push({ request: clone, locked: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that all the callbacks were called on aRequest.
|
// Ensure that all the callbacks were called on aRequest.
|
||||||
function checkSizeAndLoad(listener, aRequest)
|
function checkSizeAndLoad(listener, aRequest) {
|
||||||
{
|
|
||||||
Assert.notEqual(listener.state & SIZE_AVAILABLE, 0);
|
Assert.notEqual(listener.state & SIZE_AVAILABLE, 0);
|
||||||
Assert.notEqual(listener.state & LOAD_COMPLETE, 0);
|
Assert.notEqual(listener.state & LOAD_COMPLETE, 0);
|
||||||
|
|
||||||
do_test_finished();
|
do_test_finished();
|
||||||
}
|
}
|
||||||
|
|
||||||
function secondLoadDone(oldlistener, aRequest)
|
function secondLoadDone(oldlistener, aRequest) {
|
||||||
{
|
|
||||||
do_test_pending();
|
do_test_pending();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -68,11 +69,12 @@ function secondLoadDone(oldlistener, aRequest)
|
||||||
// clone state reliably.
|
// clone state reliably.
|
||||||
var listener = new ImageListener(null, checkSizeAndLoad);
|
var listener = new ImageListener(null, checkSizeAndLoad);
|
||||||
listener.synchronous = false;
|
listener.synchronous = false;
|
||||||
var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
|
var outer = Cc["@mozilla.org/image/tools;1"]
|
||||||
.createScriptedObserver(listener);
|
.getService(Ci.imgITools)
|
||||||
|
.createScriptedObserver(listener);
|
||||||
var staticrequestclone = staticrequest.clone(outer);
|
var staticrequestclone = staticrequest.clone(outer);
|
||||||
requests.push({ request: staticrequestclone, locked: false });
|
requests.push({ request: staticrequestclone, locked: false });
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
// We can't create a static request. Most likely the request we started
|
// We can't create a static request. Most likely the request we started
|
||||||
// with didn't load successfully.
|
// with didn't load successfully.
|
||||||
do_test_finished();
|
do_test_finished();
|
||||||
|
@ -85,22 +87,32 @@ function secondLoadDone(oldlistener, aRequest)
|
||||||
|
|
||||||
// Load the request a second time. This should come from the image cache, and
|
// Load the request a second time. This should come from the image cache, and
|
||||||
// therefore would be at most risk of being served synchronously.
|
// therefore would be at most risk of being served synchronously.
|
||||||
function checkSecondLoad()
|
function checkSecondLoad() {
|
||||||
{
|
|
||||||
do_test_pending();
|
do_test_pending();
|
||||||
|
|
||||||
var listener = new ImageListener(checkClone, secondLoadDone);
|
var listener = new ImageListener(checkClone, secondLoadDone);
|
||||||
var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
|
var outer = Cc["@mozilla.org/image/tools;1"]
|
||||||
.createScriptedObserver(listener);
|
.getService(Ci.imgITools)
|
||||||
|
.createScriptedObserver(listener);
|
||||||
requests.push({
|
requests.push({
|
||||||
request: gCurrentLoader.loadImageXPCOM(uri, null, null, "default", null, null, outer, null, 0, null),
|
request: gCurrentLoader.loadImageXPCOM(
|
||||||
|
uri,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"default",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
outer,
|
||||||
|
null,
|
||||||
|
0,
|
||||||
|
null
|
||||||
|
),
|
||||||
locked: false,
|
locked: false,
|
||||||
});
|
});
|
||||||
listener.synchronous = false;
|
listener.synchronous = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function firstLoadDone(oldlistener, aRequest)
|
function firstLoadDone(oldlistener, aRequest) {
|
||||||
{
|
|
||||||
checkSecondLoad(uri);
|
checkSecondLoad(uri);
|
||||||
|
|
||||||
do_test_finished();
|
do_test_finished();
|
||||||
|
@ -108,33 +120,37 @@ function firstLoadDone(oldlistener, aRequest)
|
||||||
|
|
||||||
// Return a closure that allows us to check the stream listener's status when the
|
// Return a closure that allows us to check the stream listener's status when the
|
||||||
// image finishes loading.
|
// image finishes loading.
|
||||||
function getChannelLoadImageStopCallback(streamlistener, next)
|
function getChannelLoadImageStopCallback(streamlistener, next) {
|
||||||
{
|
|
||||||
return function channelLoadStop(imglistener, aRequest) {
|
return function channelLoadStop(imglistener, aRequest) {
|
||||||
|
|
||||||
next();
|
next();
|
||||||
|
|
||||||
do_test_finished();
|
do_test_finished();
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the request a second time. This should come from the image cache, and
|
// Load the request a second time. This should come from the image cache, and
|
||||||
// therefore would be at most risk of being served synchronously.
|
// therefore would be at most risk of being served synchronously.
|
||||||
function checkSecondChannelLoad()
|
function checkSecondChannelLoad() {
|
||||||
{
|
|
||||||
do_test_pending();
|
do_test_pending();
|
||||||
var channel = NetUtil.newChannel({uri, loadUsingSystemPrincipal: true});
|
var channel = NetUtil.newChannel({ uri, loadUsingSystemPrincipal: true });
|
||||||
var channellistener = new ChannelListener();
|
var channellistener = new ChannelListener();
|
||||||
channel.asyncOpen(channellistener);
|
channel.asyncOpen(channellistener);
|
||||||
|
|
||||||
var listener = new ImageListener(null,
|
var listener = new ImageListener(
|
||||||
getChannelLoadImageStopCallback(channellistener,
|
null,
|
||||||
all_done_callback));
|
getChannelLoadImageStopCallback(channellistener, all_done_callback)
|
||||||
var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
|
);
|
||||||
.createScriptedObserver(listener);
|
var outer = Cc["@mozilla.org/image/tools;1"]
|
||||||
|
.getService(Ci.imgITools)
|
||||||
|
.createScriptedObserver(listener);
|
||||||
var outlistener = {};
|
var outlistener = {};
|
||||||
requests.push({
|
requests.push({
|
||||||
request: gCurrentLoader.loadImageWithChannelXPCOM(channel, outer, null, outlistener),
|
request: gCurrentLoader.loadImageWithChannelXPCOM(
|
||||||
|
channel,
|
||||||
|
outer,
|
||||||
|
null,
|
||||||
|
outlistener
|
||||||
|
),
|
||||||
locked: false,
|
locked: false,
|
||||||
});
|
});
|
||||||
channellistener.outputListener = outlistener.value;
|
channellistener.outputListener = outlistener.value;
|
||||||
|
@ -142,24 +158,32 @@ function checkSecondChannelLoad()
|
||||||
listener.synchronous = false;
|
listener.synchronous = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function run_loadImageWithChannel_tests()
|
function run_loadImageWithChannel_tests() {
|
||||||
{
|
|
||||||
// To ensure we're testing what we expect to, create a new loader and cache.
|
// To ensure we're testing what we expect to, create a new loader and cache.
|
||||||
gCurrentLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader);
|
gCurrentLoader = Cc["@mozilla.org/image/loader;1"].createInstance(
|
||||||
|
Ci.imgILoader
|
||||||
|
);
|
||||||
|
|
||||||
do_test_pending();
|
do_test_pending();
|
||||||
var channel = NetUtil.newChannel({uri, loadUsingSystemPrincipal: true});
|
var channel = NetUtil.newChannel({ uri, loadUsingSystemPrincipal: true });
|
||||||
var channellistener = new ChannelListener();
|
var channellistener = new ChannelListener();
|
||||||
channel.asyncOpen(channellistener);
|
channel.asyncOpen(channellistener);
|
||||||
|
|
||||||
var listener = new ImageListener(null,
|
var listener = new ImageListener(
|
||||||
getChannelLoadImageStopCallback(channellistener,
|
null,
|
||||||
checkSecondChannelLoad));
|
getChannelLoadImageStopCallback(channellistener, checkSecondChannelLoad)
|
||||||
var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
|
);
|
||||||
.createScriptedObserver(listener);
|
var outer = Cc["@mozilla.org/image/tools;1"]
|
||||||
|
.getService(Ci.imgITools)
|
||||||
|
.createScriptedObserver(listener);
|
||||||
var outlistener = {};
|
var outlistener = {};
|
||||||
requests.push({
|
requests.push({
|
||||||
request: gCurrentLoader.loadImageWithChannelXPCOM(channel, outer, null, outlistener),
|
request: gCurrentLoader.loadImageWithChannelXPCOM(
|
||||||
|
channel,
|
||||||
|
outer,
|
||||||
|
null,
|
||||||
|
outlistener
|
||||||
|
),
|
||||||
locked: false,
|
locked: false,
|
||||||
});
|
});
|
||||||
channellistener.outputListener = outlistener.value;
|
channellistener.outputListener = outlistener.value;
|
||||||
|
@ -167,54 +191,84 @@ function run_loadImageWithChannel_tests()
|
||||||
listener.synchronous = false;
|
listener.synchronous = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function all_done_callback()
|
function all_done_callback() {
|
||||||
{
|
server.stop(function() {
|
||||||
server.stop(function() { do_test_finished(); });
|
do_test_finished();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function startImageCallback(otherCb)
|
function startImageCallback(otherCb) {
|
||||||
{
|
return function(listener, request) {
|
||||||
return function(listener, request)
|
|
||||||
{
|
|
||||||
// Make sure we can load the same image immediately out of the cache.
|
// Make sure we can load the same image immediately out of the cache.
|
||||||
do_test_pending();
|
do_test_pending();
|
||||||
var listener2 = new ImageListener(null, function(foo, bar) { do_test_finished(); });
|
var listener2 = new ImageListener(null, function(foo, bar) {
|
||||||
var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
|
do_test_finished();
|
||||||
.createScriptedObserver(listener2);
|
});
|
||||||
|
var outer = Cc["@mozilla.org/image/tools;1"]
|
||||||
|
.getService(Ci.imgITools)
|
||||||
|
.createScriptedObserver(listener2);
|
||||||
requests.push({
|
requests.push({
|
||||||
request: gCurrentLoader.loadImageXPCOM(uri, null, null, "default", null, null, outer, null, 0, null),
|
request: gCurrentLoader.loadImageXPCOM(
|
||||||
|
uri,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"default",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
outer,
|
||||||
|
null,
|
||||||
|
0,
|
||||||
|
null
|
||||||
|
),
|
||||||
locked: false,
|
locked: false,
|
||||||
});
|
});
|
||||||
listener2.synchronous = false;
|
listener2.synchronous = false;
|
||||||
|
|
||||||
// Now that we've started another load, chain to the callback.
|
// Now that we've started another load, chain to the callback.
|
||||||
otherCb(listener, request);
|
otherCb(listener, request);
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var gCurrentLoader;
|
var gCurrentLoader;
|
||||||
|
|
||||||
function cleanup()
|
function cleanup() {
|
||||||
{
|
for (let { request, locked } of requests) {
|
||||||
for (let {request, locked} of requests) {
|
|
||||||
if (locked) {
|
if (locked) {
|
||||||
try { request.unlockImage() } catch (e) {}
|
try {
|
||||||
|
request.unlockImage();
|
||||||
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
request.cancelAndForgetObserver(0);
|
request.cancelAndForgetObserver(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function run_test()
|
function run_test() {
|
||||||
{
|
|
||||||
registerCleanupFunction(cleanup);
|
registerCleanupFunction(cleanup);
|
||||||
|
|
||||||
gCurrentLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader);
|
gCurrentLoader = Cc["@mozilla.org/image/loader;1"].createInstance(
|
||||||
|
Ci.imgILoader
|
||||||
|
);
|
||||||
|
|
||||||
do_test_pending();
|
do_test_pending();
|
||||||
var listener = new ImageListener(startImageCallback(checkClone), firstLoadDone);
|
var listener = new ImageListener(
|
||||||
var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
|
startImageCallback(checkClone),
|
||||||
.createScriptedObserver(listener);
|
firstLoadDone
|
||||||
var req = gCurrentLoader.loadImageXPCOM(uri, null, null, "default", null, null, outer, null, 0, null);
|
);
|
||||||
|
var outer = Cc["@mozilla.org/image/tools;1"]
|
||||||
|
.getService(Ci.imgITools)
|
||||||
|
.createScriptedObserver(listener);
|
||||||
|
var req = gCurrentLoader.loadImageXPCOM(
|
||||||
|
uri,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"default",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
outer,
|
||||||
|
null,
|
||||||
|
0,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
// Ensure that we don't cause any mayhem when we lock an image.
|
// Ensure that we don't cause any mayhem when we lock an image.
|
||||||
req.lockImage();
|
req.lockImage();
|
||||||
|
|
|
@ -21,44 +21,37 @@ do_get_profile();
|
||||||
|
|
||||||
// An implementation of imgIScriptedNotificationObserver with the ability to
|
// An implementation of imgIScriptedNotificationObserver with the ability to
|
||||||
// call specified functions on onStartRequest and onStopRequest.
|
// call specified functions on onStartRequest and onStopRequest.
|
||||||
function ImageListener(start_callback, stop_callback)
|
function ImageListener(start_callback, stop_callback) {
|
||||||
{
|
this.sizeAvailable = function onSizeAvailable(aRequest) {
|
||||||
this.sizeAvailable = function onSizeAvailable(aRequest)
|
|
||||||
{
|
|
||||||
Assert.ok(!this.synchronous);
|
Assert.ok(!this.synchronous);
|
||||||
|
|
||||||
this.state |= SIZE_AVAILABLE;
|
this.state |= SIZE_AVAILABLE;
|
||||||
|
|
||||||
if (this.start_callback)
|
if (this.start_callback) {
|
||||||
this.start_callback(this, aRequest);
|
this.start_callback(this, aRequest);
|
||||||
}
|
}
|
||||||
this.frameComplete = function onFrameComplete(aRequest)
|
};
|
||||||
{
|
this.frameComplete = function onFrameComplete(aRequest) {
|
||||||
Assert.ok(!this.synchronous);
|
Assert.ok(!this.synchronous);
|
||||||
|
|
||||||
this.state |= FRAME_COMPLETE;
|
this.state |= FRAME_COMPLETE;
|
||||||
}
|
};
|
||||||
this.decodeComplete = function onDecodeComplete(aRequest)
|
this.decodeComplete = function onDecodeComplete(aRequest) {
|
||||||
{
|
|
||||||
Assert.ok(!this.synchronous);
|
Assert.ok(!this.synchronous);
|
||||||
|
|
||||||
this.state |= DECODE_COMPLETE;
|
this.state |= DECODE_COMPLETE;
|
||||||
}
|
};
|
||||||
this.loadComplete = function onLoadcomplete(aRequest)
|
this.loadComplete = function onLoadcomplete(aRequest) {
|
||||||
{
|
|
||||||
Assert.ok(!this.synchronous);
|
Assert.ok(!this.synchronous);
|
||||||
|
|
||||||
this.state |= LOAD_COMPLETE;
|
this.state |= LOAD_COMPLETE;
|
||||||
|
|
||||||
if (this.stop_callback)
|
if (this.stop_callback) {
|
||||||
this.stop_callback(this, aRequest);
|
this.stop_callback(this, aRequest);
|
||||||
}
|
}
|
||||||
this.frameUpdate = function onFrameUpdate(aRequest)
|
};
|
||||||
{
|
this.frameUpdate = function onFrameUpdate(aRequest) {};
|
||||||
}
|
this.isAnimated = function onIsAnimated() {};
|
||||||
this.isAnimated = function onIsAnimated()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize the synchronous flag to true to start. This must be set to
|
// Initialize the synchronous flag to true to start. This must be set to
|
||||||
// false before exiting to the event loop!
|
// false before exiting to the event loop!
|
||||||
|
@ -76,41 +69,50 @@ function ImageListener(start_callback, stop_callback)
|
||||||
this.state = 0;
|
this.state = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function NS_FAILED(val)
|
function NS_FAILED(val) {
|
||||||
{
|
|
||||||
return !!(val & 0x80000000);
|
return !!(val & 0x80000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ChannelListener()
|
function ChannelListener() {
|
||||||
{
|
this.onStartRequest = function onStartRequest(aRequest) {
|
||||||
this.onStartRequest = function onStartRequest(aRequest)
|
if (this.outputListener) {
|
||||||
{
|
|
||||||
if (this.outputListener)
|
|
||||||
this.outputListener.onStartRequest(aRequest);
|
this.outputListener.onStartRequest(aRequest);
|
||||||
|
}
|
||||||
|
|
||||||
this.requestStatus |= START_REQUEST;
|
this.requestStatus |= START_REQUEST;
|
||||||
}
|
};
|
||||||
|
|
||||||
this.onDataAvailable = function onDataAvailable(aRequest, aInputStream, aOffset, aCount)
|
this.onDataAvailable = function onDataAvailable(
|
||||||
{
|
aRequest,
|
||||||
if (this.outputListener)
|
aInputStream,
|
||||||
this.outputListener.onDataAvailable(aRequest, aInputStream, aOffset, aCount);
|
aOffset,
|
||||||
|
aCount
|
||||||
|
) {
|
||||||
|
if (this.outputListener) {
|
||||||
|
this.outputListener.onDataAvailable(
|
||||||
|
aRequest,
|
||||||
|
aInputStream,
|
||||||
|
aOffset,
|
||||||
|
aCount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
this.requestStatus |= DATA_AVAILABLE;
|
this.requestStatus |= DATA_AVAILABLE;
|
||||||
}
|
};
|
||||||
|
|
||||||
this.onStopRequest = function onStopRequest(aRequest, aStatusCode)
|
this.onStopRequest = function onStopRequest(aRequest, aStatusCode) {
|
||||||
{
|
if (this.outputListener) {
|
||||||
if (this.outputListener)
|
|
||||||
this.outputListener.onStopRequest(aRequest, aStatusCode);
|
this.outputListener.onStopRequest(aRequest, aStatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
// If we failed (or were canceled - failure is implied if canceled),
|
// If we failed (or were canceled - failure is implied if canceled),
|
||||||
// there's no use tracking our state, since it's meaningless.
|
// there's no use tracking our state, since it's meaningless.
|
||||||
if (NS_FAILED(aStatusCode))
|
if (NS_FAILED(aStatusCode)) {
|
||||||
this.requestStatus = 0;
|
this.requestStatus = 0;
|
||||||
else
|
} else {
|
||||||
this.requestStatus |= STOP_REQUEST;
|
this.requestStatus |= STOP_REQUEST;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// A listener to pass the notifications we get to.
|
// A listener to pass the notifications we get to.
|
||||||
this.outputListener = null;
|
this.outputListener = null;
|
||||||
|
|
|
@ -3,8 +3,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// A simple 3x3 png; rows go red, green, blue. Stolen from the PNG encoder test.
|
// A simple 3x3 png; rows go red, green, blue. Stolen from the PNG encoder test.
|
||||||
var pngspec = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAEUlEQVQImWP4z8AAQTAamQkAhpcI+DeMzFcAAAAASUVORK5CYII=";
|
var pngspec =
|
||||||
var ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
|
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAEUlEQVQImWP4z8AAQTAamQkAhpcI+DeMzFcAAAAASUVORK5CYII=";
|
||||||
|
var ioService = Cc["@mozilla.org/network/io-service;1"].getService(
|
||||||
|
Ci.nsIIOService
|
||||||
|
);
|
||||||
var uri = ioService.newURI(pngspec);
|
var uri = ioService.newURI(pngspec);
|
||||||
|
|
||||||
load('async_load_tests.js');
|
load("async_load_tests.js");
|
||||||
|
|
|
@ -2,15 +2,20 @@
|
||||||
* Test to ensure that load/decode notifications are delivered completely and
|
* Test to ensure that load/decode notifications are delivered completely and
|
||||||
* asynchronously when dealing with a file that's a 404.
|
* asynchronously when dealing with a file that's a 404.
|
||||||
*/
|
*/
|
||||||
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
const { XPCOMUtils } = ChromeUtils.import(
|
||||||
|
"resource://gre/modules/XPCOMUtils.jsm"
|
||||||
|
);
|
||||||
|
|
||||||
var ioService = Cc["@mozilla.org/network/io-service;1"]
|
var ioService = Cc["@mozilla.org/network/io-service;1"].getService(
|
||||||
.getService(Ci.nsIIOService);
|
Ci.nsIIOService
|
||||||
|
);
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGetter(this, "uri", function() {
|
XPCOMUtils.defineLazyGetter(this, "uri", function() {
|
||||||
return ioService.newURI("http://localhost:" +
|
return ioService.newURI(
|
||||||
server.identity.primaryPort +
|
"http://localhost:" +
|
||||||
"/async-notification-never-here.jpg");
|
server.identity.primaryPort +
|
||||||
|
"/async-notification-never-here.jpg"
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
load('async_load_tests.js');
|
load("async_load_tests.js");
|
||||||
|
|
|
@ -7,8 +7,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// transparent-animation.gif from the gif reftests.
|
// transparent-animation.gif from the gif reftests.
|
||||||
var spec = "data:image/gif;base64,R0lGODlhZABkAIABAP8AAP///yH5BAkBAAEALAAAAABLAGQAAAK8jI+py+0Po5y02ouz3rz7D4biSJbmiabqyrbuC8fyTNf2jef6zvf+DwwKh8Si8YhMKpchgPMJjUqnVOipis1ir9qul+sNV8HistVkTj/JajG7/UXDy+95tm4fy/NdPF/q93dWIqgVWAhwWKgoyPjnyAeZJ2lHOWcJh9mmqcaZ5mkGSreHOCXqRloadRrGGkeoapoa6+TaN0tra4gbq3vHq+q7BVwqrMeEnKy8zNzs/AwdLT1NXW19jZ1tUgAAIfkECQEAAQAsAAAAADQAZAAAArCMj6nL7Q+jnLTai7PevPsPhuJIluaJpurKtu4Lx/JM1/aN5/rO9/7vAAiHxKLxiCRCkswmc+mMSqHSapJqzSof2u4Q67WCw1MuOTs+N9Pqq7kdZcON8vk2aF+/88g6358HaCc4Rwhn2IaopnjGSOYYBukl2UWpZYm2x0enuXnX4NnXGQqAKTYaalqlWoZH+snwWsQah+pJ64Sr5ypbCvQLHCw8TFxsfIycrLzM3PxQAAAh+QQJAQABACwAAAAAGwBkAAACUIyPqcvtD6OctNqLs968+w+G4kiW5omm6sq27gTE8kzX9o3n+s73/g8MCofEovGITCqXzKbzCY1Kp9Sq9YrNarfcrvdrfYnH5LL5jE6r16sCADs=";
|
var spec =
|
||||||
var ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
|
"data:image/gif;base64,R0lGODlhZABkAIABAP8AAP///yH5BAkBAAEALAAAAABLAGQAAAK8jI+py+0Po5y02ouz3rz7D4biSJbmiabqyrbuC8fyTNf2jef6zvf+DwwKh8Si8YhMKpchgPMJjUqnVOipis1ir9qul+sNV8HistVkTj/JajG7/UXDy+95tm4fy/NdPF/q93dWIqgVWAhwWKgoyPjnyAeZJ2lHOWcJh9mmqcaZ5mkGSreHOCXqRloadRrGGkeoapoa6+TaN0tra4gbq3vHq+q7BVwqrMeEnKy8zNzs/AwdLT1NXW19jZ1tUgAAIfkECQEAAQAsAAAAADQAZAAAArCMj6nL7Q+jnLTai7PevPsPhuJIluaJpurKtu4Lx/JM1/aN5/rO9/7vAAiHxKLxiCRCkswmc+mMSqHSapJqzSof2u4Q67WCw1MuOTs+N9Pqq7kdZcON8vk2aF+/88g6358HaCc4Rwhn2IaopnjGSOYYBukl2UWpZYm2x0enuXnX4NnXGQqAKTYaalqlWoZH+snwWsQah+pJ64Sr5ypbCvQLHCw8TFxsfIycrLzM3PxQAAAh+QQJAQABACwAAAAAGwBkAAACUIyPqcvtD6OctNqLs968+w+G4kiW5omm6sq27gTE8kzX9o3n+s73/g8MCofEovGITCqXzKbzCY1Kp9Sq9YrNarfcrvdrfYnH5LL5jE6r16sCADs=";
|
||||||
|
var ioService = Cc["@mozilla.org/network/io-service;1"].getService(
|
||||||
|
Ci.nsIIOService
|
||||||
|
);
|
||||||
var uri = ioService.newURI(spec);
|
var uri = ioService.newURI(spec);
|
||||||
|
|
||||||
load('async_load_tests.js');
|
load("async_load_tests.js");
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -4,250 +4,379 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var png1A = {
|
var png1A = {
|
||||||
// A 3x3 image, rows are red, green, blue.
|
// A 3x3 image, rows are red, green, blue.
|
||||||
// RGB format, transparency defaults.
|
// RGB format, transparency defaults.
|
||||||
|
|
||||||
transparency : null,
|
transparency: null,
|
||||||
|
|
||||||
frames : [
|
frames: [
|
||||||
{
|
{
|
||||||
width : 3, height : 3,
|
width: 3,
|
||||||
|
height: 3,
|
||||||
|
|
||||||
format : Ci.imgIEncoder.INPUT_FORMAT_RGB, stride : 9,
|
format: Ci.imgIEncoder.INPUT_FORMAT_RGB,
|
||||||
|
stride: 9,
|
||||||
|
|
||||||
pixels : [
|
pixels: [
|
||||||
255,0,0, 255,0,0, 255,0,0,
|
255,
|
||||||
0,255,0, 0,255,0, 0,255,0,
|
0,
|
||||||
0,0,255, 0,0,255, 0,0,255,
|
0,
|
||||||
]
|
255,
|
||||||
}
|
0,
|
||||||
|
0,
|
||||||
],
|
255,
|
||||||
expected : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAEUlEQVQImWP4z8AAQTAamQkAhpcI+DeMzFcAAAAASUVORK5CYII="
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
expected:
|
||||||
|
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAEUlEQVQImWP4z8AAQTAamQkAhpcI+DeMzFcAAAAASUVORK5CYII=",
|
||||||
};
|
};
|
||||||
|
|
||||||
var png1B = {
|
var png1B = {
|
||||||
// A 3x3 image, rows are red, green, blue.
|
// A 3x3 image, rows are red, green, blue.
|
||||||
// RGB format, transparency=none.
|
// RGB format, transparency=none.
|
||||||
|
|
||||||
transparency : "none",
|
transparency: "none",
|
||||||
|
|
||||||
frames : [
|
frames: [
|
||||||
{
|
{
|
||||||
width : 3, height : 3,
|
width: 3,
|
||||||
|
height: 3,
|
||||||
|
|
||||||
format : Ci.imgIEncoder.INPUT_FORMAT_RGB, stride : 9,
|
format: Ci.imgIEncoder.INPUT_FORMAT_RGB,
|
||||||
|
stride: 9,
|
||||||
|
|
||||||
pixels : [
|
pixels: [
|
||||||
255,0,0, 255,0,0, 255,0,0,
|
255,
|
||||||
0,255,0, 0,255,0, 0,255,0,
|
0,
|
||||||
0,0,255, 0,0,255, 0,0,255,
|
0,
|
||||||
]
|
255,
|
||||||
}
|
0,
|
||||||
|
0,
|
||||||
],
|
255,
|
||||||
expected : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAEUlEQVQImWP4z8AAQTAamQkAhpcI+DeMzFcAAAAASUVORK5CYII="
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
expected:
|
||||||
|
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAEUlEQVQImWP4z8AAQTAamQkAhpcI+DeMzFcAAAAASUVORK5CYII=",
|
||||||
};
|
};
|
||||||
|
|
||||||
var png2A = {
|
var png2A = {
|
||||||
// A 3x3 image, rows are: red, green, blue. Columns are: 0%, 33%, 66% transparent.
|
// A 3x3 image, rows are: red, green, blue. Columns are: 0%, 33%, 66% transparent.
|
||||||
|
|
||||||
transparency : null,
|
transparency: null,
|
||||||
|
|
||||||
frames : [
|
frames: [
|
||||||
{
|
{
|
||||||
width : 3, height : 3,
|
width: 3,
|
||||||
|
height: 3,
|
||||||
|
|
||||||
format : Ci.imgIEncoder.INPUT_FORMAT_RGBA, stride : 12,
|
format: Ci.imgIEncoder.INPUT_FORMAT_RGBA,
|
||||||
|
stride: 12,
|
||||||
|
|
||||||
pixels : [
|
pixels: [
|
||||||
255,0,0,255, 255,0,0,170, 255,0,0,85,
|
255,
|
||||||
0,255,0,255, 0,255,0,170, 0,255,0,85,
|
0,
|
||||||
0,0,255,255, 0,0,255,170, 0,0,255,85
|
0,
|
||||||
]
|
255,
|
||||||
}
|
255,
|
||||||
|
0,
|
||||||
],
|
0,
|
||||||
expected : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAYAAABWKLW/AAAAIElEQVQImSXJMQEAMAwEIUy+yZi8DmVFFBcjycn86GgPJw4O8v9DkkEAAAAASUVORK5CYII="
|
170,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
85,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
170,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
85,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
170,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
85,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
expected:
|
||||||
|
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAYAAABWKLW/AAAAIElEQVQImSXJMQEAMAwEIUy+yZi8DmVFFBcjycn86GgPJw4O8v9DkkEAAAAASUVORK5CYII=",
|
||||||
};
|
};
|
||||||
|
|
||||||
var png2B = {
|
var png2B = {
|
||||||
// A 3x3 image, rows are: red, green, blue. Columns are: 0%, 33%, 66% transparent,
|
// A 3x3 image, rows are: red, green, blue. Columns are: 0%, 33%, 66% transparent,
|
||||||
// but transparency will be ignored.
|
// but transparency will be ignored.
|
||||||
|
|
||||||
transparency : "none",
|
transparency: "none",
|
||||||
|
|
||||||
frames : [
|
frames: [
|
||||||
{
|
{
|
||||||
width : 3, height : 3,
|
width: 3,
|
||||||
|
height: 3,
|
||||||
|
|
||||||
format : Ci.imgIEncoder.INPUT_FORMAT_RGBA, stride : 12,
|
format: Ci.imgIEncoder.INPUT_FORMAT_RGBA,
|
||||||
|
stride: 12,
|
||||||
|
|
||||||
pixels : [
|
pixels: [
|
||||||
255,0,0,255, 255,0,0,170, 255,0,0,85,
|
255,
|
||||||
0,255,0,255, 0,255,0,170, 0,255,0,85,
|
0,
|
||||||
0,0,255,255, 0,0,255,170, 0,0,255,85
|
0,
|
||||||
]
|
255,
|
||||||
}
|
255,
|
||||||
|
0,
|
||||||
],
|
0,
|
||||||
expected : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAEUlEQVQImWP4z8AAQTAamQkAhpcI+DeMzFcAAAAASUVORK5CYII="
|
170,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
85,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
170,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
85,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
170,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
85,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
expected:
|
||||||
|
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAEUlEQVQImWP4z8AAQTAamQkAhpcI+DeMzFcAAAAASUVORK5CYII=",
|
||||||
};
|
};
|
||||||
|
|
||||||
// Main test entry point.
|
// Main test entry point.
|
||||||
function run_test() {
|
function run_test() {
|
||||||
dump("Checking png1A...\n")
|
dump("Checking png1A...\n");
|
||||||
run_test_for(png1A);
|
run_test_for(png1A);
|
||||||
dump("Checking png1B...\n")
|
dump("Checking png1B...\n");
|
||||||
run_test_for(png1B);
|
run_test_for(png1B);
|
||||||
dump("Checking png2A...\n")
|
dump("Checking png2A...\n");
|
||||||
run_test_for(png2A);
|
run_test_for(png2A);
|
||||||
dump("Checking png2B...\n")
|
dump("Checking png2B...\n");
|
||||||
run_test_for(png2B);
|
run_test_for(png2B);
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
function run_test_for(input) {
|
function run_test_for(input) {
|
||||||
var encoder, dataURL;
|
var encoder, dataURL;
|
||||||
|
|
||||||
encoder = encodeImage(input);
|
encoder = encodeImage(input);
|
||||||
dataURL = makeDataURL(encoder, "image/png");
|
dataURL = makeDataURL(encoder, "image/png");
|
||||||
Assert.equal(dataURL, input.expected);
|
Assert.equal(dataURL, input.expected);
|
||||||
|
|
||||||
encoder = encodeImageAsync(input);
|
|
||||||
dataURL = makeDataURLFromAsync(encoder, "image/png", input.expected);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
encoder = encodeImageAsync(input);
|
||||||
|
dataURL = makeDataURLFromAsync(encoder, "image/png", input.expected);
|
||||||
|
}
|
||||||
|
|
||||||
function encodeImage(input) {
|
function encodeImage(input) {
|
||||||
var encoder = Cc["@mozilla.org/image/encoder;2?type=image/png"].createInstance();
|
var encoder = Cc[
|
||||||
encoder.QueryInterface(Ci.imgIEncoder);
|
"@mozilla.org/image/encoder;2?type=image/png"
|
||||||
|
].createInstance();
|
||||||
|
encoder.QueryInterface(Ci.imgIEncoder);
|
||||||
|
|
||||||
var options = "";
|
var options = "";
|
||||||
if (input.transparency) {
|
if (input.transparency) {
|
||||||
options += "transparency=" + input.transparency;
|
options += "transparency=" + input.transparency;
|
||||||
}
|
}
|
||||||
|
|
||||||
var frame = input.frames[0];
|
var frame = input.frames[0];
|
||||||
encoder.initFromData(frame.pixels, frame.pixels.length,
|
encoder.initFromData(
|
||||||
frame.width, frame.height, frame.stride,
|
frame.pixels,
|
||||||
frame.format, options);
|
frame.pixels.length,
|
||||||
return encoder;
|
frame.width,
|
||||||
|
frame.height,
|
||||||
|
frame.stride,
|
||||||
|
frame.format,
|
||||||
|
options
|
||||||
|
);
|
||||||
|
return encoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _encodeImageAsyncFactory(frame, options, encoder)
|
function _encodeImageAsyncFactory(frame, options, encoder) {
|
||||||
{
|
function finishEncode() {
|
||||||
function finishEncode() {
|
encoder.addImageFrame(
|
||||||
encoder.addImageFrame(frame.pixels, frame.pixels.length,
|
frame.pixels,
|
||||||
frame.width, frame.height, frame.stride,
|
frame.pixels.length,
|
||||||
frame.format, options);
|
frame.width,
|
||||||
encoder.endImageEncode();
|
frame.height,
|
||||||
}
|
frame.stride,
|
||||||
return finishEncode;
|
frame.format,
|
||||||
|
options
|
||||||
|
);
|
||||||
|
encoder.endImageEncode();
|
||||||
|
}
|
||||||
|
return finishEncode;
|
||||||
}
|
}
|
||||||
|
|
||||||
function encodeImageAsync(input)
|
function encodeImageAsync(input) {
|
||||||
{
|
var encoder = Cc[
|
||||||
var encoder = Cc["@mozilla.org/image/encoder;2?type=image/png"].createInstance();
|
"@mozilla.org/image/encoder;2?type=image/png"
|
||||||
encoder.QueryInterface(Ci.imgIEncoder);
|
].createInstance();
|
||||||
|
encoder.QueryInterface(Ci.imgIEncoder);
|
||||||
|
|
||||||
var options = "";
|
var options = "";
|
||||||
if (input.transparency) {
|
if (input.transparency) {
|
||||||
options += "transparency=" + input.transparency;
|
options += "transparency=" + input.transparency;
|
||||||
}
|
}
|
||||||
|
|
||||||
var frame = input.frames[0];
|
var frame = input.frames[0];
|
||||||
encoder.startImageEncode(frame.width, frame.height,
|
encoder.startImageEncode(frame.width, frame.height, frame.format, options);
|
||||||
frame.format, options);
|
|
||||||
|
|
||||||
do_timeout(50, _encodeImageAsyncFactory(frame, options, encoder));
|
do_timeout(50, _encodeImageAsyncFactory(frame, options, encoder));
|
||||||
return encoder;
|
return encoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function makeDataURL(encoder, mimetype) {
|
function makeDataURL(encoder, mimetype) {
|
||||||
var rawStream = encoder.QueryInterface(Ci.nsIInputStream);
|
var rawStream = encoder.QueryInterface(Ci.nsIInputStream);
|
||||||
|
|
||||||
var stream = Cc["@mozilla.org/binaryinputstream;1"].createInstance();
|
var stream = Cc["@mozilla.org/binaryinputstream;1"].createInstance();
|
||||||
stream.QueryInterface(Ci.nsIBinaryInputStream);
|
stream.QueryInterface(Ci.nsIBinaryInputStream);
|
||||||
|
|
||||||
stream.setInputStream(rawStream);
|
stream.setInputStream(rawStream);
|
||||||
|
|
||||||
var bytes = stream.readByteArray(stream.available()); // returns int[]
|
var bytes = stream.readByteArray(stream.available()); // returns int[]
|
||||||
|
|
||||||
var base64String = toBase64(bytes);
|
var base64String = toBase64(bytes);
|
||||||
|
|
||||||
return "data:" + mimetype + ";base64," + base64String;
|
return "data:" + mimetype + ";base64," + base64String;
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeDataURLFromAsync(encoder, mimetype, expected) {
|
function makeDataURLFromAsync(encoder, mimetype, expected) {
|
||||||
do_test_pending();
|
do_test_pending();
|
||||||
var rawStream = encoder.QueryInterface(Ci.nsIAsyncInputStream);
|
var rawStream = encoder.QueryInterface(Ci.nsIAsyncInputStream);
|
||||||
|
|
||||||
var currentThread = Cc["@mozilla.org/thread-manager;1"].getService().currentThread;
|
var currentThread = Cc["@mozilla.org/thread-manager;1"].getService()
|
||||||
|
.currentThread;
|
||||||
|
|
||||||
var bytes = [];
|
var bytes = [];
|
||||||
|
|
||||||
var binarystream = Cc["@mozilla.org/binaryinputstream;1"].createInstance();
|
var binarystream = Cc["@mozilla.org/binaryinputstream;1"].createInstance();
|
||||||
binarystream.QueryInterface(Ci.nsIBinaryInputStream);
|
binarystream.QueryInterface(Ci.nsIBinaryInputStream);
|
||||||
|
|
||||||
var asyncReader =
|
var asyncReader = {
|
||||||
{
|
onInputStreamReady(stream) {
|
||||||
onInputStreamReady(stream)
|
binarystream.setInputStream(stream);
|
||||||
{
|
var available = 0;
|
||||||
binarystream.setInputStream(stream);
|
try {
|
||||||
var available = 0;
|
available = stream.available();
|
||||||
try {
|
} catch (e) {}
|
||||||
available = stream.available();
|
|
||||||
} catch(e) { }
|
|
||||||
|
|
||||||
if (available > 0)
|
if (available > 0) {
|
||||||
{
|
bytes = bytes.concat(binarystream.readByteArray(available));
|
||||||
bytes = bytes.concat(binarystream.readByteArray(available));
|
stream.asyncWait(this, 0, 0, currentThread);
|
||||||
stream.asyncWait(this, 0, 0, currentThread);
|
} else {
|
||||||
} else {
|
var base64String = toBase64(bytes);
|
||||||
var base64String = toBase64(bytes);
|
var dataURL = "data:" + mimetype + ";base64," + base64String;
|
||||||
var dataURL = "data:" + mimetype + ";base64," + base64String;
|
Assert.equal(dataURL, expected);
|
||||||
Assert.equal(dataURL, expected);
|
do_test_finished();
|
||||||
do_test_finished();
|
}
|
||||||
}
|
},
|
||||||
|
};
|
||||||
}
|
rawStream.asyncWait(asyncReader, 0, 0, currentThread);
|
||||||
};
|
|
||||||
rawStream.asyncWait(asyncReader, 0, 0, currentThread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* toBase64 copied from extensions/xml-rpc/src/nsXmlRpcClient.js */
|
/* toBase64 copied from extensions/xml-rpc/src/nsXmlRpcClient.js */
|
||||||
|
|
||||||
/* Convert data (an array of integers) to a Base64 string. */
|
/* Convert data (an array of integers) to a Base64 string. */
|
||||||
const toBase64Table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' +
|
const toBase64Table =
|
||||||
'0123456789+/';
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789+/";
|
||||||
const base64Pad = '=';
|
const base64Pad = "=";
|
||||||
function toBase64(data) {
|
function toBase64(data) {
|
||||||
var result = '';
|
var result = "";
|
||||||
var length = data.length;
|
var length = data.length;
|
||||||
var i;
|
var i;
|
||||||
// Convert every three bytes to 4 ascii characters.
|
// Convert every three bytes to 4 ascii characters.
|
||||||
for (i = 0; i < (length - 2); i += 3) {
|
for (i = 0; i < length - 2; i += 3) {
|
||||||
result += toBase64Table[data[i] >> 2];
|
result += toBase64Table[data[i] >> 2];
|
||||||
result += toBase64Table[((data[i] & 0x03) << 4) + (data[i+1] >> 4)];
|
result += toBase64Table[((data[i] & 0x03) << 4) + (data[i + 1] >> 4)];
|
||||||
result += toBase64Table[((data[i+1] & 0x0f) << 2) + (data[i+2] >> 6)];
|
result += toBase64Table[((data[i + 1] & 0x0f) << 2) + (data[i + 2] >> 6)];
|
||||||
result += toBase64Table[data[i+2] & 0x3f];
|
result += toBase64Table[data[i + 2] & 0x3f];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the remaining 1 or 2 bytes, pad out to 4 characters.
|
// Convert the remaining 1 or 2 bytes, pad out to 4 characters.
|
||||||
if (length%3) {
|
if (length % 3) {
|
||||||
i = length - (length%3);
|
i = length - (length % 3);
|
||||||
result += toBase64Table[data[i] >> 2];
|
result += toBase64Table[data[i] >> 2];
|
||||||
if ((length%3) == 2) {
|
if (length % 3 == 2) {
|
||||||
result += toBase64Table[((data[i] & 0x03) << 4) + (data[i+1] >> 4)];
|
result += toBase64Table[((data[i] & 0x03) << 4) + (data[i + 1] >> 4)];
|
||||||
result += toBase64Table[(data[i+1] & 0x0f) << 2];
|
result += toBase64Table[(data[i + 1] & 0x0f) << 2];
|
||||||
result += base64Pad;
|
result += base64Pad;
|
||||||
} else {
|
} else {
|
||||||
result += toBase64Table[(data[i] & 0x03) << 4];
|
result += toBase64Table[(data[i] & 0x03) << 4];
|
||||||
result += base64Pad + base64Pad;
|
result += base64Pad + base64Pad;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1,18 +1,24 @@
|
||||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||||
const {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
|
const { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
|
||||||
const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
|
const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
|
||||||
|
|
||||||
var server = new HttpServer();
|
var server = new HttpServer();
|
||||||
server.registerPathHandler('/image.png', imageHandler);
|
server.registerPathHandler("/image.png", imageHandler);
|
||||||
server.start(-1);
|
server.start(-1);
|
||||||
|
|
||||||
load('image_load_helpers.js');
|
load("image_load_helpers.js");
|
||||||
|
|
||||||
var gHits = 0;
|
var gHits = 0;
|
||||||
|
|
||||||
var gIoService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
|
var gIoService = Cc["@mozilla.org/network/io-service;1"].getService(
|
||||||
var gPublicLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader);
|
Ci.nsIIOService
|
||||||
var gPrivateLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader);
|
);
|
||||||
|
var gPublicLoader = Cc["@mozilla.org/image/loader;1"].createInstance(
|
||||||
|
Ci.imgILoader
|
||||||
|
);
|
||||||
|
var gPrivateLoader = Cc["@mozilla.org/image/loader;1"].createInstance(
|
||||||
|
Ci.imgILoader
|
||||||
|
);
|
||||||
gPrivateLoader.QueryInterface(Ci.imgICache).respectPrivacyNotifications();
|
gPrivateLoader.QueryInterface(Ci.imgICache).respectPrivacyNotifications();
|
||||||
|
|
||||||
var nonPrivateLoadContext = Cu.createLoadContext();
|
var nonPrivateLoadContext = Cu.createLoadContext();
|
||||||
|
@ -23,49 +29,75 @@ function imageHandler(metadata, response) {
|
||||||
response.setHeader("Cache-Control", "max-age=10000", false);
|
response.setHeader("Cache-Control", "max-age=10000", false);
|
||||||
response.setStatusLine(metadata.httpVersion, 200, "OK");
|
response.setStatusLine(metadata.httpVersion, 200, "OK");
|
||||||
response.setHeader("Content-Type", "image/png", false);
|
response.setHeader("Content-Type", "image/png", false);
|
||||||
var body = "iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAEUlEQVQImWP4z8AAQTAamQkAhpcI+DeMzFcAAAAASUVORK5CYII=";
|
var body =
|
||||||
|
"iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAEUlEQVQImWP4z8AAQTAamQkAhpcI+DeMzFcAAAAASUVORK5CYII=";
|
||||||
response.bodyOutputStream.write(body, body.length);
|
response.bodyOutputStream.write(body, body.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
var requests = [];
|
var requests = [];
|
||||||
var listeners = [];
|
var listeners = [];
|
||||||
|
|
||||||
var gImgPath = 'http://localhost:' + server.identity.primaryPort + '/image.png';
|
var gImgPath = "http://localhost:" + server.identity.primaryPort + "/image.png";
|
||||||
|
|
||||||
function setup_chan(path, isPrivate, callback) {
|
function setup_chan(path, isPrivate, callback) {
|
||||||
var uri = NetUtil.newURI(gImgPath);
|
var uri = NetUtil.newURI(gImgPath);
|
||||||
var securityFlags = Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
|
var securityFlags = Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
|
||||||
var principal = Services.scriptSecurityManager
|
var principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {
|
||||||
.createCodebasePrincipal(uri, {privateBrowsingId: isPrivate ? 1 : 0});
|
privateBrowsingId: isPrivate ? 1 : 0,
|
||||||
var chan = NetUtil.newChannel({uri, loadingPrincipal: principal,
|
});
|
||||||
securityFlags,
|
var chan = NetUtil.newChannel({
|
||||||
contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE});
|
uri,
|
||||||
chan.notificationCallbacks = isPrivate ? privateLoadContext
|
loadingPrincipal: principal,
|
||||||
: nonPrivateLoadContext;
|
securityFlags,
|
||||||
|
contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE,
|
||||||
|
});
|
||||||
|
chan.notificationCallbacks = isPrivate
|
||||||
|
? privateLoadContext
|
||||||
|
: nonPrivateLoadContext;
|
||||||
var channelListener = new ChannelListener();
|
var channelListener = new ChannelListener();
|
||||||
chan.asyncOpen(channelListener);
|
chan.asyncOpen(channelListener);
|
||||||
|
|
||||||
var listener = new ImageListener(null, callback);
|
var listener = new ImageListener(null, callback);
|
||||||
var outlistener = {};
|
var outlistener = {};
|
||||||
var loader = isPrivate ? gPrivateLoader : gPublicLoader;
|
var loader = isPrivate ? gPrivateLoader : gPublicLoader;
|
||||||
var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
|
var outer = Cc["@mozilla.org/image/tools;1"]
|
||||||
.createScriptedObserver(listener);
|
.getService(Ci.imgITools)
|
||||||
|
.createScriptedObserver(listener);
|
||||||
listeners.push(outer);
|
listeners.push(outer);
|
||||||
requests.push(loader.loadImageWithChannelXPCOM(chan, outer, null, outlistener));
|
requests.push(
|
||||||
|
loader.loadImageWithChannelXPCOM(chan, outer, null, outlistener)
|
||||||
|
);
|
||||||
channelListener.outputListener = outlistener.value;
|
channelListener.outputListener = outlistener.value;
|
||||||
listener.synchronous = false;
|
listener.synchronous = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadImage(isPrivate, callback) {
|
function loadImage(isPrivate, callback) {
|
||||||
var listener = new ImageListener(null, callback);
|
var listener = new ImageListener(null, callback);
|
||||||
var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
|
var outer = Cc["@mozilla.org/image/tools;1"]
|
||||||
.createScriptedObserver(listener);
|
.getService(Ci.imgITools)
|
||||||
|
.createScriptedObserver(listener);
|
||||||
var uri = gIoService.newURI(gImgPath);
|
var uri = gIoService.newURI(gImgPath);
|
||||||
var loadGroup = Cc["@mozilla.org/network/load-group;1"].createInstance(Ci.nsILoadGroup);
|
var loadGroup = Cc["@mozilla.org/network/load-group;1"].createInstance(
|
||||||
loadGroup.notificationCallbacks = isPrivate ? privateLoadContext
|
Ci.nsILoadGroup
|
||||||
: nonPrivateLoadContext;
|
);
|
||||||
|
loadGroup.notificationCallbacks = isPrivate
|
||||||
|
? privateLoadContext
|
||||||
|
: nonPrivateLoadContext;
|
||||||
var loader = isPrivate ? gPrivateLoader : gPublicLoader;
|
var loader = isPrivate ? gPrivateLoader : gPublicLoader;
|
||||||
requests.push(loader.loadImageXPCOM(uri, null, null, "default", null, loadGroup, outer, null, 0, null));
|
requests.push(
|
||||||
|
loader.loadImageXPCOM(
|
||||||
|
uri,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"default",
|
||||||
|
null,
|
||||||
|
loadGroup,
|
||||||
|
outer,
|
||||||
|
null,
|
||||||
|
0,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
);
|
||||||
listener.synchronous = false;
|
listener.synchronous = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,13 +118,13 @@ function run_loadImage_tests() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Services.obs.addObserver(observer, "cacheservice:empty-cache");
|
Services.obs.addObserver(observer, "cacheservice:empty-cache");
|
||||||
let cs = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
|
let cs = Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(
|
||||||
.getService(Ci.nsICacheStorageService);
|
Ci.nsICacheStorageService
|
||||||
|
);
|
||||||
cs.clear();
|
cs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup()
|
function cleanup() {
|
||||||
{
|
|
||||||
for (var i = 0; i < requests.length; ++i) {
|
for (var i = 0; i < requests.length; ++i) {
|
||||||
requests[i].cancelAndForgetObserver(0);
|
requests[i].cancelAndForgetObserver(0);
|
||||||
}
|
}
|
||||||
|
@ -110,10 +142,10 @@ function run_test() {
|
||||||
// and load the same image, and do that a second time to ensure a cache
|
// and load the same image, and do that a second time to ensure a cache
|
||||||
// read. In total, we should cause two separate http responses to occur,
|
// read. In total, we should cause two separate http responses to occur,
|
||||||
// since the private channels shouldn't be able to use the public cache.
|
// since the private channels shouldn't be able to use the public cache.
|
||||||
setup_chan('/image.png', false, function() {
|
setup_chan("/image.png", false, function() {
|
||||||
setup_chan('/image.png', false, function() {
|
setup_chan("/image.png", false, function() {
|
||||||
setup_chan('/image.png', true, function() {
|
setup_chan("/image.png", true, function() {
|
||||||
setup_chan('/image.png', true, function() {
|
setup_chan("/image.png", true, function() {
|
||||||
Assert.equal(gHits, 2);
|
Assert.equal(gHits, 2);
|
||||||
run_loadImage_tests();
|
run_loadImage_tests();
|
||||||
});
|
});
|
||||||
|
|
Загрузка…
Ссылка в новой задаче