/* 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/. */
nameChange(name, parent) { this._form.name = name; // Name change event affects the tree rendering, we fire this event on // accessibility walker as the point of interaction for UI. const accessibilityWalkerFront = this.getParent(); if (accessibilityWalkerFront) {
events.emit(accessibilityWalkerFront, "name-change", this, parent);
}
}
reorder(childCount) { this._form.childCount = childCount; // Reorder event affects the tree rendering, we fire this event on // accessibility walker as the point of interaction for UI. const accessibilityWalkerFront = this.getParent(); if (accessibilityWalkerFront) {
events.emit(accessibilityWalkerFront, "reorder", this);
}
}
textChange() { // Text event affects the tree rendering, we fire this event on // accessibility walker as the point of interaction for UI. const accessibilityWalkerFront = this.getParent(); if (accessibilityWalkerFront) {
events.emit(accessibilityWalkerFront, "text-change", this);
}
}
async children() { if (!this.useChildTargetToFetchChildren) { returnsuper.children();
}
const { walker: domWalkerFront } =
await this.targetFront.getFront("inspector"); const node = await domWalkerFront.getNodeFromActor(this.actorID, [ "rawAccessible", "DOMNode",
]); // We are using DOM inspector/walker API here because we want to keep both // the accessiblity tree and the DOM tree in sync. This is necessary for // several features that the accessibility panel provides such as inspecting // a corresponding DOM node or any other functionality that requires DOM // node ancestries to be resolved all the way up to the top level document. const {
nodes: [documentNodeFront],
} = await domWalkerFront.children(node); const accessibilityFront =
await documentNodeFront.targetFront.getFront("accessibility");
/** * Helper function that helps with building a complete snapshot of * accessibility tree starting at the level of current accessible front. It * accumulates subtrees from possible out of process frames that are children * of the current accessible front. * @param {JSON} snapshot * Snapshot of the current accessible front or one of its in process * children when recursing. * * @return {JSON} * Complete snapshot of current accessible front.
*/
async _accumulateSnapshot(snapshot) { const { childCount, useChildTargetToFetchChildren } = snapshot; // No children, we are done. if (childCount === 0) { return snapshot;
}
// If current accessible is not a remote frame, continue accumulating inside // its children. if (!useChildTargetToFetchChildren) { const childSnapshots = []; for (const childSnapshot of snapshot.children) {
childSnapshots.push(this._accumulateSnapshot(childSnapshot));
}
await Promise.all(childSnapshots); return snapshot;
}
// When we have a remote frame, we need to obtain an accessible front for a // remote frame document and retrieve its snapshot. const inspectorFront = await this.targetFront.getFront("inspector"); const frameNodeFront =
await inspectorFront.getNodeActorFromContentDomReference(
snapshot.contentDOMReference
); // Remove contentDOMReference and useChildTargetToFetchChildren properties. delete snapshot.contentDOMReference; delete snapshot.useChildTargetToFetchChildren; if (!frameNodeFront) { return snapshot;
}
// Remote frame lives in the same process as the current accessible // front we can retrieve the accessible front directly. const frameAccessibleFront =
await this.parentFront.getAccessibleFor(frameNodeFront); if (!frameAccessibleFront) { return snapshot;
}
/** * Retrieves a complete JSON snapshot for an accessible subtree of a given * accessible front (inclduing OOP frames).
*/
async snapshot() { const snapshot = await super.snapshot();
await this._accumulateSnapshot(snapshot); return snapshot;
}
}
documentReady() { if (this.targetFront.isTopLevel) { this.emit("top-level-document-ready");
}
}
pick(doFocus) { if (doFocus) { returnthis.pickAndFocus();
}
returnsuper.pick();
}
/** * Get the accessible object ancestry starting from the given accessible to * the top level document. The top level document is in the top level content process. * @param {Object} accessible * Accessible front to determine the ancestry for. * * @return {Array} ancestry * List of ancestry objects which consist of an accessible with its * children.
*/
async getAncestry(accessible) { const ancestry = await super.getAncestry(accessible);
// Get an accessible front for the parent frame. We go through the // inspector's walker to keep both inspector and accessibility trees in // sync. const { walker: domWalkerFront } =
await this.targetFront.getFront("inspector"); const frameNodeFront = (await domWalkerFront.getRootNode()).parentNode(); const accessibilityFront = await parentTarget.getFront("accessibility"); const { accessibleWalkerFront } = accessibilityFront; const frameAccessibleFront =
await accessibleWalkerFront.getAccessibleFor(frameNodeFront);
if (!frameAccessibleFront) { // Most likely we are inside a hidden frame. return Promise.reject(
`Can't get the ancestry for an accessible front ${accessible.actorID}. It is in the detached tree.`
);
}
// Compose the final ancestry out of ancestry for the given accessible in // the current process and recursively get the ancestry for the frame // accessible.
ancestry.push(
{
accessible: frameAccessibleFront,
children: await frameAccessibleFront.children(),
},
...(await accessibleWalkerFront.getAncestry(frameAccessibleFront))
);
return ancestry;
}
/** * Run an accessibility audit for a document that accessibility walker is * responsible for (in process). In addition to plainly running an audit (in * cases when the document is in the OOP frame), this method also updates * relative ancestries of audited accessible objects all the way up to the top * level document for the toolbox. * @param {Object} options * - {Array} types * types of the accessibility issues to audit for * - {Function} onProgress * callback function for a progress audit-event * - {Boolean} retrieveAncestries (defaults to true) * Set to false to _not_ retrieve ancestries of audited accessible objects. * This is used when a specific document is selected in the iframe picker * and we want to treat it as the root of the accessibility panel tree.
*/
async audit({ types, onProgress, retrieveAncestries = true }) { const onAudit = new Promise(resolve => { const auditEventHandler = ({ type, ancestries, progress }) => { switch (type) { case"error": this.off("audit-event", auditEventHandler);
resolve({ error: true }); break; case"completed": this.off("audit-event", auditEventHandler);
resolve({ ancestries }); break; case"progress":
onProgress(progress); break; default: break;
}
};
const audit = await onAudit; // If audit resulted in an error, if there's nothing to report or if the callsite // explicitly asked to not retrieve ancestries, we are done. // (no need to check for ancestry across the remote frame hierarchy). // See also https://bugzilla.mozilla.org/show_bug.cgi?id=1641551 why the rest of // the code path is only supported when content toolbox fission is enabled. if (audit.error || audit.ancestries.length === 0 || !retrieveAncestries) { return audit;
}
const parentTarget = await this.targetFront.getParentTarget(); // If there is no parent target, we do not need to update ancestries as we // are in the top level document. if (!parentTarget) { return audit;
}
// Retrieve an ancestry (cross process) for a current root document and make // audit report ancestries relative to it. const [docAccessibleFront] = await this.children();
let docAccessibleAncestry; try {
docAccessibleAncestry = await this.getAncestry(docAccessibleFront);
} catch (e) { // We are in a detached subtree. We do not consider this an error, instead // we need to ignore the audit for this frame and return an empty report. return { ancestries: [] };
} for (const ancestry of audit.ancestries) { // Compose the final ancestries out of the ones in the audit report // relative to this document and the ancestry of the document itself // (cross process).
ancestry.push(...docAccessibleAncestry);
}
return audit;
}
/** * A helper wrapper function to show tabbing order overlay for a given target. * The only additional work done is resolving domnode front from a * ContentDOMReference received from a remote target. * * @param {Object} startElm * domnode front to be used as the starting point for generating the * tabbing order. * @param {Number} startIndex * Starting index for the tabbing order.
*/
async _showTabbingOrder(startElm, startIndex) { const { contentDOMReference, index } = await super.showTabbingOrder(
startElm,
startIndex
);
let elm; if (contentDOMReference) { const inspectorFront = await this.targetFront.getFront("inspector");
elm =
await inspectorFront.getNodeActorFromContentDomReference(
contentDOMReference
);
}
return { elm, index };
}
/** * Show tabbing order overlay for a given target. * * @param {Object} startElm * domnode front to be used as the starting point for generating the * tabbing order. * @param {Number} startIndex * Starting index for the tabbing order. * * @return {JSON} * Tabbing order information for the last element in the tabbing * order. It includes a domnode front and a tabbing index. If we are * at the end of the tabbing order for the top level content document, * the domnode front will be null. If focus manager discovered a * remote IFRAME, then the domnode front is for the IFRAME itself.
*/
async showTabbingOrder(startElm, startIndex) {
let { elm: currentElm, index: currentIndex } = await this._showTabbingOrder(
startElm,
startIndex
);
// If no remote frames were found, currentElm will be null. while (currentElm) { // Safety check to ensure that the currentElm is a remote frame. if (currentElm.useChildTargetToFetchChildren) { const { walker: domWalkerFront } =
await currentElm.targetFront.getFront("inspector"); const {
nodes: [childDocumentNodeFront],
} = await domWalkerFront.children(currentElm); const { accessibleWalkerFront } =
await childDocumentNodeFront.targetFront.getFront("accessibility"); // Show tabbing order in the remote target, while updating the tabbing // index.
({ index: currentIndex } = await accessibleWalkerFront.showTabbingOrder(
childDocumentNodeFront,
currentIndex
));
}
// Finished with the remote frame, continue in tabbing order, from the // remote frame.
({ elm: currentElm, index: currentIndex } = await this._showTabbingOrder(
currentElm,
currentIndex
));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.