forked from mirrors/gecko-dev
Bug 1561435 - Format gfx/, a=automatic-formatting
# ignore-this-changeset Differential Revision: https://phabricator.services.mozilla.com/D35903 --HG-- extra : source : 00faaa954cecb534fa97f4e87de61635c8c526bc
This commit is contained in:
parent
5af464dcc4
commit
85064fe4c3
10 changed files with 844 additions and 286 deletions
|
|
@ -45,7 +45,6 @@ module.exports = {
|
||||||
"overrides": [{
|
"overrides": [{
|
||||||
"files": [
|
"files": [
|
||||||
"devtools/**",
|
"devtools/**",
|
||||||
"gfx/**",
|
|
||||||
"gradle/**",
|
"gradle/**",
|
||||||
"hal/**",
|
"hal/**",
|
||||||
"image/**",
|
"image/**",
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
gfx/**
|
|
||||||
gradle/**
|
gradle/**
|
||||||
hal/**
|
hal/**
|
||||||
image/**
|
image/**
|
||||||
|
|
|
||||||
|
|
@ -27,27 +27,36 @@ class FissionTestHelperChild extends JSWindowActorChild {
|
||||||
// namespace.
|
// namespace.
|
||||||
|
|
||||||
let cw = this.cw();
|
let cw = this.cw();
|
||||||
Cu.exportFunction((cond, msg) => this.sendAsyncMessage("ok", {cond, msg}),
|
|
||||||
cw, { defineAs: "ok" });
|
|
||||||
Cu.exportFunction((a, b, msg) => this.sendAsyncMessage("is", {a, b, msg}),
|
|
||||||
cw, { defineAs: "is" });
|
|
||||||
|
|
||||||
let FissionTestHelper = Cu.createObjectIn(cw, { defineAs: "FissionTestHelper" });
|
|
||||||
FissionTestHelper.startTestPromise =
|
|
||||||
new cw.Promise(
|
|
||||||
Cu.exportFunction(
|
Cu.exportFunction(
|
||||||
(resolve) => {
|
(cond, msg) => this.sendAsyncMessage("ok", { cond, msg }),
|
||||||
|
cw,
|
||||||
|
{ defineAs: "ok" }
|
||||||
|
);
|
||||||
|
Cu.exportFunction(
|
||||||
|
(a, b, msg) => this.sendAsyncMessage("is", { a, b, msg }),
|
||||||
|
cw,
|
||||||
|
{ defineAs: "is" }
|
||||||
|
);
|
||||||
|
|
||||||
|
let FissionTestHelper = Cu.createObjectIn(cw, {
|
||||||
|
defineAs: "FissionTestHelper",
|
||||||
|
});
|
||||||
|
FissionTestHelper.startTestPromise = new cw.Promise(
|
||||||
|
Cu.exportFunction(resolve => {
|
||||||
this._startTestPromiseResolver = resolve;
|
this._startTestPromiseResolver = resolve;
|
||||||
},
|
}, cw)
|
||||||
cw));
|
);
|
||||||
|
|
||||||
Cu.exportFunction(this.subtestDone.bind(this),
|
Cu.exportFunction(this.subtestDone.bind(this), FissionTestHelper, {
|
||||||
FissionTestHelper, { defineAs: "subtestDone" });
|
defineAs: "subtestDone",
|
||||||
|
});
|
||||||
|
|
||||||
Cu.exportFunction(this.sendToOopif.bind(this),
|
Cu.exportFunction(this.sendToOopif.bind(this), FissionTestHelper, {
|
||||||
FissionTestHelper, { defineAs: "sendToOopif" });
|
defineAs: "sendToOopif",
|
||||||
Cu.exportFunction(this.fireEventInEmbedder.bind(this),
|
});
|
||||||
FissionTestHelper, { defineAs: "fireEventInEmbedder" });
|
Cu.exportFunction(this.fireEventInEmbedder.bind(this), FissionTestHelper, {
|
||||||
|
defineAs: "fireEventInEmbedder",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by the subtest to indicate completion to the top-level browser-chrome
|
// Called by the subtest to indicate completion to the top-level browser-chrome
|
||||||
|
|
@ -67,12 +76,15 @@ class FissionTestHelperChild extends JSWindowActorChild {
|
||||||
let msgId = ++this._msgCounter;
|
let msgId = ++this._msgCounter;
|
||||||
let cw = this.cw();
|
let cw = this.cw();
|
||||||
let responsePromise = new cw.Promise(
|
let responsePromise = new cw.Promise(
|
||||||
Cu.exportFunction(
|
Cu.exportFunction(resolve => {
|
||||||
(resolve) => {
|
|
||||||
this._oopifResponsePromiseResolvers[msgId] = resolve;
|
this._oopifResponsePromiseResolvers[msgId] = resolve;
|
||||||
},
|
}, cw)
|
||||||
cw));
|
);
|
||||||
this.sendAsyncMessage("EmbedderToOopif", {browsingContextId, msgId, stringToEval});
|
this.sendAsyncMessage("EmbedderToOopif", {
|
||||||
|
browsingContextId,
|
||||||
|
msgId,
|
||||||
|
stringToEval,
|
||||||
|
});
|
||||||
return responsePromise;
|
return responsePromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -91,7 +103,9 @@ class FissionTestHelperChild extends JSWindowActorChild {
|
||||||
// is fired by the content. See comments in fission_subtest_init().
|
// is fired by the content. See comments in fission_subtest_init().
|
||||||
// Once bug 1557486 is fixed we can just register the FissionTestHelper:Init
|
// Once bug 1557486 is fixed we can just register the FissionTestHelper:Init
|
||||||
// event directly instead of DOMWindowCreated.
|
// event directly instead of DOMWindowCreated.
|
||||||
this.contentWindow.addEventListener("FissionTestHelper:Init", this, { wantUntrusted: true });
|
this.contentWindow.addEventListener("FissionTestHelper:Init", this, {
|
||||||
|
wantUntrusted: true,
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case "FissionTestHelper:Init":
|
case "FissionTestHelper:Init":
|
||||||
this.initialize();
|
this.initialize();
|
||||||
|
|
@ -107,14 +121,23 @@ class FissionTestHelperChild extends JSWindowActorChild {
|
||||||
break;
|
break;
|
||||||
case "FromEmbedder":
|
case "FromEmbedder":
|
||||||
let evalResult = this.contentWindow.eval(msg.data.stringToEval);
|
let evalResult = this.contentWindow.eval(msg.data.stringToEval);
|
||||||
this.sendAsyncMessage("OopifToEmbedder", {msgId: msg.data.msgId, evalResult});
|
this.sendAsyncMessage("OopifToEmbedder", {
|
||||||
|
msgId: msg.data.msgId,
|
||||||
|
evalResult,
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case "FromOopif":
|
case "FromOopif":
|
||||||
if (typeof msg.data.msgId == "number") {
|
if (typeof msg.data.msgId == "number") {
|
||||||
if (!(msg.data.msgId in this._oopifResponsePromiseResolvers)) {
|
if (!(msg.data.msgId in this._oopifResponsePromiseResolvers)) {
|
||||||
dump("Error: FromOopif got a message with unknown numeric msgId in " + this.contentWindow.location.href + "\n");
|
dump(
|
||||||
|
"Error: FromOopif got a message with unknown numeric msgId in " +
|
||||||
|
this.contentWindow.location.href +
|
||||||
|
"\n"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
this._oopifResponsePromiseResolvers[msg.data.msgId](msg.data.evalResult);
|
this._oopifResponsePromiseResolvers[msg.data.msgId](
|
||||||
|
msg.data.evalResult
|
||||||
|
);
|
||||||
delete this._oopifResponsePromiseResolvers[msg.data.msgId];
|
delete this._oopifResponsePromiseResolvers[msg.data.msgId];
|
||||||
} else if (typeof msg.data.eventType == "string") {
|
} else if (typeof msg.data.eventType == "string") {
|
||||||
let cw = this.cw();
|
let cw = this.cw();
|
||||||
|
|
@ -122,7 +145,11 @@ class FissionTestHelperChild extends JSWindowActorChild {
|
||||||
event.data = Cu.cloneInto(msg.data.data, cw);
|
event.data = Cu.cloneInto(msg.data.data, cw);
|
||||||
this.contentWindow.dispatchEvent(event);
|
this.contentWindow.dispatchEvent(event);
|
||||||
} else {
|
} else {
|
||||||
dump("Warning: Unrecognized FromOopif message received in " + this.contentWindow.location.href + "\n");
|
dump(
|
||||||
|
"Warning: Unrecognized FromOopif message received in " +
|
||||||
|
this.contentWindow.location.href +
|
||||||
|
"\n"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ var EXPORTED_SYMBOLS = ["FissionTestHelperParent"];
|
||||||
class FissionTestHelperParent extends JSWindowActorParent {
|
class FissionTestHelperParent extends JSWindowActorParent {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this._testCompletePromise = new Promise((resolve) => {
|
this._testCompletePromise = new Promise(resolve => {
|
||||||
this._testCompletePromiseResolver = resolve;
|
this._testCompletePromiseResolver = resolve;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -42,11 +42,18 @@ class FissionTestHelperParent extends JSWindowActorParent {
|
||||||
receiveMessage(msg) {
|
receiveMessage(msg) {
|
||||||
switch (msg.name) {
|
switch (msg.name) {
|
||||||
case "ok":
|
case "ok":
|
||||||
FissionTestHelperParent.SimpleTest.ok(msg.data.cond, this.docURI() + " | " + msg.data.msg);
|
FissionTestHelperParent.SimpleTest.ok(
|
||||||
|
msg.data.cond,
|
||||||
|
this.docURI() + " | " + msg.data.msg
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "is":
|
case "is":
|
||||||
FissionTestHelperParent.SimpleTest.is(msg.data.a, msg.data.b, this.docURI() + " | " + msg.data.msg);
|
FissionTestHelperParent.SimpleTest.is(
|
||||||
|
msg.data.a,
|
||||||
|
msg.data.b,
|
||||||
|
this.docURI() + " | " + msg.data.msg
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "Test:Complete":
|
case "Test:Complete":
|
||||||
|
|
@ -56,14 +63,24 @@ class FissionTestHelperParent extends JSWindowActorParent {
|
||||||
case "EmbedderToOopif":
|
case "EmbedderToOopif":
|
||||||
// This relays messages from the embedder to an OOP-iframe. The browsing
|
// This relays messages from the embedder to an OOP-iframe. The browsing
|
||||||
// context id in the message data identifies the OOP-iframe.
|
// context id in the message data identifies the OOP-iframe.
|
||||||
let oopifBrowsingContext = BrowsingContext.get(msg.data.browsingContextId);
|
let oopifBrowsingContext = BrowsingContext.get(
|
||||||
|
msg.data.browsingContextId
|
||||||
|
);
|
||||||
if (oopifBrowsingContext == null) {
|
if (oopifBrowsingContext == null) {
|
||||||
FissionTestHelperParent.SimpleTest.ok(false, "EmbedderToOopif couldn't find oopif");
|
FissionTestHelperParent.SimpleTest.ok(
|
||||||
|
false,
|
||||||
|
"EmbedderToOopif couldn't find oopif"
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let oopifActor = oopifBrowsingContext.currentWindowGlobal.getActor("FissionTestHelper");
|
let oopifActor = oopifBrowsingContext.currentWindowGlobal.getActor(
|
||||||
|
"FissionTestHelper"
|
||||||
|
);
|
||||||
if (!oopifActor) {
|
if (!oopifActor) {
|
||||||
FissionTestHelperParent.SimpleTest.ok(false, "EmbedderToOopif couldn't find oopif actor");
|
FissionTestHelperParent.SimpleTest.ok(
|
||||||
|
false,
|
||||||
|
"EmbedderToOopif couldn't find oopif actor"
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
oopifActor.sendAsyncMessage("FromEmbedder", msg.data);
|
oopifActor.sendAsyncMessage("FromEmbedder", msg.data);
|
||||||
|
|
@ -74,7 +91,10 @@ class FissionTestHelperParent extends JSWindowActorParent {
|
||||||
// window which is embedding it.
|
// window which is embedding it.
|
||||||
let embedderActor = this.embedderWindow().getActor("FissionTestHelper");
|
let embedderActor = this.embedderWindow().getActor("FissionTestHelper");
|
||||||
if (!embedderActor) {
|
if (!embedderActor) {
|
||||||
FissionTestHelperParent.SimpleTest.ok(false, "OopifToEmbedder couldn't find embedder");
|
FissionTestHelperParent.SimpleTest.ok(
|
||||||
|
false,
|
||||||
|
"OopifToEmbedder couldn't find embedder"
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
embedderActor.sendAsyncMessage("FromOopif", msg.data);
|
embedderActor.sendAsyncMessage("FromOopif", msg.data);
|
||||||
|
|
|
||||||
|
|
@ -28,20 +28,30 @@ function getPlatform() {
|
||||||
|
|
||||||
function nativeVerticalWheelEventMsg() {
|
function nativeVerticalWheelEventMsg() {
|
||||||
switch (getPlatform()) {
|
switch (getPlatform()) {
|
||||||
case "windows": return 0x020A; // WM_MOUSEWHEEL
|
case "windows":
|
||||||
case "mac": return 0; // value is unused, can be anything
|
return 0x020a; // WM_MOUSEWHEEL
|
||||||
case "linux": return 4; // value is unused, pass GDK_SCROLL_SMOOTH anyway
|
case "mac":
|
||||||
|
return 0; // value is unused, can be anything
|
||||||
|
case "linux":
|
||||||
|
return 4; // value is unused, pass GDK_SCROLL_SMOOTH anyway
|
||||||
}
|
}
|
||||||
throw new Error("Native wheel events not supported on platform " + getPlatform());
|
throw new Error(
|
||||||
|
"Native wheel events not supported on platform " + getPlatform()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function nativeHorizontalWheelEventMsg() {
|
function nativeHorizontalWheelEventMsg() {
|
||||||
switch (getPlatform()) {
|
switch (getPlatform()) {
|
||||||
case "windows": return 0x020E; // WM_MOUSEHWHEEL
|
case "windows":
|
||||||
case "mac": return 0; // value is unused, can be anything
|
return 0x020e; // WM_MOUSEHWHEEL
|
||||||
case "linux": return 4; // value is unused, pass GDK_SCROLL_SMOOTH anyway
|
case "mac":
|
||||||
|
return 0; // value is unused, can be anything
|
||||||
|
case "linux":
|
||||||
|
return 4; // value is unused, pass GDK_SCROLL_SMOOTH anyway
|
||||||
}
|
}
|
||||||
throw new Error("Native wheel events not supported on platform " + getPlatform());
|
throw new Error(
|
||||||
|
"Native wheel events not supported on platform " + getPlatform()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given an event target which may be a window or an element, get the associated window.
|
// Given an event target which may be a window or an element, get the associated window.
|
||||||
|
|
@ -72,7 +82,9 @@ function nativeScrollUnits(aTarget, aDimen) {
|
||||||
// GTK deltas are treated as line height divided by 3 by gecko.
|
// GTK deltas are treated as line height divided by 3 by gecko.
|
||||||
var targetWindow = windowForTarget(aTarget);
|
var targetWindow = windowForTarget(aTarget);
|
||||||
var targetElement = elementForTarget(aTarget);
|
var targetElement = elementForTarget(aTarget);
|
||||||
var lineHeight = targetWindow.getComputedStyle(targetElement)["font-size"];
|
var lineHeight = targetWindow.getComputedStyle(targetElement)[
|
||||||
|
"font-size"
|
||||||
|
];
|
||||||
return aDimen / (parseInt(lineHeight) * 3);
|
return aDimen / (parseInt(lineHeight) * 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -81,38 +93,57 @@ function nativeScrollUnits(aTarget, aDimen) {
|
||||||
|
|
||||||
function nativeMouseDownEventMsg() {
|
function nativeMouseDownEventMsg() {
|
||||||
switch (getPlatform()) {
|
switch (getPlatform()) {
|
||||||
case "windows": return 2; // MOUSEEVENTF_LEFTDOWN
|
case "windows":
|
||||||
case "mac": return 1; // NSLeftMouseDown
|
return 2; // MOUSEEVENTF_LEFTDOWN
|
||||||
case "linux": return 4; // GDK_BUTTON_PRESS
|
case "mac":
|
||||||
case "android": return 5; // ACTION_POINTER_DOWN
|
return 1; // NSLeftMouseDown
|
||||||
|
case "linux":
|
||||||
|
return 4; // GDK_BUTTON_PRESS
|
||||||
|
case "android":
|
||||||
|
return 5; // ACTION_POINTER_DOWN
|
||||||
}
|
}
|
||||||
throw new Error("Native mouse-down events not supported on platform " + getPlatform());
|
throw new Error(
|
||||||
|
"Native mouse-down events not supported on platform " + getPlatform()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function nativeMouseMoveEventMsg() {
|
function nativeMouseMoveEventMsg() {
|
||||||
switch (getPlatform()) {
|
switch (getPlatform()) {
|
||||||
case "windows": return 1; // MOUSEEVENTF_MOVE
|
case "windows":
|
||||||
case "mac": return 5; // NSMouseMoved
|
return 1; // MOUSEEVENTF_MOVE
|
||||||
case "linux": return 3; // GDK_MOTION_NOTIFY
|
case "mac":
|
||||||
case "android": return 7; // ACTION_HOVER_MOVE
|
return 5; // NSMouseMoved
|
||||||
|
case "linux":
|
||||||
|
return 3; // GDK_MOTION_NOTIFY
|
||||||
|
case "android":
|
||||||
|
return 7; // ACTION_HOVER_MOVE
|
||||||
}
|
}
|
||||||
throw new Error("Native mouse-move events not supported on platform " + getPlatform());
|
throw new Error(
|
||||||
|
"Native mouse-move events not supported on platform " + getPlatform()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function nativeMouseUpEventMsg() {
|
function nativeMouseUpEventMsg() {
|
||||||
switch (getPlatform()) {
|
switch (getPlatform()) {
|
||||||
case "windows": return 4; // MOUSEEVENTF_LEFTUP
|
case "windows":
|
||||||
case "mac": return 2; // NSLeftMouseUp
|
return 4; // MOUSEEVENTF_LEFTUP
|
||||||
case "linux": return 7; // GDK_BUTTON_RELEASE
|
case "mac":
|
||||||
case "android": return 6; // ACTION_POINTER_UP
|
return 2; // NSLeftMouseUp
|
||||||
|
case "linux":
|
||||||
|
return 7; // GDK_BUTTON_RELEASE
|
||||||
|
case "android":
|
||||||
|
return 6; // ACTION_POINTER_UP
|
||||||
}
|
}
|
||||||
throw new Error("Native mouse-up events not supported on platform " + getPlatform());
|
throw new Error(
|
||||||
|
"Native mouse-up events not supported on platform " + getPlatform()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBoundingClientRectRelativeToVisualViewport(aElement) {
|
function getBoundingClientRectRelativeToVisualViewport(aElement) {
|
||||||
let utils = SpecialPowers.getDOMWindowUtils(window);
|
let utils = SpecialPowers.getDOMWindowUtils(window);
|
||||||
var rect = aElement.getBoundingClientRect();
|
var rect = aElement.getBoundingClientRect();
|
||||||
var offsetX = {}, offsetY = {};
|
var offsetX = {},
|
||||||
|
offsetY = {};
|
||||||
// TODO: Audit whether these offset values are correct or not for
|
// TODO: Audit whether these offset values are correct or not for
|
||||||
// position:fixed elements especially in the case where the visual viewport
|
// position:fixed elements especially in the case where the visual viewport
|
||||||
// offset is not 0.
|
// offset is not 0.
|
||||||
|
|
@ -135,14 +166,19 @@ function coordinatesRelativeToScreen(aX, aY, aTarget) {
|
||||||
var targetWindow = windowForTarget(aTarget);
|
var targetWindow = windowForTarget(aTarget);
|
||||||
var deviceScale = targetWindow.devicePixelRatio;
|
var deviceScale = targetWindow.devicePixelRatio;
|
||||||
var resolution = getResolution();
|
var resolution = getResolution();
|
||||||
var rect = (aTarget instanceof Window)
|
var rect =
|
||||||
|
aTarget instanceof Window
|
||||||
? { left: 0, top: 0 } /* we don't use the width or height */
|
? { left: 0, top: 0 } /* we don't use the width or height */
|
||||||
: getBoundingClientRectRelativeToVisualViewport(aTarget);
|
: getBoundingClientRectRelativeToVisualViewport(aTarget);
|
||||||
// moxInnerScreen{X,Y} are in CSS coordinates of the browser chrome.
|
// moxInnerScreen{X,Y} are in CSS coordinates of the browser chrome.
|
||||||
// The device scale applies to them, but the resolution only zooms the content.
|
// The device scale applies to them, but the resolution only zooms the content.
|
||||||
return {
|
return {
|
||||||
x: (targetWindow.mozInnerScreenX + ((rect.left + aX) * resolution)) * deviceScale,
|
x:
|
||||||
y: (targetWindow.mozInnerScreenY + ((rect.top + aY) * resolution)) * deviceScale,
|
(targetWindow.mozInnerScreenX + (rect.left + aX) * resolution) *
|
||||||
|
deviceScale,
|
||||||
|
y:
|
||||||
|
(targetWindow.mozInnerScreenY + (rect.top + aY) * resolution) *
|
||||||
|
deviceScale,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -155,8 +191,8 @@ function rectRelativeToScreen(aElement) {
|
||||||
return {
|
return {
|
||||||
x: (targetWindow.mozInnerScreenX + rect.left) * scale,
|
x: (targetWindow.mozInnerScreenX + rect.left) * scale,
|
||||||
y: (targetWindow.mozInnerScreenY + rect.top) * scale,
|
y: (targetWindow.mozInnerScreenY + rect.top) * scale,
|
||||||
w: (rect.width * scale),
|
w: rect.width * scale,
|
||||||
h: (rect.height * scale),
|
h: rect.height * scale,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -169,14 +205,29 @@ function rectRelativeToScreen(aElement) {
|
||||||
function synthesizeNativeWheel(aTarget, aX, aY, aDeltaX, aDeltaY, aObserver) {
|
function synthesizeNativeWheel(aTarget, aX, aY, aDeltaX, aDeltaY, aObserver) {
|
||||||
var pt = coordinatesRelativeToScreen(aX, aY, aTarget);
|
var pt = coordinatesRelativeToScreen(aX, aY, aTarget);
|
||||||
if (aDeltaX && aDeltaY) {
|
if (aDeltaX && aDeltaY) {
|
||||||
throw new Error("Simultaneous wheeling of horizontal and vertical is not supported on all platforms.");
|
throw new Error(
|
||||||
|
"Simultaneous wheeling of horizontal and vertical is not supported on all platforms."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
aDeltaX = nativeScrollUnits(aTarget, aDeltaX);
|
aDeltaX = nativeScrollUnits(aTarget, aDeltaX);
|
||||||
aDeltaY = nativeScrollUnits(aTarget, aDeltaY);
|
aDeltaY = nativeScrollUnits(aTarget, aDeltaY);
|
||||||
var msg = aDeltaX ? nativeHorizontalWheelEventMsg() : nativeVerticalWheelEventMsg();
|
var msg = aDeltaX
|
||||||
|
? nativeHorizontalWheelEventMsg()
|
||||||
|
: nativeVerticalWheelEventMsg();
|
||||||
var utils = utilsForTarget(aTarget);
|
var utils = utilsForTarget(aTarget);
|
||||||
var element = elementForTarget(aTarget);
|
var element = elementForTarget(aTarget);
|
||||||
utils.sendNativeMouseScrollEvent(pt.x, pt.y, msg, aDeltaX, aDeltaY, 0, 0, 0, element, aObserver);
|
utils.sendNativeMouseScrollEvent(
|
||||||
|
pt.x,
|
||||||
|
pt.y,
|
||||||
|
msg,
|
||||||
|
aDeltaX,
|
||||||
|
aDeltaY,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
element,
|
||||||
|
aObserver
|
||||||
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,7 +235,14 @@ function synthesizeNativeWheel(aTarget, aX, aY, aDeltaX, aDeltaY, aObserver) {
|
||||||
// request has been successfully made to the OS. This does not necessarily
|
// request has been successfully made to the OS. This does not necessarily
|
||||||
// guarantee that the OS generates the event we requested. See
|
// guarantee that the OS generates the event we requested. See
|
||||||
// synthesizeNativeWheel for details on the parameters.
|
// synthesizeNativeWheel for details on the parameters.
|
||||||
function synthesizeNativeWheelAndWaitForObserver(aElement, aX, aY, aDeltaX, aDeltaY, aCallback) {
|
function synthesizeNativeWheelAndWaitForObserver(
|
||||||
|
aElement,
|
||||||
|
aX,
|
||||||
|
aY,
|
||||||
|
aDeltaX,
|
||||||
|
aDeltaY,
|
||||||
|
aCallback
|
||||||
|
) {
|
||||||
var observer = {
|
var observer = {
|
||||||
observe(aSubject, aTopic, aData) {
|
observe(aSubject, aTopic, aData) {
|
||||||
if (aCallback && aTopic == "mousescrollevent") {
|
if (aCallback && aTopic == "mousescrollevent") {
|
||||||
|
|
@ -200,11 +258,22 @@ function synthesizeNativeWheelAndWaitForObserver(aElement, aX, aY, aDeltaX, aDel
|
||||||
// targets content in a subdocument, |aTarget| should be inside the
|
// targets content in a subdocument, |aTarget| should be inside the
|
||||||
// subdocument (or the subdocument's window). See synthesizeNativeWheel for
|
// subdocument (or the subdocument's window). See synthesizeNativeWheel for
|
||||||
// details on the other parameters.
|
// details on the other parameters.
|
||||||
function synthesizeNativeWheelAndWaitForWheelEvent(aTarget, aX, aY, aDeltaX, aDeltaY, aCallback) {
|
function synthesizeNativeWheelAndWaitForWheelEvent(
|
||||||
|
aTarget,
|
||||||
|
aX,
|
||||||
|
aY,
|
||||||
|
aDeltaX,
|
||||||
|
aDeltaY,
|
||||||
|
aCallback
|
||||||
|
) {
|
||||||
var targetWindow = windowForTarget(aTarget);
|
var targetWindow = windowForTarget(aTarget);
|
||||||
targetWindow.addEventListener("wheel", function(e) {
|
targetWindow.addEventListener(
|
||||||
|
"wheel",
|
||||||
|
function(e) {
|
||||||
setTimeout(aCallback, 0);
|
setTimeout(aCallback, 0);
|
||||||
}, {once: true});
|
},
|
||||||
|
{ once: true }
|
||||||
|
);
|
||||||
return synthesizeNativeWheel(aTarget, aX, aY, aDeltaX, aDeltaY);
|
return synthesizeNativeWheel(aTarget, aX, aY, aDeltaX, aDeltaY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -213,11 +282,22 @@ function synthesizeNativeWheelAndWaitForWheelEvent(aTarget, aX, aY, aDeltaX, aDe
|
||||||
// If the event targets content in a subdocument, |aTarget| should be inside
|
// If the event targets content in a subdocument, |aTarget| should be inside
|
||||||
// the subdocument (or the subdocument's window). See synthesizeNativeWheel
|
// the subdocument (or the subdocument's window). See synthesizeNativeWheel
|
||||||
// for details on the other parameters.
|
// for details on the other parameters.
|
||||||
function synthesizeNativeWheelAndWaitForScrollEvent(aTarget, aX, aY, aDeltaX, aDeltaY, aCallback) {
|
function synthesizeNativeWheelAndWaitForScrollEvent(
|
||||||
|
aTarget,
|
||||||
|
aX,
|
||||||
|
aY,
|
||||||
|
aDeltaX,
|
||||||
|
aDeltaY,
|
||||||
|
aCallback
|
||||||
|
) {
|
||||||
var targetWindow = windowForTarget(aTarget);
|
var targetWindow = windowForTarget(aTarget);
|
||||||
targetWindow.addEventListener("scroll", function() {
|
targetWindow.addEventListener(
|
||||||
|
"scroll",
|
||||||
|
function() {
|
||||||
setTimeout(aCallback, 0);
|
setTimeout(aCallback, 0);
|
||||||
}, {capture: true, once: true}); // scroll events don't always bubble
|
},
|
||||||
|
{ capture: true, once: true }
|
||||||
|
); // scroll events don't always bubble
|
||||||
return synthesizeNativeWheel(aTarget, aX, aY, aDeltaX, aDeltaY);
|
return synthesizeNativeWheel(aTarget, aX, aY, aDeltaX, aDeltaY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -236,17 +316,33 @@ function synthesizeNativeMouseMove(aTarget, aX, aY) {
|
||||||
// targets content in a subdocument, |aTarget| should be inside the
|
// targets content in a subdocument, |aTarget| should be inside the
|
||||||
// subdocument (or the subdocument window). See synthesizeNativeMouseMove for
|
// subdocument (or the subdocument window). See synthesizeNativeMouseMove for
|
||||||
// details on the other parameters.
|
// details on the other parameters.
|
||||||
function synthesizeNativeMouseMoveAndWaitForMoveEvent(aTarget, aX, aY, aCallback) {
|
function synthesizeNativeMouseMoveAndWaitForMoveEvent(
|
||||||
|
aTarget,
|
||||||
|
aX,
|
||||||
|
aY,
|
||||||
|
aCallback
|
||||||
|
) {
|
||||||
var targetWindow = windowForTarget(aTarget);
|
var targetWindow = windowForTarget(aTarget);
|
||||||
targetWindow.addEventListener("mousemove", function(e) {
|
targetWindow.addEventListener(
|
||||||
|
"mousemove",
|
||||||
|
function(e) {
|
||||||
setTimeout(aCallback, 0);
|
setTimeout(aCallback, 0);
|
||||||
}, {once: true});
|
},
|
||||||
|
{ once: true }
|
||||||
|
);
|
||||||
return synthesizeNativeMouseMove(aTarget, aX, aY);
|
return synthesizeNativeMouseMove(aTarget, aX, aY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synthesizes a native touch event and dispatches it. aX and aY in CSS pixels
|
// Synthesizes a native touch event and dispatches it. aX and aY in CSS pixels
|
||||||
// relative to the top-left of |aTarget|'s bounding rect.
|
// relative to the top-left of |aTarget|'s bounding rect.
|
||||||
function synthesizeNativeTouch(aTarget, aX, aY, aType, aObserver = null, aTouchId = 0) {
|
function synthesizeNativeTouch(
|
||||||
|
aTarget,
|
||||||
|
aX,
|
||||||
|
aY,
|
||||||
|
aType,
|
||||||
|
aObserver = null,
|
||||||
|
aTouchId = 0
|
||||||
|
) {
|
||||||
var pt = coordinatesRelativeToScreen(aX, aY, aTarget);
|
var pt = coordinatesRelativeToScreen(aX, aY, aTarget);
|
||||||
var utils = utilsForTarget(aTarget);
|
var utils = utilsForTarget(aTarget);
|
||||||
utils.sendNativeTouchPoint(aTouchId, aType, pt.x, pt.y, 1, 90, aObserver);
|
utils.sendNativeTouchPoint(aTouchId, aType, pt.x, pt.y, 1, 90, aObserver);
|
||||||
|
|
@ -271,7 +367,12 @@ function synthesizeNativeTouch(aTarget, aX, aY, aType, aObserver = null, aTouchI
|
||||||
// aObserver is the observer that will get registered on the very last
|
// aObserver is the observer that will get registered on the very last
|
||||||
// synthesizeNativeTouch call this function makes.
|
// synthesizeNativeTouch call this function makes.
|
||||||
// aTouchIds is an array holding the touch ID values of each "finger".
|
// aTouchIds is an array holding the touch ID values of each "finger".
|
||||||
function* synthesizeNativeTouchSequences(aTarget, aPositions, aObserver = null, aTouchIds = [0]) {
|
function* synthesizeNativeTouchSequences(
|
||||||
|
aTarget,
|
||||||
|
aPositions,
|
||||||
|
aObserver = null,
|
||||||
|
aTouchIds = [0]
|
||||||
|
) {
|
||||||
// We use lastNonNullValue to figure out which synthesizeNativeTouch call
|
// We use lastNonNullValue to figure out which synthesizeNativeTouch call
|
||||||
// will be the last one we make, so that we can register aObserver on it.
|
// will be the last one we make, so that we can register aObserver on it.
|
||||||
var lastNonNullValue = -1;
|
var lastNonNullValue = -1;
|
||||||
|
|
@ -284,12 +385,14 @@ function* synthesizeNativeTouchSequences(aTarget, aPositions, aObserver = null,
|
||||||
if (aPositions[i].length != aTouchIds.length) {
|
if (aPositions[i].length != aTouchIds.length) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`aPositions[${i}] did not have the expected number of positions; ` +
|
`aPositions[${i}] did not have the expected number of positions; ` +
|
||||||
`expected ${aTouchIds.length} touch points but found ${aPositions[i].length}`
|
`expected ${aTouchIds.length} touch points but found ${
|
||||||
|
aPositions[i].length
|
||||||
|
}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
for (let j = 0; j < aTouchIds.length; j++) {
|
for (let j = 0; j < aTouchIds.length; j++) {
|
||||||
if (aPositions[i][j] != null) {
|
if (aPositions[i][j] != null) {
|
||||||
lastNonNullValue = ((i - yields) * aTouchIds.length) + j;
|
lastNonNullValue = (i - yields) * aTouchIds.length + j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -328,13 +431,27 @@ function* synthesizeNativeTouchSequences(aTarget, aPositions, aObserver = null,
|
||||||
} else {
|
} else {
|
||||||
// synthesize the touch-up. If this is the last call we're going to
|
// synthesize the touch-up. If this is the last call we're going to
|
||||||
// make, pass the observer as well
|
// make, pass the observer as well
|
||||||
var thisIndex = ((i - yields) * aTouchIds.length) + j;
|
var thisIndex = (i - yields) * aTouchIds.length + j;
|
||||||
var observer = (lastSynthesizeCall == thisIndex) ? aObserver : null;
|
var observer = lastSynthesizeCall == thisIndex ? aObserver : null;
|
||||||
synthesizeNativeTouch(aTarget, currentPositions[j].x, currentPositions[j].y, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, observer, aTouchIds[j]);
|
synthesizeNativeTouch(
|
||||||
|
aTarget,
|
||||||
|
currentPositions[j].x,
|
||||||
|
currentPositions[j].y,
|
||||||
|
SpecialPowers.DOMWindowUtils.TOUCH_REMOVE,
|
||||||
|
observer,
|
||||||
|
aTouchIds[j]
|
||||||
|
);
|
||||||
currentPositions[j] = null;
|
currentPositions[j] = null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
synthesizeNativeTouch(aTarget, aPositions[i][j].x, aPositions[i][j].y, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, null, aTouchIds[j]);
|
synthesizeNativeTouch(
|
||||||
|
aTarget,
|
||||||
|
aPositions[i][j].x,
|
||||||
|
aPositions[i][j].y,
|
||||||
|
SpecialPowers.DOMWindowUtils.TOUCH_CONTACT,
|
||||||
|
null,
|
||||||
|
aTouchIds[j]
|
||||||
|
);
|
||||||
currentPositions[j] = aPositions[i][j];
|
currentPositions[j] = aPositions[i][j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -345,7 +462,15 @@ function* synthesizeNativeTouchSequences(aTarget, aPositions, aObserver = null,
|
||||||
// Note that when calling this function you'll want to make sure that the pref
|
// Note that when calling this function you'll want to make sure that the pref
|
||||||
// "apz.touch_start_tolerance" is set to 0, or some of the touchmove will get
|
// "apz.touch_start_tolerance" is set to 0, or some of the touchmove will get
|
||||||
// consumed to overcome the panning threshold.
|
// consumed to overcome the panning threshold.
|
||||||
function synthesizeNativeTouchDrag(aTarget, aX, aY, aDeltaX, aDeltaY, aObserver = null, aTouchId = 0) {
|
function synthesizeNativeTouchDrag(
|
||||||
|
aTarget,
|
||||||
|
aX,
|
||||||
|
aY,
|
||||||
|
aDeltaX,
|
||||||
|
aDeltaY,
|
||||||
|
aObserver = null,
|
||||||
|
aTouchId = 0
|
||||||
|
) {
|
||||||
var steps = Math.max(Math.abs(aDeltaX), Math.abs(aDeltaY));
|
var steps = Math.max(Math.abs(aDeltaX), Math.abs(aDeltaY));
|
||||||
var positions = [[{ x: aX, y: aY }]];
|
var positions = [[{ x: aX, y: aY }]];
|
||||||
for (var i = 1; i < steps; i++) {
|
for (var i = 1; i < steps; i++) {
|
||||||
|
|
@ -355,7 +480,12 @@ function synthesizeNativeTouchDrag(aTarget, aX, aY, aDeltaX, aDeltaY, aObserver
|
||||||
positions.push([pos]);
|
positions.push([pos]);
|
||||||
}
|
}
|
||||||
positions.push([{ x: aX + aDeltaX, y: aY + aDeltaY }]);
|
positions.push([{ x: aX + aDeltaX, y: aY + aDeltaY }]);
|
||||||
var continuation = synthesizeNativeTouchSequences(aTarget, positions, aObserver, [aTouchId]);
|
var continuation = synthesizeNativeTouchSequences(
|
||||||
|
aTarget,
|
||||||
|
positions,
|
||||||
|
aObserver,
|
||||||
|
[aTouchId]
|
||||||
|
);
|
||||||
var yielded = continuation.next();
|
var yielded = continuation.next();
|
||||||
while (!yielded.done) {
|
while (!yielded.done) {
|
||||||
yielded = continuation.next();
|
yielded = continuation.next();
|
||||||
|
|
@ -365,7 +495,9 @@ function synthesizeNativeTouchDrag(aTarget, aX, aY, aDeltaX, aDeltaY, aObserver
|
||||||
|
|
||||||
function synthesizeNativeTap(aElement, aX, aY, aObserver = null) {
|
function synthesizeNativeTap(aElement, aX, aY, aObserver = null) {
|
||||||
var pt = coordinatesRelativeToScreen(aX, aY, aElement);
|
var pt = coordinatesRelativeToScreen(aX, aY, aElement);
|
||||||
var utils = SpecialPowers.getDOMWindowUtils(aElement.ownerDocument.defaultView);
|
var utils = SpecialPowers.getDOMWindowUtils(
|
||||||
|
aElement.ownerDocument.defaultView
|
||||||
|
);
|
||||||
utils.sendNativeTouchTap(pt.x, pt.y, false, aObserver);
|
utils.sendNativeTouchTap(pt.x, pt.y, false, aObserver);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -380,10 +512,26 @@ function synthesizeNativeMouseEvent(aTarget, aX, aY, aType, aObserver = null) {
|
||||||
|
|
||||||
function synthesizeNativeClick(aElement, aX, aY, aObserver = null) {
|
function synthesizeNativeClick(aElement, aX, aY, aObserver = null) {
|
||||||
var pt = coordinatesRelativeToScreen(aX, aY, aElement);
|
var pt = coordinatesRelativeToScreen(aX, aY, aElement);
|
||||||
var utils = SpecialPowers.getDOMWindowUtils(aElement.ownerDocument.defaultView);
|
var utils = SpecialPowers.getDOMWindowUtils(
|
||||||
utils.sendNativeMouseEvent(pt.x, pt.y, nativeMouseDownEventMsg(), 0, aElement, function() {
|
aElement.ownerDocument.defaultView
|
||||||
utils.sendNativeMouseEvent(pt.x, pt.y, nativeMouseUpEventMsg(), 0, aElement, aObserver);
|
);
|
||||||
});
|
utils.sendNativeMouseEvent(
|
||||||
|
pt.x,
|
||||||
|
pt.y,
|
||||||
|
nativeMouseDownEventMsg(),
|
||||||
|
0,
|
||||||
|
aElement,
|
||||||
|
function() {
|
||||||
|
utils.sendNativeMouseEvent(
|
||||||
|
pt.x,
|
||||||
|
pt.y,
|
||||||
|
nativeMouseUpEventMsg(),
|
||||||
|
0,
|
||||||
|
aElement,
|
||||||
|
aObserver
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -395,20 +543,50 @@ function synthesizeNativeClick(aElement, aX, aY, aObserver = null) {
|
||||||
// We also wait for the mouse move event to be processed before sending the
|
// We also wait for the mouse move event to be processed before sending the
|
||||||
// wheel event, otherwise there is a chance they might get reordered, and
|
// wheel event, otherwise there is a chance they might get reordered, and
|
||||||
// we have the transaction problem again.
|
// we have the transaction problem again.
|
||||||
function moveMouseAndScrollWheelOver(target, dx, dy, testDriver, waitForScroll = true) {
|
function moveMouseAndScrollWheelOver(
|
||||||
return synthesizeNativeMouseMoveAndWaitForMoveEvent(target, dx, dy, function() {
|
target,
|
||||||
|
dx,
|
||||||
|
dy,
|
||||||
|
testDriver,
|
||||||
|
waitForScroll = true
|
||||||
|
) {
|
||||||
|
return synthesizeNativeMouseMoveAndWaitForMoveEvent(
|
||||||
|
target,
|
||||||
|
dx,
|
||||||
|
dy,
|
||||||
|
function() {
|
||||||
if (waitForScroll) {
|
if (waitForScroll) {
|
||||||
synthesizeNativeWheelAndWaitForScrollEvent(target, dx, dy, 0, -10, testDriver);
|
synthesizeNativeWheelAndWaitForScrollEvent(
|
||||||
|
target,
|
||||||
|
dx,
|
||||||
|
dy,
|
||||||
|
0,
|
||||||
|
-10,
|
||||||
|
testDriver
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
synthesizeNativeWheelAndWaitForWheelEvent(target, dx, dy, 0, -10, testDriver);
|
synthesizeNativeWheelAndWaitForWheelEvent(
|
||||||
|
target,
|
||||||
|
dx,
|
||||||
|
dy,
|
||||||
|
0,
|
||||||
|
-10,
|
||||||
|
testDriver
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Same as moveMouseAndScrollWheelOver, but returns a promise instead of taking
|
// Same as moveMouseAndScrollWheelOver, but returns a promise instead of taking
|
||||||
// a callback function. Eventually we should convert all these callback-taking
|
// a callback function. Eventually we should convert all these callback-taking
|
||||||
// functions into promise-producing functions but for now this is a stopgap.
|
// functions into promise-producing functions but for now this is a stopgap.
|
||||||
function promiseMoveMouseAndScrollWheelOver(target, dx, dy, waitForScroll = true) {
|
function promiseMoveMouseAndScrollWheelOver(
|
||||||
|
target,
|
||||||
|
dx,
|
||||||
|
dy,
|
||||||
|
waitForScroll = true
|
||||||
|
) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
moveMouseAndScrollWheelOver(target, dx, dy, resolve, waitForScroll);
|
moveMouseAndScrollWheelOver(target, dx, dy, resolve, waitForScroll);
|
||||||
});
|
});
|
||||||
|
|
@ -425,9 +603,15 @@ function promiseMoveMouseAndScrollWheelOver(target, dx, dy, waitForScroll = true
|
||||||
// Note: helper_scrollbar_snap_bug1501062.html contains a copy of this code
|
// Note: helper_scrollbar_snap_bug1501062.html contains a copy of this code
|
||||||
// with modifications. Fixes here should be copied there if appropriate.
|
// with modifications. Fixes here should be copied there if appropriate.
|
||||||
// |target| can be an element (for subframes) or a window (for root frames).
|
// |target| can be an element (for subframes) or a window (for root frames).
|
||||||
function* dragVerticalScrollbar(target, testDriver, distance = 20, increment = 5) {
|
function* dragVerticalScrollbar(
|
||||||
|
target,
|
||||||
|
testDriver,
|
||||||
|
distance = 20,
|
||||||
|
increment = 5
|
||||||
|
) {
|
||||||
var targetElement = elementForTarget(target);
|
var targetElement = elementForTarget(target);
|
||||||
var w = {}, h = {};
|
var w = {},
|
||||||
|
h = {};
|
||||||
utilsForTarget(target).getScrollbarSizes(targetElement, w, h);
|
utilsForTarget(target).getScrollbarSizes(targetElement, w, h);
|
||||||
var verticalScrollbarWidth = w.value;
|
var verticalScrollbarWidth = w.value;
|
||||||
if (verticalScrollbarWidth == 0) {
|
if (verticalScrollbarWidth == 0) {
|
||||||
|
|
@ -435,24 +619,62 @@ function* dragVerticalScrollbar(target, testDriver, distance = 20, increment = 5
|
||||||
}
|
}
|
||||||
|
|
||||||
var upArrowHeight = verticalScrollbarWidth; // assume square scrollbar buttons
|
var upArrowHeight = verticalScrollbarWidth; // assume square scrollbar buttons
|
||||||
var mouseX = targetElement.clientWidth + (verticalScrollbarWidth / 2);
|
var mouseX = targetElement.clientWidth + verticalScrollbarWidth / 2;
|
||||||
var mouseY = upArrowHeight + 5; // start dragging somewhere in the thumb
|
var mouseY = upArrowHeight + 5; // start dragging somewhere in the thumb
|
||||||
|
|
||||||
dump("Starting drag at " + mouseX + ", " + mouseY + " from top-left of #" + targetElement.id + "\n");
|
dump(
|
||||||
|
"Starting drag at " +
|
||||||
|
mouseX +
|
||||||
|
", " +
|
||||||
|
mouseY +
|
||||||
|
" from top-left of #" +
|
||||||
|
targetElement.id +
|
||||||
|
"\n"
|
||||||
|
);
|
||||||
|
|
||||||
// Move the mouse to the scrollbar thumb and drag it down
|
// Move the mouse to the scrollbar thumb and drag it down
|
||||||
yield synthesizeNativeMouseEvent(target, mouseX, mouseY, nativeMouseMoveEventMsg(), testDriver);
|
yield synthesizeNativeMouseEvent(
|
||||||
|
target,
|
||||||
|
mouseX,
|
||||||
|
mouseY,
|
||||||
|
nativeMouseMoveEventMsg(),
|
||||||
|
testDriver
|
||||||
|
);
|
||||||
// mouse down
|
// mouse down
|
||||||
yield synthesizeNativeMouseEvent(target, mouseX, mouseY, nativeMouseDownEventMsg(), testDriver);
|
yield synthesizeNativeMouseEvent(
|
||||||
|
target,
|
||||||
|
mouseX,
|
||||||
|
mouseY,
|
||||||
|
nativeMouseDownEventMsg(),
|
||||||
|
testDriver
|
||||||
|
);
|
||||||
// drag vertically by |increment| until we reach the specified distance
|
// drag vertically by |increment| until we reach the specified distance
|
||||||
for (var y = increment; y < distance; y += increment) {
|
for (var y = increment; y < distance; y += increment) {
|
||||||
yield synthesizeNativeMouseEvent(target, mouseX, mouseY + y, nativeMouseMoveEventMsg(), testDriver);
|
yield synthesizeNativeMouseEvent(
|
||||||
|
target,
|
||||||
|
mouseX,
|
||||||
|
mouseY + y,
|
||||||
|
nativeMouseMoveEventMsg(),
|
||||||
|
testDriver
|
||||||
|
);
|
||||||
}
|
}
|
||||||
yield synthesizeNativeMouseEvent(target, mouseX, mouseY + distance, nativeMouseMoveEventMsg(), testDriver);
|
yield synthesizeNativeMouseEvent(
|
||||||
|
target,
|
||||||
|
mouseX,
|
||||||
|
mouseY + distance,
|
||||||
|
nativeMouseMoveEventMsg(),
|
||||||
|
testDriver
|
||||||
|
);
|
||||||
|
|
||||||
// and return a generator to call afterwards to finish up the drag
|
// and return a generator to call afterwards to finish up the drag
|
||||||
return function*() {
|
return function*() {
|
||||||
dump("Finishing drag of #" + targetElement.id + "\n");
|
dump("Finishing drag of #" + targetElement.id + "\n");
|
||||||
yield synthesizeNativeMouseEvent(target, mouseX, mouseY + distance, nativeMouseUpEventMsg(), testDriver);
|
yield synthesizeNativeMouseEvent(
|
||||||
|
target,
|
||||||
|
mouseX,
|
||||||
|
mouseY + distance,
|
||||||
|
nativeMouseUpEventMsg(),
|
||||||
|
testDriver
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,35 +24,55 @@ function convertEntries(entries) {
|
||||||
function parseRect(str) {
|
function parseRect(str) {
|
||||||
var pieces = str.replace(/[()\s]+/g, "").split(",");
|
var pieces = str.replace(/[()\s]+/g, "").split(",");
|
||||||
SimpleTest.is(pieces.length, 4, "expected string of form (x,y,w,h)");
|
SimpleTest.is(pieces.length, 4, "expected string of form (x,y,w,h)");
|
||||||
return { x: parseInt(pieces[0]),
|
return {
|
||||||
|
x: parseInt(pieces[0]),
|
||||||
y: parseInt(pieces[1]),
|
y: parseInt(pieces[1]),
|
||||||
w: parseInt(pieces[2]),
|
w: parseInt(pieces[2]),
|
||||||
h: parseInt(pieces[3]) };
|
h: parseInt(pieces[3]),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// These functions expect rects with fields named x/y/w/h, such as
|
// These functions expect rects with fields named x/y/w/h, such as
|
||||||
// that returned by parseRect().
|
// that returned by parseRect().
|
||||||
function rectContains(haystack, needle) {
|
function rectContains(haystack, needle) {
|
||||||
return haystack.x <= needle.x
|
return (
|
||||||
&& haystack.y <= needle.y
|
haystack.x <= needle.x &&
|
||||||
&& (haystack.x + haystack.w) >= (needle.x + needle.w)
|
haystack.y <= needle.y &&
|
||||||
&& (haystack.y + haystack.h) >= (needle.y + needle.h);
|
haystack.x + haystack.w >= needle.x + needle.w &&
|
||||||
|
haystack.y + haystack.h >= needle.y + needle.h
|
||||||
|
);
|
||||||
}
|
}
|
||||||
function rectToString(rect) {
|
function rectToString(rect) {
|
||||||
return "(" + rect.x + "," + rect.y + "," + rect.w + "," + rect.h + ")";
|
return "(" + rect.x + "," + rect.y + "," + rect.w + "," + rect.h + ")";
|
||||||
}
|
}
|
||||||
function assertRectContainment(haystackRect, haystackDesc, needleRect, needleDesc) {
|
function assertRectContainment(
|
||||||
SimpleTest.ok(rectContains(haystackRect, needleRect),
|
haystackRect,
|
||||||
haystackDesc + " " + rectToString(haystackRect) + " should contain " +
|
haystackDesc,
|
||||||
needleDesc + " " + rectToString(needleRect));
|
needleRect,
|
||||||
|
needleDesc
|
||||||
|
) {
|
||||||
|
SimpleTest.ok(
|
||||||
|
rectContains(haystackRect, needleRect),
|
||||||
|
haystackDesc +
|
||||||
|
" " +
|
||||||
|
rectToString(haystackRect) +
|
||||||
|
" should contain " +
|
||||||
|
needleDesc +
|
||||||
|
" " +
|
||||||
|
rectToString(needleRect)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPropertyAsRect(scrollFrames, scrollId, prop) {
|
function getPropertyAsRect(scrollFrames, scrollId, prop) {
|
||||||
SimpleTest.ok(scrollId in scrollFrames,
|
SimpleTest.ok(
|
||||||
"expected scroll frame data for scroll id " + scrollId);
|
scrollId in scrollFrames,
|
||||||
|
"expected scroll frame data for scroll id " + scrollId
|
||||||
|
);
|
||||||
var scrollFrameData = scrollFrames[scrollId];
|
var scrollFrameData = scrollFrames[scrollId];
|
||||||
SimpleTest.ok("displayport" in scrollFrameData,
|
SimpleTest.ok(
|
||||||
"expected a " + prop + " for scroll id " + scrollId);
|
"displayport" in scrollFrameData,
|
||||||
|
"expected a " + prop + " for scroll id " + scrollId
|
||||||
|
);
|
||||||
var value = scrollFrameData[prop];
|
var value = scrollFrameData[prop];
|
||||||
return parseRect(value);
|
return parseRect(value);
|
||||||
}
|
}
|
||||||
|
|
@ -68,7 +88,9 @@ function convertScrollFrameData(scrollFrames) {
|
||||||
function convertBuckets(buckets) {
|
function convertBuckets(buckets) {
|
||||||
var result = {};
|
var result = {};
|
||||||
for (var i = 0; i < buckets.length; ++i) {
|
for (var i = 0; i < buckets.length; ++i) {
|
||||||
result[buckets[i].sequenceNumber] = convertScrollFrameData(buckets[i].scrollFrames);
|
result[buckets[i].sequenceNumber] = convertScrollFrameData(
|
||||||
|
buckets[i].scrollFrames
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -94,14 +116,20 @@ function getLastNonemptyBucket(buckets) {
|
||||||
|
|
||||||
// Takes something like "matrix(1, 0, 0, 1, 234.024, 528.29023)"" and returns a number array
|
// Takes something like "matrix(1, 0, 0, 1, 234.024, 528.29023)"" and returns a number array
|
||||||
function parseTransform(transform) {
|
function parseTransform(transform) {
|
||||||
return /matrix\((.*),(.*),(.*),(.*),(.*),(.*)\)/.exec(transform)
|
return /matrix\((.*),(.*),(.*),(.*),(.*),(.*)\)/
|
||||||
.slice(1).map(parseFloat);
|
.exec(transform)
|
||||||
|
.slice(1)
|
||||||
|
.map(parseFloat);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isTransformClose(a, b, name) {
|
function isTransformClose(a, b, name) {
|
||||||
is(a.length, b.length, `expected transforms ${a} and ${b} to be the same length`);
|
is(
|
||||||
|
a.length,
|
||||||
|
b.length,
|
||||||
|
`expected transforms ${a} and ${b} to be the same length`
|
||||||
|
);
|
||||||
for (let i = 0; i < a.length; i++) {
|
for (let i = 0; i < a.length; i++) {
|
||||||
ok(Math.abs(a[i] - b[i]) < .01, name);
|
ok(Math.abs(a[i] - b[i]) < 0.01, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,7 +163,8 @@ function buildApzcTree(paint) {
|
||||||
// Given an APZC tree produced by buildApzcTree, return the RCD node in
|
// Given an APZC tree produced by buildApzcTree, return the RCD node in
|
||||||
// the tree, or null if there was none.
|
// the tree, or null if there was none.
|
||||||
function findRcdNode(apzcTree) {
|
function findRcdNode(apzcTree) {
|
||||||
if (apzcTree.isRootContent) { // isRootContent will be undefined or "1"
|
if (apzcTree.isRootContent) {
|
||||||
|
// isRootContent will be undefined or "1"
|
||||||
return apzcTree;
|
return apzcTree;
|
||||||
}
|
}
|
||||||
for (var i = 0; i < apzcTree.children.length; i++) {
|
for (var i = 0; i < apzcTree.children.length; i++) {
|
||||||
|
|
@ -151,7 +180,9 @@ function findRcdNode(apzcTree) {
|
||||||
// Assumes |elementId| will be present in the content description for the
|
// Assumes |elementId| will be present in the content description for the
|
||||||
// element, and not in the content descriptions of other elements.
|
// element, and not in the content descriptions of other elements.
|
||||||
function isLayerized(elementId) {
|
function isLayerized(elementId) {
|
||||||
var contentTestData = SpecialPowers.getDOMWindowUtils(window).getContentAPZTestData();
|
var contentTestData = SpecialPowers.getDOMWindowUtils(
|
||||||
|
window
|
||||||
|
).getContentAPZTestData();
|
||||||
var nonEmptyBucket = getLastNonemptyBucket(contentTestData.paints);
|
var nonEmptyBucket = getLastNonemptyBucket(contentTestData.paints);
|
||||||
ok(nonEmptyBucket != null, "expected at least one nonempty paint");
|
ok(nonEmptyBucket != null, "expected at least one nonempty paint");
|
||||||
var seqno = nonEmptyBucket.sequenceNumber;
|
var seqno = nonEmptyBucket.sequenceNumber;
|
||||||
|
|
@ -170,14 +201,19 @@ function isLayerized(elementId) {
|
||||||
function promiseApzRepaintsFlushed(aWindow = window) {
|
function promiseApzRepaintsFlushed(aWindow = window) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
var repaintDone = function() {
|
var repaintDone = function() {
|
||||||
SpecialPowers.Services.obs.removeObserver(repaintDone, "apz-repaints-flushed");
|
SpecialPowers.Services.obs.removeObserver(
|
||||||
|
repaintDone,
|
||||||
|
"apz-repaints-flushed"
|
||||||
|
);
|
||||||
setTimeout(resolve, 0);
|
setTimeout(resolve, 0);
|
||||||
};
|
};
|
||||||
SpecialPowers.Services.obs.addObserver(repaintDone, "apz-repaints-flushed");
|
SpecialPowers.Services.obs.addObserver(repaintDone, "apz-repaints-flushed");
|
||||||
if (SpecialPowers.getDOMWindowUtils(aWindow).flushApzRepaints()) {
|
if (SpecialPowers.getDOMWindowUtils(aWindow).flushApzRepaints()) {
|
||||||
dump("Flushed APZ repaints, waiting for callback...\n");
|
dump("Flushed APZ repaints, waiting for callback...\n");
|
||||||
} else {
|
} else {
|
||||||
dump("Flushing APZ repaints was a no-op, triggering callback directly...\n");
|
dump(
|
||||||
|
"Flushing APZ repaints was a no-op, triggering callback directly...\n"
|
||||||
|
);
|
||||||
repaintDone();
|
repaintDone();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -248,18 +284,24 @@ function runSubtestsSeriallyInFreshWindows(aSubtests) {
|
||||||
|
|
||||||
// If the "apz.subtest" pref has been set, only a single subtest whose name matches
|
// If the "apz.subtest" pref has been set, only a single subtest whose name matches
|
||||||
// the pref's value (if any) will be run.
|
// the pref's value (if any) will be run.
|
||||||
var onlyOneSubtest = SpecialPowers.getCharPref("apz.subtest", /* default = */ "");
|
var onlyOneSubtest = SpecialPowers.getCharPref(
|
||||||
|
"apz.subtest",
|
||||||
|
/* default = */ ""
|
||||||
|
);
|
||||||
|
|
||||||
function advanceSubtestExecution() {
|
function advanceSubtestExecution() {
|
||||||
var test = aSubtests[testIndex];
|
var test = aSubtests[testIndex];
|
||||||
if (w) {
|
if (w) {
|
||||||
// Run any cleanup functions registered in the subtest
|
// Run any cleanup functions registered in the subtest
|
||||||
if (w.ApzCleanup) { // guard against the subtest not loading apz_test_utils.js
|
if (w.ApzCleanup) {
|
||||||
|
// guard against the subtest not loading apz_test_utils.js
|
||||||
w.ApzCleanup.execute();
|
w.ApzCleanup.execute();
|
||||||
}
|
}
|
||||||
if (typeof test.dp_suppression != "undefined") {
|
if (typeof test.dp_suppression != "undefined") {
|
||||||
// We modified the suppression when starting the test, so now undo that.
|
// We modified the suppression when starting the test, so now undo that.
|
||||||
SpecialPowers.getDOMWindowUtils(window).respectDisplayPortSuppression(!test.dp_suppression);
|
SpecialPowers.getDOMWindowUtils(window).respectDisplayPortSuppression(
|
||||||
|
!test.dp_suppression
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (test.prefs) {
|
if (test.prefs) {
|
||||||
// We pushed some prefs for this test, pop them, and re-invoke
|
// We pushed some prefs for this test, pop them, and re-invoke
|
||||||
|
|
@ -286,15 +328,29 @@ function runSubtestsSeriallyInFreshWindows(aSubtests) {
|
||||||
let recognizedProps = ["file", "prefs", "dp_suppression", "onload"];
|
let recognizedProps = ["file", "prefs", "dp_suppression", "onload"];
|
||||||
for (let prop in test) {
|
for (let prop in test) {
|
||||||
if (!recognizedProps.includes(prop)) {
|
if (!recognizedProps.includes(prop)) {
|
||||||
SimpleTest.ok(false, "Subtest " + test.file + " has unrecognized property '" + prop + "'");
|
SimpleTest.ok(
|
||||||
setTimeout(function() { advanceSubtestExecution(); }, 0);
|
false,
|
||||||
|
"Subtest " + test.file + " has unrecognized property '" + prop + "'"
|
||||||
|
);
|
||||||
|
setTimeout(function() {
|
||||||
|
advanceSubtestExecution();
|
||||||
|
}, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onlyOneSubtest && onlyOneSubtest != test.file) {
|
if (onlyOneSubtest && onlyOneSubtest != test.file) {
|
||||||
SimpleTest.ok(true, "Skipping " + test.file + " because only " + onlyOneSubtest + " is being run");
|
SimpleTest.ok(
|
||||||
setTimeout(function() { advanceSubtestExecution(); }, 0);
|
true,
|
||||||
|
"Skipping " +
|
||||||
|
test.file +
|
||||||
|
" because only " +
|
||||||
|
onlyOneSubtest +
|
||||||
|
" is being run"
|
||||||
|
);
|
||||||
|
setTimeout(function() {
|
||||||
|
advanceSubtestExecution();
|
||||||
|
}, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -306,7 +362,9 @@ function runSubtestsSeriallyInFreshWindows(aSubtests) {
|
||||||
// unsuppression can trigger a repaint which interferes with the test, so
|
// unsuppression can trigger a repaint which interferes with the test, so
|
||||||
// to avoid that we can force the displayport to be unsuppressed for the
|
// to avoid that we can force the displayport to be unsuppressed for the
|
||||||
// entire test which is more deterministic.
|
// entire test which is more deterministic.
|
||||||
SpecialPowers.getDOMWindowUtils(window).respectDisplayPortSuppression(test.dp_suppression);
|
SpecialPowers.getDOMWindowUtils(window).respectDisplayPortSuppression(
|
||||||
|
test.dp_suppression
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function spawnTest(aFile) {
|
function spawnTest(aFile) {
|
||||||
|
|
@ -314,21 +372,39 @@ function runSubtestsSeriallyInFreshWindows(aSubtests) {
|
||||||
w.subtestDone = advanceSubtestExecution;
|
w.subtestDone = advanceSubtestExecution;
|
||||||
w.isApzSubtest = true;
|
w.isApzSubtest = true;
|
||||||
w.SimpleTest = SimpleTest;
|
w.SimpleTest = SimpleTest;
|
||||||
w.dump = function(msg) { return dump(aFile + " | " + msg); };
|
w.dump = function(msg) {
|
||||||
w.is = function(a, b, msg) { return is(a, b, aFile + " | " + msg); };
|
return dump(aFile + " | " + msg);
|
||||||
w.isfuzzy = function(a, b, eps, msg) { return isfuzzy(a, b, eps, aFile + " | " + msg); };
|
};
|
||||||
|
w.is = function(a, b, msg) {
|
||||||
|
return is(a, b, aFile + " | " + msg);
|
||||||
|
};
|
||||||
|
w.isfuzzy = function(a, b, eps, msg) {
|
||||||
|
return isfuzzy(a, b, eps, aFile + " | " + msg);
|
||||||
|
};
|
||||||
w.ok = function(cond, msg) {
|
w.ok = function(cond, msg) {
|
||||||
arguments[1] = aFile + " | " + msg;
|
arguments[1] = aFile + " | " + msg;
|
||||||
// Forward all arguments to SimpleTest.ok where we will check that ok() was
|
// Forward all arguments to SimpleTest.ok where we will check that ok() was
|
||||||
// called with at most 2 arguments.
|
// called with at most 2 arguments.
|
||||||
return SimpleTest.ok.apply(SimpleTest, arguments);
|
return SimpleTest.ok.apply(SimpleTest, arguments);
|
||||||
};
|
};
|
||||||
w.todo_is = function(a, b, msg) { return todo_is(a, b, aFile + " | " + msg); };
|
w.todo_is = function(a, b, msg) {
|
||||||
w.todo = function(cond, msg) { return todo(cond, aFile + " | " + msg); };
|
return todo_is(a, b, aFile + " | " + msg);
|
||||||
|
};
|
||||||
|
w.todo = function(cond, msg) {
|
||||||
|
return todo(cond, aFile + " | " + msg);
|
||||||
|
};
|
||||||
if (test.onload) {
|
if (test.onload) {
|
||||||
w.addEventListener("load", function(e) { test.onload(w); }, { once: true });
|
w.addEventListener(
|
||||||
|
"load",
|
||||||
|
function(e) {
|
||||||
|
test.onload(w);
|
||||||
|
},
|
||||||
|
{ once: true }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
var subtestUrl = location.href.substring(0, location.href.lastIndexOf("/") + 1) + aFile;
|
var subtestUrl =
|
||||||
|
location.href.substring(0, location.href.lastIndexOf("/") + 1) +
|
||||||
|
aFile;
|
||||||
function urlResolves(url) {
|
function urlResolves(url) {
|
||||||
var request = new XMLHttpRequest();
|
var request = new XMLHttpRequest();
|
||||||
request.open("GET", url, false);
|
request.open("GET", url, false);
|
||||||
|
|
@ -336,8 +412,13 @@ function runSubtestsSeriallyInFreshWindows(aSubtests) {
|
||||||
return request.status !== 404;
|
return request.status !== 404;
|
||||||
}
|
}
|
||||||
if (!urlResolves(subtestUrl)) {
|
if (!urlResolves(subtestUrl)) {
|
||||||
SimpleTest.ok(false, "Subtest URL " + subtestUrl + " does not resolve. " +
|
SimpleTest.ok(
|
||||||
"Be sure it's present in the support-files section of mochitest.ini.");
|
false,
|
||||||
|
"Subtest URL " +
|
||||||
|
subtestUrl +
|
||||||
|
" does not resolve. " +
|
||||||
|
"Be sure it's present in the support-files section of mochitest.ini."
|
||||||
|
);
|
||||||
reject();
|
reject();
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
@ -347,7 +428,7 @@ function runSubtestsSeriallyInFreshWindows(aSubtests) {
|
||||||
|
|
||||||
if (test.prefs) {
|
if (test.prefs) {
|
||||||
// Got some prefs for this subtest, push them
|
// Got some prefs for this subtest, push them
|
||||||
SpecialPowers.pushPrefEnv({"set": test.prefs}, function() {
|
SpecialPowers.pushPrefEnv({ set: test.prefs }, function() {
|
||||||
w = spawnTest(test.file);
|
w = spawnTest(test.file);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -362,7 +443,7 @@ function runSubtestsSeriallyInFreshWindows(aSubtests) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function pushPrefs(prefs) {
|
function pushPrefs(prefs) {
|
||||||
return SpecialPowers.pushPrefEnv({"set": prefs});
|
return SpecialPowers.pushPrefEnv({ set: prefs });
|
||||||
}
|
}
|
||||||
|
|
||||||
async function waitUntilApzStable() {
|
async function waitUntilApzStable() {
|
||||||
|
|
@ -379,7 +460,9 @@ async function waitUntilApzStable() {
|
||||||
/* eslint-env mozilla/frame-script */
|
/* eslint-env mozilla/frame-script */
|
||||||
function parentProcessFlush() {
|
function parentProcessFlush() {
|
||||||
function apzFlush() {
|
function apzFlush() {
|
||||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
const { Services } = ChromeUtils.import(
|
||||||
|
"resource://gre/modules/Services.jsm"
|
||||||
|
);
|
||||||
var topWin = Services.wm.getMostRecentWindow("navigator:browser");
|
var topWin = Services.wm.getMostRecentWindow("navigator:browser");
|
||||||
if (!topWin) {
|
if (!topWin) {
|
||||||
topWin = Services.wm.getMostRecentWindow("navigator:geckoview");
|
topWin = Services.wm.getMostRecentWindow("navigator:geckoview");
|
||||||
|
|
@ -393,15 +476,21 @@ async function waitUntilApzStable() {
|
||||||
};
|
};
|
||||||
var flushRepaint = function() {
|
var flushRepaint = function() {
|
||||||
if (topUtils.isMozAfterPaintPending) {
|
if (topUtils.isMozAfterPaintPending) {
|
||||||
topWin.addEventListener("MozAfterPaint", flushRepaint, { once: true });
|
topWin.addEventListener("MozAfterPaint", flushRepaint, {
|
||||||
|
once: true,
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Services.obs.addObserver(repaintDone, "apz-repaints-flushed");
|
Services.obs.addObserver(repaintDone, "apz-repaints-flushed");
|
||||||
if (topUtils.flushApzRepaints()) {
|
if (topUtils.flushApzRepaints()) {
|
||||||
dump("Parent process: flushed APZ repaints, waiting for callback...\n");
|
dump(
|
||||||
|
"Parent process: flushed APZ repaints, waiting for callback...\n"
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
dump("Parent process: flushing APZ repaints was a no-op, triggering callback directly...\n");
|
dump(
|
||||||
|
"Parent process: flushing APZ repaints was a no-op, triggering callback directly...\n"
|
||||||
|
);
|
||||||
repaintDone();
|
repaintDone();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -420,7 +509,9 @@ async function waitUntilApzStable() {
|
||||||
|
|
||||||
// This is the first time waitUntilApzStable is being called, do initialization
|
// This is the first time waitUntilApzStable is being called, do initialization
|
||||||
if (typeof waitUntilApzStable.chromeHelper == "undefined") {
|
if (typeof waitUntilApzStable.chromeHelper == "undefined") {
|
||||||
waitUntilApzStable.chromeHelper = SpecialPowers.loadChromeScript(parentProcessFlush);
|
waitUntilApzStable.chromeHelper = SpecialPowers.loadChromeScript(
|
||||||
|
parentProcessFlush
|
||||||
|
);
|
||||||
ApzCleanup.register(() => {
|
ApzCleanup.register(() => {
|
||||||
waitUntilApzStable.chromeHelper.sendAsyncMessage("cleanup", null);
|
waitUntilApzStable.chromeHelper.sendAsyncMessage("cleanup", null);
|
||||||
waitUntilApzStable.chromeHelper.destroy();
|
waitUntilApzStable.chromeHelper.destroy();
|
||||||
|
|
@ -510,7 +601,10 @@ function runContinuation(testFunction) {
|
||||||
try {
|
try {
|
||||||
driveTest();
|
driveTest();
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
SimpleTest.ok(false, "APZ test continuation failed with exception: " + ex);
|
SimpleTest.ok(
|
||||||
|
false,
|
||||||
|
"APZ test continuation failed with exception: " + ex
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -527,7 +621,10 @@ function runAsyncContinuation(testFunction) {
|
||||||
ret = await asyncContinuation.next();
|
ret = await asyncContinuation.next();
|
||||||
}
|
}
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
SimpleTest.ok(false, "APZ async test continuation failed with exception: " + ex);
|
SimpleTest.ok(
|
||||||
|
false,
|
||||||
|
"APZ async test continuation failed with exception: " + ex
|
||||||
|
);
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -551,7 +648,9 @@ function runAsyncContinuation(testFunction) {
|
||||||
function getSnapshot(rect) {
|
function getSnapshot(rect) {
|
||||||
function parentProcessSnapshot() {
|
function parentProcessSnapshot() {
|
||||||
addMessageListener("snapshot", function(parentRect) {
|
addMessageListener("snapshot", function(parentRect) {
|
||||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
const { Services } = ChromeUtils.import(
|
||||||
|
"resource://gre/modules/Services.jsm"
|
||||||
|
);
|
||||||
var topWin = Services.wm.getMostRecentWindow("navigator:browser");
|
var topWin = Services.wm.getMostRecentWindow("navigator:browser");
|
||||||
if (!topWin) {
|
if (!topWin) {
|
||||||
topWin = Services.wm.getMostRecentWindow("navigator:geckoview");
|
topWin = Services.wm.getMostRecentWindow("navigator:geckoview");
|
||||||
|
|
@ -563,21 +662,36 @@ function getSnapshot(rect) {
|
||||||
parentRect.y -= topWin.mozInnerScreenY;
|
parentRect.y -= topWin.mozInnerScreenY;
|
||||||
|
|
||||||
// take the snapshot
|
// take the snapshot
|
||||||
var canvas = topWin.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
var canvas = topWin.document.createElementNS(
|
||||||
|
"http://www.w3.org/1999/xhtml",
|
||||||
|
"canvas"
|
||||||
|
);
|
||||||
canvas.width = parentRect.w;
|
canvas.width = parentRect.w;
|
||||||
canvas.height = parentRect.h;
|
canvas.height = parentRect.h;
|
||||||
var ctx = canvas.getContext("2d");
|
var ctx = canvas.getContext("2d");
|
||||||
ctx.drawWindow(topWin, parentRect.x, parentRect.y, parentRect.w, parentRect.h,
|
ctx.drawWindow(
|
||||||
|
topWin,
|
||||||
|
parentRect.x,
|
||||||
|
parentRect.y,
|
||||||
|
parentRect.w,
|
||||||
|
parentRect.h,
|
||||||
"rgb(255,255,255)",
|
"rgb(255,255,255)",
|
||||||
ctx.DRAWWINDOW_DRAW_VIEW | ctx.DRAWWINDOW_USE_WIDGET_LAYERS | ctx.DRAWWINDOW_DRAW_CARET);
|
ctx.DRAWWINDOW_DRAW_VIEW |
|
||||||
|
ctx.DRAWWINDOW_USE_WIDGET_LAYERS |
|
||||||
|
ctx.DRAWWINDOW_DRAW_CARET
|
||||||
|
);
|
||||||
return canvas.toDataURL();
|
return canvas.toDataURL();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof getSnapshot.chromeHelper == "undefined") {
|
if (typeof getSnapshot.chromeHelper == "undefined") {
|
||||||
// This is the first time getSnapshot is being called; do initialization
|
// This is the first time getSnapshot is being called; do initialization
|
||||||
getSnapshot.chromeHelper = SpecialPowers.loadChromeScript(parentProcessSnapshot);
|
getSnapshot.chromeHelper = SpecialPowers.loadChromeScript(
|
||||||
ApzCleanup.register(function() { getSnapshot.chromeHelper.destroy(); });
|
parentProcessSnapshot
|
||||||
|
);
|
||||||
|
ApzCleanup.register(function() {
|
||||||
|
getSnapshot.chromeHelper.destroy();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return getSnapshot.chromeHelper.sendQuery("snapshot", JSON.stringify(rect));
|
return getSnapshot.chromeHelper.sendQuery("snapshot", JSON.stringify(rect));
|
||||||
|
|
@ -641,8 +755,8 @@ function injectScript(aScript, aWindow = window) {
|
||||||
function getHitTestConfig() {
|
function getHitTestConfig() {
|
||||||
if (!("hitTestConfig" in window)) {
|
if (!("hitTestConfig" in window)) {
|
||||||
var utils = SpecialPowers.getDOMWindowUtils(window);
|
var utils = SpecialPowers.getDOMWindowUtils(window);
|
||||||
var isWebRender = (utils.layerManagerType == "WebRender");
|
var isWebRender = utils.layerManagerType == "WebRender";
|
||||||
var isWindows = (getPlatform() == "windows");
|
var isWindows = getPlatform() == "windows";
|
||||||
window.hitTestConfig = { utils, isWebRender, isWindows };
|
window.hitTestConfig = { utils, isWebRender, isWindows };
|
||||||
}
|
}
|
||||||
return window.hitTestConfig;
|
return window.hitTestConfig;
|
||||||
|
|
@ -656,7 +770,7 @@ function centerOf(element) {
|
||||||
element = document.getElementById(element);
|
element = document.getElementById(element);
|
||||||
}
|
}
|
||||||
var bounds = element.getBoundingClientRect();
|
var bounds = element.getBoundingClientRect();
|
||||||
return { x: bounds.x + (bounds.width / 2), y: bounds.y + (bounds.height / 2) };
|
return { x: bounds.x + bounds.width / 2, y: bounds.y + bounds.height / 2 };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Peform a compositor hit test at the given point and return the result.
|
// Peform a compositor hit test at the given point and return the result.
|
||||||
|
|
@ -666,11 +780,30 @@ function centerOf(element) {
|
||||||
function hitTest(point) {
|
function hitTest(point) {
|
||||||
var utils = getHitTestConfig().utils;
|
var utils = getHitTestConfig().utils;
|
||||||
dump("Hit-testing point (" + point.x + ", " + point.y + ")\n");
|
dump("Hit-testing point (" + point.x + ", " + point.y + ")\n");
|
||||||
utils.sendMouseEvent("MozMouseHittest", point.x, point.y, 0, 0, 0, true, 0, 0, true, true);
|
utils.sendMouseEvent(
|
||||||
|
"MozMouseHittest",
|
||||||
|
point.x,
|
||||||
|
point.y,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
true,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
true,
|
||||||
|
true
|
||||||
|
);
|
||||||
var data = utils.getCompositorAPZTestData();
|
var data = utils.getCompositorAPZTestData();
|
||||||
ok(data.hitResults.length >= 1, "Expected at least one hit result in the APZTestData");
|
ok(
|
||||||
|
data.hitResults.length >= 1,
|
||||||
|
"Expected at least one hit result in the APZTestData"
|
||||||
|
);
|
||||||
var result = data.hitResults[data.hitResults.length - 1];
|
var result = data.hitResults[data.hitResults.length - 1];
|
||||||
return { hitInfo: result.hitResult, scrollId: result.scrollId, layersId: result.layersId };
|
return {
|
||||||
|
hitInfo: result.hitResult,
|
||||||
|
scrollId: result.scrollId,
|
||||||
|
layersId: result.layersId,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a canonical stringification of the hitInfo bitfield.
|
// Returns a canonical stringification of the hitInfo bitfield.
|
||||||
|
|
@ -693,8 +826,18 @@ function hitInfoToString(hitInfo) {
|
||||||
// Takes an object returned by hitTest, along with the expected values, and
|
// Takes an object returned by hitTest, along with the expected values, and
|
||||||
// asserts that they match. Notably, it uses hitInfoToString to provide a
|
// asserts that they match. Notably, it uses hitInfoToString to provide a
|
||||||
// more useful message for the case that the hit info doesn't match
|
// more useful message for the case that the hit info doesn't match
|
||||||
function checkHitResult(hitResult, expectedHitInfo, expectedScrollId, expectedLayersId, desc) {
|
function checkHitResult(
|
||||||
is(hitInfoToString(hitResult.hitInfo), hitInfoToString(expectedHitInfo), desc + " hit info");
|
hitResult,
|
||||||
|
expectedHitInfo,
|
||||||
|
expectedScrollId,
|
||||||
|
expectedLayersId,
|
||||||
|
desc
|
||||||
|
) {
|
||||||
|
is(
|
||||||
|
hitInfoToString(hitResult.hitInfo),
|
||||||
|
hitInfoToString(expectedHitInfo),
|
||||||
|
desc + " hit info"
|
||||||
|
);
|
||||||
is(hitResult.scrollId, expectedScrollId, desc + " scrollid");
|
is(hitResult.scrollId, expectedScrollId, desc + " scrollid");
|
||||||
is(hitResult.layersId, expectedLayersId, desc + " layersid");
|
is(hitResult.layersId, expectedLayersId, desc + " layersid");
|
||||||
}
|
}
|
||||||
|
|
@ -743,8 +886,12 @@ function hitTestScrollbar(params) {
|
||||||
// coordinates for hit-testing we need to account for this. We assume the
|
// coordinates for hit-testing we need to account for this. We assume the
|
||||||
// buttons are square, and so can use the scrollbar width/height to estimate
|
// buttons are square, and so can use the scrollbar width/height to estimate
|
||||||
// the size of the buttons
|
// the size of the buttons
|
||||||
var scrollbarArrowButtonHeight = config.isWindows ? verticalScrollbarWidth : 0;
|
var scrollbarArrowButtonHeight = config.isWindows
|
||||||
var scrollbarArrowButtonWidth = config.isWindows ? horizontalScrollbarHeight : 0;
|
? verticalScrollbarWidth
|
||||||
|
: 0;
|
||||||
|
var scrollbarArrowButtonWidth = config.isWindows
|
||||||
|
? horizontalScrollbarHeight
|
||||||
|
: 0;
|
||||||
|
|
||||||
// Compute the expected hit result flags.
|
// Compute the expected hit result flags.
|
||||||
// The direction flag (APZHitResultFlags.SCROLLBAR_VERTICAL) is added in
|
// The direction flag (APZHitResultFlags.SCROLLBAR_VERTICAL) is added in
|
||||||
|
|
@ -774,37 +921,51 @@ function hitTestScrollbar(params) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var scrollframeMsg = (params.layerState == LayerState.ACTIVE)
|
var scrollframeMsg =
|
||||||
? "active scrollframe" : "inactive scrollframe";
|
params.layerState == LayerState.ACTIVE
|
||||||
|
? "active scrollframe"
|
||||||
|
: "inactive scrollframe";
|
||||||
|
|
||||||
// Hit-test the targeted areas, assuming we don't have overlay scrollbars
|
// Hit-test the targeted areas, assuming we don't have overlay scrollbars
|
||||||
// with zero dimensions.
|
// with zero dimensions.
|
||||||
if (params.directions.vertical && verticalScrollbarWidth > 0) {
|
if (params.directions.vertical && verticalScrollbarWidth > 0) {
|
||||||
var verticalScrollbarPoint = {
|
var verticalScrollbarPoint = {
|
||||||
x: boundingClientRect.right - (verticalScrollbarWidth / 2),
|
x: boundingClientRect.right - verticalScrollbarWidth / 2,
|
||||||
y: (params.trackLocation == ScrollbarTrackLocation.START)
|
y:
|
||||||
? (boundingClientRect.y + scrollbarArrowButtonHeight + 5)
|
params.trackLocation == ScrollbarTrackLocation.START
|
||||||
: (boundingClientRect.bottom - horizontalScrollbarHeight - scrollbarArrowButtonHeight - 5),
|
? boundingClientRect.y + scrollbarArrowButtonHeight + 5
|
||||||
|
: boundingClientRect.bottom -
|
||||||
|
horizontalScrollbarHeight -
|
||||||
|
scrollbarArrowButtonHeight -
|
||||||
|
5,
|
||||||
};
|
};
|
||||||
checkHitResult(hitTest(verticalScrollbarPoint),
|
checkHitResult(
|
||||||
|
hitTest(verticalScrollbarPoint),
|
||||||
expectedHitInfo | APZHitResultFlags.SCROLLBAR_VERTICAL,
|
expectedHitInfo | APZHitResultFlags.SCROLLBAR_VERTICAL,
|
||||||
params.expectedScrollId,
|
params.expectedScrollId,
|
||||||
params.expectedLayersId,
|
params.expectedLayersId,
|
||||||
scrollframeMsg + " - vertical scrollbar");
|
scrollframeMsg + " - vertical scrollbar"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.directions.horizontal && horizontalScrollbarHeight > 0) {
|
if (params.directions.horizontal && horizontalScrollbarHeight > 0) {
|
||||||
var horizontalScrollbarPoint = {
|
var horizontalScrollbarPoint = {
|
||||||
x: (params.trackLocation == ScrollbarTrackLocation.START)
|
x:
|
||||||
? (boundingClientRect.x + scrollbarArrowButtonWidth + 5)
|
params.trackLocation == ScrollbarTrackLocation.START
|
||||||
: (boundingClientRect.right - verticalScrollbarWidth - scrollbarArrowButtonWidth - 5),
|
? boundingClientRect.x + scrollbarArrowButtonWidth + 5
|
||||||
y: boundingClientRect.bottom - (horizontalScrollbarHeight / 2),
|
: boundingClientRect.right -
|
||||||
|
verticalScrollbarWidth -
|
||||||
|
scrollbarArrowButtonWidth -
|
||||||
|
5,
|
||||||
|
y: boundingClientRect.bottom - horizontalScrollbarHeight / 2,
|
||||||
};
|
};
|
||||||
checkHitResult(hitTest(horizontalScrollbarPoint),
|
checkHitResult(
|
||||||
|
hitTest(horizontalScrollbarPoint),
|
||||||
expectedHitInfo,
|
expectedHitInfo,
|
||||||
params.expectedScrollId,
|
params.expectedScrollId,
|
||||||
params.expectedLayersId,
|
params.expectedLayersId,
|
||||||
scrollframeMsg + " - horizontal scrollbar");
|
scrollframeMsg + " - horizontal scrollbar"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -862,7 +1023,16 @@ var ApzCleanup = {
|
||||||
try {
|
try {
|
||||||
func();
|
func();
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
SimpleTest.ok(false, "Subtest cleanup function [" + func.toString() + "] threw exception [" + ex + "] on page [" + location.href + "]");
|
SimpleTest.ok(
|
||||||
|
false,
|
||||||
|
"Subtest cleanup function [" +
|
||||||
|
func.toString() +
|
||||||
|
"] threw exception [" +
|
||||||
|
ex +
|
||||||
|
"] on page [" +
|
||||||
|
location.href +
|
||||||
|
"]"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
add_task(async function test_main() {
|
add_task(async function test_main() {
|
||||||
function httpURL(filename) {
|
function httpURL(filename) {
|
||||||
let chromeURL = getRootDirectory(gTestPath) + filename;
|
let chromeURL = getRootDirectory(gTestPath) + filename;
|
||||||
return chromeURL.replace("chrome://mochitests/content/", "http://mochi.test:8888/");
|
return chromeURL.replace(
|
||||||
|
"chrome://mochitests/content/",
|
||||||
|
"http://mochi.test:8888/"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var utils = SpecialPowers.getDOMWindowUtils(window);
|
var utils = SpecialPowers.getDOMWindowUtils(window);
|
||||||
var isWebRender = (utils.layerManagerType == "WebRender");
|
var isWebRender = utils.layerManagerType == "WebRender";
|
||||||
|
|
||||||
// Each of these URLs will get opened in a new top-level browser window that
|
// Each of these URLs will get opened in a new top-level browser window that
|
||||||
// is fission-enabled.
|
// is fission-enabled.
|
||||||
|
|
@ -21,12 +24,15 @@ add_task(async function test_main() {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let fissionWindow = await BrowserTestUtils.openNewBrowserWindow({fission: true});
|
let fissionWindow = await BrowserTestUtils.openNewBrowserWindow({
|
||||||
|
fission: true,
|
||||||
|
});
|
||||||
|
|
||||||
// We import the JSM here so that we can install functions on the class
|
// We import the JSM here so that we can install functions on the class
|
||||||
// below.
|
// below.
|
||||||
const { FissionTestHelperParent } = ChromeUtils.import(
|
const { FissionTestHelperParent } = ChromeUtils.import(
|
||||||
getRootDirectory(gTestPath) + "FissionTestHelperParent.jsm");
|
getRootDirectory(gTestPath) + "FissionTestHelperParent.jsm"
|
||||||
|
);
|
||||||
FissionTestHelperParent.SimpleTest = SimpleTest;
|
FissionTestHelperParent.SimpleTest = SimpleTest;
|
||||||
|
|
||||||
ChromeUtils.registerWindowActor("FissionTestHelper", {
|
ChromeUtils.registerWindowActor("FissionTestHelper", {
|
||||||
|
|
@ -36,7 +42,7 @@ add_task(async function test_main() {
|
||||||
child: {
|
child: {
|
||||||
moduleURI: getRootDirectory(gTestPath) + "FissionTestHelperChild.jsm",
|
moduleURI: getRootDirectory(gTestPath) + "FissionTestHelperChild.jsm",
|
||||||
events: {
|
events: {
|
||||||
"DOMWindowCreated": {},
|
DOMWindowCreated: {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
allFrames: true,
|
allFrames: true,
|
||||||
|
|
@ -50,12 +56,15 @@ add_task(async function test_main() {
|
||||||
// completion.
|
// completion.
|
||||||
await BrowserTestUtils.withNewTab(
|
await BrowserTestUtils.withNewTab(
|
||||||
{ gBrowser: fissionWindow.gBrowser, url },
|
{ gBrowser: fissionWindow.gBrowser, url },
|
||||||
async (browser) => {
|
async browser => {
|
||||||
let tabActor = browser.browsingContext.currentWindowGlobal.getActor("FissionTestHelper");
|
let tabActor = browser.browsingContext.currentWindowGlobal.getActor(
|
||||||
|
"FissionTestHelper"
|
||||||
|
);
|
||||||
let donePromise = tabActor.getTestCompletePromise();
|
let donePromise = tabActor.getTestCompletePromise();
|
||||||
tabActor.startTest();
|
tabActor.startTest();
|
||||||
await donePromise;
|
await donePromise;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
dump(`Finished test ${url}\n`);
|
dump(`Finished test ${url}\n`);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,16 @@ function promiseOneEvent(eventType, filter) {
|
||||||
try {
|
try {
|
||||||
success = filter(e);
|
success = filter(e);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
dump(`ERROR: Filter passed to promiseOneEvent threw exception: ${ex}\n`);
|
dump(
|
||||||
|
`ERROR: Filter passed to promiseOneEvent threw exception: ${ex}\n`
|
||||||
|
);
|
||||||
reject();
|
reject();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dump("ERROR: Filter passed to promiseOneEvent was neither null nor a function\n");
|
dump(
|
||||||
|
"ERROR: Filter passed to promiseOneEvent was neither null nor a function\n"
|
||||||
|
);
|
||||||
reject();
|
reject();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -54,14 +58,18 @@ function promiseOneEvent(eventType, filter) {
|
||||||
function loadOOPIFrame(iframeElementId, iframePage) {
|
function loadOOPIFrame(iframeElementId, iframePage) {
|
||||||
return async function() {
|
return async function() {
|
||||||
if (window.location.href.startsWith("https://example.com/")) {
|
if (window.location.href.startsWith("https://example.com/")) {
|
||||||
dump(`WARNING: Calling loadOOPIFrame from ${window.location.href} so the iframe may not be OOP\n`);
|
dump(
|
||||||
|
`WARNING: Calling loadOOPIFrame from ${
|
||||||
|
window.location.href
|
||||||
|
} so the iframe may not be OOP\n`
|
||||||
|
);
|
||||||
ok(false, "Current origin is not example.com:443");
|
ok(false, "Current origin is not example.com:443");
|
||||||
}
|
}
|
||||||
|
|
||||||
let url = "https://example.com/browser/gfx/layers/apz/test/mochitest/" + iframePage;
|
let url =
|
||||||
|
"https://example.com/browser/gfx/layers/apz/test/mochitest/" + iframePage;
|
||||||
let loadPromise = promiseOneEvent("OOPIF:Load", function(e) {
|
let loadPromise = promiseOneEvent("OOPIF:Load", function(e) {
|
||||||
return (typeof e.data.content) == "string" &&
|
return typeof e.data.content == "string" && e.data.content == url;
|
||||||
e.data.content == url;
|
|
||||||
});
|
});
|
||||||
let elem = document.getElementById(iframeElementId);
|
let elem = document.getElementById(iframeElementId);
|
||||||
elem.src = url;
|
elem.src = url;
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,9 @@ function parseDisplayList(lines) {
|
||||||
root = layerObject;
|
root = layerObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
var matches = line.match("(\\s*)(\\w+)\\sp=(\\w+)\\sf=(.*?)\\((.*?)\\)\\s(z=(\\w+)\\s)?(.*?)?( layer=(\\w+))?$");
|
var matches = line.match(
|
||||||
|
"(\\s*)(\\w+)\\sp=(\\w+)\\sf=(.*?)\\((.*?)\\)\\s(z=(\\w+)\\s)?(.*?)?( layer=(\\w+))?$"
|
||||||
|
);
|
||||||
if (!matches) {
|
if (!matches) {
|
||||||
dump("Failed to match: " + line + "\n");
|
dump("Failed to match: " + line + "\n");
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -62,7 +64,8 @@ function parseDisplayList(lines) {
|
||||||
layerObject.contentDescriptor = matches[5];
|
layerObject.contentDescriptor = matches[5];
|
||||||
layerObject.z = matches[7];
|
layerObject.z = matches[7];
|
||||||
var rest = matches[8];
|
var rest = matches[8];
|
||||||
if (matches[10]) { // WrapList don't provide a layer
|
if (matches[10]) {
|
||||||
|
// WrapList don't provide a layer
|
||||||
layerObject.layer = matches[10];
|
layerObject.layer = matches[10];
|
||||||
}
|
}
|
||||||
layerObject.rest = rest;
|
layerObject.rest = rest;
|
||||||
|
|
@ -115,9 +118,12 @@ function getDataURI(str) {
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
var matches = str.match("data:image/lz4bgra;base64,([0-9]+),([0-9]+),([0-9]+),(.*)");
|
var matches = str.match(
|
||||||
if (!matches)
|
"data:image/lz4bgra;base64,([0-9]+),([0-9]+),([0-9]+),(.*)"
|
||||||
|
);
|
||||||
|
if (!matches) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var canvas = document.createElement("canvas");
|
var canvas = document.createElement("canvas");
|
||||||
var w = parseInt(matches[1]);
|
var w = parseInt(matches[1]);
|
||||||
|
|
@ -212,8 +218,10 @@ function parseLayers(layersDumpLines) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var rect = [
|
var rect = [
|
||||||
parseFloat(rectMatches[1]), parseFloat(rectMatches[2]),
|
parseFloat(rectMatches[1]),
|
||||||
parseFloat(rectMatches[3]), parseFloat(rectMatches[4]),
|
parseFloat(rectMatches[2]),
|
||||||
|
parseFloat(rectMatches[3]),
|
||||||
|
parseFloat(rectMatches[4]),
|
||||||
];
|
];
|
||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
@ -228,14 +236,18 @@ function parseLayers(layersDumpLines) {
|
||||||
var region = [];
|
var region = [];
|
||||||
str = trim(str.substring(1, str.length - 1));
|
str = trim(str.substring(1, str.length - 1));
|
||||||
while (str != "") {
|
while (str != "") {
|
||||||
var rectMatches = str.match("^\\(x=(.*?), y=(.*?), w=(.*?), h=(.*?)\\);(.*)$");
|
var rectMatches = str.match(
|
||||||
|
"^\\(x=(.*?), y=(.*?), w=(.*?), h=(.*?)\\);(.*)$"
|
||||||
|
);
|
||||||
if (!rectMatches) {
|
if (!rectMatches) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var rect = [
|
var rect = [
|
||||||
parseFloat(rectMatches[1]), parseFloat(rectMatches[2]),
|
parseFloat(rectMatches[1]),
|
||||||
parseFloat(rectMatches[3]), parseFloat(rectMatches[4]),
|
parseFloat(rectMatches[2]),
|
||||||
|
parseFloat(rectMatches[3]),
|
||||||
|
parseFloat(rectMatches[4]),
|
||||||
];
|
];
|
||||||
str = trim(rectMatches[5]);
|
str = trim(rectMatches[5]);
|
||||||
region.push(rect);
|
region.push(rect);
|
||||||
|
|
@ -271,16 +283,21 @@ function parseLayers(layersDumpLines) {
|
||||||
var surfaceMatches = line.match("(\\s*)Surface: (.*)");
|
var surfaceMatches = line.match("(\\s*)Surface: (.*)");
|
||||||
if (surfaceMatches) {
|
if (surfaceMatches) {
|
||||||
let indentation = Math.floor(matches[1].length / 2);
|
let indentation = Math.floor(matches[1].length / 2);
|
||||||
let parent = objectAtIndentation[indentation - 1] || objectAtIndentation[indentation - 2];
|
let parent =
|
||||||
|
objectAtIndentation[indentation - 1] ||
|
||||||
|
objectAtIndentation[indentation - 2];
|
||||||
|
|
||||||
var surfaceURI = surfaceMatches[2];
|
var surfaceURI = surfaceMatches[2];
|
||||||
if (parent.surfaceURI != null) {
|
if (parent.surfaceURI != null) {
|
||||||
console.log("error: surfaceURI already set for this layer " + parent.line);
|
console.log(
|
||||||
|
"error: surfaceURI already set for this layer " + parent.line
|
||||||
|
);
|
||||||
}
|
}
|
||||||
parent.surfaceURI = surfaceURI;
|
parent.surfaceURI = surfaceURI;
|
||||||
|
|
||||||
// Look for the buffer-rect offset
|
// Look for the buffer-rect offset
|
||||||
var contentHostLine = layersDumpLines[i - 2].name || layersDumpLines[i - 2];
|
var contentHostLine =
|
||||||
|
layersDumpLines[i - 2].name || layersDumpLines[i - 2];
|
||||||
let matches = contentHostLine.match(LAYERS_LINE_REGEX);
|
let matches = contentHostLine.match(LAYERS_LINE_REGEX);
|
||||||
if (matches) {
|
if (matches) {
|
||||||
var contentHostRest = matches[4];
|
var contentHostRest = matches[4];
|
||||||
|
|
@ -304,11 +321,13 @@ function parseLayers(layersDumpLines) {
|
||||||
continue; // Something like a texturehost dump. Safe to ignore
|
continue; // Something like a texturehost dump. Safe to ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matches[2].includes("TiledContentHost") ||
|
if (
|
||||||
|
matches[2].includes("TiledContentHost") ||
|
||||||
matches[2].includes("ContentHost") ||
|
matches[2].includes("ContentHost") ||
|
||||||
matches[2].includes("ContentClient") ||
|
matches[2].includes("ContentClient") ||
|
||||||
matches[2].includes("MemoryTextureHost") ||
|
matches[2].includes("MemoryTextureHost") ||
|
||||||
matches[2].includes("ImageHost")) {
|
matches[2].includes("ImageHost")
|
||||||
|
) {
|
||||||
continue; // We're already pretty good at visualizing these
|
continue; // We're already pretty good at visualizing these
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -414,10 +433,15 @@ function parseLayers(layersDumpLines) {
|
||||||
// Compute screenTransformX/screenTransformY
|
// Compute screenTransformX/screenTransformY
|
||||||
// TODO Fully support transforms
|
// TODO Fully support transforms
|
||||||
if (layerObject["shadow-transform"] && layerObject.transform) {
|
if (layerObject["shadow-transform"] && layerObject.transform) {
|
||||||
layerObject["screen-transform"] = [layerObject["shadow-transform"][2][0], layerObject["shadow-transform"][2][1]];
|
layerObject["screen-transform"] = [
|
||||||
|
layerObject["shadow-transform"][2][0],
|
||||||
|
layerObject["shadow-transform"][2][1],
|
||||||
|
];
|
||||||
var currIndentation = indentation - 1;
|
var currIndentation = indentation - 1;
|
||||||
while (currIndentation >= 0) {
|
while (currIndentation >= 0) {
|
||||||
var transform = objectAtIndentation[currIndentation]["shadow-transform"] || objectAtIndentation[currIndentation].transform;
|
var transform =
|
||||||
|
objectAtIndentation[currIndentation]["shadow-transform"] ||
|
||||||
|
objectAtIndentation[currIndentation].transform;
|
||||||
if (transform) {
|
if (transform) {
|
||||||
layerObject["screen-transform"][0] += transform[2][0];
|
layerObject["screen-transform"][0] += transform[2][0];
|
||||||
layerObject["screen-transform"][1] += transform[2][1];
|
layerObject["screen-transform"][1] += transform[2][1];
|
||||||
|
|
@ -432,7 +456,15 @@ function parseLayers(layersDumpLines) {
|
||||||
// dump("OBJECTS: " + JSON.stringify(root) + "\n");
|
// dump("OBJECTS: " + JSON.stringify(root) + "\n");
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
function populateLayers(root, displayList, pane, previewParent, hasSeenRoot, contentScale, rootPreviewParent) {
|
function populateLayers(
|
||||||
|
root,
|
||||||
|
displayList,
|
||||||
|
pane,
|
||||||
|
previewParent,
|
||||||
|
hasSeenRoot,
|
||||||
|
contentScale,
|
||||||
|
rootPreviewParent
|
||||||
|
) {
|
||||||
contentScale = contentScale || 1;
|
contentScale = contentScale || 1;
|
||||||
rootPreviewParent = rootPreviewParent || previewParent;
|
rootPreviewParent = rootPreviewParent || previewParent;
|
||||||
|
|
||||||
|
|
@ -521,7 +553,8 @@ function populateLayers(root, displayList, pane, previewParent, hasSeenRoot, con
|
||||||
});
|
});
|
||||||
layerViewportMatrix[4] += -clip[0];
|
layerViewportMatrix[4] += -clip[0];
|
||||||
layerViewportMatrix[5] += -clip[1];
|
layerViewportMatrix[5] += -clip[1];
|
||||||
layerViewport.style.transform = "translate(-" + clip[0] + "px, -" + clip[1] + "px)";
|
layerViewport.style.transform =
|
||||||
|
"translate(-" + clip[0] + "px, -" + clip[1] + "px)";
|
||||||
}
|
}
|
||||||
if (root["shadow-transform"] || root.transform) {
|
if (root["shadow-transform"] || root.transform) {
|
||||||
var matrix = root["shadow-transform"] || root.transform;
|
var matrix = root["shadow-transform"] || root.transform;
|
||||||
|
|
@ -532,10 +565,24 @@ function populateLayers(root, displayList, pane, previewParent, hasSeenRoot, con
|
||||||
layerViewportMatrix[4] += matrix[2][0];
|
layerViewportMatrix[4] += matrix[2][0];
|
||||||
layerViewportMatrix[5] += matrix[2][1];
|
layerViewportMatrix[5] += matrix[2][1];
|
||||||
}
|
}
|
||||||
layerViewport.style.transform = "matrix(" + layerViewportMatrix[0] + "," + layerViewportMatrix[1] + "," + layerViewportMatrix[2] + "," + layerViewportMatrix[3] + "," + layerViewportMatrix[4] + "," + layerViewportMatrix[5] + ")";
|
layerViewport.style.transform =
|
||||||
|
"matrix(" +
|
||||||
|
layerViewportMatrix[0] +
|
||||||
|
"," +
|
||||||
|
layerViewportMatrix[1] +
|
||||||
|
"," +
|
||||||
|
layerViewportMatrix[2] +
|
||||||
|
"," +
|
||||||
|
layerViewportMatrix[3] +
|
||||||
|
"," +
|
||||||
|
layerViewportMatrix[4] +
|
||||||
|
"," +
|
||||||
|
layerViewportMatrix[5] +
|
||||||
|
")";
|
||||||
if (!hasSeenRoot) {
|
if (!hasSeenRoot) {
|
||||||
hasSeenRoot = true;
|
hasSeenRoot = true;
|
||||||
layerViewport.style.transform = "scale(" + 1 / contentScale + "," + 1 / contentScale + ")";
|
layerViewport.style.transform =
|
||||||
|
"scale(" + 1 / contentScale + "," + 1 / contentScale + ")";
|
||||||
}
|
}
|
||||||
if (clipElem) {
|
if (clipElem) {
|
||||||
previewParent.appendChild(clipElem);
|
previewParent.appendChild(clipElem);
|
||||||
|
|
@ -557,14 +604,19 @@ function populateLayers(root, displayList, pane, previewParent, hasSeenRoot, con
|
||||||
height: rect2d[3] + "px",
|
height: rect2d[3] + "px",
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
border: "solid 1px black",
|
border: "solid 1px black",
|
||||||
background: 'url("noise.png"), linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.2))',
|
background:
|
||||||
|
'url("noise.png"), linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.2))',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
layerViewport.appendChild(layerPreview);
|
layerViewport.appendChild(layerPreview);
|
||||||
|
|
||||||
function isInside(rect1, rect2) {
|
function isInside(rect1, rect2) {
|
||||||
if (rect1[0] + rect1[2] < rect2[0] && rect2[0] + rect2[2] < rect1[0] &&
|
if (
|
||||||
rect1[1] + rect1[3] < rect2[1] && rect2[1] + rect2[3] < rect1[1]) {
|
rect1[0] + rect1[2] < rect2[0] &&
|
||||||
|
rect2[0] + rect2[2] < rect1[0] &&
|
||||||
|
rect1[1] + rect1[3] < rect2[1] &&
|
||||||
|
rect2[1] + rect2[3] < rect1[1]
|
||||||
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -583,8 +635,8 @@ function populateLayers(root, displayList, pane, previewParent, hasSeenRoot, con
|
||||||
src: getDataURI(root.tiles[x][y]),
|
src: getDataURI(root.tiles[x][y]),
|
||||||
style: {
|
style: {
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
left: (x - previewOffset[0]) + "px",
|
left: x - previewOffset[0] + "px",
|
||||||
top: (y - previewOffset[1]) + "px",
|
top: y - previewOffset[1] + "px",
|
||||||
pointerEvents: "auto",
|
pointerEvents: "auto",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
@ -605,8 +657,8 @@ function populateLayers(root, displayList, pane, previewParent, hasSeenRoot, con
|
||||||
src: getDataURI(root.surfaceURI),
|
src: getDataURI(root.surfaceURI),
|
||||||
style: {
|
style: {
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
left: (offsetX - previewOffset[0]) + "px",
|
left: offsetX - previewOffset[0] + "px",
|
||||||
top: (offsetY - previewOffset[1]) + "px",
|
top: offsetY - previewOffset[1] + "px",
|
||||||
pointerEvents: "auto",
|
pointerEvents: "auto",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
@ -614,7 +666,16 @@ function populateLayers(root, displayList, pane, previewParent, hasSeenRoot, con
|
||||||
layerPreview.style.background = "";
|
layerPreview.style.background = "";
|
||||||
} else if (root.color) {
|
} else if (root.color) {
|
||||||
hasImg = true;
|
hasImg = true;
|
||||||
layerPreview.style.background = "rgba(" + root.color.r + ", " + root.color.g + ", " + root.color.b + ", " + root.color.a + ")";
|
layerPreview.style.background =
|
||||||
|
"rgba(" +
|
||||||
|
root.color.r +
|
||||||
|
", " +
|
||||||
|
root.color.g +
|
||||||
|
", " +
|
||||||
|
root.color.b +
|
||||||
|
", " +
|
||||||
|
root.color.a +
|
||||||
|
")";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasImg || true) {
|
if (hasImg || true) {
|
||||||
|
|
@ -649,13 +710,28 @@ function populateLayers(root, displayList, pane, previewParent, hasSeenRoot, con
|
||||||
} else {
|
} else {
|
||||||
description += "Content: Unknown";
|
description += "Content: Unknown";
|
||||||
}
|
}
|
||||||
description += "<br>Item: " + this.displayItem.name + " (" + this.displayItem.address + ")";
|
description +=
|
||||||
description += "<br>Layer: " + root.name + " (" + root.address + ")";
|
"<br>Item: " +
|
||||||
|
this.displayItem.name +
|
||||||
|
" (" +
|
||||||
|
this.displayItem.address +
|
||||||
|
")";
|
||||||
|
description +=
|
||||||
|
"<br>Layer: " + root.name + " (" + root.address + ")";
|
||||||
if (this.displayItem.frame) {
|
if (this.displayItem.frame) {
|
||||||
description += "<br>Frame: " + this.displayItem.frame;
|
description += "<br>Frame: " + this.displayItem.frame;
|
||||||
}
|
}
|
||||||
if (this.displayItem.layerBounds) {
|
if (this.displayItem.layerBounds) {
|
||||||
description += "<br>Bounds: [" + toFixed(this.displayItem.layerBounds[0] / 60, 2) + ", " + toFixed(this.displayItem.layerBounds[1] / 60, 2) + ", " + toFixed(this.displayItem.layerBounds[2] / 60, 2) + ", " + toFixed(this.displayItem.layerBounds[3] / 60, 2) + "] (CSS Pixels)";
|
description +=
|
||||||
|
"<br>Bounds: [" +
|
||||||
|
toFixed(this.displayItem.layerBounds[0] / 60, 2) +
|
||||||
|
", " +
|
||||||
|
toFixed(this.displayItem.layerBounds[1] / 60, 2) +
|
||||||
|
", " +
|
||||||
|
toFixed(this.displayItem.layerBounds[2] / 60, 2) +
|
||||||
|
", " +
|
||||||
|
toFixed(this.displayItem.layerBounds[3] / 60, 2) +
|
||||||
|
"] (CSS Pixels)";
|
||||||
}
|
}
|
||||||
if (this.displayItem.z) {
|
if (this.displayItem.z) {
|
||||||
description += "<br>Z: " + this.displayItem.z;
|
description += "<br>Z: " + this.displayItem.z;
|
||||||
|
|
@ -670,7 +746,11 @@ function populateLayers(root, displayList, pane, previewParent, hasSeenRoot, con
|
||||||
className: "csstooltip",
|
className: "csstooltip",
|
||||||
innerHTML: description,
|
innerHTML: description,
|
||||||
style: {
|
style: {
|
||||||
top: Math.min(box.bottom, document.documentElement.clientHeight - 150) + "px",
|
top:
|
||||||
|
Math.min(
|
||||||
|
box.bottom,
|
||||||
|
document.documentElement.clientHeight - 150
|
||||||
|
) + "px",
|
||||||
left: box.left + "px",
|
left: box.left + "px",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
@ -699,7 +779,8 @@ function populateLayers(root, displayList, pane, previewParent, hasSeenRoot, con
|
||||||
// bounds doesn't adjust for within the layer. It's not a bad fallback but
|
// bounds doesn't adjust for within the layer. It's not a bad fallback but
|
||||||
// will have the wrong offset
|
// will have the wrong offset
|
||||||
let rect2d = displayItem.layerBounds || displayItem.bounds;
|
let rect2d = displayItem.layerBounds || displayItem.bounds;
|
||||||
if (rect2d) { // This doesn't place them corectly
|
if (rect2d) {
|
||||||
|
// This doesn't place them corectly
|
||||||
var appUnitsToPixels = 60 / contentScale;
|
var appUnitsToPixels = 60 / contentScale;
|
||||||
let diPreview = createElement("div", {
|
let diPreview = createElement("div", {
|
||||||
id: "displayitem_" + displayItem.content + "_" + displayItem.address,
|
id: "displayitem_" + displayItem.content + "_" + displayItem.address,
|
||||||
|
|
@ -729,7 +810,15 @@ function populateLayers(root, displayList, pane, previewParent, hasSeenRoot, con
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < root.children.length; i++) {
|
for (var i = 0; i < root.children.length; i++) {
|
||||||
populateLayers(root.children[i], displayList, pane, previewParent, hasSeenRoot, contentScale, rootPreviewParent);
|
populateLayers(
|
||||||
|
root.children[i],
|
||||||
|
displayList,
|
||||||
|
pane,
|
||||||
|
previewParent,
|
||||||
|
hasSeenRoot,
|
||||||
|
contentScale,
|
||||||
|
rootPreviewParent
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -796,7 +885,7 @@ function parseMultiLineDump(log) {
|
||||||
display: "block",
|
display: "block",
|
||||||
},
|
},
|
||||||
href: "#",
|
href: "#",
|
||||||
textContent: "LayerTree " + (frameID++),
|
textContent: "LayerTree " + frameID++,
|
||||||
onclick() {
|
onclick() {
|
||||||
contents.innerHTML = "";
|
contents.innerHTML = "";
|
||||||
var matchLines = matches[i].split("\n");
|
var matchLines = matches[i].split("\n");
|
||||||
|
|
@ -829,7 +918,9 @@ function parseDump(log, displayList, compositeTitle, compositeTime) {
|
||||||
style: {
|
style: {
|
||||||
width: "100%",
|
width: "100%",
|
||||||
},
|
},
|
||||||
textContent: compositeTitle + (compositeTitle ? " (near " + compositeTime.toFixed(0) + " ms)" : ""),
|
textContent:
|
||||||
|
compositeTitle +
|
||||||
|
(compositeTitle ? " (near " + compositeTime.toFixed(0) + " ms)" : ""),
|
||||||
});
|
});
|
||||||
container.appendChild(titleDiv);
|
container.appendChild(titleDiv);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,14 @@ add_task(async function test_windowlessBrowserTroubleshootCrash() {
|
||||||
let docShell = webNav.docShell;
|
let docShell = webNav.docShell;
|
||||||
let listener = {
|
let listener = {
|
||||||
observe(contentWindow, topic, data) {
|
observe(contentWindow, topic, data) {
|
||||||
let observedDocShell = contentWindow.docShell
|
let observedDocShell = contentWindow.docShell.sameTypeRootTreeItem.QueryInterface(
|
||||||
.sameTypeRootTreeItem
|
Ci.nsIDocShell
|
||||||
.QueryInterface(Ci.nsIDocShell);
|
);
|
||||||
if (docShell === observedDocShell) {
|
if (docShell === observedDocShell) {
|
||||||
Services.obs.removeObserver(listener, "content-document-global-created");
|
Services.obs.removeObserver(
|
||||||
|
listener,
|
||||||
|
"content-document-global-created"
|
||||||
|
);
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -25,21 +28,31 @@ add_task(async function test_windowlessBrowserTroubleshootCrash() {
|
||||||
|
|
||||||
let winUtils = webNav.document.defaultView.windowUtils;
|
let winUtils = webNav.document.defaultView.windowUtils;
|
||||||
try {
|
try {
|
||||||
is(winUtils.layerManagerType, "Basic", "windowless browser's layerManagerType should be 'Basic'");
|
is(
|
||||||
|
winUtils.layerManagerType,
|
||||||
|
"Basic",
|
||||||
|
"windowless browser's layerManagerType should be 'Basic'"
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// The windowless browser may not have a layermanager at all yet, and that's ok.
|
// The windowless browser may not have a layermanager at all yet, and that's ok.
|
||||||
// The troubleshooting code similarly skips over windows with no layer managers.
|
// The troubleshooting code similarly skips over windows with no layer managers.
|
||||||
}
|
}
|
||||||
ok(true, "not crashed");
|
ok(true, "not crashed");
|
||||||
|
|
||||||
var Troubleshoot = ChromeUtils.import("resource://gre/modules/Troubleshoot.jsm", {}).Troubleshoot;
|
var Troubleshoot = ChromeUtils.import(
|
||||||
|
"resource://gre/modules/Troubleshoot.jsm",
|
||||||
|
{}
|
||||||
|
).Troubleshoot;
|
||||||
var data = await new Promise((resolve, reject) => {
|
var data = await new Promise((resolve, reject) => {
|
||||||
Troubleshoot.snapshot((data) => {
|
Troubleshoot.snapshot(data => {
|
||||||
resolve(data);
|
resolve(data);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
ok(data.graphics.windowLayerManagerType !== "None", "windowless browser window should not set windowLayerManagerType to 'None'");
|
ok(
|
||||||
|
data.graphics.windowLayerManagerType !== "None",
|
||||||
|
"windowless browser window should not set windowLayerManagerType to 'None'"
|
||||||
|
);
|
||||||
|
|
||||||
webNav.close();
|
webNav.close();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue