зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1598026 - connect to the OOP frame server when children of the remote iframe are queried. r=jdescottes
Differential Revision: https://phabricator.services.mozilla.com/D66156 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
969e685d94
Коммит
cd3662346d
|
@ -32,5 +32,6 @@ skip-if = (os == 'linux' && debug && bits == 64) # Bug 1511247
|
|||
[browser_accessibility_tree_audit_toolbar.js]
|
||||
[browser_accessibility_tree_audit.js]
|
||||
[browser_accessibility_tree_contrast.js]
|
||||
[browser_accessibility_tree_nagivation_oop.js]
|
||||
[browser_accessibility_tree_nagivation.js]
|
||||
[browser_accessibility_tree.js]
|
||||
|
|
|
@ -66,18 +66,18 @@ const tests = [
|
|||
{
|
||||
desc: "Select an accessible object.",
|
||||
setup: async env => {
|
||||
await selectAccessibleForNode(env, "body");
|
||||
await selectAccessibleForNode(env, "h1");
|
||||
},
|
||||
expected: {
|
||||
tree: [
|
||||
{
|
||||
role: "document",
|
||||
name: `"Accessibility Panel Test"`,
|
||||
selected: true,
|
||||
},
|
||||
{
|
||||
role: "heading",
|
||||
name: `"Top level header"`,
|
||||
selected: true,
|
||||
},
|
||||
{
|
||||
role: "text leaf",
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URI = `<h1>Top level header</h1><p>This is a paragraph.</p>`;
|
||||
|
||||
/**
|
||||
* Test data has the format of:
|
||||
* {
|
||||
* desc {String} description for better logging
|
||||
* setup {Function} An optional setup that needs to be performed before
|
||||
* the state of the tree and the sidebar can be checked.
|
||||
* expected {JSON} An expected states for the tree and the sidebar.
|
||||
* }
|
||||
*/
|
||||
const tests = [
|
||||
{
|
||||
desc: "Test the initial accessibility tree and sidebar states.",
|
||||
expected: {
|
||||
tree: [
|
||||
{
|
||||
role: "document",
|
||||
name: `""text label`,
|
||||
badges: ["text label"],
|
||||
},
|
||||
],
|
||||
sidebar: {
|
||||
name: "",
|
||||
role: "document",
|
||||
actions: [],
|
||||
value: "",
|
||||
description: "",
|
||||
keyboardShortcut: "",
|
||||
childCount: 1,
|
||||
indexInParent: 0,
|
||||
states: ["readonly", "focusable", "opaque", "enabled", "sensitive"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Expand first tree node.",
|
||||
setup: ({ doc }) => toggleRow(doc, 0),
|
||||
expected: {
|
||||
tree: [
|
||||
{
|
||||
role: "document",
|
||||
name: `""text label`,
|
||||
badges: ["text label"],
|
||||
},
|
||||
{
|
||||
role: "internal frame",
|
||||
name: `"Accessibility Panel Test (OOP)"`,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Expand second tree node. Display OOP document.",
|
||||
setup: ({ doc }) => toggleRow(doc, 1),
|
||||
expected: {
|
||||
tree: [
|
||||
{
|
||||
role: "document",
|
||||
name: `""text label`,
|
||||
badges: ["text label"],
|
||||
},
|
||||
{
|
||||
role: "internal frame",
|
||||
name: `"Accessibility Panel Test (OOP)"`,
|
||||
},
|
||||
{
|
||||
role: "document",
|
||||
name: `"Accessibility Panel Test (OOP)"`,
|
||||
},
|
||||
],
|
||||
sidebar: {
|
||||
name: "Accessibility Panel Test (OOP)",
|
||||
role: "internal frame",
|
||||
actions: [],
|
||||
value: "",
|
||||
description: "",
|
||||
keyboardShortcut: "",
|
||||
childCount: 1,
|
||||
indexInParent: 0,
|
||||
states: ["focusable", "opaque", "enabled", "sensitive"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Expand third tree node. Display OOP frame content.",
|
||||
setup: ({ doc }) => toggleRow(doc, 2),
|
||||
expected: {
|
||||
tree: [
|
||||
{
|
||||
role: "document",
|
||||
name: `""text label`,
|
||||
badges: ["text label"],
|
||||
},
|
||||
{
|
||||
role: "internal frame",
|
||||
name: `"Accessibility Panel Test (OOP)"`,
|
||||
},
|
||||
{
|
||||
role: "document",
|
||||
name: `"Accessibility Panel Test (OOP)"`,
|
||||
},
|
||||
{
|
||||
role: "heading",
|
||||
name: `"Top level header"`,
|
||||
},
|
||||
{
|
||||
role: "paragraph",
|
||||
name: `""`,
|
||||
},
|
||||
],
|
||||
sidebar: {
|
||||
name: "Accessibility Panel Test (OOP)",
|
||||
role: "document",
|
||||
actions: [],
|
||||
value: "",
|
||||
description: "",
|
||||
keyboardShortcut: "",
|
||||
childCount: 2,
|
||||
indexInParent: 0,
|
||||
states: ["readonly", "focusable", "opaque", "enabled", "sensitive"],
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* Check navigation within the tree.
|
||||
*/
|
||||
addA11yPanelTestsTask(
|
||||
tests,
|
||||
TEST_URI,
|
||||
"Test Accessibility panel tree navigation with OOP frame.",
|
||||
{ remoteIframe: true }
|
||||
);
|
|
@ -752,16 +752,32 @@ async function runA11yPanelTests(tests, env) {
|
|||
|
||||
/**
|
||||
* Build a valid URL from an HTML snippet.
|
||||
* @param {String} uri HTML snippet
|
||||
* @param {String} uri HTML snippet
|
||||
* @param {Object} options options for the test
|
||||
* @return {String} built URL
|
||||
*/
|
||||
function buildURL(uri) {
|
||||
function buildURL(uri, options = {}) {
|
||||
if (options.remoteIframe) {
|
||||
const srcURL = new URL(`http://example.net/document-builder.sjs`);
|
||||
srcURL.searchParams.append(
|
||||
"html",
|
||||
`<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Accessibility Panel Test (OOP)</title>
|
||||
</head>
|
||||
<body>${uri}</body>
|
||||
</html>`
|
||||
);
|
||||
uri = `<iframe title="Accessibility Panel Test (OOP)" src="${srcURL.href}"/>`;
|
||||
}
|
||||
|
||||
return `data:text/html;charset=UTF-8,${encodeURIComponent(uri)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a test task based on the test structure and a test URL.
|
||||
* @param {JSON} tests test data that has the format of:
|
||||
* @param {JSON} tests test data that has the format of:
|
||||
* {
|
||||
* desc {String} description for better logging
|
||||
* setup {Function} An optional setup that needs to be
|
||||
|
@ -770,11 +786,12 @@ function buildURL(uri) {
|
|||
* expected {JSON} An expected states for the tree and
|
||||
* the sidebar
|
||||
* }
|
||||
* @param {String} uri test URL
|
||||
* @param {String} msg a message that is printed for the test
|
||||
* @param {String} uri test URL
|
||||
* @param {String} msg a message that is printed for the test
|
||||
* @param {Object} options options for the test
|
||||
*/
|
||||
function addA11yPanelTestsTask(tests, uri, msg) {
|
||||
addA11YPanelTask(msg, uri, env => runA11yPanelTests(tests, env));
|
||||
function addA11yPanelTestsTask(tests, uri, msg, options) {
|
||||
addA11YPanelTask(msg, uri, env => runA11yPanelTests(tests, env), options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -783,11 +800,12 @@ function addA11yPanelTestsTask(tests, uri, msg) {
|
|||
* @param {String} msg a message that is printed for the test
|
||||
* @param {String} uri test URL
|
||||
* @param {Function} task task function containing the tests.
|
||||
* @param {Object} options options for the test
|
||||
*/
|
||||
function addA11YPanelTask(msg, uri, task) {
|
||||
function addA11YPanelTask(msg, uri, task, options = {}) {
|
||||
add_task(async function a11YPanelTask() {
|
||||
info(msg);
|
||||
const env = await addTestTab(buildURL(uri));
|
||||
const env = await addTestTab(buildURL(uri, options));
|
||||
await task(env);
|
||||
await disableAccessibilityInspector(env);
|
||||
});
|
||||
|
|
|
@ -16,6 +16,11 @@ const {
|
|||
simulatorSpec,
|
||||
} = require("devtools/shared/specs/accessibility");
|
||||
const events = require("devtools/shared/event-emitter");
|
||||
const Services = require("Services");
|
||||
const BROWSER_TOOLBOX_FISSION_ENABLED = Services.prefs.getBoolPref(
|
||||
"devtools.browsertoolbox.fission",
|
||||
false
|
||||
);
|
||||
|
||||
class AccessibleFront extends FrontClassWithSpec(accessibleSpec) {
|
||||
constructor(client, targetFront, parentFront) {
|
||||
|
@ -38,6 +43,10 @@ class AccessibleFront extends FrontClassWithSpec(accessibleSpec) {
|
|||
return this.getParent();
|
||||
}
|
||||
|
||||
get remoteFrame() {
|
||||
return BROWSER_TOOLBOX_FISSION_ENABLED && this._form.remoteFrame;
|
||||
}
|
||||
|
||||
get role() {
|
||||
return this._form.role;
|
||||
}
|
||||
|
@ -159,6 +168,34 @@ class AccessibleFront extends FrontClassWithSpec(accessibleSpec) {
|
|||
Object.assign(this._form, properties);
|
||||
});
|
||||
}
|
||||
|
||||
async children() {
|
||||
if (!this.remoteFrame) {
|
||||
return super.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"
|
||||
);
|
||||
await accessibilityFront.bootstrap();
|
||||
|
||||
return accessibilityFront.accessibleWalkerFront.children();
|
||||
}
|
||||
}
|
||||
|
||||
class AccessibleWalkerFront extends FrontClassWithSpec(accessibleWalkerSpec) {
|
||||
|
|
|
@ -48,6 +48,12 @@ loader.lazyRequireGetter(
|
|||
"devtools/server/actors/highlighters/utils/accessibility",
|
||||
true
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"isRemoteFrame",
|
||||
"devtools/shared/layout/utils",
|
||||
true
|
||||
);
|
||||
|
||||
const RELATIONS_TO_IGNORE = new Set([
|
||||
Ci.nsIAccessibleRelation.RELATION_CONTAINING_APPLICATION,
|
||||
|
@ -240,6 +246,12 @@ const AccessibleActor = ActorClassWithSpec(accessibleSpec, {
|
|||
if (this.isDefunct) {
|
||||
return 0;
|
||||
}
|
||||
// In case of a remote frame declare at least one child (the #document
|
||||
// element) so that they can be expanded.
|
||||
if (this.remoteFrame) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return this.rawAccessible.childCount;
|
||||
},
|
||||
|
||||
|
@ -413,11 +425,23 @@ const AccessibleActor = ActorClassWithSpec(accessibleSpec, {
|
|||
return relationObjects;
|
||||
},
|
||||
|
||||
get remoteFrame() {
|
||||
if (this.isDefunct) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
this.rawAccessible.role === Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME &&
|
||||
isRemoteFrame(this.rawAccessible.DOMNode)
|
||||
);
|
||||
},
|
||||
|
||||
form() {
|
||||
return {
|
||||
actor: this.actorID,
|
||||
role: this.role,
|
||||
name: this.name,
|
||||
remoteFrame: this.remoteFrame,
|
||||
childCount: this.childCount,
|
||||
checks: this._lastAudit,
|
||||
};
|
||||
|
|
|
@ -484,9 +484,17 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
|
|||
*/
|
||||
getAccessibleFor(domNode) {
|
||||
// We need to make sure that the document is loaded processed by a11y first.
|
||||
return this.getDocument().then(() =>
|
||||
this.addRef(this.getRawAccessibleFor(domNode.rawNode))
|
||||
);
|
||||
return this.getDocument().then(() => {
|
||||
const rawAccessible = this.getRawAccessibleFor(domNode.rawNode);
|
||||
// Not all DOM nodes have corresponding accessible objects. It's usually
|
||||
// the case where there is no semantics or relevance to the accessibility
|
||||
// client.
|
||||
if (!rawAccessible) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.addRef(rawAccessible);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -169,7 +169,7 @@ const accessibleWalkerSpec = generateActorSpec({
|
|||
getAccessibleFor: {
|
||||
request: { node: Arg(0, "domnode") },
|
||||
response: {
|
||||
accessible: RetVal("accessible"),
|
||||
accessible: RetVal("nullable:accessible"),
|
||||
},
|
||||
},
|
||||
getAncestry: {
|
||||
|
|
Загрузка…
Ссылка в новой задаче