Backed out 3 changesets (bug 1648161, bug 1650094) as requeste by yzen

Backed out changeset a05fbae74197 (bug 1650094)
Backed out changeset b1c3cfa3b77b (bug 1648161)
Backed out changeset 7cd63199f143 (bug 1648161)
This commit is contained in:
Narcis Beleuzu 2020-07-20 18:01:00 +03:00
parent 9eb346196f
commit 0a0d8f9451
34 changed files with 840 additions and 306 deletions

View File

@ -6,7 +6,6 @@
// Test whether AnimationInspector and base pane exists.
add_task(async function() {
await addTab(URL_ROOT + "doc_simple_animation.html");
const { animationInspector, panel } = await openAnimationInspector();
ok(animationInspector, "AnimationInspector should exist");
ok(panel, "Main animation-inspector panel should exist");

View File

@ -118,13 +118,12 @@ Because of the way content is inserted into the page, it isn't wanted to give co
In order to help with the API described in the previous section, the `CanvasFrameAnonymousContentHelper` class was introduced.
Its goal is to provide a simple way for highlighters to insert their content into the page and modify it dynamically later. One of its goal is also to re-insert the highlighters' content on page navigation. Indeed, the frame tree is destroyed when the page is navigated away from since it represents the document element. One thing to note is that highlighter content insertion is asynchronous and `CanvasFrameAnonymousContentHelper` users must call and wait for its `initialize` method to resolve.
Its goal is to provide a simple way for highlighters to insert their content into the page and modify it dynamically later. One of its goal is also to re-insert the highlighters' content on page navigation. Indeed, the frame tree is destroyed when the page is navigated away from since it represents the document element.
Using this helper is quite simple:
```js
let helper = new CanvasFrameAnonymousContentHelper(targetActor, this.buildMarkup.bind(this));
await helper.initialize();
```
It only requires a `targetActor`, which highlighters get when they are instantiated, and a callback function that will be used to create and insert the content the first time the highlighter is shown, and every time there's a page navigation.

View File

@ -507,7 +507,7 @@ const AccessibleActor = ActorClassWithSpec(accessibleSpec, {
// Keep the reference to the walker actor in case the actor gets destroyed
// during the colour contrast ratio calculation.
const { walker } = this;
await walker.clearStyles(win);
walker.clearStyles(win);
const contrastRatio = await getContrastRatioFor(rawNode.parentNode, {
bounds: getBounds(win, bounds),
win,
@ -518,7 +518,7 @@ const AccessibleActor = ActorClassWithSpec(accessibleSpec, {
// This accessible actor is destroyed.
return null;
}
await walker.restoreStyles(win);
walker.restoreStyles(win);
return contrastRatio;
},

View File

@ -287,10 +287,25 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
get highlighter() {
if (!this._highlighter) {
if (!isTypeRegistered("AccessibleHighlighter")) {
register("AccessibleHighlighter", "accessible");
if (isXUL(this.rootWin)) {
if (!isTypeRegistered("XULWindowAccessibleHighlighter")) {
register("XULWindowAccessibleHighlighter", "xul-accessible");
}
this._highlighter = CustomHighlighterActor(
this,
"XULWindowAccessibleHighlighter"
);
} else {
if (!isTypeRegistered("AccessibleHighlighter")) {
register("AccessibleHighlighter", "accessible");
}
this._highlighter = CustomHighlighterActor(
this,
"AccessibleHighlighter"
);
}
this._highlighter = CustomHighlighterActor(this, "AccessibleHighlighter");
this.manage(this._highlighter);
this._highlighter.on("highlighter-event", this.onHighlighterEvent);
@ -316,10 +331,6 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
return this.targetActor && this.targetActor.window.document;
},
get isXUL() {
return isXUL(this.rootWin);
},
get colorMatrix() {
if (!this.targetActor.docShell) {
return null;
@ -457,7 +468,7 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
return this.once("document-ready").then(docAcc => this.addRef(docAcc));
}
if (this.isXUL) {
if (isXUL(this.rootWin)) {
const doc = this.addRef(this.getRawAccessibleFor(this.rootDoc));
return Promise.resolve(doc);
}
@ -747,7 +758,7 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
* @param {Object} win
* Window where highlighting happens.
*/
async clearStyles(win) {
clearStyles(win) {
const requests = this._loadedSheets.get(win);
if (requests != null) {
this._loadedSheets.set(win, requests + 1);
@ -760,7 +771,7 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
// taking a snapshot for contrast measurement).
loadSheetForBackgroundCalculation(win);
this._loadedSheets.set(win, 1);
await this.hideHighlighter();
this.hideHighlighter();
},
/**
@ -771,7 +782,7 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
* @param {Object} win
* Window where highlighting was happenning.
*/
async restoreStyles(win) {
restoreStyles(win) {
const requests = this._loadedSheets.get(win);
if (!requests) {
return;
@ -782,27 +793,25 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
return;
}
await this.showHighlighter();
this.showHighlighter();
removeSheetForBackgroundCalculation(win);
this._loadedSheets.delete(win);
},
async hideHighlighter() {
hideHighlighter() {
// TODO: Fix this workaround that temporarily removes higlighter bounds
// overlay that can interfere with the contrast ratio calculation.
if (this._highlighter) {
const highlighter = this._highlighter.instance;
await highlighter.isReady;
highlighter.hideAccessibleBounds();
}
},
async showHighlighter() {
showHighlighter() {
// TODO: Fix this workaround that temporarily removes higlighter bounds
// overlay that can interfere with the contrast ratio calculation.
if (this._highlighter) {
const highlighter = this._highlighter.instance;
await highlighter.isReady;
highlighter.showAccessibleBounds();
}
},
@ -840,15 +849,9 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
}
const { name, role } = accessible;
const { highlighter } = this;
await highlighter.instance.isReady;
if (this._highlightingAccessible !== accessible) {
return false;
}
const shown = highlighter.show(
const shown = this.highlighter.show(
{ rawNode },
{ ...options, ...bounds, name, role, audit, isXUL: this.isXUL }
{ ...options, ...bounds, name, role, audit }
);
this._highlightingAccessible = null;
@ -1116,8 +1119,7 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
const target = event.originalTarget || event.target;
const docAcc = this.getRawAccessibleFor(this.rootDoc);
const win = target.ownerGlobal;
const zoom = this.isXUL ? 1 : getCurrentZoom(win);
const scale = this.pixelRatio / zoom;
const scale = this.pixelRatio / getCurrentZoom(win);
const rawAccessible = docAcc.getDeepestChildAtPointInProcess(
event.screenX * scale,
event.screenY * scale

View File

@ -20,6 +20,12 @@ loader.lazyRequireGetter(
"devtools/server/actors/highlighters/utils/markup",
true
);
loader.lazyRequireGetter(
this,
"SimpleOutlineHighlighter",
"devtools/server/actors/highlighters/simple-outline",
true
);
loader.lazyRequireGetter(
this,
"BoxModelHighlighter",
@ -96,6 +102,14 @@ exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
this._highlighterEnv.initFromTargetActor(this._targetActor);
this._onNavigate = this._onNavigate.bind(this);
const doc = this._targetActor.window.document;
// Only try to create the highlighter when the document is loaded,
// otherwise, wait for the navigate event to fire.
if (doc.documentElement && doc.readyState != "uninitialized") {
this._createHighlighter();
}
// Listen to navigation events to switch from the BoxModelHighlighter to the
// SimpleOutlineHighlighter, and back, if the top level window changes.
this._targetActor.on("navigate", this._onNavigate);
@ -105,41 +119,23 @@ exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
return this._inspector && this._inspector.conn;
},
/**
* Get an instance of the box model highlighter.
*/
get instance() {
return this._highlighter;
},
form: function() {
return {
actor: this.actorID,
};
},
initializeInstance() {
// _createHighlighter will resolve this promise once the highlighter
// instance is created.
const onInitialized = new Promise(resolve => {
this._initialized = resolve;
});
// Only try to create the highlighter isntance when the document is loaded,
// otherwise, wait for the navigate event to fire.
const doc = this._targetActor.window.document;
if (doc.documentElement && doc.readyState != "uninitialized") {
this._createHighlighter();
}
return onInitialized;
},
_createHighlighter: function() {
this._highlighter = new BoxModelHighlighter(
this._highlighterEnv,
this._inspector
);
this._initialized();
this._isPreviousWindowXUL = isXUL(this._targetActor.window);
if (!this._isPreviousWindowXUL) {
this._highlighter = new BoxModelHighlighter(
this._highlighterEnv,
this._inspector
);
} else {
this._highlighter = new SimpleOutlineHighlighter(this._highlighterEnv);
}
},
_destroyHighlighter: function() {
@ -156,8 +152,11 @@ exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
return;
}
this._destroyHighlighter();
this._createHighlighter();
// Only rebuild the highlighter if the window type changed.
if (isXUL(this._targetActor.window) !== this._isPreviousWindowXUL) {
this._destroyHighlighter();
this._createHighlighter();
}
},
destroy: function() {

View File

@ -17,10 +17,7 @@ const {
TEXT_NODE,
DOCUMENT_NODE,
} = require("devtools/shared/dom-node-constants");
const {
getCurrentZoom,
setIgnoreLayoutChanges,
} = require("devtools/shared/layout/utils");
const { setIgnoreLayoutChanges } = require("devtools/shared/layout/utils");
loader.lazyRequireGetter(
this,
@ -28,12 +25,6 @@ loader.lazyRequireGetter(
"devtools/server/actors/highlighters/utils/accessibility",
true
);
loader.lazyRequireGetter(
this,
"getBoundsXUL",
"devtools/server/actors/highlighters/utils/accessibility",
true
);
loader.lazyRequireGetter(
this,
"Infobar",
@ -93,7 +84,6 @@ class AccessibleHighlighter extends AutoRefreshHighlighter {
this.highlighterEnv,
this._buildMarkup.bind(this)
);
this.isReady = this.markup.initialize();
this.onPageHide = this.onPageHide.bind(this);
this.onWillNavigate = this.onWillNavigate.bind(this);
@ -104,14 +94,6 @@ class AccessibleHighlighter extends AutoRefreshHighlighter {
this.pageListenerTarget.addEventListener("pagehide", this.onPageHide);
}
/**
* Static getter that indicates that AccessibleHighlighter supports
* highlighting in XUL windows.
*/
static get XULSupported() {
return true;
}
/**
* Build highlighter markup.
*
@ -336,20 +318,7 @@ class AccessibleHighlighter extends AutoRefreshHighlighter {
* information for the accessible object.
*/
get _bounds() {
let { win, options } = this;
let getBoundsFn = getBounds;
if (this.options.isXUL) {
// Zoom level for the top level browser window does not change and only
// inner frames do. So we need to get the zoom level of the current node's
// parent window.
let zoom = getCurrentZoom(this.currentNode);
zoom *= zoom;
options = { ...options, zoom };
getBoundsFn = getBoundsXUL;
win = this.win.parent.ownerGlobal;
}
return getBoundsFn(win, options);
return getBounds(this.win, this.options);
}
/**

View File

@ -107,7 +107,6 @@ class BoxModelHighlighter extends AutoRefreshHighlighter {
this.highlighterEnv,
this._buildMarkup.bind(this)
);
this.isReady = this.markup.initialize();
/**
* Optionally customize each region's fill color by adding an entry to the

View File

@ -237,7 +237,6 @@ class CssGridHighlighter extends AutoRefreshHighlighter {
this.highlighterEnv,
this._buildMarkup.bind(this)
);
this.isReady = this.markup.initialize();
this.onPageHide = this.onPageHide.bind(this);
this.onWillNavigate = this.onWillNavigate.bind(this);

View File

@ -38,7 +38,6 @@ class CssTransformHighlighter extends AutoRefreshHighlighter {
this.highlighterEnv,
this._buildMarkup.bind(this)
);
this.isReady = this.markup.initialize();
}
_buildMarkup() {

View File

@ -58,7 +58,6 @@ function EyeDropper(highlighterEnv) {
this.highlighterEnv,
this._buildMarkup.bind(this)
);
this.isReady = this.markup.initialize();
// Get a couple of settings from prefs.
this.format = Services.prefs.getCharPref(FORMAT_PREF);

View File

@ -86,7 +86,6 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
this.highlighterEnv,
this._buildMarkup.bind(this)
);
this.isReady = this.markup.initialize();
this.onPageHide = this.onPageHide.bind(this);
this.onWillNavigate = this.onWillNavigate.bind(this);

View File

@ -223,20 +223,12 @@ class GeometryEditorHighlighter extends AutoRefreshHighlighter {
highlighterEnv,
this._buildMarkup.bind(this)
);
this.isReady = this.initialize();
const { pageListenerTarget } = this.highlighterEnv;
// Register the geometry editor instance to all events we're interested in.
DOM_EVENTS.forEach(type => pageListenerTarget.addEventListener(type, this));
this.onWillNavigate = this.onWillNavigate.bind(this);
this.highlighterEnv.on("will-navigate", this.onWillNavigate);
}
async initialize() {
await this.markup.initialize();
// Register the mousedown event for each Geometry Editor's handler.
// Those events are automatically removed when the markup is destroyed.
const onMouseDown = this.handleEvent.bind(this);
@ -247,6 +239,10 @@ class GeometryEditorHighlighter extends AutoRefreshHighlighter {
onMouseDown
);
}
this.onWillNavigate = this.onWillNavigate.bind(this);
this.highlighterEnv.on("will-navigate", this.onWillNavigate);
}
_buildMarkup() {

View File

@ -52,7 +52,6 @@ function MeasuringToolHighlighter(highlighterEnv) {
highlighterEnv,
this._buildMarkup.bind(this)
);
this.isReady = this.markup.initialize();
this.coords = {
x: 0,

View File

@ -24,4 +24,6 @@ DevToolsModules(
'rulers.js',
'selector.js',
'shapes.js',
'simple-outline.js',
'xul-accessible.js'
)

View File

@ -33,7 +33,6 @@ function PausedDebuggerOverlay(highlighterEnv, options = {}) {
highlighterEnv,
this._buildMarkup.bind(this)
);
this.isReady = this.markup.initialize();
}
PausedDebuggerOverlay.prototype = {

View File

@ -36,7 +36,6 @@ function RulersHighlighter(highlighterEnv) {
highlighterEnv,
this._buildMarkup.bind(this)
);
this.isReady = this.markup.initialize();
const { pageListenerTarget } = highlighterEnv;
pageListenerTarget.addEventListener("scroll", this);

View File

@ -37,7 +37,7 @@ SelectorHighlighter.prototype = {
* string that will be used in querySelectorAll. On top of this, all of the
* valid options to BoxModelHighlighter.show are also valid here.
*/
show: async function(node, options = {}) {
show: function(node, options = {}) {
this.hide();
if (!isNodeValid(node) || !options.selector) {
@ -55,30 +55,23 @@ SelectorHighlighter.prototype = {
delete options.selector;
let i = 0;
const highlighters = [];
for (const matchingNode of nodes) {
if (i++ >= MAX_HIGHLIGHTED_ELEMENTS) {
if (i >= MAX_HIGHLIGHTED_ELEMENTS) {
break;
}
highlighters.push(this._accumulateHighlighter(matchingNode, options));
const highlighter = new BoxModelHighlighter(this.highlighterEnv);
if (options.fill) {
highlighter.regionFill[options.region || "border"] = options.fill;
}
highlighter.show(matchingNode, options);
this._highlighters.push(highlighter);
i++;
}
await Promise.all(highlighters);
return true;
},
_accumulateHighlighter: async function(node, options) {
const highlighter = new BoxModelHighlighter(this.highlighterEnv);
await highlighter.ready;
if (options.fill) {
highlighter.regionFill[options.region || "border"] = options.fill;
}
highlighter.show(node, options);
this._highlighters.push(highlighter);
},
hide: function() {
for (const highlighter of this._highlighters) {
highlighter.destroy();

View File

@ -103,7 +103,6 @@ class ShapesHighlighter extends AutoRefreshHighlighter {
this.highlighterEnv,
this._buildMarkup.bind(this)
);
this.isReady = this.markup.initialize();
this.onPageHide = this.onPageHide.bind(this);
const { pageListenerTarget } = this.highlighterEnv;

View File

@ -0,0 +1,72 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {
isNodeValid,
addPseudoClassLock,
removePseudoClassLock,
} = require("devtools/server/actors/highlighters/utils/markup");
const { loadSheet } = require("devtools/shared/layout/utils");
// SimpleOutlineHighlighter's stylesheet
const HIGHLIGHTED_PSEUDO_CLASS = ":-moz-devtools-highlighted";
const SIMPLE_OUTLINE_SHEET =
"data:text/css;charset=utf-8," +
encodeURIComponent(`
.__fx-devtools-hide-shortcut__ {
visibility: hidden !important
}
${HIGHLIGHTED_PSEUDO_CLASS} {
outline: 2px dashed #F06!important;
outline-offset: -2px!important
}`);
/**
* The SimpleOutlineHighlighter is a class that has the same API than the
* BoxModelHighlighter, but adds a pseudo-class on the target element itself
* to draw a simple css outline around the element.
* It is used by the HighlighterActor when canvasframe-based highlighters can't
* be used. This is the case for XUL windows.
*/
function SimpleOutlineHighlighter(highlighterEnv) {
this.chromeDoc = highlighterEnv.document;
}
SimpleOutlineHighlighter.prototype = {
/**
* Destroy the nodes. Remove listeners.
*/
destroy: function() {
this.hide();
this.chromeDoc = null;
},
/**
* Show the highlighter on a given node
* @param {DOMNode} node
*/
show: function(node) {
if (isNodeValid(node) && (!this.currentNode || node !== this.currentNode)) {
this.hide();
this.currentNode = node;
loadSheet(node.ownerGlobal, SIMPLE_OUTLINE_SHEET);
addPseudoClassLock(node, HIGHLIGHTED_PSEUDO_CLASS);
}
return true;
},
/**
* Hide the highlighter, the outline and the infobar.
*/
hide: function() {
if (this.currentNode) {
removePseudoClassLock(this.currentNode, HIGHLIGHTED_PSEUDO_CLASS);
this.currentNode = null;
}
},
};
exports.SimpleOutlineHighlighter = SimpleOutlineHighlighter;

View File

@ -5,7 +5,10 @@
"use strict";
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
const { getCurrentZoom } = require("devtools/shared/layout/utils");
const {
getCurrentZoom,
getViewportDimensions,
} = require("devtools/shared/layout/utils");
const {
moveInfobar,
createNode,
@ -275,6 +278,148 @@ class Infobar {
}
}
/**
* The XULAccessibleInfobar handles building the XUL infobar markup where it isn't
* possible with the regular accessible highlighter.
*/
class XULWindowInfobar extends Infobar {
/**
* A helper function that calculates the positioning of a XUL accessible's infobar.
*
* @param {Object} container
* The infobar container.
*/
_moveInfobar(container) {
const arrow = this.getElement("arrow");
// Show the container and arrow elements first.
container.removeAttribute("hidden");
arrow.removeAttribute("hidden");
// Set the left value of the infobar container in relation to
// highlighter's bounds position.
const {
left: boundsLeft,
right: boundsRight,
top: boundsTop,
bottom: boundsBottom,
} = this.bounds;
const boundsMidPoint = (boundsLeft + boundsRight) / 2;
container.style.left = `${boundsMidPoint}px`;
const zoom = getCurrentZoom(this.win);
let {
width: viewportWidth,
height: viewportHeight,
} = getViewportDimensions(this.win);
const { width, height, left } = container.getBoundingClientRect();
const containerHalfWidth = width / 2;
const containerHeight = height;
const margin = 100 * zoom;
viewportHeight *= zoom;
viewportWidth *= zoom;
// Determine viewport boundaries for infobar.
const topBoundary = margin;
const bottomBoundary = viewportHeight - containerHeight;
const leftBoundary = containerHalfWidth;
const rightBoundary = viewportWidth - containerHalfWidth;
// Determine if an infobar's position is offscreen.
const isOffScreenOnTop = boundsBottom < topBoundary;
const isOffScreenOnBottom = boundsBottom > bottomBoundary;
const isOffScreenOnLeft = left < leftBoundary;
const isOffScreenOnRight = left > rightBoundary;
// Check if infobar is offscreen on either left/right of viewport and position.
if (isOffScreenOnLeft) {
container.style.left = `${leftBoundary + boundsLeft}px`;
arrow.setAttribute("hidden", "true");
} else if (isOffScreenOnRight) {
const leftOffset = rightBoundary - boundsRight;
container.style.left = `${rightBoundary -
leftOffset -
containerHalfWidth}px`;
arrow.setAttribute("hidden", "true");
}
// Check if infobar is offscreen on either top/bottom of viewport and position.
const bubbleArrowSize = "var(--highlighter-bubble-arrow-size)";
if (isOffScreenOnTop) {
if (boundsTop < 0) {
container.style.top = bubbleArrowSize;
} else {
container.style.top = `calc(${boundsBottom}px + ${bubbleArrowSize})`;
}
arrow.setAttribute("class", "accessible-arrow top");
} else if (isOffScreenOnBottom) {
container.style.top = `calc(${bottomBoundary}px - ${bubbleArrowSize})`;
arrow.setAttribute("hidden", "true");
} else {
container.style.top = `calc(${boundsTop}px -
(${containerHeight}px + ${bubbleArrowSize}))`;
arrow.setAttribute("class", "accessible-arrow bottom");
}
}
/**
* Build markup for XUL window infobar.
*
* @param {Element} root
* Root element to build infobar with.
*/
buildMarkup(root) {
super.buildMarkup(root, createNode);
createNode(this.win, {
parent: this.getElement("infobar"),
attributes: {
class: "arrow",
id: "arrow",
},
prefix: this.prefix,
});
}
/**
* Override of Infobar class's getTextContent method.
*
* @param {String} id
* Element ID to retrieve text content from.
* @return {String} Returns the text content of the element.
*/
getTextContent(id) {
return this.getElement(id).textContent;
}
/**
* Override of Infobar class's getElement method.
*
* @param {String} id
* Element ID.
* @return {String} Returns the specified element.
*/
getElement(id) {
return this.win.document.getElementById(`${this.prefix}${id}`);
}
/**
* Override of Infobar class's setTextContent method.
*
* @param {Element} el
* Element to set text content on.
* @param {String} text
* Text for content.
*/
setTextContent(el, text) {
el.textContent = text;
}
}
/**
* Audit component used within the accessible highlighter infobar. This component is
* responsible for rendering and updating its containing AuditReport components that
@ -689,70 +834,38 @@ class TextLabel extends AuditReport {
* width of the the accessible object
* - {Number} h
* height of the the accessible object
* - {Number} zoom
* zoom level of the accessible object's parent window
* @return {Object|null} Returns, if available, positioning and bounds information for
* the accessible object.
*/
function getBounds(win, { x, y, w, h }) {
const { mozInnerScreenX, mozInnerScreenY, scrollX, scrollY } = win;
const zoom = getCurrentZoom(win);
function getBounds(win, { x, y, w, h, zoom }) {
let { mozInnerScreenX, mozInnerScreenY, scrollX, scrollY } = win;
let zoomFactor = getCurrentZoom(win);
let left = x;
let right = x + w;
let top = y;
let bottom = y + h;
// For a XUL accessible, normalize the top-level window with its current zoom level.
// We need to do this because top-level browser content does not allow zooming.
if (zoom) {
zoomFactor = zoom;
mozInnerScreenX /= zoomFactor;
mozInnerScreenY /= zoomFactor;
scrollX /= zoomFactor;
scrollY /= zoomFactor;
}
left -= mozInnerScreenX - scrollX;
right -= mozInnerScreenX - scrollX;
top -= mozInnerScreenY - scrollY;
bottom -= mozInnerScreenY - scrollY;
left *= zoom;
right *= zoom;
top *= zoom;
bottom *= zoom;
const width = right - left;
const height = bottom - top;
return { left, right, top, bottom, width, height };
}
/**
* A helper function that calculate accessible object bounds and positioning to
* be used for highlighting in browser toolbox.
*
* @param {Object} win
* window that contains accessible object.
* @param {Object} options
* Object used for passing options:
* - {Number} x
* x coordinate of the top left corner of the accessible object
* - {Number} y
* y coordinate of the top left corner of the accessible object
* - {Number} w
* width of the the accessible object
* - {Number} h
* height of the the accessible object
* - {Number} zoom
* zoom level of the accessible object's parent window
* @return {Object|null} Returns, if available, positioning and bounds information for
* the accessible object.
*/
function getBoundsXUL(win, { x, y, w, h, zoom }) {
const { mozInnerScreenX, mozInnerScreenY } = win;
let left = x;
let right = x + w;
let top = y;
let bottom = y + h;
left *= zoom;
right *= zoom;
top *= zoom;
bottom *= zoom;
left -= mozInnerScreenX;
right -= mozInnerScreenX;
top -= mozInnerScreenY;
bottom -= mozInnerScreenY;
left *= zoomFactor;
right *= zoomFactor;
top *= zoomFactor;
bottom *= zoomFactor;
const width = right - left;
const height = bottom - top;
@ -762,5 +875,5 @@ function getBoundsXUL(win, { x, y, w, h, zoom }) {
exports.MAX_STRING_LENGTH = MAX_STRING_LENGTH;
exports.getBounds = getBounds;
exports.getBoundsXUL = getBoundsXUL;
exports.Infobar = Infobar;
exports.XULWindowInfobar = XULWindowInfobar;

View File

@ -236,6 +236,18 @@ exports.createNode = createNode;
function CanvasFrameAnonymousContentHelper(highlighterEnv, nodeBuilder) {
this.highlighterEnv = highlighterEnv;
this.nodeBuilder = nodeBuilder;
this.anonymousContentDocument = this.highlighterEnv.document;
// XXX the next line is a wallpaper for bug 1123362.
this.anonymousContentGlobal = Cu.getGlobalForObject(
this.anonymousContentDocument
);
// Only try to create the highlighter when the document is loaded,
// otherwise, wait for the window-ready event to fire.
const doc = this.highlighterEnv.document;
if (doc.documentElement && doc.readyState != "uninitialized") {
this._insert();
}
this._onWindowReady = this._onWindowReady.bind(this);
this.highlighterEnv.on("window-ready", this._onWindowReady);
@ -245,83 +257,37 @@ function CanvasFrameAnonymousContentHelper(highlighterEnv, nodeBuilder) {
}
CanvasFrameAnonymousContentHelper.prototype = {
initialize() {
// _insert will resolve this promise once the markup is displayed
const onInitialized = new Promise(resolve => {
this._initialized = resolve;
});
// Only try to create the highlighter when the document is loaded,
// otherwise, wait for the window-ready event to fire.
const doc = this.highlighterEnv.document;
if (doc.documentElement && doc.readyState != "uninitialized") {
this._insert();
}
return onInitialized;
},
destroy() {
this._remove();
if (this._iframe) {
this._iframe.remove();
this._iframe = null;
}
this.highlighterEnv.off("window-ready", this._onWindowReady);
this.highlighterEnv = this.nodeBuilder = this._content = null;
this.anonymousContentDocument = null;
this.anonymousContentWindow = null;
this.pageListenerTarget = null;
this.anonymousContentGlobal = null;
this._removeAllListeners();
this.elements.clear();
},
async _insert() {
await waitForContentLoaded(this.highlighterEnv.window);
const chromeWindow = this.highlighterEnv.window.browsingContext
.topChromeWindow;
if (isXUL(this.highlighterEnv.window) && chromeWindow) {
// In order to use anonymous content, we need to create and use an IFRAME
// inside a XUL document first and use its window/document the same way we
// would normally use highlighter environment's window/document. See
// TODO: bug 1594587 for more details.
//
// Note: xul:window is not necessarily the top chrome window (as it's the
// case with about:devtools-toolbox). We need to ensure that we use the
// top chrome window to look up or create the iframe.
if (!this._iframe) {
const { documentElement } = chromeWindow.document;
this._iframe = documentElement.querySelector(
":scope > .devtools-highlighter-renderer"
);
if (!this._iframe) {
this._iframe = chromeWindow.document.createElement("iframe");
this._iframe.classList.add("devtools-highlighter-renderer");
documentElement.append(this._iframe);
}
}
await waitForContentLoaded(this._iframe.contentWindow);
// If it's a XUL window anonymous content will be inserted inside a newly
// created IFRAME in the chrome window.
this.anonymousContentDocument = this._iframe.contentDocument;
this.anonymousContentWindow = this._iframe.contentWindow;
this.pageListenerTarget = this._iframe.contentWindow;
} else {
// Regular highlighters are drawn inside the anonymous content of the
// highlighter environment document.
this.anonymousContentDocument = this.highlighterEnv.document;
this.anonymousContentWindow = this.highlighterEnv.window;
this.pageListenerTarget = this.highlighterEnv.pageListenerTarget;
_insert() {
const doc = this.highlighterEnv.document;
// Wait for DOMContentLoaded before injecting the anonymous content.
if (doc.readyState != "interactive" && doc.readyState != "complete") {
doc.addEventListener("DOMContentLoaded", this._insert.bind(this), {
once: true,
});
return;
}
// Reject XUL documents. Check that after DOMContentLoaded as we query
// documentElement which is only available after this event.
if (isXUL(this.highlighterEnv.window)) {
return;
}
// For now highlighters.css is injected in content as a ua sheet because
// we no longer support scoped style sheets (see bug 1345702).
// If it did, highlighters.css would be injected as an anonymous content
// node using CanvasFrameAnonymousContentHelper instead.
loadSheet(this.anonymousContentWindow, STYLESHEET_URI);
loadSheet(this.highlighterEnv.window, STYLESHEET_URI);
const node = this.nodeBuilder();
@ -331,9 +297,7 @@ CanvasFrameAnonymousContentHelper.prototype = {
// that scenario, fixes when we're adding anonymous content in a tab that
// is not the active one (see bug 1260043 and bug 1260044)
try {
this._content = this.anonymousContentDocument.insertAnonymousContent(
node
);
this._content = doc.insertAnonymousContent(node);
} catch (e) {
// If the `insertAnonymousContent` fails throwing a `NS_ERROR_UNEXPECTED`, it means
// we don't have access to a `CustomContentContainer` yet (see bug 1365075).
@ -342,30 +306,26 @@ CanvasFrameAnonymousContentHelper.prototype = {
// again.
if (
e.result === Cr.NS_ERROR_UNEXPECTED &&
this.anonymousContentDocument.readyState === "interactive"
doc.readyState === "interactive"
) {
// The next state change will be "complete" since the current is "interactive"
await new Promise(resolve => {
this.anonymousContentDocument.addEventListener(
"readystatechange",
resolve,
{ once: true }
);
});
this._content = this.anonymousContentDocument.insertAnonymousContent(
node
doc.addEventListener(
"readystatechange",
() => {
this._content = doc.insertAnonymousContent(node);
},
{ once: true }
);
} else {
throw e;
}
}
this._initialized();
},
_remove() {
try {
this.anonymousContentDocument.removeAnonymousContent(this._content);
const doc = this.anonymousContentDocument;
doc.removeAnonymousContent(this._content);
} catch (e) {
// If the current window isn't the one the content was inserted into, this
// will fail, but that's fine.
@ -384,6 +344,7 @@ CanvasFrameAnonymousContentHelper.prototype = {
this._removeAllListeners();
this.elements.clear();
this._insert();
this.anonymousContentDocument = this.highlighterEnv.document;
}
},
@ -472,7 +433,7 @@ CanvasFrameAnonymousContentHelper.prototype = {
// If no one is listening for this type of event yet, add one listener.
if (!this.listeners.has(type)) {
const target = this.pageListenerTarget;
const target = this.highlighterEnv.pageListenerTarget;
target.addEventListener(type, this, true);
// Each type entry in the map is a map of ids:handlers.
this.listeners.set(type, new Map());
@ -497,7 +458,7 @@ CanvasFrameAnonymousContentHelper.prototype = {
// If no one is listening for event type anymore, remove the listener.
if (!this.listeners.has(type)) {
const target = this.pageListenerTarget;
const target = this.highlighterEnv.pageListenerTarget;
target.removeEventListener(type, this, true);
}
},
@ -540,8 +501,8 @@ CanvasFrameAnonymousContentHelper.prototype = {
},
_removeAllListeners() {
if (this.pageListenerTarget) {
const target = this.pageListenerTarget;
if (this.highlighterEnv && this.highlighterEnv.pageListenerTarget) {
const target = this.highlighterEnv.pageListenerTarget;
for (const [type] of this.listeners) {
target.removeEventListener(type, this, true);
}
@ -638,25 +599,6 @@ CanvasFrameAnonymousContentHelper.prototype = {
};
exports.CanvasFrameAnonymousContentHelper = CanvasFrameAnonymousContentHelper;
/**
* Wait for document readyness.
* @param {Object} win
* Window for which the content should be loaded.
*/
function waitForContentLoaded(win) {
const { document } = win;
if (
document.readyState == "interactive" ||
document.readyState == "complete"
) {
return Promise.resolve();
}
return new Promise(resolve => {
win.addEventListener("DOMContentLoaded", resolve, { once: true });
});
}
/**
* Move the infobar to the right place in the highlighter. This helper method is utilized
* in both css-grid.js and box-model.js to help position the infobar in an appropriate

View File

@ -0,0 +1,469 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {
getBounds,
XULWindowInfobar,
} = require("devtools/server/actors/highlighters/utils/accessibility");
const {
createNode,
isNodeValid,
} = require("devtools/server/actors/highlighters/utils/markup");
const { getCurrentZoom, loadSheet } = require("devtools/shared/layout/utils");
const { TEXT_NODE } = require("devtools/shared/dom-node-constants");
/**
* Stylesheet used for highlighter styling of accessible objects in chrome. It
* is consistent with the styling of an in-content accessible highlighter.
*/
const ACCESSIBLE_BOUNDS_SHEET =
"data:text/css;charset=utf-8," +
encodeURIComponent(`
.highlighter-container {
--highlighter-bubble-background-color: hsl(214, 13%, 24%);
--highlighter-bubble-border-color: rgba(255, 255, 255, 0.2);
--highlighter-bubble-arrow-size: 8px;
--grey-40: #b1b1b3;
--red-40: #ff3b6b;
--yellow-60: #d7b600;
}
.accessible-bounds {
position: fixed;
pointer-events: none;
z-index: 10;
display: block;
background-color: #6a5acd!important;
opacity: 0.6;
}
.accessible-infobar-container {
position: fixed;
max-width: 90%;
z-index: 11;
}
.accessible-infobar {
position: relative;
left: -50%;
background-color: var(--highlighter-bubble-background-color);
border: 1px solid var(--highlighter-bubble-border-color);
border-radius: 3px;
padding: 5px;
}
.accessible-arrow {
position: absolute;
width: 0;
height: 0;
border-left: var(--highlighter-bubble-arrow-size) solid transparent;
border-right: var(--highlighter-bubble-arrow-size) solid transparent;
left: calc(50% - var(--highlighter-bubble-arrow-size));
}
.top {
border-bottom: var(--highlighter-bubble-arrow-size) solid
var(--highlighter-bubble-background-color);
top: calc(-1 * var(--highlighter-bubble-arrow-size));
}
.bottom {
border-top: var(--highlighter-bubble-arrow-size) solid
var(--highlighter-bubble-background-color);
bottom: calc(-1 * var(--highlighter-bubble-arrow-size));
}
.accessible-infobar-text {
display: grid;
grid-template-areas:
"role name"
"audit audit";
grid-template-columns: min-content 1fr;
overflow: hidden;
white-space: nowrap;
justify-content: center;
}
.accessible-infobar-role {
color: #9CDCFE;
grid-area: role;
}
.accessible-infobar-name {
grid-area: name;
}
.accessible-infobar-audit {
grid-area: audit;
padding-top: 5px;
padding-bottom: 2px;
}
.accessible-infobar-name,
.accessible-infobar-audit {
color: hsl(210, 30%, 85%);
}
.accessible-infobar-audit .accessible-contrast-ratio:empty::before,
.accessible-infobar-audit .accessible-contrast-ratio:empty::after,
.accessible-infobar-name:empty {
display: none;
}
.accessible-infobar-audit .accessible-contrast-ratio::before {
content: "";
height: 8px;
width: 8px;
display: inline-flex;
background-color: var(--accessibility-highlighter-contrast-ratio-color);
box-shadow: 0 0 0 1px var(--grey-40),
4px 3px var(--accessibility-highlighter-contrast-ratio-bg),
4px 3px 0 1px var(--grey-40);
margin-inline-start: 3px;
margin-inline-end: 9px;
}
.accessible-infobar-audit .accessible-contrast-ratio::after {
margin-inline-start: 2px;
}
.accessible-infobar-audit .accessible-contrast-ratio.AA::after,
.accessible-infobar-audit .accessible-contrast-ratio.AAA::after {
color: #90E274;
}
.accessible-infobar-audit .accessible-audit::before,
.accessible-infobar-audit .accessible-contrast-ratio.FAIL::after {
display: inline-block;
width: 12px;
height: 12px;
content: "";
vertical-align: -2px;
background-position: center;
background-repeat: no-repeat;
-moz-context-properties: fill;
}
.accessible-infobar-audit .accessible-contrast-ratio.FAIL:after {
color: #E57180;
margin-inline-start: 3px;
background-image: url(chrome://devtools/skin/images/error-small.svg);
fill: var(--red-40);
}
.accessible-infobar-audit .accessible-contrast-ratio.AA::after {
content: "AA\u2713";
}
.accessible-infobar-audit .accessible-contrast-ratio.AAA::after {
content: "AAA\u2713";
}
.accessible-infobar-audit .accessible-contrast-ratio-label,
.accessible-infobar-audit .accessible-contrast-ratio-separator::before {
margin-inline-end: 3px;
}
.accessible-infobar-audit .accessible-contrast-ratio-separator::before {
content: "-";
margin-inline-start: 3px;
}
.accessible-infobar-audit .accessible-audit {
display: block;
padding-block-end: 5px;
}
.accessible-infobar-audit .accessible-audit:last-child {
padding-block-end: 0;
}
.accessible-infobar-audit .accessible-audit::before {
margin-inline-end: 4px;
background-image: none;
fill: currentColor;
}
.accessible-infobar-audit .accessible-audit.FAIL::before {
background-image: url(chrome://devtools/skin/images/error-small.svg);
fill: var(--red-40);
}
.accessible-infobar-audit .accessible-audit.WARNING::before {
background-image: url(chrome://devtools/skin/images/alert-small.svg);
fill: var(--yellow-60);
}
.accessible-infobar-audit .accessible-audit.BEST_PRACTICES::before {
background-image: url(chrome://devtools/skin/images/info-small.svg);
}
.accessible-infobar-name {
border-inline-start: 1px solid #5a6169;
margin-inline-start: 6px;
padding-inline-start: 6px;
}`);
/**
* The XULWindowAccessibleHighlighter is a class that has the same API as the
* AccessibleHighlighter, and by extension other highlighters that implement
* auto-refresh highlighter, but instead of drawing in canvas frame anonymous
* content (that is not available for chrome accessible highlighting) it adds a
* transparrent inactionable element with the same position and bounds as the
* accessible object highlighted. Unlike SimpleOutlineHighlighter, we can't use
* element (that corresponds to accessible object) itself because the accessible
* position and bounds are calculated differently.
*
* It is used when canvasframe-based AccessibleHighlighter can't be used. This
* is the case for XUL windows.
*/
class XULWindowAccessibleHighlighter {
constructor(highlighterEnv) {
this.ID_CLASS_PREFIX = "accessible-";
this.highlighterEnv = highlighterEnv;
this.win = highlighterEnv.window;
this.accessibleInfobar = new XULWindowInfobar(this);
}
/**
* Static getter that indicates that XULWindowAccessibleHighlighter supports
* highlighting in XUL windows.
*/
static get XULSupported() {
return true;
}
/**
* Build highlighter markup.
*/
_buildMarkup() {
const doc = this.win.document;
loadSheet(doc.ownerGlobal, ACCESSIBLE_BOUNDS_SHEET);
this.container = createNode(this.win, {
parent: doc.body || doc.documentElement,
attributes: {
class: "highlighter-container",
"aria-hidden": "true",
},
});
this.bounds = createNode(this.win, {
parent: this.container,
attributes: {
class: "accessible-bounds",
},
});
this.accessibleInfobar.buildMarkup(this.container);
}
/**
* Get current accessible bounds.
*
* @return {Object|null} Returns, if available, positioning and bounds
* information for the accessible object.
*/
get _bounds() {
// Zoom level for the top level browser window does not change and only inner frames
// do. So we need to get the zoom level of the current node's parent window.
const zoom = getCurrentZoom(this.currentNode);
return getBounds(this.win, { ...this.options, zoom });
}
/**
* Show the highlighter on a given accessible.
*
* @param {DOMNode} node
* A dom node that corresponds to the accessible object.
* @param {Object} options
* Object used for passing options. Available options:
* - {Number} x
* x coordinate of the top left corner of the accessible object
* - {Number} y
* y coordinate of the top left corner of the accessible object
* - {Number} w
* width of the the accessible object
* - {Number} h
* height of the the accessible object
* - duration {Number}
* Duration of time that the highlighter should be shown.
* - {String|null} name
* name of the the accessible object
* - {String} role
* role of the the accessible object
*
* @return {Boolean} True if accessible is highlighted, false otherwise.
*/
show(node, options = {}) {
const isSameNode = node === this.currentNode;
const hasBounds =
options &&
typeof options.x == "number" &&
typeof options.y == "number" &&
typeof options.w == "number" &&
typeof options.h == "number";
if (!hasBounds || !this._isNodeValid(node) || isSameNode) {
return false;
}
this.options = options;
this.currentNode = node;
return this._show();
}
/**
* Internal show method that updates bounds and tracks duration based
* highlighting.
*
* @return {Boolean} True if accessible is highlighted, false otherwise.
*/
_show() {
if (this._highlightTimer) {
clearTimeout(this._highlightTimer);
this._highlightTimer = null;
}
const shown = this._update();
const { duration } = this.options;
if (shown && duration) {
this._highlightTimer = setTimeout(() => {
this._hideAccessibleBounds();
}, duration);
}
return shown;
}
/**
* Update accessible bounds for a current accessible. Re-draw highlighter
* markup.
*
* @return {Boolean} True if accessible is highlighted, false otherwise.
*/
_update() {
this._hideAccessibleBounds();
const bounds = this._bounds;
if (!bounds) {
return false;
}
let boundsEl = this.bounds;
if (!boundsEl) {
this._buildMarkup();
boundsEl = this.bounds;
}
const { left, top, width, height } = bounds;
boundsEl.style.top = `${top}px`;
boundsEl.style.left = `${left}px`;
boundsEl.style.width = `${width}px`;
boundsEl.style.height = `${height}px`;
this._showAccessibleBounds();
this.accessibleInfobar.show();
return true;
}
/**
* Hide the highlighter
*/
hide() {
if (!this.currentNode || !this.highlighterEnv.window) {
return;
}
this._hideAccessibleBounds();
this.accessibleInfobar.hide();
this.currentNode = null;
this.options = null;
}
/**
* Check if node is a valid element or text node.
*
* @param {DOMNode} node
* The node to highlight.
* @return {Boolean} whether or not node is valid.
*/
_isNodeValid(node) {
return isNodeValid(node) || isNodeValid(node, TEXT_NODE);
}
/**
* Public API method to temporarily hide accessible bounds for things like
* color contrast calculation.
*/
hideAccessibleBounds() {
if (this.container.hasAttribute("hidden")) {
return;
}
this._hideAccessibleBounds();
this._shouldRestoreBoundsVisibility = true;
}
/**
* Public API method to show accessible bounds in case they were temporarily
* hidden.
*/
showAccessibleBounds() {
if (this._shouldRestoreBoundsVisibility) {
this._showAccessibleBounds();
}
}
/**
* Show accessible bounds highlighter.
*/
_showAccessibleBounds() {
this._shouldRestoreBoundsVisibility = null;
if (this.container) {
if (!this.currentNode || !this.highlighterEnv.window) {
return;
}
this.container.removeAttribute("hidden");
}
}
/**
* Hide accessible bounds highlighter.
*/
_hideAccessibleBounds() {
this._shouldRestoreBoundsVisibility = null;
if (this.container) {
this.container.setAttribute("hidden", "true");
}
}
/**
* Hide accessible highlighter, clean up and remove the markup.
*/
destroy() {
if (this._highlightTimer) {
clearTimeout(this._highlightTimer);
this._highlightTimer = null;
}
this.hide();
if (this.container) {
this.container.remove();
}
this.accessibleInfobar.destroy();
this.accessibleInfobar = null;
this.win = null;
}
}
exports.XULWindowAccessibleHighlighter = XULWindowAccessibleHighlighter;

View File

@ -216,10 +216,8 @@ exports.InspectorActor = protocol.ActorClassWithSpec(inspectorSpec, {
return this._highlighterPromise;
}
this._highlighterPromise = this.getWalker().then(async walker => {
this._highlighterPromise = this.getWalker().then(walker => {
const highlighter = HighlighterActor(this, autohide);
await highlighter.initializeInstance();
await highlighter.instance.isReady;
this.manage(highlighter);
return highlighter;
});
@ -237,14 +235,9 @@ exports.InspectorActor = protocol.ActorClassWithSpec(inspectorSpec, {
* @return {Highlighter} The highlighter actor instance or null if the
* typeName passed doesn't match any available highlighter
*/
getHighlighterByType: async function(typeName) {
getHighlighterByType: function(typeName) {
if (isTypeRegistered(typeName)) {
const highlighterActor = CustomHighlighterActor(this, typeName);
if (highlighterActor.instance.isReady) {
await highlighterActor.instance.isReady;
}
return highlighterActor;
return CustomHighlighterActor(this, typeName);
}
return null;
},
@ -303,7 +296,6 @@ exports.InspectorActor = protocol.ActorClassWithSpec(inspectorSpec, {
this._highlighterEnv = new HighlighterEnvironment();
this._highlighterEnv.initFromTargetActor(this.targetActor);
this._eyeDropper = new EyeDropper(this._highlighterEnv);
return this._eyeDropper.isReady;
},
/**
@ -325,8 +317,8 @@ exports.InspectorActor = protocol.ActorClassWithSpec(inspectorSpec, {
* cancels the picker.
* @param {Object} options
*/
pickColorFromPage: async function(options) {
await this.createEyeDropper();
pickColorFromPage: function(options) {
this.createEyeDropper();
this._eyeDropper.show(this.window.document.documentElement, options);
this._eyeDropper.once("selected", this._onColorPicked);
this._eyeDropper.once("canceled", this._onColorPickCanceled);

View File

@ -515,7 +515,7 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
return highlighter;
},
async showOverlay() {
showOverlay() {
if (
this._options.shouldShowOverlay &&
this.isPaused() &&
@ -525,7 +525,6 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
this.pauseOverlay
) {
const reason = this._priorPause.why.type;
await this.pauseOverlay.isReady;
this.pauseOverlay.show(null, { reason });
}
},

View File

@ -104,7 +104,6 @@ fail-if = fission
[browser_canvasframe_helper_01.js]
skip-if = e10s # Bug 1183605 - devtools/server/tests/browser/ tests are still disabled in E10S
[browser_canvasframe_helper_02.js]
skip-if = true # iframe will not be loaded in xul:window with strict xhtml.
[browser_canvasframe_helper_03.js]
skip-if = e10s # Bug 1183605 - devtools/server/tests/browser/ tests are still disabled in E10S
[browser_canvasframe_helper_04.js]

View File

@ -99,7 +99,6 @@ add_task(async function() {
const node = content.document.createElement("div");
content.document.body.append(node);
const highlighter = new AccessibleHighlighter(env);
await highlighter.isReady;
const infobar = highlighter.accessibleInfobar;
const bounds = {
x: 0,

View File

@ -100,7 +100,6 @@ add_task(async function() {
const node = content.document.createElement("div");
content.document.body.append(node);
const highlighter = new AccessibleHighlighter(env);
await highlighter.isReady;
const infobar = highlighter.accessibleInfobar;
const bounds = {
x: 0,

View File

@ -23,6 +23,9 @@ add_task(async function() {
const {
AccessibleHighlighter,
} = require("devtools/server/actors/highlighters/accessible");
const {
XULWindowAccessibleHighlighter,
} = require("devtools/server/actors/highlighters/xul-accessible");
/**
* Get whether or not infobar container is hidden.
@ -173,8 +176,11 @@ add_task(async function() {
info("Checks for Infobar's show method");
const highlighter = new AccessibleHighlighter(env);
await highlighter.isReady;
testInfobar(node, highlighter);
info("Checks for XULWindowInfobar's show method");
const xulWindowHighlighter = new XULWindowAccessibleHighlighter(env);
testInfobar(node, xulWindowHighlighter);
});
}
);

View File

@ -38,7 +38,6 @@ add_task(async function() {
const env = new HighlighterEnvironment();
env.initFromWindow(doc.defaultView);
const helper = new CanvasFrameAnonymousContentHelper(env, nodeBuilder);
await helper.initialize();
ok(
helper.content instanceof content.AnonymousContent,

View File

@ -37,7 +37,6 @@ add_task(async function() {
const env = new HighlighterEnvironment();
env.initFromWindow(doc.defaultView);
const helper = new CanvasFrameAnonymousContentHelper(env, nodeBuilder);
await helper.initialize();
const el = helper.getElement("child-element");

View File

@ -41,7 +41,6 @@ add_task(async function() {
const env = new HighlighterEnvironment();
env.initFromWindow(doc.defaultView);
const helper = new CanvasFrameAnonymousContentHelper(env, nodeBuilder);
await helper.initialize();
info("Get an element from the helper");
const el = helper.getElement("child-element");

View File

@ -45,7 +45,6 @@ add_task(async function() {
const env = new HighlighterEnvironment();
env.initFromWindow(doc.defaultView);
const helper = new CanvasFrameAnonymousContentHelper(env, nodeBuilder);
await helper.initialize();
info("Getting the parent and child elements");
const parentEl = helper.getElement("parent-element");

View File

@ -45,7 +45,6 @@ add_task(async function() {
const env = new HighlighterEnvironment();
env.initFromWindow(doc.defaultView);
const helper = new CanvasFrameAnonymousContentHelper(env, nodeBuilder);
await helper.initialize();
info("Getting the parent and child elements");
const parentEl = helper.getElement("parent-element");

View File

@ -14,7 +14,7 @@ Test the PausedDebuggerOverlay highlighter.
<script>
"use strict";
window.onload = async function() {
window.onload = function() {
SimpleTest.waitForExplicitFinish();
const {require} = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
@ -26,7 +26,6 @@ window.onload = async function() {
env.initFromWindow(window);
const highlighter = new PausedDebuggerOverlay(env);
await highlighter.isReady;
const anonymousContent = highlighter.markup.content;
const id = elementID => `${highlighter.ID_CLASS_PREFIX}${elementID}`;