Bug 1561435 - Format layout/, a=automatic-formatting

# ignore-this-changeset

Differential Revision: https://phabricator.services.mozilla.com/D35927

--HG--
extra : source : b9cc96337c05dbb9a9f811c63dcc5fd63588d652
This commit is contained in:
Victor Porof 2019-07-05 10:50:41 +02:00
parent baef0fa817
commit 6a261b9e77
29 changed files with 9192 additions and 4513 deletions

View file

@ -45,7 +45,6 @@ module.exports = {
"overrides": [{
"files": [
"devtools/**",
"layout/**",
"media/**",
"memory/**",
"mfbt/**",

View file

@ -40,7 +40,6 @@ toolkit/components/telemetry/datareporting-prefs.js
toolkit/components/telemetry/healthreport-prefs.js
# Ignore all top-level directories for now.
layout/**
media/**
memory/**
mfbt/**

View file

@ -11,7 +11,10 @@
add_task(async function test() {
// Open the test tab
let testTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:addons");
let testTab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
"about:addons"
);
// insert button into test page content
await ContentTask.spawn(gBrowser.selectedBrowser, null, async function() {
@ -24,7 +27,11 @@ add_task(async function test() {
});
// open a second tab and select it
let tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank", true);
let tab2 = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
"about:blank",
true
);
gBrowser.selectedTab = tab2;
// Select the testTab then perform mouse events on inserted button
@ -32,9 +39,27 @@ add_task(async function test() {
let browser = gBrowser.selectedBrowser;
EventUtils.disableNonTestMouseEvents(true);
try {
await BrowserTestUtils.synthesizeMouse("#test-button", 1, 1, { type: "mouseover" }, browser);
await BrowserTestUtils.synthesizeMouse("#test-button", 2, 6, { type: "mousemove" }, browser);
await BrowserTestUtils.synthesizeMouse("#test-button", 2, 4, { type: "mousemove" }, browser);
await BrowserTestUtils.synthesizeMouse(
"#test-button",
1,
1,
{ type: "mouseover" },
browser
);
await BrowserTestUtils.synthesizeMouse(
"#test-button",
2,
6,
{ type: "mousemove" },
browser
);
await BrowserTestUtils.synthesizeMouse(
"#test-button",
2,
4,
{ type: "mousemove" },
browser
);
} finally {
EventUtils.disableNonTestMouseEvents(false);
}

View file

@ -1,15 +1,22 @@
function pageScript() {
window.addEventListener("beforeunload", function (event) {
var str = "Some text that causes the beforeunload dialog to be shown";
event.returnValue = str;
return str;
}, true);
window.addEventListener(
"beforeunload",
function(event) {
var str = "Some text that causes the beforeunload dialog to be shown";
event.returnValue = str;
return str;
},
true
);
}
SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", false]]});
SpecialPowers.pushPrefEnv({
set: [["dom.require_user_interaction_for_beforeunload", false]],
});
const PAGE_URL =
"data:text/html," + encodeURIComponent("<script>(" + pageScript.toSource() + ")();</script>");
"data:text/html," +
encodeURIComponent("<script>(" + pageScript.toSource() + ")();</script>");
add_task(async function enableDialogs() {
// The onbeforeunload dialog should appear.
@ -34,22 +41,27 @@ add_task(async function disableDialogs() {
async function openPage(enableDialogs) {
// Open about:blank in a new tab.
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, async function(browser) {
// Load the content script in the frame.
let methodName = enableDialogs ? "enableDialogs" : "disableDialogs";
await ContentTask.spawn(browser, methodName, async function(name) {
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
Services.obs.addObserver(doc => {
if (content && doc == content.document) {
content.windowUtils[name]();
}
}, "document-element-inserted");
});
// Load the page.
await BrowserTestUtils.loadURI(browser, PAGE_URL);
await BrowserTestUtils.browserLoaded(browser);
// And then navigate away.
await BrowserTestUtils.loadURI(browser, "http://example.com/");
await BrowserTestUtils.browserLoaded(browser);
});
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:blank" },
async function(browser) {
// Load the content script in the frame.
let methodName = enableDialogs ? "enableDialogs" : "disableDialogs";
await ContentTask.spawn(browser, methodName, async function(name) {
const { Services } = ChromeUtils.import(
"resource://gre/modules/Services.jsm"
);
Services.obs.addObserver(doc => {
if (content && doc == content.document) {
content.windowUtils[name]();
}
}, "document-element-inserted");
});
// Load the page.
await BrowserTestUtils.loadURI(browser, PAGE_URL);
await BrowserTestUtils.browserLoaded(browser);
// And then navigate away.
await BrowserTestUtils.loadURI(browser, "http://example.com/");
await BrowserTestUtils.browserLoaded(browser);
}
);
}

View file

@ -1,15 +1,22 @@
function pageScript() {
window.addEventListener("beforeunload", function (event) {
var str = "Some text that causes the beforeunload dialog to be shown";
event.returnValue = str;
return str;
}, true);
window.addEventListener(
"beforeunload",
function(event) {
var str = "Some text that causes the beforeunload dialog to be shown";
event.returnValue = str;
return str;
},
true
);
}
SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", true]]});
SpecialPowers.pushPrefEnv({
set: [["dom.require_user_interaction_for_beforeunload", true]],
});
const PAGE_URL =
"data:text/html," + encodeURIComponent("<script>(" + pageScript.toSource() + ")();</script>");
"data:text/html," +
encodeURIComponent("<script>(" + pageScript.toSource() + ")();</script>");
add_task(async function doClick() {
// The onbeforeunload dialog should appear.
@ -34,20 +41,27 @@ add_task(async function noClick() {
async function openPage(shouldClick) {
// Open about:blank in a new tab.
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, async function(browser) {
// Load the page.
await BrowserTestUtils.loadURI(browser, PAGE_URL);
await BrowserTestUtils.browserLoaded(browser);
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:blank" },
async function(browser) {
// Load the page.
await BrowserTestUtils.loadURI(browser, PAGE_URL);
await BrowserTestUtils.browserLoaded(browser);
if (shouldClick) {
await BrowserTestUtils.synthesizeMouse("body", 2, 2, {}, browser);
if (shouldClick) {
await BrowserTestUtils.synthesizeMouse("body", 2, 2, {}, browser);
}
let hasInteractedWith = await ContentTask.spawn(browser, "", function() {
return content.document.userHasInteracted;
});
is(
shouldClick,
hasInteractedWith,
"Click should update document interactivity state"
);
// And then navigate away.
await BrowserTestUtils.loadURI(browser, "http://example.com/");
await BrowserTestUtils.browserLoaded(browser);
}
let hasInteractedWith = await ContentTask.spawn(browser, "", function() {
return content.document.userHasInteracted;
});
is(shouldClick, hasInteractedWith, "Click should update document interactivity state");
// And then navigate away.
await BrowserTestUtils.loadURI(browser, "http://example.com/");
await BrowserTestUtils.browserLoaded(browser);
});
);
}

View file

@ -1,19 +1,34 @@
function pageScript() {
window.addEventListener("beforeunload", function (event) {
var str = "Some text that causes the beforeunload dialog to be shown";
event.returnValue = str;
return str;
}, true);
window.addEventListener(
"beforeunload",
function(event) {
var str = "Some text that causes the beforeunload dialog to be shown";
event.returnValue = str;
return str;
},
true
);
}
SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", true],
["security.allow_eval_with_system_principal", true]]});
SpecialPowers.pushPrefEnv({
set: [
["dom.require_user_interaction_for_beforeunload", true],
["security.allow_eval_with_system_principal", true],
],
});
const FRAME_URL =
"data:text/html," + encodeURIComponent("<body>Just a frame</body>");
const PAGE_URL =
"data:text/html," + encodeURIComponent("<iframe src='" + FRAME_URL + "'></iframe><script>(" + pageScript.toSource() + ")();</script>");
"data:text/html," +
encodeURIComponent(
"<iframe src='" +
FRAME_URL +
"'></iframe><script>(" +
pageScript.toSource() +
")();</script>"
);
add_task(async function doClick() {
// The onbeforeunload dialog should appear.
@ -38,23 +53,43 @@ add_task(async function noClick() {
async function openPage(shouldClick) {
// Open about:blank in a new tab.
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, async function(browser) {
// Load the page.
await BrowserTestUtils.loadURI(browser, PAGE_URL);
await BrowserTestUtils.browserLoaded(browser);
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:blank" },
async function(browser) {
// Load the page.
await BrowserTestUtils.loadURI(browser, PAGE_URL);
await BrowserTestUtils.browserLoaded(browser);
if (shouldClick) {
await BrowserTestUtils.synthesizeMouse(function() {
return content.frames[0].document.body;
}, 2, 2, {}, browser);
if (shouldClick) {
await BrowserTestUtils.synthesizeMouse(
function() {
return content.frames[0].document.body;
},
2,
2,
{},
browser
);
}
let hasInteractedWith = await ContentTask.spawn(browser, "", function() {
return [
content.document.userHasInteracted,
content.frames[0].document.userHasInteracted,
];
});
is(
shouldClick,
hasInteractedWith[0],
"Click should update parent interactivity state"
);
is(
shouldClick,
hasInteractedWith[1],
"Click should update frame interactivity state"
);
// And then navigate away.
await BrowserTestUtils.loadURI(browser, "http://example.com/");
await BrowserTestUtils.browserLoaded(browser);
}
let hasInteractedWith = await ContentTask.spawn(browser, "", function() {
return [content.document.userHasInteracted, content.frames[0].document.userHasInteracted];
});
is(shouldClick, hasInteractedWith[0], "Click should update parent interactivity state");
is(shouldClick, hasInteractedWith[1], "Click should update frame interactivity state");
// And then navigate away.
await BrowserTestUtils.loadURI(browser, "http://example.com/");
await BrowserTestUtils.browserLoaded(browser);
});
);
}

View file

@ -1,20 +1,24 @@
// -*- Mode: Javascript; tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*-
// vim: set ts=2 sw=2 et tw=78:
function clearSelection(w)
{
function clearSelection(w) {
var sel = (w ? w : window).getSelection();
sel.removeAllRanges();
}
function getNode(e, index) {
if (!(typeof index==='number')) return index;
if (index >= 0) return e.childNodes[index];
while (++index != 0) e = e.parentNode;
function getNode(e, index) {
if (!(typeof index === "number")) {
return index;
}
if (index >= 0) {
return e.childNodes[index];
}
while (++index != 0) {
e = e.parentNode;
}
return e;
}
function dragSelectPointsWithData()
{
function dragSelectPointsWithData() {
var event = arguments[0];
var e = arguments[1];
var x1 = arguments[2];
@ -22,111 +26,111 @@ function dragSelectPointsWithData()
var x2 = arguments[4];
var y2 = arguments[5];
dir = x2 > x1 ? 1 : -1;
event['type'] = "mousedown";
event["type"] = "mousedown";
synthesizeMouse(e, x1, y1, event);
event['type'] = "mousemove";
event["type"] = "mousemove";
synthesizeMouse(e, x1 + dir, y1, event);
for (var i = 6; i < arguments.length; ++i)
for (var i = 6; i < arguments.length; ++i) {
synthesizeMouse(e, arguments[i], y1, event);
}
synthesizeMouse(e, x2 - dir, y2, event);
event['type'] = "mouseup";
event["type"] = "mouseup";
synthesizeMouse(e, x2, y2, event);
}
function dragSelectPoints()
{
function dragSelectPoints() {
var args = Array.prototype.slice.call(arguments);
dragSelectPointsWithData.apply(this, [{}].concat(args));
}
function dragSelect()
{
function dragSelect() {
var args = Array.prototype.slice.call(arguments);
var e = args.shift();
var x1 = args.shift();
var x2 = args.shift();
dragSelectPointsWithData.apply(this, [{},e,x1,5,x2,5].concat(args));
dragSelectPointsWithData.apply(this, [{}, e, x1, 5, x2, 5].concat(args));
}
function accelDragSelect()
{
function accelDragSelect() {
var args = Array.prototype.slice.call(arguments);
var e = args.shift();
var x1 = args.shift();
var x2 = args.shift();
var y = args.length != 0 ? args.shift() : 5;
dragSelectPointsWithData.apply(this, [{accelKey: true},e,x1,y,x2,y].concat(args));
dragSelectPointsWithData.apply(
this,
[{ accelKey: true }, e, x1, y, x2, y].concat(args)
);
}
function shiftClick(e, x, y)
{
function pos(p) { return (typeof p === "undefined") ? 5 : p }
function shiftClick(e, x, y) {
function pos(p) {
return typeof p === "undefined" ? 5 : p;
}
synthesizeMouse(e, pos(x), pos(y), { shiftKey: true });
}
function keyRepeat(key,data,repeat)
{
while (repeat-- > 0)
function keyRepeat(key, data, repeat) {
while (repeat-- > 0) {
synthesizeKey(key, data);
}
}
function keyRight(data)
{
function keyRight(data) {
var repeat = arguments.length > 1 ? arguments[1] : 1;
keyRepeat("VK_RIGHT", data, repeat);
}
function keyLeft(data)
{
function keyLeft(data) {
var repeat = arguments.length > 1 ? arguments[1] : 1;
keyRepeat("VK_LEFT", data, repeat);
}
function shiftAccelClick(e, x, y)
{
function pos(p) { return (typeof p === "undefined") ? 5 : p }
function shiftAccelClick(e, x, y) {
function pos(p) {
return typeof p === "undefined" ? 5 : p;
}
synthesizeMouse(e, pos(x), pos(y), { shiftKey: true, accelKey: true });
}
function accelClick(e, x, y)
{
function pos(p) { return (typeof p === "undefined") ? 5 : p }
function accelClick(e, x, y) {
function pos(p) {
return typeof p === "undefined" ? 5 : p;
}
synthesizeMouse(e, pos(x), pos(y), { accelKey: true });
}
function addChildRanges(arr, e)
{
function addChildRanges(arr, e) {
var sel = window.getSelection();
for (i = 0; i < arr.length; ++i) {
var data = arr[i];
var r = new Range()
var r = new Range();
r.setStart(getNode(e, data[0]), data[1]);
r.setEnd(getNode(e, data[2]), data[3]);
sel.addRange(r);
}
}
function checkText(text, e)
{
function checkText(text, e) {
var sel = window.getSelection();
is(sel.toString(), text, e.id + ": selected text")
is(sel.toString(), text, e.id + ": selected text");
}
function checkRangeText(text, index)
{
function checkRangeText(text, index) {
var r = window.getSelection().getRangeAt(index);
is(r.toString(), text, e.id + ": range["+index+"].toString()")
is(r.toString(), text, e.id + ": range[" + index + "].toString()");
}
function checkRangeCount(n, e)
{
function checkRangeCount(n, e) {
var sel = window.getSelection();
is(sel.rangeCount, n, e.id + ": Selection range count");
}
function checkRangePoints(i, expected, e) {
var sel = window.getSelection();
if (i >= sel.rangeCount) return;
if (i >= sel.rangeCount) {
return;
}
var r = sel.getRangeAt(i);
is(r.startContainer, expected[0], e.id + ": range.startContainer");
is(r.startOffset, expected[1], e.id + ": range.startOffset");
@ -136,16 +140,25 @@ function checkRangePoints(i, expected, e) {
function checkRange(i, expected, e) {
var sel = window.getSelection();
if (i >= sel.rangeCount) return;
if (i >= sel.rangeCount) {
return;
}
var r = sel.getRangeAt(i);
is(r.startContainer, getNode(e, expected[0]), e.id + ": range["+i+"].startContainer");
is(r.startOffset, expected[1], e.id + ": range["+i+"].startOffset");
is(r.endContainer, getNode(e, expected[2]), e.id + ": range["+i+"].endContainer");
is(r.endOffset, expected[3], e.id + ": range["+i+"].endOffset");
is(
r.startContainer,
getNode(e, expected[0]),
e.id + ": range[" + i + "].startContainer"
);
is(r.startOffset, expected[1], e.id + ": range[" + i + "].startOffset");
is(
r.endContainer,
getNode(e, expected[2]),
e.id + ": range[" + i + "].endContainer"
);
is(r.endOffset, expected[3], e.id + ": range[" + i + "].endOffset");
}
function checkRanges(arr, e)
{
function checkRanges(arr, e) {
checkRangeCount(arr.length, e);
for (i = 0; i < arr.length; ++i) {
var expected = arr[i];

View file

@ -1,163 +1,191 @@
var checkClipRegion, checkClipRegionForFrame, checkClipRegionNoBounds;
(function() {
var windowFrameX, windowFrameY;
var windowFrameX, windowFrameY;
// Import test API
var is = window.opener.is;
var ok = window.opener.ok;
var todo = window.opener.todo;
var finish = window.opener.SimpleTest.finish;
window.onerror = function (event) { window.opener.onerror(event); window.close(); };
// Import test API
var is = window.opener.is;
var ok = window.opener.ok;
var todo = window.opener.todo;
var finish = window.opener.SimpleTest.finish;
window.onerror = function(event) {
window.opener.onerror(event);
window.close();
};
function dumpRect(r) {
return "{" + r.join(",") + "}";
}
function dumpRegion(rects) {
var s = [];
for (var i = 0; i < rects.length; ++i) {
var r = rects[i];
s.push(dumpRect(r));
function dumpRect(r) {
return "{" + r.join(",") + "}";
}
return s.join(", ");
}
function generateSpan(coords) {
coords.sort(function(a,b) { return a - b; });
var result = [coords[0]];
for (var i = 1; i < coords.length; ++i) {
if (coords[i] != coords[i - 1]) {
result.push(coords[i]);
function dumpRegion(rects) {
var s = [];
for (var i = 0; i < rects.length; ++i) {
var r = rects[i];
s.push(dumpRect(r));
}
return s.join(", ");
}
return result;
}
function containsRect(r1, r2) {
return r1[0] <= r2[0] && r1[2] >= r2[2] &&
r1[1] <= r2[1] && r1[3] >= r2[3];
}
function generateSpan(coords) {
coords.sort(function(a, b) {
return a - b;
});
var result = [coords[0]];
for (var i = 1; i < coords.length; ++i) {
if (coords[i] != coords[i - 1]) {
result.push(coords[i]);
}
}
return result;
}
function subtractRect(r1, r2, rlist) {
var spanX = generateSpan([r1[0], r1[2], r2[0], r2[2]]);
var spanY = generateSpan([r1[1], r1[3], r2[1], r2[3]]);
for (var i = 1; i < spanX.length; ++i) {
for (var j = 1; j < spanY.length; ++j) {
var subrect = [spanX[i - 1], spanY[j - 1], spanX[i], spanY[j]];
if (containsRect(r1, subrect) && !containsRect(r2, subrect)) {
rlist.push(subrect);
function containsRect(r1, r2) {
return r1[0] <= r2[0] && r1[2] >= r2[2] && r1[1] <= r2[1] && r1[3] >= r2[3];
}
function subtractRect(r1, r2, rlist) {
var spanX = generateSpan([r1[0], r1[2], r2[0], r2[2]]);
var spanY = generateSpan([r1[1], r1[3], r2[1], r2[3]]);
for (var i = 1; i < spanX.length; ++i) {
for (var j = 1; j < spanY.length; ++j) {
var subrect = [spanX[i - 1], spanY[j - 1], spanX[i], spanY[j]];
if (containsRect(r1, subrect) && !containsRect(r2, subrect)) {
rlist.push(subrect);
}
}
}
}
}
function regionContainsRect(rs, r) {
var rectList = [r];
for (var i = 0; i < rs.length; ++i) {
var newList = [];
for (var j = 0; j < rectList.length; ++j) {
subtractRect(rectList[j], rs[i], newList);
function regionContainsRect(rs, r) {
var rectList = [r];
for (var i = 0; i < rs.length; ++i) {
var newList = [];
for (var j = 0; j < rectList.length; ++j) {
subtractRect(rectList[j], rs[i], newList);
}
if (newList.length == 0) {
return true;
}
rectList = newList;
}
if (newList.length == 0)
return true;
rectList = newList;
}
return false;
}
function regionContains(r1s, r2s) {
for (var i = 0; i < r2s.length; ++i) {
if (!regionContainsRect(r1s, r2s[i]))
return false;
}
return true;
}
function equalRegions(r1s, r2s) {
return regionContains(r1s, r2s) && regionContains(r2s, r1s);
}
// Checks that a plugin's clip region equals the specified rectangle list.
// The rectangles are given relative to the plugin's top-left. They are in
// [left, top, right, bottom] format.
function checkClipRegionWithDoc(doc, offsetX, offsetY, id, rects, checkBounds) {
var p = doc.getElementById(id);
var bounds = p.getBoundingClientRect();
var pX = p.getEdge(0);
var pY = p.getEdge(1);
if (checkBounds) {
var pWidth = p.getEdge(2) - pX;
var pHeight = p.getEdge(3) - pY;
is(pX, windowFrameX + bounds.left + offsetX, id + " plugin X");
is(pY, windowFrameY + bounds.top + offsetY, id + " plugin Y");
is(pWidth, bounds.width, id + " plugin width");
is(pHeight, bounds.height, id + " plugin height");
return false;
}
// Now check clip region. 'rects' is relative to the plugin's top-left.
var clipRects = [];
var n = p.getClipRegionRectCount();
for (var i = 0; i < n; ++i) {
// Convert the clip rect to be relative to the plugin's top-left.
clipRects[i] = [
p.getClipRegionRectEdge(i, 0) - pX,
p.getClipRegionRectEdge(i, 1) - pY,
p.getClipRegionRectEdge(i, 2) - pX,
p.getClipRegionRectEdge(i, 3) - pY
];
function regionContains(r1s, r2s) {
for (var i = 0; i < r2s.length; ++i) {
if (!regionContainsRect(r1s, r2s[i])) {
return false;
}
}
return true;
}
ok(equalRegions(clipRects, rects), "Matching regions for '" + id +
"': expected " + dumpRegion(rects) + ", got " + dumpRegion(clipRects));
}
checkClipRegion = function(id, rects) {
checkClipRegionWithDoc(document, 0, 0, id, rects, true);
}
checkClipRegionForFrame = function(fid, id, rects) {
var f = document.getElementById(fid);
var bounds = f.getBoundingClientRect();
checkClipRegionWithDoc(f.contentDocument, bounds.left, bounds.top, id, rects, true);
}
checkClipRegionNoBounds = function(id, rects) {
checkClipRegionWithDoc(document, 0, 0, id, rects, false);
}
function loaded() {
var h1 = document.getElementById("h1");
var h2 = document.getElementById("h2");
var hwidth = h2.screenX - h1.screenX;
if (hwidth != 100) {
// Maybe it's a DPI issue
todo(false, "Unexpected DPI?");
finish();
window.close();
return;
function equalRegions(r1s, r2s) {
return regionContains(r1s, r2s) && regionContains(r2s, r1s);
}
if (!document.getElementById("p1").identifierToStringTest) {
todo(false, "Test plugin not available");
finish();
window.close();
return;
// Checks that a plugin's clip region equals the specified rectangle list.
// The rectangles are given relative to the plugin's top-left. They are in
// [left, top, right, bottom] format.
function checkClipRegionWithDoc(
doc,
offsetX,
offsetY,
id,
rects,
checkBounds
) {
var p = doc.getElementById(id);
var bounds = p.getBoundingClientRect();
var pX = p.getEdge(0);
var pY = p.getEdge(1);
if (checkBounds) {
var pWidth = p.getEdge(2) - pX;
var pHeight = p.getEdge(3) - pY;
is(pX, windowFrameX + bounds.left + offsetX, id + " plugin X");
is(pY, windowFrameY + bounds.top + offsetY, id + " plugin Y");
is(pWidth, bounds.width, id + " plugin width");
is(pHeight, bounds.height, id + " plugin height");
}
// Now check clip region. 'rects' is relative to the plugin's top-left.
var clipRects = [];
var n = p.getClipRegionRectCount();
for (var i = 0; i < n; ++i) {
// Convert the clip rect to be relative to the plugin's top-left.
clipRects[i] = [
p.getClipRegionRectEdge(i, 0) - pX,
p.getClipRegionRectEdge(i, 1) - pY,
p.getClipRegionRectEdge(i, 2) - pX,
p.getClipRegionRectEdge(i, 3) - pY,
];
}
ok(
equalRegions(clipRects, rects),
"Matching regions for '" +
id +
"': expected " +
dumpRegion(rects) +
", got " +
dumpRegion(clipRects)
);
}
var bounds = h1.getBoundingClientRect();
windowFrameX = h1.screenX - bounds.left - window.screenX;
windowFrameY = h1.screenY - bounds.top - window.screenY;
checkClipRegion = function(id, rects) {
checkClipRegionWithDoc(document, 0, 0, id, rects, true);
};
// Run actual test code
runTests();
}
checkClipRegionForFrame = function(fid, id, rects) {
var f = document.getElementById(fid);
var bounds = f.getBoundingClientRect();
checkClipRegionWithDoc(
f.contentDocument,
bounds.left,
bounds.top,
id,
rects,
true
);
};
// Need to run 'loaded' after painting is unsuppressed, or we'll set clip
// regions to empty. The timeout must be non-zero on X11 so that
// gtk_container_idle_sizer runs after the GtkSocket gets the plug_window.
window.addEventListener("load",
function () { setTimeout(loaded, 1000); });
checkClipRegionNoBounds = function(id, rects) {
checkClipRegionWithDoc(document, 0, 0, id, rects, false);
};
function loaded() {
var h1 = document.getElementById("h1");
var h2 = document.getElementById("h2");
var hwidth = h2.screenX - h1.screenX;
if (hwidth != 100) {
// Maybe it's a DPI issue
todo(false, "Unexpected DPI?");
finish();
window.close();
return;
}
if (!document.getElementById("p1").identifierToStringTest) {
todo(false, "Test plugin not available");
finish();
window.close();
return;
}
var bounds = h1.getBoundingClientRect();
windowFrameX = h1.screenX - bounds.left - window.screenX;
windowFrameY = h1.screenY - bounds.top - window.screenY;
// Run actual test code
runTests();
}
// Need to run 'loaded' after painting is unsuppressed, or we'll set clip
// regions to empty. The timeout must be non-zero on X11 so that
// gtk_container_idle_sizer runs after the GtkSocket gets the plug_window.
window.addEventListener("load", function() {
setTimeout(loaded, 1000);
});
})();

File diff suppressed because one or more lines are too long

View file

@ -25,7 +25,7 @@ function advance_clock(milliseconds) {
if (gElem) {
ok(false, "test author forgot to call done_div/done_elem");
}
if (typeof(style) != "string") {
if (typeof style != "string") {
ok(false, "test author forgot to pass argument");
}
if (!document.getElementById("display")) {
@ -35,7 +35,7 @@ function advance_clock(milliseconds) {
gElem.setAttribute("style", style);
gElem.classList.add("target");
document.getElementById("display").appendChild(gElem);
return [ gElem, getComputedStyle(gElem, "") ];
return [gElem, getComputedStyle(gElem, "")];
}
function listen() {
@ -55,22 +55,41 @@ function advance_clock(milliseconds) {
// This function checks that the list of eventsExpected matches
// the received events -- but it only checks the properties that
// are present on eventsExpected.
is(gEventsReceived.length, eventsExpected.length,
"number of events received for " + desc);
for (var i = 0,
i_end = Math.min(eventsExpected.length, gEventsReceived.length);
i != i_end; ++i) {
is(
gEventsReceived.length,
eventsExpected.length,
"number of events received for " + desc
);
for (
var i = 0,
i_end = Math.min(eventsExpected.length, gEventsReceived.length);
i != i_end;
++i
) {
var exp = eventsExpected[i];
var rec = gEventsReceived[i];
for (var prop in exp) {
if (prop == "elapsedTime") {
// Allow floating point error.
ok(Math.abs(rec.elapsedTime - exp.elapsedTime) < 0.000002,
"events[" + i + "]." + prop + " for " + desc +
" received=" + rec.elapsedTime + " expected=" + exp.elapsedTime);
ok(
Math.abs(rec.elapsedTime - exp.elapsedTime) < 0.000002,
"events[" +
i +
"]." +
prop +
" for " +
desc +
" received=" +
rec.elapsedTime +
" expected=" +
exp.elapsedTime
);
} else {
is(rec[prop], exp[prop],
"events[" + i + "]." + prop + " for " + desc);
is(
rec[prop],
exp[prop],
"events[" + i + "]." + prop + " for " + desc
);
}
}
}
@ -82,8 +101,11 @@ function advance_clock(milliseconds) {
function done_element() {
if (!gElem) {
ok(false, "test author called done_element/done_div without matching"
+ " call to new_element/new_div");
ok(
false,
"test author called done_element/done_div without matching" +
" call to new_element/new_div"
);
}
gElem.remove();
gElem = null;
@ -92,85 +114,90 @@ function advance_clock(milliseconds) {
}
}
[ new_div
, new_element
, listen
, check_events
, done_element ]
.forEach(function(fn) {
[new_div, new_element, listen, check_events, done_element].forEach(function(
fn
) {
window[fn.name] = fn;
});
window.done_div = done_element;
})();
function px_to_num(str)
{
return Number(String(str).match(/^([\d.]+)px$/)[1]);
function px_to_num(str) {
return Number(String(str).match(/^([\d.]+)px$/)[1]);
}
function bezier(x1, y1, x2, y2) {
// Cubic bezier with control points (0, 0), (x1, y1), (x2, y2), and (1, 1).
function x_for_t(t) {
var omt = 1-t;
return 3 * omt * omt * t * x1 + 3 * omt * t * t * x2 + t * t * t;
// Cubic bezier with control points (0, 0), (x1, y1), (x2, y2), and (1, 1).
function x_for_t(t) {
var omt = 1 - t;
return 3 * omt * omt * t * x1 + 3 * omt * t * t * x2 + t * t * t;
}
function y_for_t(t) {
var omt = 1 - t;
return 3 * omt * omt * t * y1 + 3 * omt * t * t * y2 + t * t * t;
}
function t_for_x(x) {
// Binary subdivision.
var mint = 0,
maxt = 1;
for (var i = 0; i < 30; ++i) {
var guesst = (mint + maxt) / 2;
var guessx = x_for_t(guesst);
if (x < guessx) {
maxt = guesst;
} else {
mint = guesst;
}
}
function y_for_t(t) {
var omt = 1-t;
return 3 * omt * omt * t * y1 + 3 * omt * t * t * y2 + t * t * t;
return (mint + maxt) / 2;
}
return function bezier_closure(x) {
if (x == 0) {
return 0;
}
function t_for_x(x) {
// Binary subdivision.
var mint = 0, maxt = 1;
for (var i = 0; i < 30; ++i) {
var guesst = (mint + maxt) / 2;
var guessx = x_for_t(guesst);
if (x < guessx)
maxt = guesst;
else
mint = guesst;
}
return (mint + maxt) / 2;
}
return function bezier_closure(x) {
if (x == 0) return 0;
if (x == 1) return 1;
return y_for_t(t_for_x(x));
if (x == 1) {
return 1;
}
return y_for_t(t_for_x(x));
};
}
function step_end(nsteps) {
return function step_end_closure(x) {
return Math.floor(x * nsteps) / nsteps;
}
return function step_end_closure(x) {
return Math.floor(x * nsteps) / nsteps;
};
}
function step_start(nsteps) {
var stepend = step_end(nsteps);
return function step_start_closure(x) {
return 1.0 - stepend(1.0 - x);
}
var stepend = step_end(nsteps);
return function step_start_closure(x) {
return 1.0 - stepend(1.0 - x);
};
}
var gTF = {
"ease": bezier(0.25, 0.1, 0.25, 1),
"linear": function(x) { return x; },
"ease_in": bezier(0.42, 0, 1, 1),
"ease_out": bezier(0, 0, 0.58, 1),
"ease_in_out": bezier(0.42, 0, 0.58, 1),
"step_start": step_start(1),
"step_end": step_end(1),
ease: bezier(0.25, 0.1, 0.25, 1),
linear: function(x) {
return x;
},
ease_in: bezier(0.42, 0, 1, 1),
ease_out: bezier(0, 0, 0.58, 1),
ease_in_out: bezier(0.42, 0, 0.58, 1),
step_start: step_start(1),
step_end: step_end(1),
};
function is_approx(float1, float2, error, desc) {
ok(Math.abs(float1 - float2) < error,
desc + ": " + float1 + " and " + float2 + " should be within " + error);
ok(
Math.abs(float1 - float2) < error,
desc + ": " + float1 + " and " + float2 + " should be within " + error
);
}
function findKeyframesRule(name) {
for (var i = 0; i < document.styleSheets.length; i++) {
var match = [].find.call(document.styleSheets[i].cssRules, function(rule) {
return rule.type == CSSRule.KEYFRAMES_RULE &&
rule.name == name;
return rule.type == CSSRule.KEYFRAMES_RULE && rule.name == name;
});
if (match) {
return match;
@ -197,42 +224,49 @@ function findKeyframesRule(name) {
// explicitly.
function runOMTATest(aTestFunction, aOnSkip, specialPowersForPrefs) {
const OMTAPrefKey = "layers.offmainthreadcomposition.async-animations";
var utils = SpecialPowers.DOMWindowUtils;
var utils = SpecialPowers.DOMWindowUtils;
if (!specialPowersForPrefs) {
specialPowersForPrefs = SpecialPowers;
specialPowersForPrefs = SpecialPowers;
}
var expectOMTA = utils.layerManagerRemote &&
// ^ Off-main thread animation cannot be used if off-main
// thread composition (OMTC) is not available
specialPowersForPrefs.getBoolPref(OMTAPrefKey);
var expectOMTA =
utils.layerManagerRemote &&
// ^ Off-main thread animation cannot be used if off-main
// thread composition (OMTC) is not available
specialPowersForPrefs.getBoolPref(OMTAPrefKey);
isOMTAWorking().then(function(isWorking) {
if (expectOMTA) {
if (isWorking) {
aTestFunction();
isOMTAWorking()
.then(function(isWorking) {
if (expectOMTA) {
if (isWorking) {
aTestFunction();
} else {
// We only call this when we know it will fail as otherwise in the
// regular success case we will end up inflating the "passed tests"
// count by 1
ok(isWorking, "OMTA should work");
aOnSkip();
}
} else {
// We only call this when we know it will fail as otherwise in the
// regular success case we will end up inflating the "passed tests"
// count by 1
ok(isWorking, "OMTA should work");
todo(
isWorking,
"OMTA should ideally work, though we don't expect it to work on " +
"this platform/configuration"
);
aOnSkip();
}
} else {
todo(isWorking,
"OMTA should ideally work, though we don't expect it to work on " +
"this platform/configuration");
})
.catch(function(err) {
ok(false, err);
aOnSkip();
}
}).catch(function(err) {
ok(false, err);
aOnSkip();
});
});
function isOMTAWorking() {
// Create keyframes rule
const animationName = "a6ce3091ed85"; // Random name to avoid clashes
var ruleText = "@keyframes " + animationName +
" { from { opacity: 0.5 } to { opacity: 0.5 } }";
var ruleText =
"@keyframes " +
animationName +
" { from { opacity: 0.5 } to { opacity: 0.5 } }";
var style = document.createElement("style");
style.appendChild(document.createTextNode(ruleText));
document.head.appendChild(style);
@ -242,7 +276,7 @@ function runOMTATest(aTestFunction, aOnSkip, specialPowersForPrefs) {
document.body.appendChild(div);
// Give the target geometry so it is eligible for layerization
div.style.width = "100px";
div.style.width = "100px";
div.style.height = "100px";
div.style.backgroundColor = "white";
@ -264,15 +298,18 @@ function runOMTATest(aTestFunction, aOnSkip, specialPowersForPrefs) {
// notifications.
utils.advanceTimeAndRefresh(0);
return waitForPaintsFlushed();
}).then(function() {
})
.then(function() {
div.style.animation = animationName + " 10s";
return waitForPaintsFlushed();
}).then(function() {
})
.then(function() {
var opacity = utils.getOMTAStyle(div, "opacity");
cleanUp();
return Promise.resolve(opacity == 0.5);
}).catch(function(err) {
})
.catch(function(err) {
cleanUp();
return Promise.reject(err);
});
@ -290,7 +327,7 @@ function runOMTATest(aTestFunction, aOnSkip, specialPowersForPrefs) {
function loadPaintListener() {
return new Promise(function(resolve, reject) {
if (typeof(window.waitForAllPaints) !== "function") {
if (typeof window.waitForAllPaints !== "function") {
var script = document.createElement("script");
script.onload = resolve;
script.onerror = function() {
@ -329,10 +366,10 @@ function runOMTATest(aTestFunction, aOnSkip, specialPowersForPrefs) {
// runAsyncAnimTest returns a Promise that is resolved when the
// test is finished so we can chain them together
return tests.reduce(function(sequence, test) {
return sequence.then(function() {
return runAsyncAnimTest(test, aOnAbort);
});
}, Promise.resolve() /* the start of the sequence */);
return sequence.then(function() {
return runAsyncAnimTest(test, aOnAbort);
});
}, Promise.resolve() /* the start of the sequence */);
};
// Takes a generator function that represents a test case. Each point in the
@ -359,8 +396,9 @@ function runOMTATest(aTestFunction, aOnSkip, specialPowersForPrefs) {
if (next.done) {
return Promise.resolve(next.value);
} else {
return Promise.resolve(next.value)
.then(step, function(err) { throw err; });
return Promise.resolve(next.value).then(step, function(err) {
throw err;
});
}
}
@ -373,15 +411,17 @@ function runOMTATest(aTestFunction, aOnSkip, specialPowersForPrefs) {
generator = promise;
promise = step();
}
return promise.catch(function(err) {
ok(false, err.message);
if (typeof aOnAbort == "function") {
aOnAbort();
}
}).then(function() {
// Restore clock
SpecialPowers.DOMWindowUtils.restoreNormalRefresh();
});
return promise
.catch(function(err) {
ok(false, err.message);
if (typeof aOnAbort == "function") {
aOnAbort();
}
})
.then(function() {
// Restore clock
SpecialPowers.DOMWindowUtils.restoreNormalRefresh();
});
}
})();
@ -395,36 +435,70 @@ const RunningOn = {
MainThread: 0,
Compositor: 1,
Either: 2,
TodoMainThread: 3
TodoMainThread: 3,
};
const ExpectComparisonTo = {
Pass: 1,
Fail: 2
Fail: 2,
};
(function() {
window.omta_todo_is = function(elem, property, expected, runningOn, desc,
pseudo) {
return omta_is_approx(elem, property, expected, 0, runningOn, desc,
ExpectComparisonTo.Fail, pseudo);
window.omta_todo_is = function(
elem,
property,
expected,
runningOn,
desc,
pseudo
) {
return omta_is_approx(
elem,
property,
expected,
0,
runningOn,
desc,
ExpectComparisonTo.Fail,
pseudo
);
};
window.omta_is = function(elem, property, expected, runningOn, desc,
pseudo) {
return omta_is_approx(elem, property, expected, 0, runningOn, desc,
ExpectComparisonTo.Pass, pseudo);
window.omta_is = function(elem, property, expected, runningOn, desc, pseudo) {
return omta_is_approx(
elem,
property,
expected,
0,
runningOn,
desc,
ExpectComparisonTo.Pass,
pseudo
);
};
// Many callers of this method will pass 'undefined' for
// expectedComparisonResult.
window.omta_is_approx = function(elem, property, expected, tolerance,
runningOn, desc, expectedComparisonResult,
pseudo) {
window.omta_is_approx = function(
elem,
property,
expected,
tolerance,
runningOn,
desc,
expectedComparisonResult,
pseudo
) {
// Check input
// FIXME: Auto generate this array.
const omtaProperties = [ "transform", "translate", "rotate", "scale",
"opacity", "background-color" ];
const omtaProperties = [
"transform",
"translate",
"rotate",
"scale",
"opacity",
"background-color",
];
if (!omtaProperties.includes(property)) {
ok(false, property + " is not an OMTA property");
return;
@ -443,11 +517,15 @@ const ExpectComparisonTo = {
break;
case "opacity":
normalize = parseFloat;
compare = function(a, b, error) { return Math.abs(a - b) <= error; };
compare = function(a, b, error) {
return Math.abs(a - b) <= error;
};
break;
default:
normalize = value => value;
compare = function(a, b, error) { return a == b; };
compare = function(a, b, error) {
return a == b;
};
break;
}
@ -460,15 +538,23 @@ const ExpectComparisonTo = {
}
// Get actual values
var compositorStr =
SpecialPowers.DOMWindowUtils.getOMTAStyle(elem, property, pseudo);
var compositorStr = SpecialPowers.DOMWindowUtils.getOMTAStyle(
elem,
property,
pseudo
);
var computedStr = window.getComputedStyle(elem, pseudo)[property];
// Prepare expected value
var expectedValue = normalize(expected);
if (expectedValue === null) {
ok(false, desc + ": test author should provide a valid 'expected' value" +
" - got " + expected.toString());
ok(
false,
desc +
": test author should provide a valid 'expected' value" +
" - got " +
expected.toString()
);
return;
}
@ -476,9 +562,8 @@ const ExpectComparisonTo = {
var actualStr;
switch (runningOn) {
case RunningOn.Either:
runningOn = compositorStr !== "" ?
RunningOn.Compositor :
RunningOn.MainThread;
runningOn =
compositorStr !== "" ? RunningOn.Compositor : RunningOn.MainThread;
actualStr = compositorStr !== "" ? compositorStr : computedStr;
break;
@ -491,8 +576,10 @@ const ExpectComparisonTo = {
break;
case RunningOn.TodoMainThread:
todo(compositorStr === "",
desc + ": should NOT be animating on compositor");
todo(
compositorStr === "",
desc + ": should NOT be animating on compositor"
);
actualStr = compositorStr === "" ? computedStr : compositorStr;
break;
@ -505,9 +592,8 @@ const ExpectComparisonTo = {
break;
}
var okOrTodo = expectedComparisonResult == ExpectComparisonTo.Fail ?
todo :
ok;
var okOrTodo =
expectedComparisonResult == ExpectComparisonTo.Fail ? todo : ok;
// Compare animated value with expected
var actualValue = normalize(actualStr);
@ -515,9 +601,14 @@ const ExpectComparisonTo = {
ok(false, desc + ": should return a valid result - got " + actualStr);
return;
}
okOrTodo(compare(expectedValue, actualValue, tolerance),
desc + " - got " + actualStr + ", expected " +
normalizedToString(expectedValue));
okOrTodo(
compare(expectedValue, actualValue, tolerance),
desc +
" - got " +
actualStr +
", expected " +
normalizedToString(expectedValue)
);
// For transform-like properties, if we have multiple transform-like
// properties, the OMTA value and getComputedStyle() must be different,
@ -532,7 +623,7 @@ const ExpectComparisonTo = {
return;
}
if (typeof expected.computed !== 'undefined') {
if (typeof expected.computed !== "undefined") {
// For some tests we specify a separate computed value for comparing
// with getComputedStyle.
//
@ -547,21 +638,33 @@ const ExpectComparisonTo = {
// result of getComputedStyle since it will help to alert us if some
// discrepancy arises between the way we calculate values on the main
// thread and compositor.
okOrTodo(computedStr == expected.computed,
desc + ": Computed style should be equal to " +
expected.computed);
okOrTodo(
computedStr == expected.computed,
desc + ": Computed style should be equal to " + expected.computed
);
} else if (actualStr === compositorStr) {
// For compositor animations do an additional check that they match
// the value calculated on the main thread
var computedValue = normalize(computedStr);
if (computedValue === null) {
ok(false, desc + ": test framework should parse computed style" +
" - got " + computedStr);
ok(
false,
desc +
": test framework should parse computed style" +
" - got " +
computedStr
);
return;
}
okOrTodo(compare(computedValue, actualValue, 0.0),
desc + ": OMTA style and computed style should be equal" +
" - OMTA " + actualStr + ", computed " + computedStr);
okOrTodo(
compare(computedValue, actualValue, 0.0),
desc +
": OMTA style and computed style should be equal" +
" - OMTA " +
actualStr +
", computed " +
computedStr
);
}
};
@ -570,8 +673,9 @@ const ExpectComparisonTo = {
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
var diff = Math.abs(a[i][j] - b[i][j]);
if (diff > tolerance || isNaN(diff))
if (diff > tolerance || isNaN(diff)) {
return false;
}
}
}
return true;
@ -585,11 +689,11 @@ const ExpectComparisonTo = {
// [ 1, 0, 0, ... ]
// { a: 1, ty: 23 } etc.
window.convertTo3dMatrix = function(matrixLike) {
if (typeof(matrixLike) == "string") {
if (typeof matrixLike == "string") {
return convertStringTo3dMatrix(matrixLike);
} else if (Array.isArray(matrixLike)) {
return convertArrayTo3dMatrix(matrixLike);
} else if (typeof(matrixLike) == "object") {
} else if (typeof matrixLike == "object") {
return convertObjectTo3dMatrix(matrixLike);
} else {
return null;
@ -605,19 +709,22 @@ const ExpectComparisonTo = {
// Converts strings of the format "matrix(...)" and "matrix3d(...)" to a 3d
// matrix
function convertStringTo3dMatrix(str) {
if (str == "none")
if (str == "none") {
return convertArrayTo3dMatrix([1, 0, 0, 1, 0, 0]);
}
var result = str.match("^matrix(3d)?\\(");
if (result === null)
if (result === null) {
return null;
}
return convertArrayTo3dMatrix(
str.substring(result[0].length, str.length-1)
.split(",")
.map(function(component) {
return Number(component);
})
);
str
.substring(result[0].length, str.length - 1)
.split(",")
.map(function(component) {
return Number(component);
})
);
}
// Takes an array of numbers of length 6 (2d matrix) or 16 (3d matrix)
@ -625,16 +732,20 @@ const ExpectComparisonTo = {
// matrix represented as an array of arrays
function convertArrayTo3dMatrix(array) {
if (array.length == 6) {
return convertObjectTo3dMatrix(
{ a: array[0], b: array[1],
c: array[2], d: array[3],
e: array[4], f: array[5] } );
return convertObjectTo3dMatrix({
a: array[0],
b: array[1],
c: array[2],
d: array[3],
e: array[4],
f: array[5],
});
} else if (array.length == 16) {
return [
array.slice(0, 4),
array.slice(4, 8),
array.slice(8, 12),
array.slice(12, 16)
array.slice(12, 16),
];
} else {
return null;
@ -643,7 +754,7 @@ const ExpectComparisonTo = {
// Return the first defined value in args.
function defined(...args) {
return args.find(arg => typeof arg !== 'undefined');
return args.find(arg => typeof arg !== "undefined");
}
// Takes an object of the form { a: 1.1, e: 23 } and builds up a 3d matrix
@ -654,46 +765,64 @@ const ExpectComparisonTo = {
defined(obj.a, obj.sx, obj.m11, 1),
obj.b || obj.m12 || 0,
obj.m13 || 0,
obj.m14 || 0
], [
obj.m14 || 0,
],
[
obj.c || obj.m21 || 0,
defined(obj.d, obj.sy, obj.m22, 1),
obj.m23 || 0,
obj.m24 || 0
], [
obj.m31 || 0,
obj.m32 || 0,
defined(obj.sz, obj.m33, 1),
obj.m34 || 0
], [
obj.m24 || 0,
],
[obj.m31 || 0, obj.m32 || 0, defined(obj.sz, obj.m33, 1), obj.m34 || 0],
[
obj.e || obj.tx || obj.m41 || 0,
obj.f || obj.ty || obj.m42 || 0,
obj.tz || obj.m43 || 0,
defined(obj.m44, 1),
]
],
];
}
function convert3dMatrixToString(matrix) {
if (is2d(matrix)) {
return "matrix(" +
[ matrix[0][0], matrix[0][1],
matrix[1][0], matrix[1][1],
matrix[3][0], matrix[3][1] ].join(", ") + ")";
return (
"matrix(" +
[
matrix[0][0],
matrix[0][1],
matrix[1][0],
matrix[1][1],
matrix[3][0],
matrix[3][1],
].join(", ") +
")"
);
} else {
return "matrix3d(" +
matrix.reduce(function(outer, inner) {
return outer.concat(inner);
}).join(", ") + ")";
return (
"matrix3d(" +
matrix
.reduce(function(outer, inner) {
return outer.concat(inner);
})
.join(", ") +
")"
);
}
}
function is2d(matrix) {
return matrix[0][2] === 0 && matrix[0][3] === 0 &&
matrix[1][2] === 0 && matrix[1][3] === 0 &&
matrix[2][0] === 0 && matrix[2][1] === 0 &&
matrix[2][2] === 1 && matrix[2][3] === 0 &&
matrix[3][2] === 0 && matrix[3][3] === 1;
return (
matrix[0][2] === 0 &&
matrix[0][3] === 0 &&
matrix[1][2] === 0 &&
matrix[1][3] === 0 &&
matrix[2][0] === 0 &&
matrix[2][1] === 0 &&
matrix[2][2] === 1 &&
matrix[2][3] === 0 &&
matrix[3][2] === 0 &&
matrix[3][3] === 1
);
}
function getDeterminant(matrix) {
@ -701,30 +830,32 @@ const ExpectComparisonTo = {
return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];
}
return matrix[0][3] * matrix[1][2] * matrix[2][1] * matrix[3][0]
- matrix[0][2] * matrix[1][3] * matrix[2][1] * matrix[3][0]
- matrix[0][3] * matrix[1][1] * matrix[2][2] * matrix[3][0]
+ matrix[0][1] * matrix[1][3] * matrix[2][2] * matrix[3][0]
+ matrix[0][2] * matrix[1][1] * matrix[2][3] * matrix[3][0]
- matrix[0][1] * matrix[1][2] * matrix[2][3] * matrix[3][0]
- matrix[0][3] * matrix[1][2] * matrix[2][0] * matrix[3][1]
+ matrix[0][2] * matrix[1][3] * matrix[2][0] * matrix[3][1]
+ matrix[0][3] * matrix[1][0] * matrix[2][2] * matrix[3][1]
- matrix[0][0] * matrix[1][3] * matrix[2][2] * matrix[3][1]
- matrix[0][2] * matrix[1][0] * matrix[2][3] * matrix[3][1]
+ matrix[0][0] * matrix[1][2] * matrix[2][3] * matrix[3][1]
+ matrix[0][3] * matrix[1][1] * matrix[2][0] * matrix[3][2]
- matrix[0][1] * matrix[1][3] * matrix[2][0] * matrix[3][2]
- matrix[0][3] * matrix[1][0] * matrix[2][1] * matrix[3][2]
+ matrix[0][0] * matrix[1][3] * matrix[2][1] * matrix[3][2]
+ matrix[0][1] * matrix[1][0] * matrix[2][3] * matrix[3][2]
- matrix[0][0] * matrix[1][1] * matrix[2][3] * matrix[3][2]
- matrix[0][2] * matrix[1][1] * matrix[2][0] * matrix[3][3]
+ matrix[0][1] * matrix[1][2] * matrix[2][0] * matrix[3][3]
+ matrix[0][2] * matrix[1][0] * matrix[2][1] * matrix[3][3]
- matrix[0][0] * matrix[1][2] * matrix[2][1] * matrix[3][3]
- matrix[0][1] * matrix[1][0] * matrix[2][2] * matrix[3][3]
+ matrix[0][0] * matrix[1][1] * matrix[2][2] * matrix[3][3];
return (
matrix[0][3] * matrix[1][2] * matrix[2][1] * matrix[3][0] -
matrix[0][2] * matrix[1][3] * matrix[2][1] * matrix[3][0] -
matrix[0][3] * matrix[1][1] * matrix[2][2] * matrix[3][0] +
matrix[0][1] * matrix[1][3] * matrix[2][2] * matrix[3][0] +
matrix[0][2] * matrix[1][1] * matrix[2][3] * matrix[3][0] -
matrix[0][1] * matrix[1][2] * matrix[2][3] * matrix[3][0] -
matrix[0][3] * matrix[1][2] * matrix[2][0] * matrix[3][1] +
matrix[0][2] * matrix[1][3] * matrix[2][0] * matrix[3][1] +
matrix[0][3] * matrix[1][0] * matrix[2][2] * matrix[3][1] -
matrix[0][0] * matrix[1][3] * matrix[2][2] * matrix[3][1] -
matrix[0][2] * matrix[1][0] * matrix[2][3] * matrix[3][1] +
matrix[0][0] * matrix[1][2] * matrix[2][3] * matrix[3][1] +
matrix[0][3] * matrix[1][1] * matrix[2][0] * matrix[3][2] -
matrix[0][1] * matrix[1][3] * matrix[2][0] * matrix[3][2] -
matrix[0][3] * matrix[1][0] * matrix[2][1] * matrix[3][2] +
matrix[0][0] * matrix[1][3] * matrix[2][1] * matrix[3][2] +
matrix[0][1] * matrix[1][0] * matrix[2][3] * matrix[3][2] -
matrix[0][0] * matrix[1][1] * matrix[2][3] * matrix[3][2] -
matrix[0][2] * matrix[1][1] * matrix[2][0] * matrix[3][3] +
matrix[0][1] * matrix[1][2] * matrix[2][0] * matrix[3][3] +
matrix[0][2] * matrix[1][0] * matrix[2][1] * matrix[3][3] -
matrix[0][0] * matrix[1][2] * matrix[2][1] * matrix[3][3] -
matrix[0][1] * matrix[1][0] * matrix[2][2] * matrix[3][3] +
matrix[0][0] * matrix[1][1] * matrix[2][2] * matrix[3][3]
);
}
})();
@ -750,9 +881,13 @@ function waitForPaintsFlushed() {
function waitForVisitedLinkColoring(visitedLink, waitProperty, waitValue) {
function checkLink(resolve) {
if (SpecialPowers.DOMWindowUtils
.getVisitedDependentComputedStyle(visitedLink, "", waitProperty) ==
waitValue) {
if (
SpecialPowers.DOMWindowUtils.getVisitedDependentComputedStyle(
visitedLink,
"",
waitProperty
) == waitValue
) {
// Our link has been styled as visited. Resolve.
resolve(true);
} else {

View file

@ -1,13 +1,16 @@
add_task(async function() {
let uri = getRootDirectory(gTestPath) + "bug453896_iframe.html";
await BrowserTestUtils.withNewTab({
gBrowser,
url: uri
}, function(browser) {
return ContentTask.spawn(browser, null, async function() {
var fake_window = { ok: ok };
content.wrappedJSObject.run(fake_window);
});
});
await BrowserTestUtils.withNewTab(
{
gBrowser,
url: uri,
},
function(browser) {
return ContentTask.spawn(browser, null, async function() {
var fake_window = { ok: ok };
content.wrappedJSObject.run(fake_window);
});
}
);
});

View file

@ -2,29 +2,40 @@ add_task(async function() {
let uri = "http://example.com/browser/layout/style/test/sourcemap_css.html";
info(`URI is ${uri}`);
await BrowserTestUtils.withNewTab({
gBrowser,
url: uri
}, async function(browser) {
await ContentTask.spawn(browser, null, function* () {
let seenSheets = 0;
await BrowserTestUtils.withNewTab(
{
gBrowser,
url: uri,
},
async function(browser) {
await ContentTask.spawn(browser, null, function*() {
let seenSheets = 0;
for (let i = 0; i < content.document.styleSheets.length; ++i) {
let sheet = content.document.styleSheets[i];
for (let i = 0; i < content.document.styleSheets.length; ++i) {
let sheet = content.document.styleSheets[i];
info(`Checking ${sheet.href}`);
if (/mapped\.css/.test(sheet.href)) {
is(sheet.sourceMapURL, "mapped.css.map", "X-SourceMap header took effect");
seenSheets |= 1;
} else if (/mapped2\.css/.test(sheet.href)) {
is(sheet.sourceMapURL, "mapped2.css.map", "SourceMap header took effect");
seenSheets |= 2;
} else {
ok(false, "sheet does not have source map URL");
info(`Checking ${sheet.href}`);
if (/mapped\.css/.test(sheet.href)) {
is(
sheet.sourceMapURL,
"mapped.css.map",
"X-SourceMap header took effect"
);
seenSheets |= 1;
} else if (/mapped2\.css/.test(sheet.href)) {
is(
sheet.sourceMapURL,
"mapped2.css.map",
"SourceMap header took effect"
);
seenSheets |= 2;
} else {
ok(false, "sheet does not have source map URL");
}
}
}
is(seenSheets, 3, "seen all source-mapped sheets");
});
});
});
}
);
});

View file

@ -17,24 +17,33 @@ add_task(async function() {
let page = "<!DOCTYPE HTML>\n<html>\n<head>\n";
for (let i = 0; i < test_cases.length; ++i) {
page += `<style type="text/css"> #x${i} { color: red; }${test_cases[i][0]}</style>\n`;
page += `<style type="text/css"> #x${i} { color: red; }${
test_cases[i][0]
}</style>\n`;
}
page += "</head><body>some text</body></html>";
let uri = "data:text/html;base64," + btoa(page);
info(`URI is ${uri}`);
await BrowserTestUtils.withNewTab({
gBrowser,
url: uri
}, async function(browser) {
await ContentTask.spawn(browser, test_cases, function* (tests) {
for (let i = 0; i < content.document.styleSheets.length; ++i) {
let sheet = content.document.styleSheets[i];
await BrowserTestUtils.withNewTab(
{
gBrowser,
url: uri,
},
async function(browser) {
await ContentTask.spawn(browser, test_cases, function*(tests) {
for (let i = 0; i < content.document.styleSheets.length; ++i) {
let sheet = content.document.styleSheets[i];
info(`Checking sheet #${i}`);
is(sheet.sourceMapURL, tests[i][1], `correct source map for sheet ${i}`);
}
});
});
info(`Checking sheet #${i}`);
is(
sheet.sourceMapURL,
tests[i][1],
`correct source map for sheet ${i}`
);
}
});
}
);
});

View file

@ -17,24 +17,29 @@ add_task(async function() {
let page = "<!DOCTYPE HTML>\n<html>\n<head>\n";
for (let i = 0; i < test_cases.length; ++i) {
page += `<style type="text/css"> #x${i} { color: red; }${test_cases[i][0]}</style>\n`;
page += `<style type="text/css"> #x${i} { color: red; }${
test_cases[i][0]
}</style>\n`;
}
page += "</head><body>some text</body></html>";
let uri = "data:text/html;base64," + btoa(page);
info(`URI is ${uri}`);
await BrowserTestUtils.withNewTab({
gBrowser,
url: uri
}, async function(browser) {
await ContentTask.spawn(browser, test_cases, function* (tests) {
for (let i = 0; i < content.document.styleSheets.length; ++i) {
let sheet = content.document.styleSheets[i];
await BrowserTestUtils.withNewTab(
{
gBrowser,
url: uri,
},
async function(browser) {
await ContentTask.spawn(browser, test_cases, function*(tests) {
for (let i = 0; i < content.document.styleSheets.length; ++i) {
let sheet = content.document.styleSheets[i];
info(`Checking sheet #${i}`);
is(sheet.sourceURL, tests[i][1], `correct source URL for sheet ${i}`);
}
});
});
info(`Checking sheet #${i}`);
is(sheet.sourceURL, tests[i][1], `correct source URL for sheet ${i}`);
}
});
}
);
});

View file

@ -16,26 +16,38 @@ var expected_values = [
["color", null, 8],
["color-index", null, 0],
["aspect-ratio", null, window.innerWidth + "/" + window.innerHeight],
["device-aspect-ratio", screen.width + "/" + screen.height,
window.innerWidth + "/" + window.innerHeight],
[
"device-aspect-ratio",
screen.width + "/" + screen.height,
window.innerWidth + "/" + window.innerHeight,
],
["device-height", screen.height + "px", window.innerHeight + "px"],
["device-width", screen.width + "px", window.innerWidth + "px"],
["grid", null, 0],
["height", window.innerHeight + "px", window.innerHeight + "px"],
["monochrome", null, 0],
// Square is defined as portrait:
["orientation", null,
window.innerWidth > window.innerHeight ?
"landscape" : "portrait"],
[
"orientation",
null,
window.innerWidth > window.innerHeight ? "landscape" : "portrait",
],
["resolution", null, "96dpi"],
["resolution", [0.999 * window.devicePixelRatio + "dppx",
1.001 * window.devicePixelRatio + "dppx"], "1dppx"],
[
"resolution",
[
0.999 * window.devicePixelRatio + "dppx",
1.001 * window.devicePixelRatio + "dppx",
],
"1dppx",
],
["width", window.innerWidth + "px", window.innerWidth + "px"],
["-moz-device-pixel-ratio", window.devicePixelRatio, 1],
["-moz-device-orientation", screen.width > screen.height ?
"landscape" : "portrait",
window.innerWidth > window.innerHeight ?
"landscape" : "portrait"]
[
"-moz-device-orientation",
screen.width > screen.height ? "landscape" : "portrait",
window.innerWidth > window.innerHeight ? "landscape" : "portrait",
],
];
// These media queries return value 0 or 1 when the pref is off.
@ -43,7 +55,7 @@ var expected_values = [
var suppressed_toggles = [
"-moz-mac-graphite-theme",
// Not available on most OSs.
// "-moz-maemo-classic",
// "-moz-maemo-classic",
"-moz-scrollbar-end-backward",
"-moz-scrollbar-end-forward",
"-moz-scrollbar-start-backward",
@ -62,16 +74,10 @@ var suppressed_toggles = [
"-moz-gtk-csd-reversed-placement",
];
var toggles_enabled_in_content = [
"-moz-touch-enabled",
];
var toggles_enabled_in_content = ["-moz-touch-enabled"];
// Possible values for '-moz-os-version'
var windows_versions = [
"windows-win7",
"windows-win8",
"windows-win10",
];
var windows_versions = ["windows-win7", "windows-win8", "windows-win10"];
// Read the current OS.
var OS = SpecialPowers.Services.appinfo.OS;
@ -84,18 +90,22 @@ if (OS === "WINNT") {
// __keyValMatches(key, val)__.
// Runs a media query and returns true if key matches to val.
var keyValMatches = (key, val) => matchMedia("(" + key + ":" + val +")").matches;
var keyValMatches = (key, val) =>
matchMedia("(" + key + ":" + val + ")").matches;
// __testMatch(key, val)__.
// Attempts to run a media query match for the given key and value.
// If value is an array of two elements [min max], then matches any
// value in-between.
var testMatch = function (key, val) {
var testMatch = function(key, val) {
if (val === null) {
return;
} else if (Array.isArray(val)) {
ok(keyValMatches("min-" + key, val[0]) && keyValMatches("max-" + key, val[1]),
"Expected " + key + " between " + val[0] + " and " + val[1]);
ok(
keyValMatches("min-" + key, val[0]) &&
keyValMatches("max-" + key, val[1]),
"Expected " + key + " between " + val[0] + " and " + val[1]
);
} else {
ok(keyValMatches(key, val), "Expected " + key + ":" + val);
}
@ -103,26 +113,28 @@ var testMatch = function (key, val) {
// __testToggles(resisting)__.
// Test whether we are able to match the "toggle" media queries.
var testToggles = function (resisting) {
suppressed_toggles.forEach(
function (key) {
var exists = keyValMatches(key, 0) || keyValMatches(key, 1);
if (!toggles_enabled_in_content.includes(key) && !is_chrome_window) {
ok(!exists, key + " should not exist.");
} else {
ok(exists, key + " should exist.");
if (resisting) {
ok(keyValMatches(key, 0) && !keyValMatches(key, 1), "Should always match as false");
}
var testToggles = function(resisting) {
suppressed_toggles.forEach(function(key) {
var exists = keyValMatches(key, 0) || keyValMatches(key, 1);
if (!toggles_enabled_in_content.includes(key) && !is_chrome_window) {
ok(!exists, key + " should not exist.");
} else {
ok(exists, key + " should exist.");
if (resisting) {
ok(
keyValMatches(key, 0) && !keyValMatches(key, 1),
"Should always match as false"
);
}
});
}
});
};
// __testWindowsSpecific__.
// Runs a media query on the queryName with the given possible matching values.
var testWindowsSpecific = function (resisting, queryName, possibleValues) {
var testWindowsSpecific = function(resisting, queryName, possibleValues) {
let foundValue = null;
possibleValues.forEach(function (val) {
possibleValues.forEach(function(val) {
if (keyValMatches(queryName, val)) {
foundValue = val;
}
@ -130,8 +142,12 @@ var testWindowsSpecific = function (resisting, queryName, possibleValues) {
if (resisting || !is_chrome_window) {
ok(!foundValue, queryName + " should have no match");
} else {
ok(foundValue, foundValue ? ("Match found: '" + queryName + ":" + foundValue + "'")
: "Should have a match for '" + queryName + "'");
ok(
foundValue,
foundValue
? "Match found: '" + queryName + ":" + foundValue + "'"
: "Should have a match for '" + queryName + "'"
);
}
};
@ -139,27 +155,25 @@ var testWindowsSpecific = function (resisting, queryName, possibleValues) {
// Create a series of div elements that look like:
// `<div class='spoof' id='resolution'>resolution</div>`,
// where each line corresponds to a different media query.
var generateHtmlLines = function (resisting) {
var generateHtmlLines = function(resisting) {
let fragment = document.createDocumentFragment();
expected_values.forEach(
function ([key, offVal, onVal]) {
let val = resisting ? onVal : offVal;
if (val) {
let div = document.createElementNS(HTML_NS, "div");
div.setAttribute("class", "spoof");
div.setAttribute("id", key);
div.textContent = key;
fragment.appendChild(div);
}
});
suppressed_toggles.forEach(
function (key) {
expected_values.forEach(function([key, offVal, onVal]) {
let val = resisting ? onVal : offVal;
if (val) {
let div = document.createElementNS(HTML_NS, "div");
div.setAttribute("class", "suppress");
div.setAttribute("class", "spoof");
div.setAttribute("id", key);
div.textContent = key;
fragment.appendChild(div);
});
}
});
suppressed_toggles.forEach(function(key) {
let div = document.createElementNS(HTML_NS, "div");
div.setAttribute("class", "suppress");
div.setAttribute("id", key);
div.textContent = key;
fragment.appendChild(div);
});
if (OS === "WINNT") {
let div = document.createElementNS(HTML_NS, "div");
div.setAttribute("class", "windows");
@ -173,23 +187,32 @@ var generateHtmlLines = function (resisting) {
// __cssLine__.
// Creates a line of css that looks something like
// `@media (resolution: 1ppx) { .spoof#resolution { background-color: green; } }`.
var cssLine = function (query, clazz, id, color) {
return "@media " + query + " { ." + clazz + "#" + id +
" { background-color: " + color + "; } }\n";
var cssLine = function(query, clazz, id, color) {
return (
"@media " +
query +
" { ." +
clazz +
"#" +
id +
" { background-color: " +
color +
"; } }\n"
);
};
// __constructQuery(key, val)__.
// Creates a CSS media query from key and val. If key is an array of
// two elements, constructs a range query (using min- and max-).
var constructQuery = function (key, val) {
return Array.isArray(val) ?
"(min-" + key + ": " + val[0] + ") and (max-" + key + ": " + val[1] + ")" :
"(" + key + ": " + val + ")";
var constructQuery = function(key, val) {
return Array.isArray(val)
? "(min-" + key + ": " + val[0] + ") and (max-" + key + ": " + val[1] + ")"
: "(" + key + ": " + val + ")";
};
// __mediaQueryCSSLine(key, val, color)__.
// Creates a line containing a CSS media query and a CSS expression.
var mediaQueryCSSLine = function (key, val, color) {
var mediaQueryCSSLine = function(key, val, color) {
if (val === null) {
return "";
}
@ -199,7 +222,7 @@ var mediaQueryCSSLine = function (key, val, color) {
// __suppressedMediaQueryCSSLine(key, color)__.
// Creates a CSS line that matches the existence of a
// media query that is supposed to be suppressed.
var suppressedMediaQueryCSSLine = function (key, color, suppressed) {
var suppressedMediaQueryCSSLine = function(key, color, suppressed) {
let query = "(" + key + ": 0), (" + key + ": 1)";
return cssLine(query, "suppress", key, color);
};
@ -208,25 +231,32 @@ var suppressedMediaQueryCSSLine = function (key, color, suppressed) {
// Creates a series of lines of CSS, each of which corresponds to
// a different media query. If the query produces a match to the
// expected value, then the element will be colored green.
var generateCSSLines = function (resisting) {
var generateCSSLines = function(resisting) {
let lines = ".spoof { background-color: red;}\n";
expected_values.forEach(
function ([key, offVal, onVal]) {
lines += mediaQueryCSSLine(key, resisting ? onVal : offVal, "green");
});
lines += ".suppress { background-color: " + (resisting ? "green" : "red") + ";}\n";
suppressed_toggles.forEach(
function (key) {
if (!toggles_enabled_in_content.includes(key) && !resisting && !is_chrome_window) {
lines += "#" + key + " { background-color: green; }\n";
} else {
lines += suppressedMediaQueryCSSLine(key, "green");
}
});
expected_values.forEach(function([key, offVal, onVal]) {
lines += mediaQueryCSSLine(key, resisting ? onVal : offVal, "green");
});
lines +=
".suppress { background-color: " + (resisting ? "green" : "red") + ";}\n";
suppressed_toggles.forEach(function(key) {
if (
!toggles_enabled_in_content.includes(key) &&
!resisting &&
!is_chrome_window
) {
lines += "#" + key + " { background-color: green; }\n";
} else {
lines += suppressedMediaQueryCSSLine(key, "green");
}
});
if (OS === "WINNT") {
lines += ".windows { background-color: " + (resisting ? "green" : "red") + ";}\n";
lines += windows_versions.map(val => "(-moz-os-version: " + val + ")").join(", ") +
" { #-moz-os-version { background-color: " + (resisting ? "red" : "green") + ";} }\n";
lines +=
".windows { background-color: " + (resisting ? "green" : "red") + ";}\n";
lines +=
windows_versions.map(val => "(-moz-os-version: " + val + ")").join(", ") +
" { #-moz-os-version { background-color: " +
(resisting ? "red" : "green") +
";} }\n";
}
return lines;
};
@ -239,7 +269,7 @@ var green = "rgb(0, 128, 0)";
// Creates a series of divs and CSS using media queries to set their
// background color. If all media queries match as expected, then
// all divs should have a green background color.
var testCSS = function (resisting) {
var testCSS = function(resisting) {
document.getElementById("display").appendChild(generateHtmlLines(resisting));
document.getElementById("test-css").textContent = generateCSSLines(resisting);
let cssTestDivs = document.querySelectorAll(".spoof,.suppress");
@ -252,20 +282,26 @@ var testCSS = function (resisting) {
// __testOSXFontSmoothing(resisting)__.
// When fingerprinting resistance is enabled, the `getComputedStyle`
// should always return `undefined` for `MozOSXFontSmoothing`.
var testOSXFontSmoothing = function (resisting) {
var testOSXFontSmoothing = function(resisting) {
let div = document.createElementNS(HTML_NS, "div");
div.style.MozOsxFontSmoothing = "unset";
document.documentElement.appendChild(div);
let readBack = window.getComputedStyle(div).MozOsxFontSmoothing;
div.remove();
let smoothingPref = SpecialPowers.getBoolPref("layout.css.osx-font-smoothing.enabled", false);
is(readBack, resisting ? "" : (smoothingPref ? "auto" : ""),
"-moz-osx-font-smoothing");
let smoothingPref = SpecialPowers.getBoolPref(
"layout.css.osx-font-smoothing.enabled",
false
);
is(
readBack,
resisting ? "" : smoothingPref ? "auto" : "",
"-moz-osx-font-smoothing"
);
};
// __sleep(timeoutMs)__.
// Returns a promise that resolves after the given timeout.
var sleep = function (timeoutMs) {
var sleep = function(timeoutMs) {
return new Promise(function(resolve, reject) {
window.setTimeout(resolve);
});
@ -282,7 +318,10 @@ var testMediaQueriesInPictureElements = async function(resisting) {
let query = constructQuery(key, expected);
let source = document.createElementNS(HTML_NS, "source");
source.setAttribute("srcset", "/tests/layout/style/test/chrome/match.png");
source.setAttribute(
"srcset",
"/tests/layout/style/test/chrome/match.png"
);
source.setAttribute("media", query);
let image = document.createElementNS(HTML_NS, "img");
@ -299,16 +338,19 @@ var testMediaQueriesInPictureElements = async function(resisting) {
var testImages = document.getElementsByClassName("testImage");
await sleep(0);
for (let testImage of testImages) {
ok(testImage.currentSrc.endsWith("/match.png"), "Media query '" + testImage.title + "' in picture should match.");
ok(
testImage.currentSrc.endsWith("/match.png"),
"Media query '" + testImage.title + "' in picture should match."
);
}
};
// __pushPref(key, value)__.
// Set a pref value asynchronously, returning a promise that resolves
// when it succeeds.
var pushPref = function (key, value) {
var pushPref = function(key, value) {
return new Promise(function(resolve, reject) {
SpecialPowers.pushPrefEnv({"set": [[key, value]]}, resolve);
SpecialPowers.pushPrefEnv({ set: [[key, value]] }, resolve);
});
};
@ -318,10 +360,9 @@ var test = async function(isContent) {
for (prefValue of [false, true]) {
await pushPref("privacy.resistFingerprinting", prefValue);
let resisting = prefValue && isContent;
expected_values.forEach(
function ([key, offVal, onVal]) {
testMatch(key, resisting ? onVal : offVal);
});
expected_values.forEach(function([key, offVal, onVal]) {
testMatch(key, resisting ? onVal : offVal);
});
testToggles(resisting);
if (OS === "WINNT") {
testWindowsSpecific(resisting, "-moz-os-version", windows_versions);

View file

@ -1,3 +1 @@
var gShorthandPropertiesLikeLonghand = [
{ name: "overflow", prop: "overflow"},
];
var gShorthandPropertiesLikeLonghand = [{ name: "overflow", prop: "overflow" }];

View file

@ -11,67 +11,132 @@
// should be rejected.
var gCSSFontFaceDescriptors = {
"font-family": {
domProp: "fontFamily",
values: [ "\"serif\"", "\"cursive\"", "seriff", "Times New Roman", "TimesRoman", "\"Times New Roman\"" ],
/* not clear that the generics are really invalid */
invalid_values: [ "sans-serif", "Times New Roman, serif", "'Times New Roman', serif", "cursive", "fantasy", "Times )", "Times !", "Times ! foo", "Times ! important" ]
},
"font-stretch": {
domProp: "fontStretch",
values: [ "normal", "ultra-condensed", "extra-condensed", "condensed", "semi-condensed", "semi-expanded", "expanded", "extra-expanded", "ultra-expanded" ],
invalid_values: [ "wider", "narrower", "normal ! important", "normal )" ]
},
"font-style": {
domProp: "fontStyle",
values: [ "normal", "italic", "oblique" ],
invalid_values: []
},
"font-weight": {
domProp: "fontWeight",
values: [
"normal", "400", "bold", "100", "200", "300", "500", "600",
"700", "800", "900", "107", "399", "401", "699", "710",
"calc(1001)", "calc(100 + 1)", "calc(1)", "100.6", "99",
"700 900", "300.4 500.4", "calc(200.4) calc(400.4)",
],
invalid_values: [ "bolder", "lighter", "1001", "0", "0 100", "100 1001" ]
},
"src": {
domProp: null,
values: [
"url(404.ttf)",
"url(\"404.eot\")",
"url(\'404.otf\')",
"url(404.ttf) format(\"truetype\")",
"url(404.ttf) format(\"truetype\", \"opentype\")",
"url(404.ttf) format(\"truetype\", \"opentype\"), url(\'404.eot\')",
"local(Times New Roman)",
"local(\'Times New Roman\')",
"local(\"Times New Roman\")",
"local(\"serif\")",
"url(404.ttf) format(\"truetype\", \"unknown\"), local(Times New Roman), url(\'404.eot\')",
],
invalid_values: [
"url(404.ttf) format(truetype)",
"url(404.ttf) format(\"truetype\" \"opentype\")",
"url(404.ttf) format(\"truetype\",)",
"local(\"Times New\" Roman)",
"local(serif)", /* is this valid? */
"url(404.ttf) )",
"url(404.ttf) ) foo",
"url(404.ttf) ! important",
"url(404.ttf) ! hello",
]
},
"unicode-range": {
domProp: null,
values: [ "U+0-10FFFF", "U+3-7B3", "U+3??", "U+6A", "U+3????", "U+???", "U+302-302", "U+0-7,U+A-C", "U+3??, U+500-513 ,U+612 , U+4????", "U+1FFF,U+200-27F" ],
invalid_values: [ "U+1????-2????", "U+0-7,A-C", "U+100-17F,U+200-17F", "U+100-17F,200-27F", "U+6A!important", "U+6A)" ]
},
"font-display": {
domProp: null,
values: [ "auto", "block", "swap", "fallback", "optional" ],
invalid_values: [ "normal", "initial" ]
}
}
"font-family": {
domProp: "fontFamily",
values: [
'"serif"',
'"cursive"',
"seriff",
"Times New Roman",
"TimesRoman",
'"Times New Roman"',
],
/* not clear that the generics are really invalid */
invalid_values: [
"sans-serif",
"Times New Roman, serif",
"'Times New Roman', serif",
"cursive",
"fantasy",
"Times )",
"Times !",
"Times ! foo",
"Times ! important",
],
},
"font-stretch": {
domProp: "fontStretch",
values: [
"normal",
"ultra-condensed",
"extra-condensed",
"condensed",
"semi-condensed",
"semi-expanded",
"expanded",
"extra-expanded",
"ultra-expanded",
],
invalid_values: ["wider", "narrower", "normal ! important", "normal )"],
},
"font-style": {
domProp: "fontStyle",
values: ["normal", "italic", "oblique"],
invalid_values: [],
},
"font-weight": {
domProp: "fontWeight",
values: [
"normal",
"400",
"bold",
"100",
"200",
"300",
"500",
"600",
"700",
"800",
"900",
"107",
"399",
"401",
"699",
"710",
"calc(1001)",
"calc(100 + 1)",
"calc(1)",
"100.6",
"99",
"700 900",
"300.4 500.4",
"calc(200.4) calc(400.4)",
],
invalid_values: ["bolder", "lighter", "1001", "0", "0 100", "100 1001"],
},
src: {
domProp: null,
values: [
"url(404.ttf)",
'url("404.eot")',
"url('404.otf')",
'url(404.ttf) format("truetype")',
'url(404.ttf) format("truetype", "opentype")',
'url(404.ttf) format("truetype", "opentype"), url(\'404.eot\')',
"local(Times New Roman)",
"local('Times New Roman')",
'local("Times New Roman")',
'local("serif")',
'url(404.ttf) format("truetype", "unknown"), local(Times New Roman), url(\'404.eot\')',
],
invalid_values: [
"url(404.ttf) format(truetype)",
'url(404.ttf) format("truetype" "opentype")',
'url(404.ttf) format("truetype",)',
'local("Times New" Roman)',
"local(serif)" /* is this valid? */,
"url(404.ttf) )",
"url(404.ttf) ) foo",
"url(404.ttf) ! important",
"url(404.ttf) ! hello",
],
},
"unicode-range": {
domProp: null,
values: [
"U+0-10FFFF",
"U+3-7B3",
"U+3??",
"U+6A",
"U+3????",
"U+???",
"U+302-302",
"U+0-7,U+A-C",
"U+3??, U+500-513 ,U+612 , U+4????",
"U+1FFF,U+200-27F",
],
invalid_values: [
"U+1????-2????",
"U+0-7,A-C",
"U+100-17F,U+200-17F",
"U+100-17F,200-27F",
"U+6A!important",
"U+6A)",
],
},
"font-display": {
domProp: null,
values: ["auto", "block", "swap", "fallback", "optional"],
invalid_values: ["normal", "initial"],
},
};

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,27 +1,25 @@
SimpleTest.waitForExplicitFinish();
window.addEventListener("load", runTests);
function runTests(event)
{
if (event.target != document) {
return;
}
function runTests(event) {
if (event.target != document) {
return;
}
var elt = document.getElementById("content");
var elt = document.getElementById("content");
elt.setAttribute("style", "color: blue; background-color: fuchsia");
is(elt.style.color, "blue",
"setting correct style attribute (color)");
is(elt.style.backgroundColor, "fuchsia",
"setting correct style attribute (color)");
elt.setAttribute("style", "color: blue; background-color: fuchsia");
is(elt.style.color, "blue", "setting correct style attribute (color)");
is(
elt.style.backgroundColor,
"fuchsia",
"setting correct style attribute (color)"
);
elt.setAttribute("style", "{color: blue; background-color: fuchsia}");
is(elt.style.color, "",
"setting braced style attribute (color)");
is(elt.style.backgroundColor, "",
"setting braced style attribute (color)");
elt.setAttribute("style", "{color: blue; background-color: fuchsia}");
is(elt.style.color, "", "setting braced style attribute (color)");
is(elt.style.backgroundColor, "", "setting braced style attribute (color)");
SimpleTest.finish();
SimpleTest.finish();
}

View file

@ -11,13 +11,15 @@ function test() {
const windowListener = {
onOpenWindow(win) {
info("Observed window open")
info("Observed window open");
const domWindow = win.docShell.domWindow;
waitForFocus(() => {
is(domWindow.location,
"chrome://layoutdebug/content/layoutdebug.xul",
"Window location is correct");
is(
domWindow.location,
"chrome://layoutdebug/content/layoutdebug.xul",
"Window location is correct"
);
domWindow.close();
}, domWindow);
},
@ -26,7 +28,7 @@ function test() {
info("Observed window closed");
Services.wm.removeListener(this);
finish();
}
},
};
Services.wm.addListener(windowListener);

View file

@ -1,6 +1,6 @@
function run_test() {
Assert.ok("@mozilla.org/layout-debug/layout-debuggingtools;1" in
Cc);
Assert.ok("@mozilla.org/commandlinehandler/general-startup;1?type=layoutdebug" in
Cc);
Assert.ok("@mozilla.org/layout-debug/layout-debuggingtools;1" in Cc);
Assert.ok(
"@mozilla.org/commandlinehandler/general-startup;1?type=layoutdebug" in Cc
);
}

View file

@ -6,103 +6,100 @@ var gBrowser;
var gProgressListener;
var gDebugger;
const NS_LAYOUT_DEBUGGINGTOOLS_CONTRACTID = "@mozilla.org/layout-debug/layout-debuggingtools;1";
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const NS_LAYOUT_DEBUGGINGTOOLS_CONTRACTID =
"@mozilla.org/layout-debug/layout-debuggingtools;1";
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
function nsLDBBrowserContentListener()
{
function nsLDBBrowserContentListener() {
this.init();
}
nsLDBBrowserContentListener.prototype = {
init: function() {
this.mStatusText = document.getElementById("status-text");
this.mURLBar = document.getElementById("urlbar");
this.mForwardButton = document.getElementById("forward-button");
this.mBackButton = document.getElementById("back-button");
this.mStopButton = document.getElementById("stop-button");
},
init : function()
{
this.mStatusText = document.getElementById("status-text");
this.mURLBar = document.getElementById("urlbar");
this.mForwardButton = document.getElementById("forward-button");
this.mBackButton = document.getElementById("back-button");
this.mStopButton = document.getElementById("stop-button");
},
QueryInterface: ChromeUtils.generateQI([Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference]),
QueryInterface: ChromeUtils.generateQI([
Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference,
]),
// nsIWebProgressListener implementation
onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus)
{
if (!(aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) ||
aWebProgress != gBrowser.webProgress)
return;
onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
if (
!(aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) ||
aWebProgress != gBrowser.webProgress
) {
return;
}
if (aStateFlags & Ci.nsIWebProgressListener.STATE_START) {
this.setButtonEnabled(this.mStopButton, true);
this.setButtonEnabled(this.mForwardButton, gBrowser.canGoForward);
this.setButtonEnabled(this.mBackButton, gBrowser.canGoBack);
this.mStatusText.value = "loading...";
this.mLoading = true;
} else if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
this.setButtonEnabled(this.mStopButton, false);
this.mStatusText.value = this.mURLBar.value + " loaded";
this.mLoading = false;
}
},
onProgressChange : function(aWebProgress, aRequest,
aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress)
{
},
onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags)
{
this.mURLBar.value = aLocation.spec;
if (aStateFlags & Ci.nsIWebProgressListener.STATE_START) {
this.setButtonEnabled(this.mStopButton, true);
this.setButtonEnabled(this.mForwardButton, gBrowser.canGoForward);
this.setButtonEnabled(this.mBackButton, gBrowser.canGoBack);
},
this.mStatusText.value = "loading...";
this.mLoading = true;
} else if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
this.setButtonEnabled(this.mStopButton, false);
this.mStatusText.value = this.mURLBar.value + " loaded";
this.mLoading = false;
}
},
onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage)
{
this.mStatusText.value = aMessage;
},
onProgressChange: function(
aWebProgress,
aRequest,
aCurSelfProgress,
aMaxSelfProgress,
aCurTotalProgress,
aMaxTotalProgress
) {},
onSecurityChange : function(aWebProgress, aRequest, aState)
{
},
onLocationChange: function(aWebProgress, aRequest, aLocation, aFlags) {
this.mURLBar.value = aLocation.spec;
this.setButtonEnabled(this.mForwardButton, gBrowser.canGoForward);
this.setButtonEnabled(this.mBackButton, gBrowser.canGoBack);
},
onContentBlockingEvent : function(aWebProgress, aRequest, aEvent)
{
},
onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage) {
this.mStatusText.value = aMessage;
},
onSecurityChange: function(aWebProgress, aRequest, aState) {},
onContentBlockingEvent: function(aWebProgress, aRequest, aEvent) {},
// non-interface methods
setButtonEnabled : function(aButtonElement, aEnabled)
{
if (aEnabled)
aButtonElement.removeAttribute("disabled");
else
aButtonElement.setAttribute("disabled", "true");
},
setButtonEnabled: function(aButtonElement, aEnabled) {
if (aEnabled) {
aButtonElement.removeAttribute("disabled");
} else {
aButtonElement.setAttribute("disabled", "true");
}
},
mStatusText : null,
mURLBar : null,
mForwardButton : null,
mBackButton : null,
mStopButton : null,
mStatusText: null,
mURLBar: null,
mForwardButton: null,
mBackButton: null,
mStopButton: null,
mLoading : false
mLoading: false,
};
}
function OnLDBLoad()
{
function OnLDBLoad() {
gBrowser = document.getElementById("browser");
gProgressListener = new nsLDBBrowserContentListener();
gBrowser.addProgressListener(gProgressListener);
gDebugger = Cc[NS_LAYOUT_DEBUGGINGTOOLS_CONTRACTID].
createInstance(Ci.nsILayoutDebuggingTools);
gDebugger = Cc[NS_LAYOUT_DEBUGGINGTOOLS_CONTRACTID].createInstance(
Ci.nsILayoutDebuggingTools
);
if (window.arguments && window.arguments[0]) {
gBrowser.loadURI(window.arguments[0], {
@ -110,7 +107,9 @@ function OnLDBLoad()
});
} else {
gBrowser.loadURI("about:blank", {
triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({}),
triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal(
{}
),
});
}
@ -119,14 +118,12 @@ function OnLDBLoad()
checkPersistentMenus();
}
function checkPersistentMenu(item)
{
function checkPersistentMenu(item) {
var menuitem = document.getElementById("menu_" + item);
menuitem.setAttribute("checked", gDebugger[item]);
}
function checkPersistentMenus()
{
function checkPersistentMenus() {
// Restore the toggles that are stored in prefs.
checkPersistentMenu("paintFlashing");
checkPersistentMenu("paintDumping");
@ -137,28 +134,26 @@ function checkPersistentMenus()
checkPersistentMenu("reflowCounts");
}
function OnLDBUnload()
{
function OnLDBUnload() {
gBrowser.removeProgressListener(gProgressListener);
}
function toggle(menuitem)
{
function toggle(menuitem) {
// trim the initial "menu_"
var feature = menuitem.id.substring(5);
gDebugger[feature] = menuitem.getAttribute("checked") == "true";
}
function openFile()
{
var fp = Cc["@mozilla.org/filepicker;1"]
.createInstance(Ci.nsIFilePicker);
function openFile() {
var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
fp.init(window, "Select a File", Ci.nsIFilePicker.modeOpen);
fp.appendFilters(Ci.nsIFilePicker.filterHTML | Ci.nsIFilePicker.filterAll);
fp.open(rv => {
if (rv == Ci.nsIFilePicker.returnOK && fp.fileURL.spec &&
fp.fileURL.spec.length > 0) {
if (
rv == Ci.nsIFilePicker.returnOK &&
fp.fileURL.spec &&
fp.fileURL.spec.length > 0
) {
gBrowser.loadURI(fp.fileURL.spec, {
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
});

View file

@ -3,61 +3,67 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function RecordingCmdLineHandler() {}
RecordingCmdLineHandler.prototype =
{
/* nsISupports */
QueryInterface: ChromeUtils.generateQI([Ci.nsICommandLineHandler]),
RecordingCmdLineHandler.prototype = {
/* nsISupports */
QueryInterface: ChromeUtils.generateQI([Ci.nsICommandLineHandler]),
/* nsICommandLineHandler */
handle : function handler_handle(cmdLine) {
var args = { };
args.wrappedJSObject = args;
try {
var uristr = cmdLine.handleFlagWithParam("recording", false);
if (uristr == null)
return;
try {
args.uri = cmdLine.resolveURI(uristr).spec;
}
catch (e) {
return;
}
}
catch (e) {
cmdLine.handleFlag("recording", true);
}
/* nsICommandLineHandler */
handle: function handler_handle(cmdLine) {
var args = {};
args.wrappedJSObject = args;
try {
var uristr = cmdLine.handleFlagWithParam("recording", false);
if (uristr == null) {
return;
}
try {
args.uri = cmdLine.resolveURI(uristr).spec;
} catch (e) {
return;
}
} catch (e) {
cmdLine.handleFlag("recording", true);
}
/**
* Manipulate preferences by adding to the *default* branch. Adding
* to the default branch means the changes we make won't get written
* back to user preferences.
*
* We want to do this here rather than in reftest.js because it's
* important to set the recording pref before the platform Init gets
* called.
*/
var prefs = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefService);
var branch = prefs.getDefaultBranch("");
/**
* Manipulate preferences by adding to the *default* branch. Adding
* to the default branch means the changes we make won't get written
* back to user preferences.
*
* We want to do this here rather than in reftest.js because it's
* important to set the recording pref before the platform Init gets
* called.
*/
var prefs = Cc["@mozilla.org/preferences-service;1"].getService(
Ci.nsIPrefService
);
var branch = prefs.getDefaultBranch("");
try {
var outputstr = cmdLine.handleFlagWithParam("recording-output", false);
if (outputstr != null) {
branch.setCharPref("gfx.2d.recordingfile", outputstr);
}
} catch (e) { }
try {
var outputstr = cmdLine.handleFlagWithParam("recording-output", false);
if (outputstr != null) {
branch.setCharPref("gfx.2d.recordingfile", outputstr);
}
} catch (e) {}
branch.setBoolPref("gfx.2d.recording", true);
branch.setBoolPref("gfx.2d.recording", true);
var wwatch = Cc["@mozilla.org/embedcomp/window-watcher;1"]
.getService(Ci.nsIWindowWatcher);
wwatch.openWindow(null, "chrome://recording/content/recording.xul", "_blank",
"chrome,dialog=no,all", args);
cmdLine.preventDefault = true;
},
var wwatch = Cc["@mozilla.org/embedcomp/window-watcher;1"].getService(
Ci.nsIWindowWatcher
);
wwatch.openWindow(
null,
"chrome://recording/content/recording.xul",
"_blank",
"chrome,dialog=no,all",
args
);
cmdLine.preventDefault = true;
},
helpInfo : " --recording <file> Record drawing for a given URL.\n" +
" --recording-output <file> Specify destination file for a drawing recording.\n"
helpInfo:
" --recording <file> Record drawing for a given URL.\n" +
" --recording-output <file> Specify destination file for a drawing recording.\n",
};
var EXPORTED_SYMBOLS = ["RecordingCmdLineHandler"];

View file

@ -11,36 +11,42 @@ var gContainingWindow = null;
var gBrowser;
function OnDocumentLoad(evt) {
if (evt.target != gBrowser.contentDocument || evt.target.location == "about:blank")
return;
gBrowser.removeEventListener("load", OnDocumentLoad, true);
gContainingWindow.close();
if (
evt.target != gBrowser.contentDocument ||
evt.target.location == "about:blank"
) {
return;
}
gBrowser.removeEventListener("load", OnDocumentLoad, true);
gContainingWindow.close();
}
this.OnRecordingLoad = function OnRecordingLoad(win) {
if (win === undefined || win == null) {
win = window;
}
if (gContainingWindow == null && win != null) {
gContainingWindow = win;
}
if (win === undefined || win == null) {
win = window;
}
if (gContainingWindow == null && win != null) {
gContainingWindow = win;
}
gBrowser = gContainingWindow.document.getElementById("browser");
gBrowser = gContainingWindow.document.getElementById("browser");
var gfxInfo = (NS_GFXINFO_CONTRACTID in Cc) && Cc[NS_GFXINFO_CONTRACTID].getService(Ci.nsIGfxInfo);
var info = gfxInfo.getInfo();
dump(info.AzureContentBackend + "\n");
if (info.AzureContentBackend == "none") {
alert("Page recordings may only be made with Azure content enabled.");
gContainingWindow.close();
return;
}
var gfxInfo =
NS_GFXINFO_CONTRACTID in Cc &&
Cc[NS_GFXINFO_CONTRACTID].getService(Ci.nsIGfxInfo);
var info = gfxInfo.getInfo();
dump(info.AzureContentBackend + "\n");
if (info.AzureContentBackend == "none") {
alert("Page recordings may only be made with Azure content enabled.");
gContainingWindow.close();
return;
}
gBrowser.addEventListener("load", OnDocumentLoad, true);
gBrowser.addEventListener("load", OnDocumentLoad, true);
var args = window.arguments[0].wrappedJSObject;
var args = window.arguments[0].wrappedJSObject;
gBrowser.loadURI(args.uri, {
triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({}),
});
gBrowser.loadURI(args.uri, {
triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({}),
});
};

View file

@ -1,4 +1,7 @@
ChromeUtils.import("resource://testing-common/CustomizableUITestUtils.jsm", this);
ChromeUtils.import(
"resource://testing-common/CustomizableUITestUtils.jsm",
this
);
let gCUITestUtils = new CustomizableUITestUtils(window);
add_task(async function test_setup() {
@ -12,8 +15,11 @@ add_task(async function() {
BrowserSearch.searchBar.focus();
let DOMWindowUtils = EventUtils._getDOMWindowUtils();
is(DOMWindowUtils.IMEStatus, DOMWindowUtils.IME_STATUS_ENABLED,
"IME should be available when searchbar has focus");
is(
DOMWindowUtils.IMEStatus,
DOMWindowUtils.IME_STATUS_ENABLED,
"IME should be available when searchbar has focus"
);
let searchPopup = document.getElementById("PopupSearchAutoComplete");
@ -23,8 +29,11 @@ add_task(async function() {
await shownPromise;
await new Promise(r => setTimeout(r, 0));
is(DOMWindowUtils.IMEStatus, DOMWindowUtils.IME_STATUS_ENABLED,
"IME should be available even when the popup of searchbar is open");
is(
DOMWindowUtils.IMEStatus,
DOMWindowUtils.IME_STATUS_ENABLED,
"IME should be available even when the popup of searchbar is open"
);
// Activate the menubar, then, the popup should be closed
let hiddenPromise = BrowserTestUtils.waitForEvent(searchPopup, "popuphidden");
@ -32,10 +41,16 @@ add_task(async function() {
await hiddenPromise;
await new Promise(r => setTimeout(r, 0));
is(DOMWindowUtils.IMEStatus, DOMWindowUtils.IME_STATUS_DISABLED,
"IME should not be available when menubar is active");
is(
DOMWindowUtils.IMEStatus,
DOMWindowUtils.IME_STATUS_DISABLED,
"IME should not be available when menubar is active"
);
// Inactivate the menubar (and restore the focus to the searchbar
EventUtils.synthesizeKey("KEY_Escape");
is(DOMWindowUtils.IMEStatus, DOMWindowUtils.IME_STATUS_ENABLED,
"IME should be available after focus is back to the searchbar");
is(
DOMWindowUtils.IMEStatus,
DOMWindowUtils.IME_STATUS_ENABLED,
"IME should be available after focus is back to the searchbar"
);
});

View file

@ -1,19 +1,38 @@
add_task(async function() {
const html = "<p id=\"p1\" title=\"tooltip is here\">This paragraph has a tooltip.</p>";
await BrowserTestUtils.openNewForegroundTab(gBrowser, "data:text/html," + html);
const html =
'<p id="p1" title="tooltip is here">This paragraph has a tooltip.</p>';
await BrowserTestUtils.openNewForegroundTab(
gBrowser,
"data:text/html," + html
);
await new Promise(resolve => {
SpecialPowers.pushPrefEnv({"set": [["ui.tooltipDelay", 0]]}, resolve);
SpecialPowers.pushPrefEnv({ set: [["ui.tooltipDelay", 0]] }, resolve);
});
await BrowserTestUtils.synthesizeMouseAtCenter("#p1", { type: "mousemove" },
gBrowser.selectedBrowser);
await BrowserTestUtils.synthesizeMouseAtCenter("#p1", { }, gBrowser.selectedBrowser);
await BrowserTestUtils.synthesizeMouseAtCenter(
"#p1",
{ type: "mousemove" },
gBrowser.selectedBrowser
);
await BrowserTestUtils.synthesizeMouseAtCenter(
"#p1",
{},
gBrowser.selectedBrowser
);
// Wait until the tooltip timeout triggers that would normally have opened the popup.
await new Promise(resolve => setTimeout(resolve, 0));
is(document.getElementById("aHTMLTooltip").state, "closed", "local tooltip is closed");
is(document.getElementById("remoteBrowserTooltip").state, "closed", "remote tooltip is closed");
is(
document.getElementById("aHTMLTooltip").state,
"closed",
"local tooltip is closed"
);
is(
document.getElementById("remoteBrowserTooltip").state,
"closed",
"remote tooltip is closed"
);
gBrowser.removeCurrentTab();
});

View file

@ -1,32 +1,55 @@
add_task(async function() {
const url = "data:text/html," +
const url =
"data:text/html," +
"<html onmousemove='event.stopPropagation()'" +
" onmouseenter='event.stopPropagation()' onmouseleave='event.stopPropagation()'" +
" onmouseover='event.stopPropagation()' onmouseout='event.stopPropagation()'>" +
"<p id=\"p1\" title=\"tooltip is here\">This paragraph has a tooltip.</p>" +
"<p id=\"p2\">This paragraph doesn't have tooltip.</p></html>";
'<p id="p1" title="tooltip is here">This paragraph has a tooltip.</p>' +
'<p id="p2">This paragraph doesn\'t have tooltip.</p></html>';
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
let browser = gBrowser.selectedBrowser;
await new Promise(resolve => {
SpecialPowers.pushPrefEnv({"set": [["ui.tooltipDelay", 0]]}, resolve);
SpecialPowers.pushPrefEnv({ set: [["ui.tooltipDelay", 0]] }, resolve);
});
let popupShownPromise = BrowserTestUtils.waitForEvent(document, "popupshown", false, event => {
is(event.originalTarget.localName, "tooltip", "tooltip is showing");
return true;
});
let popupHiddenPromise = BrowserTestUtils.waitForEvent(document, "popuphidden", false, event => {
is(event.originalTarget.localName, "tooltip", "tooltip is hidden");
return true;
});
let popupShownPromise = BrowserTestUtils.waitForEvent(
document,
"popupshown",
false,
event => {
is(event.originalTarget.localName, "tooltip", "tooltip is showing");
return true;
}
);
let popupHiddenPromise = BrowserTestUtils.waitForEvent(
document,
"popuphidden",
false,
event => {
is(event.originalTarget.localName, "tooltip", "tooltip is hidden");
return true;
}
);
// Send a mousemove at a known position to start the test.
await BrowserTestUtils.synthesizeMouseAtCenter("#p2", { type: "mousemove" }, browser);
await BrowserTestUtils.synthesizeMouseAtCenter("#p1", { type: "mousemove" }, browser);
await BrowserTestUtils.synthesizeMouseAtCenter(
"#p2",
{ type: "mousemove" },
browser
);
await BrowserTestUtils.synthesizeMouseAtCenter(
"#p1",
{ type: "mousemove" },
browser
);
await popupShownPromise;
await BrowserTestUtils.synthesizeMouseAtCenter("#p2", { type: "mousemove" }, browser);
await BrowserTestUtils.synthesizeMouseAtCenter(
"#p2",
{ type: "mousemove" },
browser
);
await popupHiddenPromise;
gBrowser.removeCurrentTab();

View file

@ -1,27 +1,49 @@
add_task(async function() {
const url = "data:text/html,<html><head></head><body>" +
"<a id=\"target\" href=\"about:blank\" title=\"This is tooltip text\" " +
"style=\"display:block;height:20px;margin:10px;\" " +
"onclick=\"return false;\">here is an anchor element</a></body></html>";
const url =
"data:text/html,<html><head></head><body>" +
'<a id="target" href="about:blank" title="This is tooltip text" ' +
'style="display:block;height:20px;margin:10px;" ' +
'onclick="return false;">here is an anchor element</a></body></html>';
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
let browser = gBrowser.selectedBrowser;
await new Promise(resolve => {
SpecialPowers.pushPrefEnv({"set": [["ui.tooltipDelay", 0]]}, resolve);
SpecialPowers.pushPrefEnv({ set: [["ui.tooltipDelay", 0]] }, resolve);
});
// Send a mousemove at a known position to start the test.
await BrowserTestUtils.synthesizeMouse("#target", -5, -5, { type: "mousemove" }, browser);
await BrowserTestUtils.synthesizeMouse(
"#target",
-5,
-5,
{ type: "mousemove" },
browser
);
// show tooltip by mousemove into target.
let popupShownPromise = BrowserTestUtils.waitForEvent(document, "popupshown");
await BrowserTestUtils.synthesizeMouse("#target", 5, 15, { type: "mousemove" }, browser);
await BrowserTestUtils.synthesizeMouse(
"#target",
5,
15,
{ type: "mousemove" },
browser
);
await popupShownPromise;
// hide tooltip by mousemove to outside.
let popupHiddenPromise = BrowserTestUtils.waitForEvent(document, "popuphidden");
await BrowserTestUtils.synthesizeMouse("#target", -5, 15, { type: "mousemove" }, browser);
let popupHiddenPromise = BrowserTestUtils.waitForEvent(
document,
"popuphidden"
);
await BrowserTestUtils.synthesizeMouse(
"#target",
-5,
15,
{ type: "mousemove" },
browser
);
await popupHiddenPromise;
// mousemove into the target and start drag by emulation via nsIDragService.
@ -32,48 +54,96 @@ add_task(async function() {
// Emulate a buggy mousemove event. widget might dispatch mousemove event
// during drag.
function tooltipNotExpected()
{
function tooltipNotExpected() {
ok(false, "tooltip is shown during drag");
}
addEventListener("popupshown", tooltipNotExpected, true);
let dragService = Cc["@mozilla.org/widget/dragservice;1"].
getService(Ci.nsIDragService);
let dragService = Cc["@mozilla.org/widget/dragservice;1"].getService(
Ci.nsIDragService
);
dragService.startDragSession();
await BrowserTestUtils.synthesizeMouse("#target", 5, 15, { type: "mousemove" }, browser);
await BrowserTestUtils.synthesizeMouse(
"#target",
5,
15,
{ type: "mousemove" },
browser
);
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
await new Promise(resolve => setTimeout(resolve, 100));
removeEventListener("popupshown", tooltipNotExpected, true);
dragService.endDragSession(true);
await BrowserTestUtils.synthesizeMouse("#target", -5, -5, { type: "mousemove" }, browser);
await BrowserTestUtils.synthesizeMouse(
"#target",
-5,
-5,
{ type: "mousemove" },
browser
);
// If tooltip listener used a flag for managing D&D state, we would need
// to test if the tooltip is shown after drag.
// show tooltip by mousemove into target.
popupShownPromise = BrowserTestUtils.waitForEvent(document, "popupshown");
await BrowserTestUtils.synthesizeMouse("#target", 5, 15, { type: "mousemove" }, browser);
await BrowserTestUtils.synthesizeMouse(
"#target",
5,
15,
{ type: "mousemove" },
browser
);
await popupShownPromise;
// hide tooltip by mousemove to outside.
popupHiddenPromise = BrowserTestUtils.waitForEvent(document, "popuphidden");
await BrowserTestUtils.synthesizeMouse("#target", -5, 15, { type: "mousemove" }, browser);
await BrowserTestUtils.synthesizeMouse(
"#target",
-5,
15,
{ type: "mousemove" },
browser
);
await popupHiddenPromise;
// Show tooltip after mousedown
popupShownPromise = BrowserTestUtils.waitForEvent(document, "popupshown");
await BrowserTestUtils.synthesizeMouse("#target", 5, 15, { type: "mousemove" }, browser);
await BrowserTestUtils.synthesizeMouse(
"#target",
5,
15,
{ type: "mousemove" },
browser
);
await popupShownPromise;
popupHiddenPromise = BrowserTestUtils.waitForEvent(document, "popuphidden");
await BrowserTestUtils.synthesizeMouse("#target", 5, 15, { type: "mousedown" }, browser);
await BrowserTestUtils.synthesizeMouse(
"#target",
5,
15,
{ type: "mousedown" },
browser
);
await popupHiddenPromise;
await BrowserTestUtils.synthesizeMouse("#target", 5, 15, { type: "mouseup" }, browser);
await BrowserTestUtils.synthesizeMouse("#target", -5, 15, { type: "mousemove" }, browser);
await BrowserTestUtils.synthesizeMouse(
"#target",
5,
15,
{ type: "mouseup" },
browser
);
await BrowserTestUtils.synthesizeMouse(
"#target",
-5,
15,
{ type: "mousemove" },
browser
);
ok(true, "tooltips appear properly");