Backed out changeset b4678e759a18 (bug 1569135) for mochitest failures at test_headless_screenshot.html. CLOSED TREE
This commit is contained in:
@@ -103,6 +103,9 @@ var whitelist = [
|
|||||||
{ file: "resource://gre/res/fonts/mathfontSTIXGeneral.properties" },
|
{ file: "resource://gre/res/fonts/mathfontSTIXGeneral.properties" },
|
||||||
{ file: "resource://gre/res/fonts/mathfontUnicode.properties" },
|
{ file: "resource://gre/res/fonts/mathfontUnicode.properties" },
|
||||||
|
|
||||||
|
// Needed by HiddenFrame.jsm, but can't be packaged test-only
|
||||||
|
{ file: "chrome://global/content/win.xul" },
|
||||||
|
|
||||||
// The l10n build system can't package string files only for some platforms.
|
// The l10n build system can't package string files only for some platforms.
|
||||||
{
|
{
|
||||||
file:
|
file:
|
||||||
|
|||||||
@@ -397,7 +397,7 @@ add_task(async function checkAllTheCSS() {
|
|||||||
// chrome URI so that it's allowed to load and parse any styles.
|
// chrome URI so that it's allowed to load and parse any styles.
|
||||||
let testFile = getRootDirectory(gTestPath) + "dummy_page.html";
|
let testFile = getRootDirectory(gTestPath) + "dummy_page.html";
|
||||||
let HiddenFrame = ChromeUtils.import(
|
let HiddenFrame = ChromeUtils.import(
|
||||||
"resource://gre/modules/HiddenFrame.jsm",
|
"resource://testing-common/HiddenFrame.jsm",
|
||||||
{}
|
{}
|
||||||
).HiddenFrame;
|
).HiddenFrame;
|
||||||
let hiddenFrame = new HiddenFrame();
|
let hiddenFrame = new HiddenFrame();
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* import-globals-from ../../../../../toolkit/components/extensions/test/mochitest/head_webrequest.js */
|
/* import-globals-from ../../../../../toolkit/components/extensions/test/mochitest/head_webrequest.js */
|
||||||
loadTestSubscript("head_webrequest.js");
|
loadTestSubscript("head_webrequest.js");
|
||||||
|
|
||||||
ChromeUtils.import("resource://gre/modules/HiddenFrame.jsm", this);
|
ChromeUtils.import("resource://testing-common/HiddenFrame.jsm", this);
|
||||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||||
|
|
||||||
SimpleTest.requestCompleteLog();
|
SimpleTest.requestCompleteLog();
|
||||||
|
|||||||
@@ -4,38 +4,16 @@
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var EXPORTED_SYMBOLS = ["HeadlessShell", "ScreenshotParent"];
|
var EXPORTED_SYMBOLS = ["HeadlessShell"];
|
||||||
|
|
||||||
const { E10SUtils } = ChromeUtils.import(
|
|
||||||
"resource://gre/modules/E10SUtils.jsm"
|
|
||||||
);
|
|
||||||
const { HiddenFrame } = ChromeUtils.import(
|
|
||||||
"resource://gre/modules/HiddenFrame.jsm"
|
|
||||||
);
|
|
||||||
const { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm");
|
|
||||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||||
|
const { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm");
|
||||||
|
|
||||||
// Refrences to the progress listeners to keep them from being gc'ed
|
// Refrences to the progress listeners to keep them from being gc'ed
|
||||||
// before they are called.
|
// before they are called.
|
||||||
const progressListeners = new Set();
|
const progressListeners = new Map();
|
||||||
|
|
||||||
class ScreenshotParent extends JSWindowActorParent {
|
function loadContentWindow(webNavigation, url, principal) {
|
||||||
takeScreenshot(params) {
|
|
||||||
return this.sendQuery("TakeScreenshot", params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ChromeUtils.registerWindowActor("Screenshot", {
|
|
||||||
parent: {
|
|
||||||
moduleURI: "resource:///modules/HeadlessShell.jsm",
|
|
||||||
},
|
|
||||||
child: {
|
|
||||||
moduleURI: "resource:///modules/ScreenshotChild.jsm",
|
|
||||||
messages: ["TakeScreenshot"],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
function loadContentWindow(browser, url) {
|
|
||||||
let uri;
|
let uri;
|
||||||
try {
|
try {
|
||||||
uri = Services.io.newURI(url);
|
uri = Services.io.newURI(url);
|
||||||
@@ -44,20 +22,21 @@ function loadContentWindow(browser, url) {
|
|||||||
Cu.reportError(msg);
|
Cu.reportError(msg);
|
||||||
return Promise.reject(new Error(msg));
|
return Promise.reject(new Error(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
const principal = Services.scriptSecurityManager.getSystemPrincipal();
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let loadURIOptions = {
|
let loadURIOptions = {
|
||||||
triggeringPrincipal: principal,
|
triggeringPrincipal: principal,
|
||||||
remoteType: E10SUtils.getRemoteTypeForURI(url, true, false),
|
|
||||||
};
|
};
|
||||||
browser.loadURI(uri.spec, loadURIOptions);
|
webNavigation.loadURI(uri.spec, loadURIOptions);
|
||||||
let { webProgress } = browser;
|
let docShell = webNavigation
|
||||||
|
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIDocShell);
|
||||||
|
let webProgress = docShell
|
||||||
|
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIWebProgress);
|
||||||
let progressListener = {
|
let progressListener = {
|
||||||
onLocationChange(progress, request, location, flags) {
|
onLocationChange(progress, request, location, flags) {
|
||||||
// Ignore inner-frame events
|
// Ignore inner-frame events
|
||||||
if (!progress.isTopLevel) {
|
if (progress != webProgress) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Ignore events that don't change the document
|
// Ignore events that don't change the document
|
||||||
@@ -68,17 +47,23 @@ function loadContentWindow(browser, url) {
|
|||||||
if (location.spec == "about:blank" && uri.spec != "about:blank") {
|
if (location.spec == "about:blank" && uri.spec != "about:blank") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let contentWindow = docShell.domWindow;
|
||||||
progressListeners.delete(progressListener);
|
progressListeners.delete(progressListener);
|
||||||
webProgress.removeProgressListener(progressListener);
|
webProgress.removeProgressListener(progressListener);
|
||||||
resolve();
|
contentWindow.addEventListener(
|
||||||
|
"load",
|
||||||
|
event => {
|
||||||
|
resolve(contentWindow);
|
||||||
|
},
|
||||||
|
{ once: true }
|
||||||
|
);
|
||||||
},
|
},
|
||||||
QueryInterface: ChromeUtils.generateQI([
|
QueryInterface: ChromeUtils.generateQI([
|
||||||
"nsIWebProgressListener",
|
"nsIWebProgressListener",
|
||||||
"nsISupportsWeakReference",
|
"nsISupportsWeakReference",
|
||||||
]),
|
]),
|
||||||
};
|
};
|
||||||
progressListeners.add(progressListener);
|
progressListeners.set(progressListener, progressListener);
|
||||||
webProgress.addProgressListener(
|
webProgress.addProgressListener(
|
||||||
progressListener,
|
progressListener,
|
||||||
Ci.nsIWebProgress.NOTIFY_LOCATION
|
Ci.nsIWebProgress.NOTIFY_LOCATION
|
||||||
@@ -94,35 +79,56 @@ async function takeScreenshot(
|
|||||||
path,
|
path,
|
||||||
url
|
url
|
||||||
) {
|
) {
|
||||||
let frame;
|
|
||||||
try {
|
try {
|
||||||
frame = new HiddenFrame();
|
var windowlessBrowser = Services.appShell.createWindowlessBrowser(false);
|
||||||
let windowlessBrowser = await frame.get();
|
// nsIWindowlessBrowser inherits from nsIWebNavigation.
|
||||||
|
let contentWindow = await loadContentWindow(
|
||||||
let doc = windowlessBrowser.document;
|
windowlessBrowser,
|
||||||
let browser = doc.createXULElement("browser");
|
url,
|
||||||
browser.setAttribute("remote", "true");
|
Services.scriptSecurityManager.getSystemPrincipal()
|
||||||
browser.setAttribute("type", "content");
|
|
||||||
doc.documentElement.appendChild(browser);
|
|
||||||
|
|
||||||
await loadContentWindow(browser, url);
|
|
||||||
|
|
||||||
let actor = browser.browsingContext.currentWindowGlobal.getActor(
|
|
||||||
"Screenshot"
|
|
||||||
);
|
);
|
||||||
let blob = await actor.takeScreenshot({
|
contentWindow.resizeTo(contentWidth, contentHeight);
|
||||||
fullWidth,
|
|
||||||
fullHeight,
|
|
||||||
contentWidth,
|
|
||||||
contentHeight,
|
|
||||||
});
|
|
||||||
|
|
||||||
let reader = await new Promise(resolve => {
|
let canvas = contentWindow.document.createElementNS(
|
||||||
let fr = new FileReader();
|
"http://www.w3.org/1999/xhtml",
|
||||||
fr.onloadend = () => resolve(fr);
|
"html:canvas"
|
||||||
fr.readAsArrayBuffer(blob);
|
);
|
||||||
});
|
let context = canvas.getContext("2d");
|
||||||
|
let width = fullWidth
|
||||||
|
? contentWindow.innerWidth +
|
||||||
|
contentWindow.scrollMaxX -
|
||||||
|
contentWindow.scrollMinX
|
||||||
|
: contentWindow.innerWidth;
|
||||||
|
let height = fullHeight
|
||||||
|
? contentWindow.innerHeight +
|
||||||
|
contentWindow.scrollMaxY -
|
||||||
|
contentWindow.scrollMinY
|
||||||
|
: contentWindow.innerHeight;
|
||||||
|
canvas.width = width;
|
||||||
|
canvas.height = height;
|
||||||
|
context.drawWindow(
|
||||||
|
contentWindow,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
"rgb(255, 255, 255)"
|
||||||
|
);
|
||||||
|
|
||||||
|
function getBlob() {
|
||||||
|
return new Promise(resolve => canvas.toBlob(resolve));
|
||||||
|
}
|
||||||
|
|
||||||
|
function readBlob(blob) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
let reader = new FileReader();
|
||||||
|
reader.onloadend = () => resolve(reader);
|
||||||
|
reader.readAsArrayBuffer(blob);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let blob = await getBlob();
|
||||||
|
let reader = await readBlob(blob);
|
||||||
await OS.File.writeAtomic(path, new Uint8Array(reader.result), {
|
await OS.File.writeAtomic(path, new Uint8Array(reader.result), {
|
||||||
flush: true,
|
flush: true,
|
||||||
});
|
});
|
||||||
@@ -130,8 +136,8 @@ async function takeScreenshot(
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
dump("Failure taking screenshot: " + e + "\n");
|
dump("Failure taking screenshot: " + e + "\n");
|
||||||
} finally {
|
} finally {
|
||||||
if (frame) {
|
if (windowlessBrowser) {
|
||||||
frame.destroy();
|
windowlessBrowser.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const EXPORTED_SYMBOLS = ["ScreenshotChild"];
|
|
||||||
|
|
||||||
class ScreenshotChild extends JSWindowActorChild {
|
|
||||||
receiveMessage(message) {
|
|
||||||
if (message.name == "TakeScreenshot") {
|
|
||||||
return this.takeScreenshot(message.data);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
async takeScreenshot(params) {
|
|
||||||
if (this.document.readyState != "complete") {
|
|
||||||
await new Promise(resolve =>
|
|
||||||
this.contentWindow.addEventListener("load", resolve, { once: true })
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let { fullWidth, fullHeight, contentWidth, contentHeight } = params;
|
|
||||||
let { contentWindow } = this;
|
|
||||||
contentWindow.resizeTo(contentWidth, contentHeight);
|
|
||||||
|
|
||||||
let canvas = contentWindow.document.createElementNS(
|
|
||||||
"http://www.w3.org/1999/xhtml",
|
|
||||||
"html:canvas"
|
|
||||||
);
|
|
||||||
let context = canvas.getContext("2d");
|
|
||||||
let width = contentWindow.innerWidth;
|
|
||||||
let height = contentWindow.innerHeight;
|
|
||||||
if (fullWidth) {
|
|
||||||
width += contentWindow.scrollMaxX - contentWindow.scrollMinX;
|
|
||||||
}
|
|
||||||
if (fullHeight) {
|
|
||||||
height += contentWindow.scrollMaxY - contentWindow.scrollMinY;
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas.width = width;
|
|
||||||
canvas.height = height;
|
|
||||||
context.drawWindow(
|
|
||||||
contentWindow,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
"rgb(255, 255, 255)"
|
|
||||||
);
|
|
||||||
|
|
||||||
return new Promise(resolve => canvas.toBlob(resolve));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -49,7 +49,6 @@ if SOURCES:
|
|||||||
|
|
||||||
EXTRA_JS_MODULES += [
|
EXTRA_JS_MODULES += [
|
||||||
'HeadlessShell.jsm',
|
'HeadlessShell.jsm',
|
||||||
'ScreenshotChild.jsm',
|
|
||||||
'ShellService.jsm',
|
'ShellService.jsm',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var HiddenFrame = ChromeUtils.import(
|
var HiddenFrame = ChromeUtils.import(
|
||||||
"resource://gre/modules/HiddenFrame.jsm",
|
"resource://testing-common/HiddenFrame.jsm",
|
||||||
{}
|
{}
|
||||||
).HiddenFrame;
|
).HiddenFrame;
|
||||||
|
|
||||||
|
|||||||
@@ -147,6 +147,7 @@ BROWSER_CHROME_MANIFESTS += ['tests/browser/browser.ini']
|
|||||||
MOCHITEST_CHROME_MANIFESTS += ['tests/chrome/chrome.ini']
|
MOCHITEST_CHROME_MANIFESTS += ['tests/chrome/chrome.ini']
|
||||||
|
|
||||||
TESTING_JS_MODULES += [
|
TESTING_JS_MODULES += [
|
||||||
|
'HiddenFrame.jsm',
|
||||||
'tests/modules/MockDocument.jsm',
|
'tests/modules/MockDocument.jsm',
|
||||||
'tests/modules/PromiseTestUtils.jsm',
|
'tests/modules/PromiseTestUtils.jsm',
|
||||||
'tests/modules/Task.jsm',
|
'tests/modules/Task.jsm',
|
||||||
@@ -193,7 +194,6 @@ EXTRA_JS_MODULES += [
|
|||||||
'GMPExtractorWorker.js',
|
'GMPExtractorWorker.js',
|
||||||
'GMPInstallManager.jsm',
|
'GMPInstallManager.jsm',
|
||||||
'GMPUtils.jsm',
|
'GMPUtils.jsm',
|
||||||
'HiddenFrame.jsm',
|
|
||||||
'Http.jsm',
|
'Http.jsm',
|
||||||
'IgnoreLists.jsm',
|
'IgnoreLists.jsm',
|
||||||
'IndexedDB.jsm',
|
'IndexedDB.jsm',
|
||||||
|
|||||||
Reference in New Issue
Block a user