Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
const { HttpServer } = ChromeUtils.importESModule(
);
do_get_profile();
const server = new HttpServer();
server.registerDirectory("/", do_get_cwd());
server.start(-1);
const ROOT = `http://localhost:${server.identity.primaryPort}`;
const BASE = `${ROOT}/`;
const HEADLESS_URL = Services.io.newURI(`${BASE}/headless.html`);
const HEADLESS_BUTTON_URL = Services.io.newURI(`${BASE}/headless_button.html`);
registerCleanupFunction(() => {
server.stop(() => {});
});
// Refrences to the progress listeners to keep them from being gc'ed
// before they are called.
const progressListeners = new Map();
function loadContentWindow(windowlessBrowser, uri) {
return new Promise(resolve => {
let loadURIOptions = {
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
};
windowlessBrowser.loadURI(uri, loadURIOptions);
let docShell = windowlessBrowser.docShell;
let webProgress = docShell
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebProgress);
let progressListener = {
onLocationChange(progress, request, location, flags) {
// Ignore inner-frame events
if (progress != webProgress) {
return;
}
// Ignore events that don't change the document
if (flags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) {
return;
}
let contentWindow = docShell.domWindow;
webProgress.removeProgressListener(progressListener);
progressListeners.delete(progressListener);
contentWindow.addEventListener(
"load",
() => {
resolve(contentWindow);
},
{ once: true }
);
},
QueryInterface: ChromeUtils.generateQI([
"nsIWebProgressListener",
"nsISupportsWeakReference",
]),
};
progressListeners.set(progressListener, progressListener);
webProgress.addProgressListener(
progressListener,
Ci.nsIWebProgress.NOTIFY_LOCATION
);
});
}
add_setup(function () {
Services.prefs.setBoolPref("security.allow_unsafe_parent_loads", true);
});
registerCleanupFunction(function () {
Services.prefs.clearUserPref("security.allow_unsafe_parent_loads");
});
add_task(async function test_snapshot() {
let windowlessBrowser = Services.appShell.createWindowlessBrowser(false);
let contentWindow = await loadContentWindow(windowlessBrowser, HEADLESS_URL);
const contentWidth = 400;
const contentHeight = 300;
// Verify dimensions.
contentWindow.resizeTo(contentWidth, contentHeight);
equal(contentWindow.innerWidth, contentWidth);
equal(contentWindow.innerHeight, contentHeight);
// Snapshot the test page.
let canvas = contentWindow.document.createElementNS(
"html:canvas"
);
let context = canvas.getContext("2d");
let width = contentWindow.innerWidth;
let height = contentWindow.innerHeight;
canvas.width = width;
canvas.height = height;
context.drawWindow(contentWindow, 0, 0, width, height, "rgb(255, 255, 255)");
let imageData = context.getImageData(0, 0, width, height).data;
ok(
imageData[0] === 0 &&
imageData[1] === 255 &&
imageData[2] === 0 &&
imageData[3] === 255,
"Page is green."
);
// Search for a blue pixel (a quick and dirty check to see if the blue text is
// on the page)
let found = false;
for (let i = 0; i < imageData.length; i += 4) {
if (imageData[i + 2] === 255) {
found = true;
break;
}
}
ok(found, "Found blue text on page.");
windowlessBrowser.close();
});
add_task(async function test_snapshot_widget_layers() {
let windowlessBrowser = Services.appShell.createWindowlessBrowser(false);
// nsIWindowlessBrowser inherits from nsIWebNavigation.
let contentWindow = await loadContentWindow(windowlessBrowser, HEADLESS_URL);
const contentWidth = 1;
const contentHeight = 2;
// Verify dimensions.
contentWindow.resizeTo(contentWidth, contentHeight);
equal(contentWindow.innerWidth, contentWidth);
equal(contentWindow.innerHeight, contentHeight);
// Snapshot the test page.
let canvas = contentWindow.document.createElementNS(
"html:canvas"
);
let context = canvas.getContext("2d");
let width = contentWindow.innerWidth;
let height = contentWindow.innerHeight;
canvas.width = width;
canvas.height = height;
context.drawWindow(
contentWindow,
0,
0,
width,
height,
"rgb(255, 255, 255)",
context.DRAWWINDOW_DRAW_CARET |
context.DRAWWINDOW_DRAW_VIEW |
context.DRAWWINDOW_USE_WIDGET_LAYERS
);
ok(true, "Snapshot with widget layers didn't crash.");
windowlessBrowser.close();
});
// Ensure keydown events are triggered on the windowless browser.
add_task(async function test_keydown() {
let windowlessBrowser = Services.appShell.createWindowlessBrowser(false);
// nsIWindowlessBrowser inherits from nsIWebNavigation.
let contentWindow = await loadContentWindow(windowlessBrowser, HEADLESS_URL);
let keydown = new Promise(resolve => {
contentWindow.addEventListener(
"keydown",
() => {
resolve();
},
{ once: true }
);
});
let tip = Cc["@mozilla.org/text-input-processor;1"].createInstance(
Ci.nsITextInputProcessor
);
let begun = tip.beginInputTransactionForTests(contentWindow);
ok(
begun,
"nsITextInputProcessor.beginInputTransactionForTests() should succeed"
);
tip.keydown(
new contentWindow.KeyboardEvent("", {
key: "a",
code: "KeyA",
keyCode: contentWindow.KeyboardEvent.DOM_VK_A,
})
);
await keydown;
ok(true, "Send keydown didn't crash");
windowlessBrowser.close();
});
// Test dragging the mouse on a button to ensure the creation of the drag
// service doesn't crash in headless.
add_task(async function test_mouse_drag() {
let windowlessBrowser = Services.appShell.createWindowlessBrowser(false);
// nsIWindowlessBrowser inherits from nsIWebNavigation.
let contentWindow = await loadContentWindow(
windowlessBrowser,
HEADLESS_BUTTON_URL
);
contentWindow.resizeTo(400, 400);
let target = contentWindow.document.getElementById("btn");
let rect = target.getBoundingClientRect();
let left = rect.left;
let top = rect.top;
let utils = contentWindow.windowUtils;
utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0);
utils.sendMouseEvent("mousemove", left, top, 0, 1, 0, false, 0, 0);
// Wait for a turn of the event loop since the synthetic mouse event
// that creates the drag service is processed during the refresh driver.
await new Promise(r => {
executeSoon(r);
});
utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0);
ok(true, "Send mouse event didn't crash");
windowlessBrowser.close();
});