Bug 802647 - Send browser screenshots as blobs, not base-64 strings. r=khuey,daleharvey

This commit is contained in:
Justin Lebar
2012-10-31 19:28:11 -04:00
parent c39820e22a
commit 9f178d999c
6 changed files with 139 additions and 49 deletions

View File

@@ -522,14 +522,16 @@ BrowserElementChild.prototype = {
ctx.drawWindow(content, 0, 0, content.innerWidth, content.innerHeight,
"rgb(255,255,255)");
sendAsyncMsg('got-screenshot', {
id: domRequestID,
// Use JPEG to hack around the fact that we can't specify opaque PNG.
// This requires us to unpremultiply the alpha channel, which is
// expensive on ARM processors because they lack a hardware integer
// division instruction.
successRv: canvas.toDataURL("image/jpeg")
});
// Take a JPEG screenshot to hack around the fact that we can't specify
// opaque PNG. This requires us to unpremultiply the alpha channel, which
// is expensive on ARM processors because they lack a hardware integer
// division instruction.
canvas.toBlob(function(blob) {
sendAsyncMsg('got-screenshot', {
id: domRequestID,
successRv: blob
});
}, 'image/jpeg');
},
_recvFireCtxCallback: function(data) {
@@ -539,7 +541,7 @@ BrowserElementChild.prototype = {
this._ctxHandlers[data.json.menuitem].click();
this._ctxHandlers = {};
} else {
debug("Ignored invalid contextmenu invokation");
debug("Ignored invalid contextmenu invocation");
}
},

View File

@@ -43,7 +43,6 @@ function checkScreenshotResult(expectSuccess, args) {
}
function runTest() {
dump("XXX runTest\n");
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();

View File

@@ -17,20 +17,34 @@ function runTest() {
iframe1.src = 'data:text/html,<html>' +
'<body style="background:green">hello</body></html>';
var screenshots = [];
var screenshotArrayBuffers = [];
var numLoaded = 0;
function screenshotTaken(screenshot) {
screenshots.push(screenshot);
if (screenshots.length === 1) {
function screenshotTaken(screenshotArrayBuffer) {
screenshotArrayBuffers.push(screenshotArrayBuffer);
if (screenshotArrayBuffers.length === 1) {
ok(true, 'Got initial non blank screenshot');
iframe1.src = 'data:text/html,<html>' +
'<body style="background:blue">hello</body></html>';
waitForScreenshot(function(screenshot) {
return screenshot !== screenshots[0];
// Wait until screenshotArrayBuffer !== screenshotArrayBuffers[0].
waitForScreenshot(function(screenshotArrayBuffer) {
var view1 = new Int8Array(screenshotArrayBuffer);
var view2 = new Int8Array(screenshotArrayBuffers[0]);
if (view1.length != view2.length) {
return true;
}
for (var i = 0; i < view1.length; i++) {
if (view1[i] != view2[i]) {
return true;
}
}
return false;
});
}
else if (screenshots.length === 2) {
else if (screenshotArrayBuffers.length === 2) {
ok(true, 'Got updated screenshot after source page changed');
SimpleTest.finish();
}
@@ -39,31 +53,39 @@ function runTest() {
// We continually take screenshots until we get one that we are
// happy with.
function waitForScreenshot(filter) {
function gotScreenshotArrayBuffer() {
// |this| is the FileReader whose result contains the screenshot as an
// ArrayBuffer.
function screenshotLoaded(e) {
if (filter(e.target.result)) {
screenshotTaken(e.target.result);
if (filter(this.result)) {
screenshotTaken(this.result);
return;
}
if (--attempts === 0) {
ok(false, 'Timed out waiting for correct screenshot');
SimpleTest.finish();
} else {
content.document.defaultView.setTimeout(function() {
iframe1.getScreenshot(1000, 1000).onsuccess = screenshotLoaded;
setTimeout(function() {
iframe1.getScreenshot(1000, 1000).onsuccess = getScreenshotArrayBuffer;
}, 200);
}
}
function getScreenshotArrayBuffer(e) {
var fr = new FileReader();
fr.onloadend = gotScreenshotArrayBuffer;
fr.readAsArrayBuffer(e.target.result);
}
var attempts = 10;
iframe1.getScreenshot(1000, 1000).onsuccess = screenshotLoaded;
iframe1.getScreenshot(1000, 1000).onsuccess = getScreenshotArrayBuffer;
}
function iframeLoadedHandler() {
numLoaded++;
if (numLoaded === 2) {
waitForScreenshot(function(screenshot) {
return screenshot !== 'data:,';
waitForScreenshot(function(screenshotArrayBuffer) {
return screenshotArrayBuffer.byteLength != 0;
});
}
}

View File

@@ -56,7 +56,9 @@ function runTest() {
// We assume here that iframe is completely blank, and spin until popup's
// screenshot is not the same as iframe.
iframe.getScreenshot(1000, 1000).onsuccess = function(e) {
test2(popup, e.target.result, popup);
var fr = FileReader();
fr.onloadend = function() { test2(popup, fr.result); };
fr.readAsArrayBuffer(e.target.result);
};
}
else {
@@ -68,22 +70,37 @@ function runTest() {
iframe.src = 'file_browserElement_OpenMixedProcess.html';
}
var prevScreenshot;
function test2(popup, blankScreenshot) {
function arrayBuffersEqual(a, b) {
var x = new Int8Array(a);
var y = new Int8Array(b);
if (x.length != y.length) {
return false;
}
for (var i = 0; i < x.length; i++) {
if (x[i] != y[i]) {
return false;
}
}
return true;
}
function test2(popup, blankScreenshotArrayBuffer) {
// Take screenshots of popup until it doesn't equal blankScreenshot (or we
// time out).
popup.getScreenshot(1000, 1000).onsuccess = function(e) {
var screenshot = e.target.result;
if (screenshot != blankScreenshot) {
SimpleTest.finish();
return;
}
var fr = new FileReader();
fr.onloadend = function() {
if (!arrayBuffersEqual(blankScreenshotArrayBuffer, fr.result)) {
ok(true, "Finally got a non-blank screenshot.");
SimpleTest.finish();
return;
}
if (screenshot != prevScreenshot) {
prevScreenshot = screenshot;
dump("Got screenshot: " + screenshot + "\n");
}
SimpleTest.executeSoon(function() { test2(popup, blankScreenshot) });
SimpleTest.executeSoon(function() { test2(popup, blankScreenshot) });
};
fr.readAsArrayBuffer(e.target.result);
};
}

View File

@@ -6,7 +6,23 @@
SimpleTest.waitForExplicitFinish();
var initialScreenshot = null;
var initialScreenshotArrayBuffer = null;
function arrayBuffersEqual(a, b) {
var x = new Int8Array(a);
var y = new Int8Array(b);
if (x.length != y.length) {
return false;
}
for (var i = 0; i < x.length; i++) {
if (x[i] != y[i]) {
return false;
}
}
return true;
}
function runTest() {
browserElementTestHelpers.setEnabledPref(true);
@@ -26,9 +42,13 @@ function runTest() {
e.preventDefault();
iframe.getScreenshot(1000, 1000).onsuccess = function(sshot) {
if (initialScreenshot == null)
initialScreenshot = sshot.target.result;
e.detail.unblock();
var fr = new FileReader();
fr.onloadend = function() {
if (initialScreenshotArrayBuffer == null)
initialScreenshotArrayBuffer = fr.result;
e.detail.unblock();
};
fr.readAsArrayBuffer(sshot.target.result);
};
break;
case 'step 2':
@@ -38,8 +58,13 @@ function runTest() {
// The page has now attempted to load the X-Frame-Options page; take
// another screenshot.
iframe.getScreenshot(1000, 1000).onsuccess = function(sshot) {
is(sshot.target.result, initialScreenshot, "Screenshots should be identical");
SimpleTest.finish();
var fr = new FileReader();
fr.onloadend = function() {
ok(arrayBuffersEqual(fr.result, initialScreenshotArrayBuffer),
"Screenshots should be identical");
SimpleTest.finish();
};
fr.readAsArrayBuffer(sshot.target.result);
};
break;
}

View File

@@ -7,7 +7,23 @@
SimpleTest.waitForExplicitFinish();
var initialScreenshot;
var initialScreenshotArrayBuffer;
function arrayBuffersEqual(a, b) {
var x = new Int8Array(a);
var y = new Int8Array(b);
if (x.length != y.length) {
return false;
}
for (var i = 0; i < x.length; i++) {
if (x[i] != y[i]) {
return false;
}
}
return true;
}
function runTest() {
browserElementTestHelpers.setEnabledPref(true);
@@ -29,16 +45,25 @@ function runTest() {
e.preventDefault();
iframe.getScreenshot(1000, 1000).onsuccess = function(sshot) {
initialScreenshot = sshot.target.result;
e.detail.unblock();
var fr = new FileReader();
fr.onloadend = function() {
initialScreenshotArrayBuffer = fr.result;
e.detail.unblock();
}
fr.readAsArrayBuffer(sshot.target.result);
};
break;
case 'step 2':
// The page has now attempted to load the X-Frame-Options page; take
// another screenshot.
iframe.getScreenshot(1000, 1000).onsuccess = function(sshot) {
is(sshot.target.result, initialScreenshot, "Screenshots should be identical");
SimpleTest.finish();
var fr = new FileReader();
fr.onloadend = function() {
ok(arrayBuffersEqual(fr.result, initialScreenshotArrayBuffer),
"Screenshots should be identical");
SimpleTest.finish();
}
fr.readAsArrayBuffer(sshot.target.result);
};
break;
}