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:
Victor Porof 2019-07-05 10:46:28 +02:00
parent 5af464dcc4
commit 85064fe4c3
10 changed files with 844 additions and 286 deletions

View file

@ -45,7 +45,6 @@ module.exports = {
"overrides": [{
"files": [
"devtools/**",
"gfx/**",
"gradle/**",
"hal/**",
"image/**",

View file

@ -40,7 +40,6 @@ toolkit/components/telemetry/datareporting-prefs.js
toolkit/components/telemetry/healthreport-prefs.js
# Ignore all top-level directories for now.
gfx/**
gradle/**
hal/**
image/**

View file

@ -27,27 +27,36 @@ class FissionTestHelperChild extends JSWindowActorChild {
// namespace.
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" });
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(
(resolve) => {
this._startTestPromiseResolver = resolve;
},
cw));
let FissionTestHelper = Cu.createObjectIn(cw, {
defineAs: "FissionTestHelper",
});
FissionTestHelper.startTestPromise = new cw.Promise(
Cu.exportFunction(resolve => {
this._startTestPromiseResolver = resolve;
}, cw)
);
Cu.exportFunction(this.subtestDone.bind(this),
FissionTestHelper, { defineAs: "subtestDone" });
Cu.exportFunction(this.subtestDone.bind(this), FissionTestHelper, {
defineAs: "subtestDone",
});
Cu.exportFunction(this.sendToOopif.bind(this),
FissionTestHelper, { defineAs: "sendToOopif" });
Cu.exportFunction(this.fireEventInEmbedder.bind(this),
FissionTestHelper, { defineAs: "fireEventInEmbedder" });
Cu.exportFunction(this.sendToOopif.bind(this), FissionTestHelper, {
defineAs: "sendToOopif",
});
Cu.exportFunction(this.fireEventInEmbedder.bind(this), FissionTestHelper, {
defineAs: "fireEventInEmbedder",
});
}
// 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 cw = this.cw();
let responsePromise = new cw.Promise(
Cu.exportFunction(
(resolve) => {
this._oopifResponsePromiseResolvers[msgId] = resolve;
},
cw));
this.sendAsyncMessage("EmbedderToOopif", {browsingContextId, msgId, stringToEval});
Cu.exportFunction(resolve => {
this._oopifResponsePromiseResolvers[msgId] = resolve;
}, cw)
);
this.sendAsyncMessage("EmbedderToOopif", {
browsingContextId,
msgId,
stringToEval,
});
return responsePromise;
}
@ -81,7 +93,7 @@ class FissionTestHelperChild extends JSWindowActorChild {
// things that happen. The embedder can use promiseOneEvent from
// helper_fission_utils.js to listen for these events.
fireEventInEmbedder(eventType, data) {
this.sendAsyncMessage("OopifToEmbedder", {eventType, data});
this.sendAsyncMessage("OopifToEmbedder", { eventType, data });
}
handleEvent(evt) {
@ -91,7 +103,9 @@ class FissionTestHelperChild extends JSWindowActorChild {
// is fired by the content. See comments in fission_subtest_init().
// Once bug 1557486 is fixed we can just register the FissionTestHelper:Init
// event directly instead of DOMWindowCreated.
this.contentWindow.addEventListener("FissionTestHelper:Init", this, { wantUntrusted: true });
this.contentWindow.addEventListener("FissionTestHelper:Init", this, {
wantUntrusted: true,
});
break;
case "FissionTestHelper:Init":
this.initialize();
@ -107,14 +121,23 @@ class FissionTestHelperChild extends JSWindowActorChild {
break;
case "FromEmbedder":
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;
case "FromOopif":
if (typeof msg.data.msgId == "number") {
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];
} else if (typeof msg.data.eventType == "string") {
let cw = this.cw();
@ -122,7 +145,11 @@ class FissionTestHelperChild extends JSWindowActorChild {
event.data = Cu.cloneInto(msg.data.data, cw);
this.contentWindow.dispatchEvent(event);
} 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;
}

View file

@ -11,7 +11,7 @@ var EXPORTED_SYMBOLS = ["FissionTestHelperParent"];
class FissionTestHelperParent extends JSWindowActorParent {
constructor() {
super();
this._testCompletePromise = new Promise((resolve) => {
this._testCompletePromise = new Promise(resolve => {
this._testCompletePromiseResolver = resolve;
});
}
@ -42,11 +42,18 @@ class FissionTestHelperParent extends JSWindowActorParent {
receiveMessage(msg) {
switch (msg.name) {
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;
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;
case "Test:Complete":
@ -56,14 +63,24 @@ class FissionTestHelperParent extends JSWindowActorParent {
case "EmbedderToOopif":
// This relays messages from the embedder to an OOP-iframe. The browsing
// 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) {
FissionTestHelperParent.SimpleTest.ok(false, "EmbedderToOopif couldn't find oopif");
FissionTestHelperParent.SimpleTest.ok(
false,
"EmbedderToOopif couldn't find oopif"
);
break;
}
let oopifActor = oopifBrowsingContext.currentWindowGlobal.getActor("FissionTestHelper");
let oopifActor = oopifBrowsingContext.currentWindowGlobal.getActor(
"FissionTestHelper"
);
if (!oopifActor) {
FissionTestHelperParent.SimpleTest.ok(false, "EmbedderToOopif couldn't find oopif actor");
FissionTestHelperParent.SimpleTest.ok(
false,
"EmbedderToOopif couldn't find oopif actor"
);
break;
}
oopifActor.sendAsyncMessage("FromEmbedder", msg.data);
@ -74,7 +91,10 @@ class FissionTestHelperParent extends JSWindowActorParent {
// window which is embedding it.
let embedderActor = this.embedderWindow().getActor("FissionTestHelper");
if (!embedderActor) {
FissionTestHelperParent.SimpleTest.ok(false, "OopifToEmbedder couldn't find embedder");
FissionTestHelperParent.SimpleTest.ok(
false,
"OopifToEmbedder couldn't find embedder"
);
break;
}
embedderActor.sendAsyncMessage("FromOopif", msg.data);

View file

@ -28,20 +28,30 @@ function getPlatform() {
function nativeVerticalWheelEventMsg() {
switch (getPlatform()) {
case "windows": return 0x020A; // WM_MOUSEWHEEL
case "mac": return 0; // value is unused, can be anything
case "linux": return 4; // value is unused, pass GDK_SCROLL_SMOOTH anyway
case "windows":
return 0x020a; // WM_MOUSEWHEEL
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() {
switch (getPlatform()) {
case "windows": return 0x020E; // WM_MOUSEHWHEEL
case "mac": return 0; // value is unused, can be anything
case "linux": return 4; // value is unused, pass GDK_SCROLL_SMOOTH anyway
case "windows":
return 0x020e; // WM_MOUSEHWHEEL
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.
@ -72,7 +82,9 @@ function nativeScrollUnits(aTarget, aDimen) {
// GTK deltas are treated as line height divided by 3 by gecko.
var targetWindow = windowForTarget(aTarget);
var targetElement = elementForTarget(aTarget);
var lineHeight = targetWindow.getComputedStyle(targetElement)["font-size"];
var lineHeight = targetWindow.getComputedStyle(targetElement)[
"font-size"
];
return aDimen / (parseInt(lineHeight) * 3);
}
}
@ -81,38 +93,57 @@ function nativeScrollUnits(aTarget, aDimen) {
function nativeMouseDownEventMsg() {
switch (getPlatform()) {
case "windows": return 2; // MOUSEEVENTF_LEFTDOWN
case "mac": return 1; // NSLeftMouseDown
case "linux": return 4; // GDK_BUTTON_PRESS
case "android": return 5; // ACTION_POINTER_DOWN
case "windows":
return 2; // MOUSEEVENTF_LEFTDOWN
case "mac":
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() {
switch (getPlatform()) {
case "windows": return 1; // MOUSEEVENTF_MOVE
case "mac": return 5; // NSMouseMoved
case "linux": return 3; // GDK_MOTION_NOTIFY
case "android": return 7; // ACTION_HOVER_MOVE
case "windows":
return 1; // MOUSEEVENTF_MOVE
case "mac":
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() {
switch (getPlatform()) {
case "windows": return 4; // MOUSEEVENTF_LEFTUP
case "mac": return 2; // NSLeftMouseUp
case "linux": return 7; // GDK_BUTTON_RELEASE
case "android": return 6; // ACTION_POINTER_UP
case "windows":
return 4; // MOUSEEVENTF_LEFTUP
case "mac":
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) {
let utils = SpecialPowers.getDOMWindowUtils(window);
var rect = aElement.getBoundingClientRect();
var offsetX = {}, offsetY = {};
var offsetX = {},
offsetY = {};
// TODO: Audit whether these offset values are correct or not for
// position:fixed elements especially in the case where the visual viewport
// offset is not 0.
@ -135,14 +166,19 @@ function coordinatesRelativeToScreen(aX, aY, aTarget) {
var targetWindow = windowForTarget(aTarget);
var deviceScale = targetWindow.devicePixelRatio;
var resolution = getResolution();
var rect = (aTarget instanceof Window)
? {left: 0, top: 0} /* we don't use the width or height */
: getBoundingClientRectRelativeToVisualViewport(aTarget);
var rect =
aTarget instanceof Window
? { left: 0, top: 0 } /* we don't use the width or height */
: getBoundingClientRectRelativeToVisualViewport(aTarget);
// moxInnerScreen{X,Y} are in CSS coordinates of the browser chrome.
// The device scale applies to them, but the resolution only zooms the content.
return {
x: (targetWindow.mozInnerScreenX + ((rect.left + aX) * resolution)) * deviceScale,
y: (targetWindow.mozInnerScreenY + ((rect.top + aY) * resolution)) * deviceScale,
x:
(targetWindow.mozInnerScreenX + (rect.left + aX) * resolution) *
deviceScale,
y:
(targetWindow.mozInnerScreenY + (rect.top + aY) * resolution) *
deviceScale,
};
}
@ -155,8 +191,8 @@ function rectRelativeToScreen(aElement) {
return {
x: (targetWindow.mozInnerScreenX + rect.left) * scale,
y: (targetWindow.mozInnerScreenY + rect.top) * scale,
w: (rect.width * scale),
h: (rect.height * scale),
w: rect.width * scale,
h: rect.height * scale,
};
}
@ -169,14 +205,29 @@ function rectRelativeToScreen(aElement) {
function synthesizeNativeWheel(aTarget, aX, aY, aDeltaX, aDeltaY, aObserver) {
var pt = coordinatesRelativeToScreen(aX, aY, aTarget);
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);
aDeltaY = nativeScrollUnits(aTarget, aDeltaY);
var msg = aDeltaX ? nativeHorizontalWheelEventMsg() : nativeVerticalWheelEventMsg();
var msg = aDeltaX
? nativeHorizontalWheelEventMsg()
: nativeVerticalWheelEventMsg();
var utils = utilsForTarget(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;
}
@ -184,7 +235,14 @@ function synthesizeNativeWheel(aTarget, aX, aY, aDeltaX, aDeltaY, aObserver) {
// request has been successfully made to the OS. This does not necessarily
// guarantee that the OS generates the event we requested. See
// synthesizeNativeWheel for details on the parameters.
function synthesizeNativeWheelAndWaitForObserver(aElement, aX, aY, aDeltaX, aDeltaY, aCallback) {
function synthesizeNativeWheelAndWaitForObserver(
aElement,
aX,
aY,
aDeltaX,
aDeltaY,
aCallback
) {
var observer = {
observe(aSubject, aTopic, aData) {
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
// subdocument (or the subdocument's window). See synthesizeNativeWheel for
// 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);
targetWindow.addEventListener("wheel", function(e) {
setTimeout(aCallback, 0);
}, {once: true});
targetWindow.addEventListener(
"wheel",
function(e) {
setTimeout(aCallback, 0);
},
{ once: true }
);
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
// the subdocument (or the subdocument's window). See synthesizeNativeWheel
// 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);
targetWindow.addEventListener("scroll", function() {
setTimeout(aCallback, 0);
}, {capture: true, once: true}); // scroll events don't always bubble
targetWindow.addEventListener(
"scroll",
function() {
setTimeout(aCallback, 0);
},
{ capture: true, once: true }
); // scroll events don't always bubble
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
// subdocument (or the subdocument window). See synthesizeNativeMouseMove for
// details on the other parameters.
function synthesizeNativeMouseMoveAndWaitForMoveEvent(aTarget, aX, aY, aCallback) {
function synthesizeNativeMouseMoveAndWaitForMoveEvent(
aTarget,
aX,
aY,
aCallback
) {
var targetWindow = windowForTarget(aTarget);
targetWindow.addEventListener("mousemove", function(e) {
setTimeout(aCallback, 0);
}, {once: true});
targetWindow.addEventListener(
"mousemove",
function(e) {
setTimeout(aCallback, 0);
},
{ once: true }
);
return synthesizeNativeMouseMove(aTarget, aX, aY);
}
// Synthesizes a native touch event and dispatches it. aX and aY in CSS pixels
// 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 utils = utilsForTarget(aTarget);
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
// synthesizeNativeTouch call this function makes.
// 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
// will be the last one we make, so that we can register aObserver on it.
var lastNonNullValue = -1;
@ -284,12 +385,14 @@ function* synthesizeNativeTouchSequences(aTarget, aPositions, aObserver = null,
if (aPositions[i].length != aTouchIds.length) {
throw new Error(
`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++) {
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 {
// synthesize the touch-up. If this is the last call we're going to
// make, pass the observer as well
var thisIndex = ((i - yields) * aTouchIds.length) + j;
var observer = (lastSynthesizeCall == thisIndex) ? aObserver : null;
synthesizeNativeTouch(aTarget, currentPositions[j].x, currentPositions[j].y, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, observer, aTouchIds[j]);
var thisIndex = (i - yields) * aTouchIds.length + j;
var observer = lastSynthesizeCall == thisIndex ? aObserver : null;
synthesizeNativeTouch(
aTarget,
currentPositions[j].x,
currentPositions[j].y,
SpecialPowers.DOMWindowUtils.TOUCH_REMOVE,
observer,
aTouchIds[j]
);
currentPositions[j] = null;
}
} 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];
}
}
@ -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
// "apz.touch_start_tolerance" is set to 0, or some of the touchmove will get
// 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 positions = [[{ x: aX, y: aY }]];
for (var i = 1; i < steps; i++) {
@ -355,7 +480,12 @@ function synthesizeNativeTouchDrag(aTarget, aX, aY, aDeltaX, aDeltaY, aObserver
positions.push([pos]);
}
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();
while (!yielded.done) {
yielded = continuation.next();
@ -365,7 +495,9 @@ function synthesizeNativeTouchDrag(aTarget, aX, aY, aDeltaX, aDeltaY, aObserver
function synthesizeNativeTap(aElement, aX, aY, aObserver = null) {
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);
return true;
}
@ -380,10 +512,26 @@ function synthesizeNativeMouseEvent(aTarget, aX, aY, aType, aObserver = null) {
function synthesizeNativeClick(aElement, aX, aY, aObserver = null) {
var pt = coordinatesRelativeToScreen(aX, aY, aElement);
var utils = SpecialPowers.getDOMWindowUtils(aElement.ownerDocument.defaultView);
utils.sendNativeMouseEvent(pt.x, pt.y, nativeMouseDownEventMsg(), 0, aElement, function() {
utils.sendNativeMouseEvent(pt.x, pt.y, nativeMouseUpEventMsg(), 0, aElement, aObserver);
});
var utils = SpecialPowers.getDOMWindowUtils(
aElement.ownerDocument.defaultView
);
utils.sendNativeMouseEvent(
pt.x,
pt.y,
nativeMouseDownEventMsg(),
0,
aElement,
function() {
utils.sendNativeMouseEvent(
pt.x,
pt.y,
nativeMouseUpEventMsg(),
0,
aElement,
aObserver
);
}
);
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
// wheel event, otherwise there is a chance they might get reordered, and
// we have the transaction problem again.
function moveMouseAndScrollWheelOver(target, dx, dy, testDriver, waitForScroll = true) {
return synthesizeNativeMouseMoveAndWaitForMoveEvent(target, dx, dy, function() {
if (waitForScroll) {
synthesizeNativeWheelAndWaitForScrollEvent(target, dx, dy, 0, -10, testDriver);
} else {
synthesizeNativeWheelAndWaitForWheelEvent(target, dx, dy, 0, -10, testDriver);
function moveMouseAndScrollWheelOver(
target,
dx,
dy,
testDriver,
waitForScroll = true
) {
return synthesizeNativeMouseMoveAndWaitForMoveEvent(
target,
dx,
dy,
function() {
if (waitForScroll) {
synthesizeNativeWheelAndWaitForScrollEvent(
target,
dx,
dy,
0,
-10,
testDriver
);
} else {
synthesizeNativeWheelAndWaitForWheelEvent(
target,
dx,
dy,
0,
-10,
testDriver
);
}
}
});
);
}
// Same as moveMouseAndScrollWheelOver, but returns a promise instead of taking
// a callback function. Eventually we should convert all these callback-taking
// 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 => {
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
// with modifications. Fixes here should be copied there if appropriate.
// |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 w = {}, h = {};
var w = {},
h = {};
utilsForTarget(target).getScrollbarSizes(targetElement, w, h);
var verticalScrollbarWidth = w.value;
if (verticalScrollbarWidth == 0) {
@ -435,24 +619,62 @@ function* dragVerticalScrollbar(target, testDriver, distance = 20, increment = 5
}
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
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
yield synthesizeNativeMouseEvent(target, mouseX, mouseY, nativeMouseMoveEventMsg(), testDriver);
yield synthesizeNativeMouseEvent(
target,
mouseX,
mouseY,
nativeMouseMoveEventMsg(),
testDriver
);
// 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
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
return function* () {
return function*() {
dump("Finishing drag of #" + targetElement.id + "\n");
yield synthesizeNativeMouseEvent(target, mouseX, mouseY + distance, nativeMouseUpEventMsg(), testDriver);
yield synthesizeNativeMouseEvent(
target,
mouseX,
mouseY + distance,
nativeMouseUpEventMsg(),
testDriver
);
};
}

View file

@ -24,35 +24,55 @@ function convertEntries(entries) {
function parseRect(str) {
var pieces = str.replace(/[()\s]+/g, "").split(",");
SimpleTest.is(pieces.length, 4, "expected string of form (x,y,w,h)");
return { x: parseInt(pieces[0]),
y: parseInt(pieces[1]),
w: parseInt(pieces[2]),
h: parseInt(pieces[3]) };
return {
x: parseInt(pieces[0]),
y: parseInt(pieces[1]),
w: parseInt(pieces[2]),
h: parseInt(pieces[3]),
};
}
// These functions expect rects with fields named x/y/w/h, such as
// that returned by parseRect().
function rectContains(haystack, needle) {
return haystack.x <= needle.x
&& haystack.y <= needle.y
&& (haystack.x + haystack.w) >= (needle.x + needle.w)
&& (haystack.y + haystack.h) >= (needle.y + needle.h);
return (
haystack.x <= needle.x &&
haystack.y <= needle.y &&
haystack.x + haystack.w >= needle.x + needle.w &&
haystack.y + haystack.h >= needle.y + needle.h
);
}
function rectToString(rect) {
return "(" + rect.x + "," + rect.y + "," + rect.w + "," + rect.h + ")";
}
function assertRectContainment(haystackRect, haystackDesc, needleRect, needleDesc) {
SimpleTest.ok(rectContains(haystackRect, needleRect),
haystackDesc + " " + rectToString(haystackRect) + " should contain " +
needleDesc + " " + rectToString(needleRect));
function assertRectContainment(
haystackRect,
haystackDesc,
needleRect,
needleDesc
) {
SimpleTest.ok(
rectContains(haystackRect, needleRect),
haystackDesc +
" " +
rectToString(haystackRect) +
" should contain " +
needleDesc +
" " +
rectToString(needleRect)
);
}
function getPropertyAsRect(scrollFrames, scrollId, prop) {
SimpleTest.ok(scrollId in scrollFrames,
"expected scroll frame data for scroll id " + scrollId);
SimpleTest.ok(
scrollId in scrollFrames,
"expected scroll frame data for scroll id " + scrollId
);
var scrollFrameData = scrollFrames[scrollId];
SimpleTest.ok("displayport" in scrollFrameData,
"expected a " + prop + " for scroll id " + scrollId);
SimpleTest.ok(
"displayport" in scrollFrameData,
"expected a " + prop + " for scroll id " + scrollId
);
var value = scrollFrameData[prop];
return parseRect(value);
}
@ -68,7 +88,9 @@ function convertScrollFrameData(scrollFrames) {
function convertBuckets(buckets) {
var result = {};
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;
}
@ -94,14 +116,20 @@ function getLastNonemptyBucket(buckets) {
// Takes something like "matrix(1, 0, 0, 1, 234.024, 528.29023)"" and returns a number array
function parseTransform(transform) {
return /matrix\((.*),(.*),(.*),(.*),(.*),(.*)\)/.exec(transform)
.slice(1).map(parseFloat);
return /matrix\((.*),(.*),(.*),(.*),(.*),(.*)\)/
.exec(transform)
.slice(1)
.map(parseFloat);
}
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++) {
ok(Math.abs(a[i] - b[i]) < .01, name);
ok(Math.abs(a[i] - b[i]) < 0.01, name);
}
}
@ -115,7 +143,7 @@ function buildApzcTree(paint) {
// The APZC tree can potentially have multiple root nodes,
// so we invent a node that is the parent of all roots.
// This 'root' does not correspond to an APZC.
var root = {scrollId: -1, children: []};
var root = { scrollId: -1, children: [] };
for (let scrollId in paint) {
paint[scrollId].children = [];
paint[scrollId].scrollId = scrollId;
@ -135,7 +163,8 @@ function buildApzcTree(paint) {
// Given an APZC tree produced by buildApzcTree, return the RCD node in
// the tree, or null if there was none.
function findRcdNode(apzcTree) {
if (apzcTree.isRootContent) { // isRootContent will be undefined or "1"
if (apzcTree.isRootContent) {
// isRootContent will be undefined or "1"
return apzcTree;
}
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
// element, and not in the content descriptions of other elements.
function isLayerized(elementId) {
var contentTestData = SpecialPowers.getDOMWindowUtils(window).getContentAPZTestData();
var contentTestData = SpecialPowers.getDOMWindowUtils(
window
).getContentAPZTestData();
var nonEmptyBucket = getLastNonemptyBucket(contentTestData.paints);
ok(nonEmptyBucket != null, "expected at least one nonempty paint");
var seqno = nonEmptyBucket.sequenceNumber;
@ -170,14 +201,19 @@ function isLayerized(elementId) {
function promiseApzRepaintsFlushed(aWindow = window) {
return new Promise(function(resolve, reject) {
var repaintDone = function() {
SpecialPowers.Services.obs.removeObserver(repaintDone, "apz-repaints-flushed");
SpecialPowers.Services.obs.removeObserver(
repaintDone,
"apz-repaints-flushed"
);
setTimeout(resolve, 0);
};
SpecialPowers.Services.obs.addObserver(repaintDone, "apz-repaints-flushed");
if (SpecialPowers.getDOMWindowUtils(aWindow).flushApzRepaints()) {
dump("Flushed APZ repaints, waiting for callback...\n");
} 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();
}
});
@ -248,18 +284,24 @@ function runSubtestsSeriallyInFreshWindows(aSubtests) {
// If the "apz.subtest" pref has been set, only a single subtest whose name matches
// 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() {
var test = aSubtests[testIndex];
if (w) {
// 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();
}
if (typeof test.dp_suppression != "undefined") {
// 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) {
// 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"];
for (let prop in test) {
if (!recognizedProps.includes(prop)) {
SimpleTest.ok(false, "Subtest " + test.file + " has unrecognized property '" + prop + "'");
setTimeout(function() { advanceSubtestExecution(); }, 0);
SimpleTest.ok(
false,
"Subtest " + test.file + " has unrecognized property '" + prop + "'"
);
setTimeout(function() {
advanceSubtestExecution();
}, 0);
return;
}
}
if (onlyOneSubtest && onlyOneSubtest != test.file) {
SimpleTest.ok(true, "Skipping " + test.file + " because only " + onlyOneSubtest + " is being run");
setTimeout(function() { advanceSubtestExecution(); }, 0);
SimpleTest.ok(
true,
"Skipping " +
test.file +
" because only " +
onlyOneSubtest +
" is being run"
);
setTimeout(function() {
advanceSubtestExecution();
}, 0);
return;
}
@ -306,7 +362,9 @@ function runSubtestsSeriallyInFreshWindows(aSubtests) {
// unsuppression can trigger a repaint which interferes with the test, so
// to avoid that we can force the displayport to be unsuppressed for the
// entire test which is more deterministic.
SpecialPowers.getDOMWindowUtils(window).respectDisplayPortSuppression(test.dp_suppression);
SpecialPowers.getDOMWindowUtils(window).respectDisplayPortSuppression(
test.dp_suppression
);
}
function spawnTest(aFile) {
@ -314,21 +372,39 @@ function runSubtestsSeriallyInFreshWindows(aSubtests) {
w.subtestDone = advanceSubtestExecution;
w.isApzSubtest = true;
w.SimpleTest = SimpleTest;
w.dump = function(msg) { return dump(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.dump = function(msg) {
return dump(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) {
arguments[1] = aFile + " | " + msg;
// Forward all arguments to SimpleTest.ok where we will check that ok() was
// called with at most 2 arguments.
return SimpleTest.ok.apply(SimpleTest, arguments);
};
w.todo_is = function(a, b, msg) { return todo_is(a, b, aFile + " | " + msg); };
w.todo = function(cond, msg) { return todo(cond, aFile + " | " + msg); };
w.todo_is = function(a, b, msg) {
return todo_is(a, b, aFile + " | " + msg);
};
w.todo = function(cond, msg) {
return todo(cond, aFile + " | " + msg);
};
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) {
var request = new XMLHttpRequest();
request.open("GET", url, false);
@ -336,8 +412,13 @@ function runSubtestsSeriallyInFreshWindows(aSubtests) {
return request.status !== 404;
}
if (!urlResolves(subtestUrl)) {
SimpleTest.ok(false, "Subtest URL " + subtestUrl + " does not resolve. " +
"Be sure it's present in the support-files section of mochitest.ini.");
SimpleTest.ok(
false,
"Subtest URL " +
subtestUrl +
" does not resolve. " +
"Be sure it's present in the support-files section of mochitest.ini."
);
reject();
return undefined;
}
@ -347,7 +428,7 @@ function runSubtestsSeriallyInFreshWindows(aSubtests) {
if (test.prefs) {
// Got some prefs for this subtest, push them
SpecialPowers.pushPrefEnv({"set": test.prefs}, function() {
SpecialPowers.pushPrefEnv({ set: test.prefs }, function() {
w = spawnTest(test.file);
});
} else {
@ -362,7 +443,7 @@ function runSubtestsSeriallyInFreshWindows(aSubtests) {
}
function pushPrefs(prefs) {
return SpecialPowers.pushPrefEnv({"set": prefs});
return SpecialPowers.pushPrefEnv({ set: prefs });
}
async function waitUntilApzStable() {
@ -379,7 +460,9 @@ async function waitUntilApzStable() {
/* eslint-env mozilla/frame-script */
function parentProcessFlush() {
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");
if (!topWin) {
topWin = Services.wm.getMostRecentWindow("navigator:geckoview");
@ -393,15 +476,21 @@ async function waitUntilApzStable() {
};
var flushRepaint = function() {
if (topUtils.isMozAfterPaintPending) {
topWin.addEventListener("MozAfterPaint", flushRepaint, { once: true });
topWin.addEventListener("MozAfterPaint", flushRepaint, {
once: true,
});
return;
}
Services.obs.addObserver(repaintDone, "apz-repaints-flushed");
if (topUtils.flushApzRepaints()) {
dump("Parent process: flushed APZ repaints, waiting for callback...\n");
dump(
"Parent process: flushed APZ repaints, waiting for callback...\n"
);
} 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();
}
};
@ -420,7 +509,9 @@ async function waitUntilApzStable() {
// This is the first time waitUntilApzStable is being called, do initialization
if (typeof waitUntilApzStable.chromeHelper == "undefined") {
waitUntilApzStable.chromeHelper = SpecialPowers.loadChromeScript(parentProcessFlush);
waitUntilApzStable.chromeHelper = SpecialPowers.loadChromeScript(
parentProcessFlush
);
ApzCleanup.register(() => {
waitUntilApzStable.chromeHelper.sendAsyncMessage("cleanup", null);
waitUntilApzStable.chromeHelper.destroy();
@ -510,7 +601,10 @@ function runContinuation(testFunction) {
try {
driveTest();
} 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();
}
} 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;
}
};
@ -551,7 +648,9 @@ function runAsyncContinuation(testFunction) {
function getSnapshot(rect) {
function parentProcessSnapshot() {
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");
if (!topWin) {
topWin = Services.wm.getMostRecentWindow("navigator:geckoview");
@ -563,21 +662,36 @@ function getSnapshot(rect) {
parentRect.y -= topWin.mozInnerScreenY;
// 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.height = parentRect.h;
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)",
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();
});
}
if (typeof getSnapshot.chromeHelper == "undefined") {
// This is the first time getSnapshot is being called; do initialization
getSnapshot.chromeHelper = SpecialPowers.loadChromeScript(parentProcessSnapshot);
ApzCleanup.register(function() { getSnapshot.chromeHelper.destroy(); });
getSnapshot.chromeHelper = SpecialPowers.loadChromeScript(
parentProcessSnapshot
);
ApzCleanup.register(function() {
getSnapshot.chromeHelper.destroy();
});
}
return getSnapshot.chromeHelper.sendQuery("snapshot", JSON.stringify(rect));
@ -641,8 +755,8 @@ function injectScript(aScript, aWindow = window) {
function getHitTestConfig() {
if (!("hitTestConfig" in window)) {
var utils = SpecialPowers.getDOMWindowUtils(window);
var isWebRender = (utils.layerManagerType == "WebRender");
var isWindows = (getPlatform() == "windows");
var isWebRender = utils.layerManagerType == "WebRender";
var isWindows = getPlatform() == "windows";
window.hitTestConfig = { utils, isWebRender, isWindows };
}
return window.hitTestConfig;
@ -656,7 +770,7 @@ function centerOf(element) {
element = document.getElementById(element);
}
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.
@ -666,11 +780,30 @@ function centerOf(element) {
function hitTest(point) {
var utils = getHitTestConfig().utils;
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();
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];
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.
@ -693,20 +826,30 @@ function hitInfoToString(hitInfo) {
// Takes an object returned by hitTest, along with the expected values, and
// asserts that they match. Notably, it uses hitInfoToString to provide a
// more useful message for the case that the hit info doesn't match
function checkHitResult(hitResult, expectedHitInfo, expectedScrollId, expectedLayersId, desc) {
is(hitInfoToString(hitResult.hitInfo), hitInfoToString(expectedHitInfo), desc + " hit info");
function checkHitResult(
hitResult,
expectedHitInfo,
expectedScrollId,
expectedLayersId,
desc
) {
is(
hitInfoToString(hitResult.hitInfo),
hitInfoToString(expectedHitInfo),
desc + " hit info"
);
is(hitResult.scrollId, expectedScrollId, desc + " scrollid");
is(hitResult.layersId, expectedLayersId, desc + " layersid");
}
// Symbolic constants used by hitTestScrollbar().
var ScrollbarTrackLocation = {
START: 1,
END: 2,
START: 1,
END: 2,
};
var LayerState = {
ACTIVE: 1,
INACTIVE: 2,
ACTIVE: 1,
INACTIVE: 2,
};
// Perform a hit test on the scrollbar(s) of a scroll frame.
@ -743,8 +886,12 @@ function hitTestScrollbar(params) {
// 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
// the size of the buttons
var scrollbarArrowButtonHeight = config.isWindows ? verticalScrollbarWidth : 0;
var scrollbarArrowButtonWidth = config.isWindows ? horizontalScrollbarHeight : 0;
var scrollbarArrowButtonHeight = config.isWindows
? verticalScrollbarWidth
: 0;
var scrollbarArrowButtonWidth = config.isWindows
? horizontalScrollbarHeight
: 0;
// Compute the expected hit result flags.
// The direction flag (APZHitResultFlags.SCROLLBAR_VERTICAL) is added in
@ -774,37 +921,51 @@ function hitTestScrollbar(params) {
}
}
var scrollframeMsg = (params.layerState == LayerState.ACTIVE)
? "active scrollframe" : "inactive scrollframe";
var scrollframeMsg =
params.layerState == LayerState.ACTIVE
? "active scrollframe"
: "inactive scrollframe";
// Hit-test the targeted areas, assuming we don't have overlay scrollbars
// with zero dimensions.
if (params.directions.vertical && verticalScrollbarWidth > 0) {
var verticalScrollbarPoint = {
x: boundingClientRect.right - (verticalScrollbarWidth / 2),
y: (params.trackLocation == ScrollbarTrackLocation.START)
? (boundingClientRect.y + scrollbarArrowButtonHeight + 5)
: (boundingClientRect.bottom - horizontalScrollbarHeight - scrollbarArrowButtonHeight - 5),
x: boundingClientRect.right - verticalScrollbarWidth / 2,
y:
params.trackLocation == ScrollbarTrackLocation.START
? boundingClientRect.y + scrollbarArrowButtonHeight + 5
: boundingClientRect.bottom -
horizontalScrollbarHeight -
scrollbarArrowButtonHeight -
5,
};
checkHitResult(hitTest(verticalScrollbarPoint),
expectedHitInfo | APZHitResultFlags.SCROLLBAR_VERTICAL,
params.expectedScrollId,
params.expectedLayersId,
scrollframeMsg + " - vertical scrollbar");
checkHitResult(
hitTest(verticalScrollbarPoint),
expectedHitInfo | APZHitResultFlags.SCROLLBAR_VERTICAL,
params.expectedScrollId,
params.expectedLayersId,
scrollframeMsg + " - vertical scrollbar"
);
}
if (params.directions.horizontal && horizontalScrollbarHeight > 0) {
var horizontalScrollbarPoint = {
x: (params.trackLocation == ScrollbarTrackLocation.START)
? (boundingClientRect.x + scrollbarArrowButtonWidth + 5)
: (boundingClientRect.right - verticalScrollbarWidth - scrollbarArrowButtonWidth - 5),
y: boundingClientRect.bottom - (horizontalScrollbarHeight / 2),
x:
params.trackLocation == ScrollbarTrackLocation.START
? boundingClientRect.x + scrollbarArrowButtonWidth + 5
: boundingClientRect.right -
verticalScrollbarWidth -
scrollbarArrowButtonWidth -
5,
y: boundingClientRect.bottom - horizontalScrollbarHeight / 2,
};
checkHitResult(hitTest(horizontalScrollbarPoint),
expectedHitInfo,
params.expectedScrollId,
params.expectedLayersId,
scrollframeMsg + " - horizontal scrollbar");
checkHitResult(
hitTest(horizontalScrollbarPoint),
expectedHitInfo,
params.expectedScrollId,
params.expectedLayersId,
scrollframeMsg + " - horizontal scrollbar"
);
}
}
@ -862,7 +1023,16 @@ var ApzCleanup = {
try {
func();
} 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 +
"]"
);
}
}
},

View file

@ -1,11 +1,14 @@
add_task(async function test_main() {
function httpURL(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 isWebRender = (utils.layerManagerType == "WebRender");
var isWebRender = utils.layerManagerType == "WebRender";
// Each of these URLs will get opened in a new top-level browser window that
// 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
// below.
const {FissionTestHelperParent} = ChromeUtils.import(
getRootDirectory(gTestPath) + "FissionTestHelperParent.jsm");
const { FissionTestHelperParent } = ChromeUtils.import(
getRootDirectory(gTestPath) + "FissionTestHelperParent.jsm"
);
FissionTestHelperParent.SimpleTest = SimpleTest;
ChromeUtils.registerWindowActor("FissionTestHelper", {
@ -36,7 +42,7 @@ add_task(async function test_main() {
child: {
moduleURI: getRootDirectory(gTestPath) + "FissionTestHelperChild.jsm",
events: {
"DOMWindowCreated": {},
DOMWindowCreated: {},
},
},
allFrames: true,
@ -49,13 +55,16 @@ add_task(async function test_main() {
// Load the test URL and tell it to get started, and wait until it reports
// completion.
await BrowserTestUtils.withNewTab(
{gBrowser: fissionWindow.gBrowser, url},
async (browser) => {
let tabActor = browser.browsingContext.currentWindowGlobal.getActor("FissionTestHelper");
{ gBrowser: fissionWindow.gBrowser, url },
async browser => {
let tabActor = browser.browsingContext.currentWindowGlobal.getActor(
"FissionTestHelper"
);
let donePromise = tabActor.getTestCompletePromise();
tabActor.startTest();
await donePromise;
});
}
);
dump(`Finished test ${url}\n`);
}

View file

@ -28,12 +28,16 @@ function promiseOneEvent(eventType, filter) {
try {
success = filter(e);
} catch (ex) {
dump(`ERROR: Filter passed to promiseOneEvent threw exception: ${ex}\n`);
dump(
`ERROR: Filter passed to promiseOneEvent threw exception: ${ex}\n`
);
reject();
return;
}
} 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();
return;
}
@ -54,14 +58,18 @@ function promiseOneEvent(eventType, filter) {
function loadOOPIFrame(iframeElementId, iframePage) {
return async function() {
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");
}
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) {
return (typeof e.data.content) == "string" &&
e.data.content == url;
return typeof e.data.content == "string" && e.data.content == url;
});
let elem = document.getElementById(iframeElementId);
elem.src = url;

View file

@ -1,7 +1,7 @@
function toFixed(num, fixed) {
fixed = fixed || 0;
fixed = Math.pow(10, fixed);
return Math.floor(num * fixed) / fixed;
fixed = fixed || 0;
fixed = Math.pow(10, fixed);
return Math.floor(num * fixed) / fixed;
}
function createElement(name, props) {
var el = document.createElement(name);
@ -43,7 +43,9 @@ function parseDisplayList(lines) {
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) {
dump("Failed to match: " + line + "\n");
continue;
@ -62,7 +64,8 @@ function parseDisplayList(lines) {
layerObject.contentDescriptor = matches[5];
layerObject.z = matches[7];
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.rest = rest;
@ -107,7 +110,7 @@ function parseDisplayList(lines) {
}
function trim(s) {
return ( s || "" ).replace( /^\s+|\s+$/g, "" );
return (s || "").replace(/^\s+|\s+$/g, "");
}
function getDataURI(str) {
@ -115,9 +118,12 @@ function getDataURI(str) {
return str;
}
var matches = str.match("data:image/lz4bgra;base64,([0-9]+),([0-9]+),([0-9]+),(.*)");
if (!matches)
var matches = str.match(
"data:image/lz4bgra;base64,([0-9]+),([0-9]+),([0-9]+),(.*)"
);
if (!matches) {
return null;
}
var canvas = document.createElement("canvas");
var w = parseInt(matches[1]);
@ -212,8 +218,10 @@ function parseLayers(layersDumpLines) {
}
var rect = [
parseFloat(rectMatches[1]), parseFloat(rectMatches[2]),
parseFloat(rectMatches[3]), parseFloat(rectMatches[4]),
parseFloat(rectMatches[1]),
parseFloat(rectMatches[2]),
parseFloat(rectMatches[3]),
parseFloat(rectMatches[4]),
];
return rect;
}
@ -228,14 +236,18 @@ function parseLayers(layersDumpLines) {
var region = [];
str = trim(str.substring(1, str.length - 1));
while (str != "") {
var rectMatches = str.match("^\\(x=(.*?), y=(.*?), w=(.*?), h=(.*?)\\);(.*)$");
var rectMatches = str.match(
"^\\(x=(.*?), y=(.*?), w=(.*?), h=(.*?)\\);(.*)$"
);
if (!rectMatches) {
return null;
}
var rect = [
parseFloat(rectMatches[1]), parseFloat(rectMatches[2]),
parseFloat(rectMatches[3]), parseFloat(rectMatches[4]),
parseFloat(rectMatches[1]),
parseFloat(rectMatches[2]),
parseFloat(rectMatches[3]),
parseFloat(rectMatches[4]),
];
str = trim(rectMatches[5]);
region.push(rect);
@ -271,16 +283,21 @@ function parseLayers(layersDumpLines) {
var surfaceMatches = line.match("(\\s*)Surface: (.*)");
if (surfaceMatches) {
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];
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;
// 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);
if (matches) {
var contentHostRest = matches[4];
@ -304,11 +321,13 @@ function parseLayers(layersDumpLines) {
continue; // Something like a texturehost dump. Safe to ignore
}
if (matches[2].includes("TiledContentHost") ||
matches[2].includes("ContentHost") ||
matches[2].includes("ContentClient") ||
matches[2].includes("MemoryTextureHost") ||
matches[2].includes("ImageHost")) {
if (
matches[2].includes("TiledContentHost") ||
matches[2].includes("ContentHost") ||
matches[2].includes("ContentClient") ||
matches[2].includes("MemoryTextureHost") ||
matches[2].includes("ImageHost")
) {
continue; // We're already pretty good at visualizing these
}
@ -414,10 +433,15 @@ function parseLayers(layersDumpLines) {
// Compute screenTransformX/screenTransformY
// TODO Fully support transforms
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;
while (currIndentation >= 0) {
var transform = objectAtIndentation[currIndentation]["shadow-transform"] || objectAtIndentation[currIndentation].transform;
var transform =
objectAtIndentation[currIndentation]["shadow-transform"] ||
objectAtIndentation[currIndentation].transform;
if (transform) {
layerObject["screen-transform"][0] += transform[2][0];
layerObject["screen-transform"][1] += transform[2][1];
@ -432,7 +456,15 @@ function parseLayers(layersDumpLines) {
// dump("OBJECTS: " + JSON.stringify(root) + "\n");
return root;
}
function populateLayers(root, displayList, pane, previewParent, hasSeenRoot, contentScale, rootPreviewParent) {
function populateLayers(
root,
displayList,
pane,
previewParent,
hasSeenRoot,
contentScale,
rootPreviewParent
) {
contentScale = contentScale || 1;
rootPreviewParent = rootPreviewParent || previewParent;
@ -521,7 +553,8 @@ function populateLayers(root, displayList, pane, previewParent, hasSeenRoot, con
});
layerViewportMatrix[4] += -clip[0];
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) {
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[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) {
hasSeenRoot = true;
layerViewport.style.transform = "scale(" + 1 / contentScale + "," + 1 / contentScale + ")";
layerViewport.style.transform =
"scale(" + 1 / contentScale + "," + 1 / contentScale + ")";
}
if (clipElem) {
previewParent.appendChild(clipElem);
@ -557,14 +604,19 @@ function populateLayers(root, displayList, pane, previewParent, hasSeenRoot, con
height: rect2d[3] + "px",
overflow: "hidden",
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);
function isInside(rect1, rect2) {
if (rect1[0] + rect1[2] < rect2[0] && rect2[0] + rect2[2] < rect1[0] &&
rect1[1] + rect1[3] < rect2[1] && rect2[1] + rect2[3] < rect1[1]) {
if (
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;
@ -583,8 +635,8 @@ function populateLayers(root, displayList, pane, previewParent, hasSeenRoot, con
src: getDataURI(root.tiles[x][y]),
style: {
position: "absolute",
left: (x - previewOffset[0]) + "px",
top: (y - previewOffset[1]) + "px",
left: x - previewOffset[0] + "px",
top: y - previewOffset[1] + "px",
pointerEvents: "auto",
},
});
@ -605,8 +657,8 @@ function populateLayers(root, displayList, pane, previewParent, hasSeenRoot, con
src: getDataURI(root.surfaceURI),
style: {
position: "absolute",
left: (offsetX - previewOffset[0]) + "px",
top: (offsetY - previewOffset[1]) + "px",
left: offsetX - previewOffset[0] + "px",
top: offsetY - previewOffset[1] + "px",
pointerEvents: "auto",
},
});
@ -614,7 +666,16 @@ function populateLayers(root, displayList, pane, previewParent, hasSeenRoot, con
layerPreview.style.background = "";
} else if (root.color) {
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) {
@ -648,14 +709,29 @@ function populateLayers(root, displayList, pane, previewParent, hasSeenRoot, con
description += "Content: " + this.displayItem.contentDescriptor;
} else {
description += "Content: Unknown";
}
description += "<br>Item: " + this.displayItem.name + " (" + this.displayItem.address + ")";
description += "<br>Layer: " + root.name + " (" + root.address + ")";
}
description +=
"<br>Item: " +
this.displayItem.name +
" (" +
this.displayItem.address +
")";
description +=
"<br>Layer: " + root.name + " (" + root.address + ")";
if (this.displayItem.frame) {
description += "<br>Frame: " + this.displayItem.frame;
}
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) {
description += "<br>Z: " + this.displayItem.z;
@ -670,7 +746,11 @@ function populateLayers(root, displayList, pane, previewParent, hasSeenRoot, con
className: "csstooltip",
innerHTML: description,
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",
},
});
@ -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
// will have the wrong offset
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;
let diPreview = createElement("div", {
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++) {
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",
},
href: "#",
textContent: "LayerTree " + (frameID++),
textContent: "LayerTree " + frameID++,
onclick() {
contents.innerHTML = "";
var matchLines = matches[i].split("\n");
@ -829,7 +918,9 @@ function parseDump(log, displayList, compositeTitle, compositeTime) {
style: {
width: "100%",
},
textContent: compositeTitle + (compositeTitle ? " (near " + compositeTime.toFixed(0) + " ms)" : ""),
textContent:
compositeTitle +
(compositeTitle ? " (near " + compositeTime.toFixed(0) + " ms)" : ""),
});
container.appendChild(titleDiv);
}

View file

@ -5,14 +5,17 @@ add_task(async function test_windowlessBrowserTroubleshootCrash() {
let docShell = webNav.docShell;
let listener = {
observe(contentWindow, topic, data) {
let observedDocShell = contentWindow.docShell
.sameTypeRootTreeItem
.QueryInterface(Ci.nsIDocShell);
if (docShell === observedDocShell) {
Services.obs.removeObserver(listener, "content-document-global-created");
resolve();
}
},
let observedDocShell = contentWindow.docShell.sameTypeRootTreeItem.QueryInterface(
Ci.nsIDocShell
);
if (docShell === observedDocShell) {
Services.obs.removeObserver(
listener,
"content-document-global-created"
);
resolve();
}
},
};
Services.obs.addObserver(listener, "content-document-global-created");
});
@ -25,21 +28,31 @@ add_task(async function test_windowlessBrowserTroubleshootCrash() {
let winUtils = webNav.document.defaultView.windowUtils;
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) {
// 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.
}
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) => {
Troubleshoot.snapshot((data) => {
Troubleshoot.snapshot(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();
});