mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 1648161 - use accessible highlighter instead of xul-accessible highlighter in browser toolbox. Remove xul-accessible highlighter altogether. r=ochameau
Differential Revision: https://phabricator.services.mozilla.com/D80005
This commit is contained in:
parent
d0686776d2
commit
c894b69ce1
@ -1385,13 +1385,9 @@ toolbar[keyNav=true]:not([collapsed=true]):not([customizing=true]) toolbartabsto
|
||||
}
|
||||
|
||||
/* Frame used for rendering the DevTools inspector highlighters */
|
||||
iframe.devtools-highlighter-renderer {
|
||||
:root > iframe.devtools-highlighter-renderer {
|
||||
border: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Highlighter for the Browser Toolbox */
|
||||
:root > iframe.devtools-highlighter-renderer {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
@ -1399,8 +1395,3 @@ iframe.devtools-highlighter-renderer {
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* Highlighter for web content */
|
||||
.browserStack > iframe.devtools-highlighter-renderer {
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
@ -287,25 +287,10 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
|
||||
|
||||
get highlighter() {
|
||||
if (!this._highlighter) {
|
||||
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"
|
||||
);
|
||||
if (!isTypeRegistered("AccessibleHighlighter")) {
|
||||
register("AccessibleHighlighter", "accessible");
|
||||
}
|
||||
this._highlighter = CustomHighlighterActor(this, "AccessibleHighlighter");
|
||||
|
||||
this.manage(this._highlighter);
|
||||
this._highlighter.on("highlighter-event", this.onHighlighterEvent);
|
||||
@ -331,6 +316,10 @@ 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;
|
||||
@ -468,7 +457,7 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
|
||||
return this.once("document-ready").then(docAcc => this.addRef(docAcc));
|
||||
}
|
||||
|
||||
if (isXUL(this.rootWin)) {
|
||||
if (this.isXUL) {
|
||||
const doc = this.addRef(this.getRawAccessibleFor(this.rootDoc));
|
||||
return Promise.resolve(doc);
|
||||
}
|
||||
@ -851,7 +840,7 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
|
||||
const { name, role } = accessible;
|
||||
const shown = this.highlighter.show(
|
||||
{ rawNode },
|
||||
{ ...options, ...bounds, name, role, audit }
|
||||
{ ...options, ...bounds, name, role, audit, isXUL: this.isXUL }
|
||||
);
|
||||
this._highlightingAccessible = null;
|
||||
|
||||
@ -1119,7 +1108,8 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
|
||||
const target = event.originalTarget || event.target;
|
||||
const docAcc = this.getRawAccessibleFor(this.rootDoc);
|
||||
const win = target.ownerGlobal;
|
||||
const scale = this.pixelRatio / getCurrentZoom(win);
|
||||
const zoom = this.isXUL ? 1 : getCurrentZoom(win);
|
||||
const scale = this.pixelRatio / zoom;
|
||||
const rawAccessible = docAcc.getDeepestChildAtPointInProcess(
|
||||
event.screenX * scale,
|
||||
event.screenY * scale
|
||||
|
@ -17,7 +17,10 @@ const {
|
||||
TEXT_NODE,
|
||||
DOCUMENT_NODE,
|
||||
} = require("devtools/shared/dom-node-constants");
|
||||
const { setIgnoreLayoutChanges } = require("devtools/shared/layout/utils");
|
||||
const {
|
||||
getCurrentZoom,
|
||||
setIgnoreLayoutChanges,
|
||||
} = require("devtools/shared/layout/utils");
|
||||
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
@ -25,6 +28,12 @@ loader.lazyRequireGetter(
|
||||
"devtools/server/actors/highlighters/utils/accessibility",
|
||||
true
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"getBoundsXUL",
|
||||
"devtools/server/actors/highlighters/utils/accessibility",
|
||||
true
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"Infobar",
|
||||
@ -94,6 +103,14 @@ 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.
|
||||
*
|
||||
@ -318,7 +335,20 @@ class AccessibleHighlighter extends AutoRefreshHighlighter {
|
||||
* information for the accessible object.
|
||||
*/
|
||||
get _bounds() {
|
||||
return getBounds(this.win, this.options);
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,6 +24,5 @@ DevToolsModules(
|
||||
'rulers.js',
|
||||
'selector.js',
|
||||
'shapes.js',
|
||||
'simple-outline.js',
|
||||
'xul-accessible.js'
|
||||
'simple-outline.js'
|
||||
)
|
||||
|
@ -5,10 +5,7 @@
|
||||
"use strict";
|
||||
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
const {
|
||||
getCurrentZoom,
|
||||
getViewportDimensions,
|
||||
} = require("devtools/shared/layout/utils");
|
||||
const { getCurrentZoom } = require("devtools/shared/layout/utils");
|
||||
const {
|
||||
moveInfobar,
|
||||
createNode,
|
||||
@ -278,148 +275,6 @@ 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
|
||||
@ -834,38 +689,70 @@ 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, zoom }) {
|
||||
let { mozInnerScreenX, mozInnerScreenY, scrollX, scrollY } = win;
|
||||
let zoomFactor = getCurrentZoom(win);
|
||||
function getBounds(win, { x, y, w, h }) {
|
||||
const { mozInnerScreenX, mozInnerScreenY, scrollX, scrollY } = win;
|
||||
const zoom = 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 *= zoomFactor;
|
||||
right *= zoomFactor;
|
||||
top *= zoomFactor;
|
||||
bottom *= zoomFactor;
|
||||
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;
|
||||
|
||||
const width = right - left;
|
||||
const height = bottom - top;
|
||||
@ -875,5 +762,5 @@ function getBounds(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;
|
||||
|
@ -10,6 +10,7 @@ const {
|
||||
getWindowDimensions,
|
||||
getViewportDimensions,
|
||||
loadSheet,
|
||||
removeSheet,
|
||||
} = require("devtools/shared/layout/utils");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const InspectorUtils = require("InspectorUtils");
|
||||
@ -40,6 +41,22 @@ exports.removePseudoClassLock = (...args) =>
|
||||
const SVG_NS = "http://www.w3.org/2000/svg";
|
||||
const XHTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
// Highlighter in parent process will create an iframe relative to its target
|
||||
// window. We need to make sure that the iframe is styled correctly. Note:
|
||||
// this styles are taken from browser/base/content/browser.css
|
||||
// iframe.devtools-highlighter-renderer rules.
|
||||
const XUL_HIGHLIGHTER_STYLES_SHEET = `data:text/css;charset=utf-8,
|
||||
:root > iframe.devtools-highlighter-renderer {
|
||||
border: none;
|
||||
pointer-events: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
}`;
|
||||
|
||||
const STYLESHEET_URI =
|
||||
"resource://devtools/server/actors/" + "highlighters.css";
|
||||
|
||||
@ -236,11 +253,9 @@ 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
|
||||
);
|
||||
|
||||
this._insert = this._insert.bind(this);
|
||||
this._onWindowReady = this._onWindowReady.bind(this);
|
||||
|
||||
// Only try to create the highlighter when the document is loaded,
|
||||
// otherwise, wait for the window-ready event to fire.
|
||||
@ -249,7 +264,6 @@ function CanvasFrameAnonymousContentHelper(highlighterEnv, nodeBuilder) {
|
||||
this._insert();
|
||||
}
|
||||
|
||||
this._onWindowReady = this._onWindowReady.bind(this);
|
||||
this.highlighterEnv.on("window-ready", this._onWindowReady);
|
||||
|
||||
this.listeners = new Map();
|
||||
@ -259,35 +273,94 @@ function CanvasFrameAnonymousContentHelper(highlighterEnv, nodeBuilder) {
|
||||
CanvasFrameAnonymousContentHelper.prototype = {
|
||||
destroy() {
|
||||
this._remove();
|
||||
if (this._iframe) {
|
||||
// If iframe is used, remove one ref count from its numberOfHighlighters
|
||||
// data attribute.
|
||||
const numberOfHighlighters =
|
||||
parseInt(this._iframe.dataset.numberOfHighlighters, 10) - 1;
|
||||
this._iframe.dataset.numberOfHighlighters = numberOfHighlighters;
|
||||
// If we reached 0, we can now remove the iframe and its styling from
|
||||
// target window.
|
||||
if (numberOfHighlighters === 0) {
|
||||
this._iframe.remove();
|
||||
removeSheet(this.highlighterEnv.window, XUL_HIGHLIGHTER_STYLES_SHEET);
|
||||
}
|
||||
this._iframe = null;
|
||||
}
|
||||
|
||||
this.highlighterEnv.off("window-ready", this._onWindowReady);
|
||||
this.highlighterEnv = this.nodeBuilder = this._content = null;
|
||||
this.anonymousContentDocument = null;
|
||||
this.anonymousContentGlobal = null;
|
||||
this.anonymousContentWindow = null;
|
||||
this.pageListenerTarget = null;
|
||||
|
||||
this._removeAllListeners();
|
||||
this.elements.clear();
|
||||
},
|
||||
|
||||
_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,
|
||||
});
|
||||
async _insert() {
|
||||
await waitForContentLoaded(this.highlighterEnv.window);
|
||||
if (!this.highlighterEnv) {
|
||||
// CanvasFrameAnonymousContentHelper was already destroyed.
|
||||
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;
|
||||
// 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 } = this.highlighterEnv.window.document;
|
||||
this._iframe = documentElement.querySelector(
|
||||
":scope > .devtools-highlighter-renderer"
|
||||
);
|
||||
if (this._iframe) {
|
||||
// If iframe is used and already exists, add one ref count to its
|
||||
// numberOfHighlighters data attribute.
|
||||
const numberOfHighlighters =
|
||||
parseInt(this._iframe.dataset.numberOfHighlighters, 10) + 1;
|
||||
this._iframe.dataset.numberOfHighlighters = numberOfHighlighters;
|
||||
} else {
|
||||
this._iframe = this.highlighterEnv.window.document.createElement(
|
||||
"iframe"
|
||||
);
|
||||
this._iframe.classList.add("devtools-highlighter-renderer");
|
||||
// If iframe is used for the first time, add ref count of one to its
|
||||
// numberOfHighlighters data attribute.
|
||||
this._iframe.dataset.numberOfHighlighters = 1;
|
||||
documentElement.append(this._iframe);
|
||||
loadSheet(this.highlighterEnv.window, XUL_HIGHLIGHTER_STYLES_SHEET);
|
||||
}
|
||||
}
|
||||
|
||||
await waitForContentLoaded(this._iframe);
|
||||
if (!this.highlighterEnv) {
|
||||
// CanvasFrameAnonymousContentHelper was already destroyed.
|
||||
return;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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.highlighterEnv.window, STYLESHEET_URI);
|
||||
loadSheet(this.anonymousContentWindow, STYLESHEET_URI);
|
||||
|
||||
const node = this.nodeBuilder();
|
||||
|
||||
@ -297,7 +370,9 @@ 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 = doc.insertAnonymousContent(node);
|
||||
this._content = this.anonymousContentDocument.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).
|
||||
@ -306,15 +381,18 @@ CanvasFrameAnonymousContentHelper.prototype = {
|
||||
// again.
|
||||
if (
|
||||
e.result === Cr.NS_ERROR_UNEXPECTED &&
|
||||
doc.readyState === "interactive"
|
||||
this.anonymousContentDocument.readyState === "interactive"
|
||||
) {
|
||||
// The next state change will be "complete" since the current is "interactive"
|
||||
doc.addEventListener(
|
||||
"readystatechange",
|
||||
() => {
|
||||
this._content = doc.insertAnonymousContent(node);
|
||||
},
|
||||
{ once: true }
|
||||
await new Promise(resolve => {
|
||||
this.anonymousContentDocument.addEventListener(
|
||||
"readystatechange",
|
||||
resolve,
|
||||
{ once: true }
|
||||
);
|
||||
});
|
||||
this._content = this.anonymousContentDocument.insertAnonymousContent(
|
||||
node
|
||||
);
|
||||
} else {
|
||||
throw e;
|
||||
@ -324,8 +402,7 @@ CanvasFrameAnonymousContentHelper.prototype = {
|
||||
|
||||
_remove() {
|
||||
try {
|
||||
const doc = this.anonymousContentDocument;
|
||||
doc.removeAnonymousContent(this._content);
|
||||
this.anonymousContentDocument.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.
|
||||
@ -343,8 +420,16 @@ CanvasFrameAnonymousContentHelper.prototype = {
|
||||
if (isTopLevel) {
|
||||
this._removeAllListeners();
|
||||
this.elements.clear();
|
||||
if (this._iframe) {
|
||||
// When we are switching top level targets, we can remove the iframe and
|
||||
// its styling as well, since it will be re-created for the new top
|
||||
// level target document.
|
||||
this._iframe.remove();
|
||||
removeSheet(this.highlighterEnv.window, XUL_HIGHLIGHTER_STYLES_SHEET);
|
||||
this._iframe = null;
|
||||
}
|
||||
|
||||
this._insert();
|
||||
this.anonymousContentDocument = this.highlighterEnv.document;
|
||||
}
|
||||
},
|
||||
|
||||
@ -433,7 +518,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.highlighterEnv.pageListenerTarget;
|
||||
const target = this.pageListenerTarget;
|
||||
target.addEventListener(type, this, true);
|
||||
// Each type entry in the map is a map of ids:handlers.
|
||||
this.listeners.set(type, new Map());
|
||||
@ -458,7 +543,7 @@ CanvasFrameAnonymousContentHelper.prototype = {
|
||||
|
||||
// If no one is listening for event type anymore, remove the listener.
|
||||
if (!this.listeners.has(type)) {
|
||||
const target = this.highlighterEnv.pageListenerTarget;
|
||||
const target = this.pageListenerTarget;
|
||||
target.removeEventListener(type, this, true);
|
||||
}
|
||||
},
|
||||
@ -501,8 +586,8 @@ CanvasFrameAnonymousContentHelper.prototype = {
|
||||
},
|
||||
|
||||
_removeAllListeners() {
|
||||
if (this.highlighterEnv && this.highlighterEnv.pageListenerTarget) {
|
||||
const target = this.highlighterEnv.pageListenerTarget;
|
||||
if (this.pageListenerTarget) {
|
||||
const target = this.pageListenerTarget;
|
||||
for (const [type] of this.listeners) {
|
||||
target.removeEventListener(type, this, true);
|
||||
}
|
||||
@ -599,6 +684,33 @@ CanvasFrameAnonymousContentHelper.prototype = {
|
||||
};
|
||||
exports.CanvasFrameAnonymousContentHelper = CanvasFrameAnonymousContentHelper;
|
||||
|
||||
/**
|
||||
* Wait for document readyness.
|
||||
* @param {Object} iframeOrWindow
|
||||
* IFrame or Window for which the content should be loaded.
|
||||
*/
|
||||
function waitForContentLoaded(iframeOrWindow) {
|
||||
let loadEvent = "DOMContentLoaded";
|
||||
// If we are waiting for an iframe to load and it is for a XUL window
|
||||
// highlighter that is not browser toolbox, we must wait for IFRAME's "load".
|
||||
if (
|
||||
iframeOrWindow.contentWindow &&
|
||||
iframeOrWindow.ownerGlobal !==
|
||||
iframeOrWindow.contentWindow.browsingContext.topChromeWindow
|
||||
) {
|
||||
loadEvent = "load";
|
||||
}
|
||||
|
||||
const doc = iframeOrWindow.contentDocument || iframeOrWindow.document;
|
||||
if (doc.readyState == "interactive" || doc.readyState == "complete") {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return new Promise(resolve => {
|
||||
iframeOrWindow.addEventListener(loadEvent, 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
|
||||
|
@ -1,469 +0,0 @@
|
||||
/* 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;
|
@ -23,9 +23,6 @@ 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.
|
||||
@ -177,10 +174,6 @@ add_task(async function() {
|
||||
info("Checks for Infobar's show method");
|
||||
const highlighter = new AccessibleHighlighter(env);
|
||||
testInfobar(node, highlighter);
|
||||
|
||||
info("Checks for XULWindowInfobar's show method");
|
||||
const xulWindowHighlighter = new XULWindowAccessibleHighlighter(env);
|
||||
testInfobar(node, xulWindowHighlighter);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user