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": [{ "overrides": [{
"files": [ "files": [
"devtools/**", "devtools/**",
"layout/**",
"media/**", "media/**",
"memory/**", "memory/**",
"mfbt/**", "mfbt/**",

View file

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

View file

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

View file

@ -1,15 +1,22 @@
function pageScript() { function pageScript() {
window.addEventListener("beforeunload", function (event) { window.addEventListener(
var str = "Some text that causes the beforeunload dialog to be shown"; "beforeunload",
event.returnValue = str; function(event) {
return str; var str = "Some text that causes the beforeunload dialog to be shown";
}, true); 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 = const PAGE_URL =
"data:text/html," + encodeURIComponent("<script>(" + pageScript.toSource() + ")();</script>"); "data:text/html," +
encodeURIComponent("<script>(" + pageScript.toSource() + ")();</script>");
add_task(async function enableDialogs() { add_task(async function enableDialogs() {
// The onbeforeunload dialog should appear. // The onbeforeunload dialog should appear.
@ -34,22 +41,27 @@ add_task(async function disableDialogs() {
async function openPage(enableDialogs) { async function openPage(enableDialogs) {
// Open about:blank in a new tab. // Open about:blank in a new tab.
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, async function(browser) { await BrowserTestUtils.withNewTab(
// Load the content script in the frame. { gBrowser, url: "about:blank" },
let methodName = enableDialogs ? "enableDialogs" : "disableDialogs"; async function(browser) {
await ContentTask.spawn(browser, methodName, async function(name) { // Load the content script in the frame.
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); let methodName = enableDialogs ? "enableDialogs" : "disableDialogs";
Services.obs.addObserver(doc => { await ContentTask.spawn(browser, methodName, async function(name) {
if (content && doc == content.document) { const { Services } = ChromeUtils.import(
content.windowUtils[name](); "resource://gre/modules/Services.jsm"
} );
}, "document-element-inserted"); Services.obs.addObserver(doc => {
}); if (content && doc == content.document) {
// Load the page. content.windowUtils[name]();
await BrowserTestUtils.loadURI(browser, PAGE_URL); }
await BrowserTestUtils.browserLoaded(browser); }, "document-element-inserted");
// And then navigate away. });
await BrowserTestUtils.loadURI(browser, "http://example.com/"); // Load the page.
await BrowserTestUtils.browserLoaded(browser); 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() { function pageScript() {
window.addEventListener("beforeunload", function (event) { window.addEventListener(
var str = "Some text that causes the beforeunload dialog to be shown"; "beforeunload",
event.returnValue = str; function(event) {
return str; var str = "Some text that causes the beforeunload dialog to be shown";
}, true); 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 = const PAGE_URL =
"data:text/html," + encodeURIComponent("<script>(" + pageScript.toSource() + ")();</script>"); "data:text/html," +
encodeURIComponent("<script>(" + pageScript.toSource() + ")();</script>");
add_task(async function doClick() { add_task(async function doClick() {
// The onbeforeunload dialog should appear. // The onbeforeunload dialog should appear.
@ -34,20 +41,27 @@ add_task(async function noClick() {
async function openPage(shouldClick) { async function openPage(shouldClick) {
// Open about:blank in a new tab. // Open about:blank in a new tab.
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, async function(browser) { await BrowserTestUtils.withNewTab(
// Load the page. { gBrowser, url: "about:blank" },
await BrowserTestUtils.loadURI(browser, PAGE_URL); async function(browser) {
await BrowserTestUtils.browserLoaded(browser); // Load the page.
await BrowserTestUtils.loadURI(browser, PAGE_URL);
await BrowserTestUtils.browserLoaded(browser);
if (shouldClick) { if (shouldClick) {
await BrowserTestUtils.synthesizeMouse("body", 2, 2, {}, browser); 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() { function pageScript() {
window.addEventListener("beforeunload", function (event) { window.addEventListener(
var str = "Some text that causes the beforeunload dialog to be shown"; "beforeunload",
event.returnValue = str; function(event) {
return str; var str = "Some text that causes the beforeunload dialog to be shown";
}, true); event.returnValue = str;
return str;
},
true
);
} }
SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", true], SpecialPowers.pushPrefEnv({
["security.allow_eval_with_system_principal", true]]}); set: [
["dom.require_user_interaction_for_beforeunload", true],
["security.allow_eval_with_system_principal", true],
],
});
const FRAME_URL = const FRAME_URL =
"data:text/html," + encodeURIComponent("<body>Just a frame</body>"); "data:text/html," + encodeURIComponent("<body>Just a frame</body>");
const PAGE_URL = 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() { add_task(async function doClick() {
// The onbeforeunload dialog should appear. // The onbeforeunload dialog should appear.
@ -38,23 +53,43 @@ add_task(async function noClick() {
async function openPage(shouldClick) { async function openPage(shouldClick) {
// Open about:blank in a new tab. // Open about:blank in a new tab.
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, async function(browser) { await BrowserTestUtils.withNewTab(
// Load the page. { gBrowser, url: "about:blank" },
await BrowserTestUtils.loadURI(browser, PAGE_URL); async function(browser) {
await BrowserTestUtils.browserLoaded(browser); // Load the page.
await BrowserTestUtils.loadURI(browser, PAGE_URL);
await BrowserTestUtils.browserLoaded(browser);
if (shouldClick) { if (shouldClick) {
await BrowserTestUtils.synthesizeMouse(function() { await BrowserTestUtils.synthesizeMouse(
return content.frames[0].document.body; function() {
}, 2, 2, {}, browser); 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 -*- // -*- Mode: Javascript; tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*-
// vim: set ts=2 sw=2 et tw=78: // vim: set ts=2 sw=2 et tw=78:
function clearSelection(w) function clearSelection(w) {
{
var sel = (w ? w : window).getSelection(); var sel = (w ? w : window).getSelection();
sel.removeAllRanges(); sel.removeAllRanges();
} }
function getNode(e, index) { function getNode(e, index) {
if (!(typeof index==='number')) return index; if (!(typeof index === "number")) {
if (index >= 0) return e.childNodes[index]; return index;
while (++index != 0) e = e.parentNode; }
if (index >= 0) {
return e.childNodes[index];
}
while (++index != 0) {
e = e.parentNode;
}
return e; return e;
} }
function dragSelectPointsWithData() function dragSelectPointsWithData() {
{
var event = arguments[0]; var event = arguments[0];
var e = arguments[1]; var e = arguments[1];
var x1 = arguments[2]; var x1 = arguments[2];
@ -22,111 +26,111 @@ function dragSelectPointsWithData()
var x2 = arguments[4]; var x2 = arguments[4];
var y2 = arguments[5]; var y2 = arguments[5];
dir = x2 > x1 ? 1 : -1; dir = x2 > x1 ? 1 : -1;
event['type'] = "mousedown"; event["type"] = "mousedown";
synthesizeMouse(e, x1, y1, event); synthesizeMouse(e, x1, y1, event);
event['type'] = "mousemove"; event["type"] = "mousemove";
synthesizeMouse(e, x1 + dir, y1, event); 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, arguments[i], y1, event);
}
synthesizeMouse(e, x2 - dir, y2, event); synthesizeMouse(e, x2 - dir, y2, event);
event['type'] = "mouseup"; event["type"] = "mouseup";
synthesizeMouse(e, x2, y2, event); synthesizeMouse(e, x2, y2, event);
} }
function dragSelectPoints() function dragSelectPoints() {
{
var args = Array.prototype.slice.call(arguments); var args = Array.prototype.slice.call(arguments);
dragSelectPointsWithData.apply(this, [{}].concat(args)); dragSelectPointsWithData.apply(this, [{}].concat(args));
} }
function dragSelect() function dragSelect() {
{
var args = Array.prototype.slice.call(arguments); var args = Array.prototype.slice.call(arguments);
var e = args.shift(); var e = args.shift();
var x1 = args.shift(); var x1 = args.shift();
var x2 = 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 args = Array.prototype.slice.call(arguments);
var e = args.shift(); var e = args.shift();
var x1 = args.shift(); var x1 = args.shift();
var x2 = args.shift(); var x2 = args.shift();
var y = args.length != 0 ? args.shift() : 5; 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 shiftClick(e, x, y) {
{ function pos(p) {
function pos(p) { return (typeof p === "undefined") ? 5 : p } return typeof p === "undefined" ? 5 : p;
}
synthesizeMouse(e, pos(x), pos(y), { shiftKey: true }); synthesizeMouse(e, pos(x), pos(y), { shiftKey: true });
} }
function keyRepeat(key,data,repeat) function keyRepeat(key, data, repeat) {
{ while (repeat-- > 0) {
while (repeat-- > 0)
synthesizeKey(key, data); synthesizeKey(key, data);
}
} }
function keyRight(data) function keyRight(data) {
{
var repeat = arguments.length > 1 ? arguments[1] : 1; var repeat = arguments.length > 1 ? arguments[1] : 1;
keyRepeat("VK_RIGHT", data, repeat); keyRepeat("VK_RIGHT", data, repeat);
} }
function keyLeft(data) function keyLeft(data) {
{
var repeat = arguments.length > 1 ? arguments[1] : 1; var repeat = arguments.length > 1 ? arguments[1] : 1;
keyRepeat("VK_LEFT", data, repeat); keyRepeat("VK_LEFT", data, repeat);
} }
function shiftAccelClick(e, x, y) function shiftAccelClick(e, x, y) {
{ function pos(p) {
function pos(p) { return (typeof p === "undefined") ? 5 : p } return typeof p === "undefined" ? 5 : p;
}
synthesizeMouse(e, pos(x), pos(y), { shiftKey: true, accelKey: true }); synthesizeMouse(e, pos(x), pos(y), { shiftKey: true, accelKey: true });
} }
function accelClick(e, x, y) function accelClick(e, x, y) {
{ function pos(p) {
function pos(p) { return (typeof p === "undefined") ? 5 : p } return typeof p === "undefined" ? 5 : p;
}
synthesizeMouse(e, pos(x), pos(y), { accelKey: true }); synthesizeMouse(e, pos(x), pos(y), { accelKey: true });
} }
function addChildRanges(arr, e) function addChildRanges(arr, e) {
{
var sel = window.getSelection(); var sel = window.getSelection();
for (i = 0; i < arr.length; ++i) { for (i = 0; i < arr.length; ++i) {
var data = arr[i]; var data = arr[i];
var r = new Range() var r = new Range();
r.setStart(getNode(e, data[0]), data[1]); r.setStart(getNode(e, data[0]), data[1]);
r.setEnd(getNode(e, data[2]), data[3]); r.setEnd(getNode(e, data[2]), data[3]);
sel.addRange(r); sel.addRange(r);
} }
} }
function checkText(text, e) function checkText(text, e) {
{
var sel = window.getSelection(); 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); 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(); var sel = window.getSelection();
is(sel.rangeCount, n, e.id + ": Selection range count"); is(sel.rangeCount, n, e.id + ": Selection range count");
} }
function checkRangePoints(i, expected, e) { function checkRangePoints(i, expected, e) {
var sel = window.getSelection(); var sel = window.getSelection();
if (i >= sel.rangeCount) return; if (i >= sel.rangeCount) {
return;
}
var r = sel.getRangeAt(i); var r = sel.getRangeAt(i);
is(r.startContainer, expected[0], e.id + ": range.startContainer"); is(r.startContainer, expected[0], e.id + ": range.startContainer");
is(r.startOffset, expected[1], e.id + ": range.startOffset"); is(r.startOffset, expected[1], e.id + ": range.startOffset");
@ -136,16 +140,25 @@ function checkRangePoints(i, expected, e) {
function checkRange(i, expected, e) { function checkRange(i, expected, e) {
var sel = window.getSelection(); var sel = window.getSelection();
if (i >= sel.rangeCount) return; if (i >= sel.rangeCount) {
return;
}
var r = sel.getRangeAt(i); var r = sel.getRangeAt(i);
is(r.startContainer, getNode(e, expected[0]), e.id + ": range["+i+"].startContainer"); is(
is(r.startOffset, expected[1], e.id + ": range["+i+"].startOffset"); r.startContainer,
is(r.endContainer, getNode(e, expected[2]), e.id + ": range["+i+"].endContainer"); getNode(e, expected[0]),
is(r.endOffset, expected[3], e.id + ": range["+i+"].endOffset"); 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); checkRangeCount(arr.length, e);
for (i = 0; i < arr.length; ++i) { for (i = 0; i < arr.length; ++i) {
var expected = arr[i]; var expected = arr[i];

View file

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

View file

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

View file

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

View file

@ -11,67 +11,132 @@
// should be rejected. // should be rejected.
var gCSSFontFaceDescriptors = { var gCSSFontFaceDescriptors = {
"font-family": { "font-family": {
domProp: "fontFamily", domProp: "fontFamily",
values: [ "\"serif\"", "\"cursive\"", "seriff", "Times New Roman", "TimesRoman", "\"Times New Roman\"" ], values: [
/* not clear that the generics are really invalid */ '"serif"',
invalid_values: [ "sans-serif", "Times New Roman, serif", "'Times New Roman', serif", "cursive", "fantasy", "Times )", "Times !", "Times ! foo", "Times ! important" ] '"cursive"',
}, "seriff",
"font-stretch": { "Times New Roman",
domProp: "fontStretch", "TimesRoman",
values: [ "normal", "ultra-condensed", "extra-condensed", "condensed", "semi-condensed", "semi-expanded", "expanded", "extra-expanded", "ultra-expanded" ], '"Times New Roman"',
invalid_values: [ "wider", "narrower", "normal ! important", "normal )" ] ],
}, /* not clear that the generics are really invalid */
"font-style": { invalid_values: [
domProp: "fontStyle", "sans-serif",
values: [ "normal", "italic", "oblique" ], "Times New Roman, serif",
invalid_values: [] "'Times New Roman', serif",
}, "cursive",
"font-weight": { "fantasy",
domProp: "fontWeight", "Times )",
values: [ "Times !",
"normal", "400", "bold", "100", "200", "300", "500", "600", "Times ! foo",
"700", "800", "900", "107", "399", "401", "699", "710", "Times ! important",
"calc(1001)", "calc(100 + 1)", "calc(1)", "100.6", "99", ],
"700 900", "300.4 500.4", "calc(200.4) calc(400.4)", },
], "font-stretch": {
invalid_values: [ "bolder", "lighter", "1001", "0", "0 100", "100 1001" ] domProp: "fontStretch",
}, values: [
"src": { "normal",
domProp: null, "ultra-condensed",
values: [ "extra-condensed",
"url(404.ttf)", "condensed",
"url(\"404.eot\")", "semi-condensed",
"url(\'404.otf\')", "semi-expanded",
"url(404.ttf) format(\"truetype\")", "expanded",
"url(404.ttf) format(\"truetype\", \"opentype\")", "extra-expanded",
"url(404.ttf) format(\"truetype\", \"opentype\"), url(\'404.eot\')", "ultra-expanded",
"local(Times New Roman)", ],
"local(\'Times New Roman\')", invalid_values: ["wider", "narrower", "normal ! important", "normal )"],
"local(\"Times New Roman\")", },
"local(\"serif\")", "font-style": {
"url(404.ttf) format(\"truetype\", \"unknown\"), local(Times New Roman), url(\'404.eot\')", domProp: "fontStyle",
], values: ["normal", "italic", "oblique"],
invalid_values: [ invalid_values: [],
"url(404.ttf) format(truetype)", },
"url(404.ttf) format(\"truetype\" \"opentype\")", "font-weight": {
"url(404.ttf) format(\"truetype\",)", domProp: "fontWeight",
"local(\"Times New\" Roman)", values: [
"local(serif)", /* is this valid? */ "normal",
"url(404.ttf) )", "400",
"url(404.ttf) ) foo", "bold",
"url(404.ttf) ! important", "100",
"url(404.ttf) ! hello", "200",
] "300",
}, "500",
"unicode-range": { "600",
domProp: null, "700",
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" ], "800",
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)" ] "900",
}, "107",
"font-display": { "399",
domProp: null, "401",
values: [ "auto", "block", "swap", "fallback", "optional" ], "699",
invalid_values: [ "normal", "initial" ] "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(); SimpleTest.waitForExplicitFinish();
window.addEventListener("load", runTests); window.addEventListener("load", runTests);
function runTests(event) function runTests(event) {
{ if (event.target != document) {
if (event.target != document) { return;
return; }
}
var elt = document.getElementById("content"); var elt = document.getElementById("content");
elt.setAttribute("style", "color: blue; background-color: fuchsia"); elt.setAttribute("style", "color: blue; background-color: fuchsia");
is(elt.style.color, "blue", is(elt.style.color, "blue", "setting correct style attribute (color)");
"setting correct style attribute (color)"); is(
is(elt.style.backgroundColor, "fuchsia", elt.style.backgroundColor,
"setting correct style attribute (color)"); "fuchsia",
"setting correct style attribute (color)"
);
elt.setAttribute("style", "{color: blue; background-color: fuchsia}"); elt.setAttribute("style", "{color: blue; background-color: fuchsia}");
is(elt.style.color, "", is(elt.style.color, "", "setting braced style attribute (color)");
"setting braced style attribute (color)"); is(elt.style.backgroundColor, "", "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 = { const windowListener = {
onOpenWindow(win) { onOpenWindow(win) {
info("Observed window open") info("Observed window open");
const domWindow = win.docShell.domWindow; const domWindow = win.docShell.domWindow;
waitForFocus(() => { waitForFocus(() => {
is(domWindow.location, is(
"chrome://layoutdebug/content/layoutdebug.xul", domWindow.location,
"Window location is correct"); "chrome://layoutdebug/content/layoutdebug.xul",
"Window location is correct"
);
domWindow.close(); domWindow.close();
}, domWindow); }, domWindow);
}, },
@ -26,7 +28,7 @@ function test() {
info("Observed window closed"); info("Observed window closed");
Services.wm.removeListener(this); Services.wm.removeListener(this);
finish(); finish();
} },
}; };
Services.wm.addListener(windowListener); Services.wm.addListener(windowListener);

View file

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

View file

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

View file

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

View file

@ -11,36 +11,42 @@ var gContainingWindow = null;
var gBrowser; var gBrowser;
function OnDocumentLoad(evt) { function OnDocumentLoad(evt) {
if (evt.target != gBrowser.contentDocument || evt.target.location == "about:blank") if (
return; evt.target != gBrowser.contentDocument ||
gBrowser.removeEventListener("load", OnDocumentLoad, true); evt.target.location == "about:blank"
gContainingWindow.close(); ) {
return;
}
gBrowser.removeEventListener("load", OnDocumentLoad, true);
gContainingWindow.close();
} }
this.OnRecordingLoad = function OnRecordingLoad(win) { this.OnRecordingLoad = function OnRecordingLoad(win) {
if (win === undefined || win == null) { if (win === undefined || win == null) {
win = window; win = window;
} }
if (gContainingWindow == null && win != null) { if (gContainingWindow == null && win != null) {
gContainingWindow = win; 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 gfxInfo =
var info = gfxInfo.getInfo(); NS_GFXINFO_CONTRACTID in Cc &&
dump(info.AzureContentBackend + "\n"); Cc[NS_GFXINFO_CONTRACTID].getService(Ci.nsIGfxInfo);
if (info.AzureContentBackend == "none") { var info = gfxInfo.getInfo();
alert("Page recordings may only be made with Azure content enabled."); dump(info.AzureContentBackend + "\n");
gContainingWindow.close(); if (info.AzureContentBackend == "none") {
return; 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, { gBrowser.loadURI(args.uri, {
triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({}), 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); let gCUITestUtils = new CustomizableUITestUtils(window);
add_task(async function test_setup() { add_task(async function test_setup() {
@ -12,8 +15,11 @@ add_task(async function() {
BrowserSearch.searchBar.focus(); BrowserSearch.searchBar.focus();
let DOMWindowUtils = EventUtils._getDOMWindowUtils(); let DOMWindowUtils = EventUtils._getDOMWindowUtils();
is(DOMWindowUtils.IMEStatus, DOMWindowUtils.IME_STATUS_ENABLED, is(
"IME should be available when searchbar has focus"); DOMWindowUtils.IMEStatus,
DOMWindowUtils.IME_STATUS_ENABLED,
"IME should be available when searchbar has focus"
);
let searchPopup = document.getElementById("PopupSearchAutoComplete"); let searchPopup = document.getElementById("PopupSearchAutoComplete");
@ -23,8 +29,11 @@ add_task(async function() {
await shownPromise; await shownPromise;
await new Promise(r => setTimeout(r, 0)); await new Promise(r => setTimeout(r, 0));
is(DOMWindowUtils.IMEStatus, DOMWindowUtils.IME_STATUS_ENABLED, is(
"IME should be available even when the popup of searchbar is open"); 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 // Activate the menubar, then, the popup should be closed
let hiddenPromise = BrowserTestUtils.waitForEvent(searchPopup, "popuphidden"); let hiddenPromise = BrowserTestUtils.waitForEvent(searchPopup, "popuphidden");
@ -32,10 +41,16 @@ add_task(async function() {
await hiddenPromise; await hiddenPromise;
await new Promise(r => setTimeout(r, 0)); await new Promise(r => setTimeout(r, 0));
is(DOMWindowUtils.IMEStatus, DOMWindowUtils.IME_STATUS_DISABLED, is(
"IME should not be available when menubar is active"); 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 // Inactivate the menubar (and restore the focus to the searchbar
EventUtils.synthesizeKey("KEY_Escape"); EventUtils.synthesizeKey("KEY_Escape");
is(DOMWindowUtils.IMEStatus, DOMWindowUtils.IME_STATUS_ENABLED, is(
"IME should be available after focus is back to the searchbar"); 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() { add_task(async function() {
const html = "<p id=\"p1\" title=\"tooltip is here\">This paragraph has a tooltip.</p>"; const html =
await BrowserTestUtils.openNewForegroundTab(gBrowser, "data:text/html," + 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 => { await new Promise(resolve => {
SpecialPowers.pushPrefEnv({"set": [["ui.tooltipDelay", 0]]}, resolve); SpecialPowers.pushPrefEnv({ set: [["ui.tooltipDelay", 0]] }, resolve);
}); });
await BrowserTestUtils.synthesizeMouseAtCenter("#p1", { type: "mousemove" }, await BrowserTestUtils.synthesizeMouseAtCenter(
gBrowser.selectedBrowser); "#p1",
await BrowserTestUtils.synthesizeMouseAtCenter("#p1", { }, gBrowser.selectedBrowser); { type: "mousemove" },
gBrowser.selectedBrowser
);
await BrowserTestUtils.synthesizeMouseAtCenter(
"#p1",
{},
gBrowser.selectedBrowser
);
// Wait until the tooltip timeout triggers that would normally have opened the popup. // Wait until the tooltip timeout triggers that would normally have opened the popup.
await new Promise(resolve => setTimeout(resolve, 0)); await new Promise(resolve => setTimeout(resolve, 0));
is(document.getElementById("aHTMLTooltip").state, "closed", "local tooltip is closed"); is(
is(document.getElementById("remoteBrowserTooltip").state, "closed", "remote tooltip is closed"); document.getElementById("aHTMLTooltip").state,
"closed",
"local tooltip is closed"
);
is(
document.getElementById("remoteBrowserTooltip").state,
"closed",
"remote tooltip is closed"
);
gBrowser.removeCurrentTab(); gBrowser.removeCurrentTab();
}); });

View file

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

View file

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