0

Portals: Extract name from child tree root

This CL adds a change similar to https://crrev.com/c/2024110, but
for the automation API.

Bug: 1057598, 1045608
Change-Id: Ib27c661a6fda9c1ac0c952abf727367d9f0a79b9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2112512
Commit-Queue: Adithya Srinivasan <adithyas@chromium.org>
Reviewed-by: David Tseng <dtseng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#757999}
This commit is contained in:
Adithya Srinivasan
2020-04-09 20:47:05 +00:00
committed by Commit Bot
parent 8dfb00f1c2
commit 7d22c5843a
5 changed files with 95 additions and 18 deletions
chrome
browser
resources
chromeos
accessibility
chromevox
background
test
extensions/renderer

@ -41,6 +41,45 @@ ChromeVoxPortalsTest = class extends ChromeVoxNextE2ETest {
CommandHandler.onCommand(cmd);
};
}
/**
* Waits for |portal|'s tree to be ready.
* @param {chrome.automation.AutomationNode} portal
* @return {Promise}
*/
async waitForPortal(portal) {
const waitForChildren = () => new Promise(r => {
const hasChildren = () => portal.children.length > 0;
if (hasChildren()) {
r();
return;
}
const onChildrenChanged = () => {
portal.removeEventListener(
EventType.CHILDREN_CHANGED, onChildrenChanged, true);
r();
};
portal.addEventListener(
EventType.CHILDREN_CHANGED, onChildrenChanged, true);
});
const waitForLoaded = () => new Promise(r => {
const hasLoaded = () => portal.children[0].docLoaded;
if (hasLoaded()) {
r();
return;
}
const onLoadComplete = () => {
portal.removeEventListener(
EventType.LOAD_COMPLETE, onLoadComplete, true);
r();
};
portal.addEventListener(EventType.LOAD_COMPLETE, onLoadComplete, true);
});
await waitForChildren();
await waitForLoaded();
}
};
TEST_F('ChromeVoxPortalsTest', 'ShouldFocusPortal', function() {
@ -62,23 +101,24 @@ TEST_F('ChromeVoxPortalsTest', 'ShouldFocusPortal', function() {
doCmd('nextObject')();
});
const onChildrenChanged = evt => {
if (portal.children.length) {
portal.removeEventListener(
EventType.CHILDREN_CHANGED, onChildrenChanged, true);
afterPortalIsReady();
}
};
button.focus();
button.addEventListener(EventType.FOCUS, this.newCallback(function() {
if (!portal.children.length) {
portal.addEventListener(
EventType.CHILDREN_CHANGED, onChildrenChanged, true);
return;
}
afterPortalIsReady();
}));
button.addEventListener(
EventType.FOCUS,
() => this.waitForPortal(portal).then(afterPortalIsReady));
}.bind(this),
`${testRunnerParams.testServerBaseUrl}portal/portal-and-button.html`);
});
TEST_F('ChromeVoxPortalsTest', 'PortalName', function() {
this.runWithLoadedTree(
undefined,
function(root) {
const portal = root.find({role: RoleType.PORTAL});
assertEquals(RoleType.PORTAL, portal.role);
this.waitForPortal(portal).then(this.newCallback(() => {
assertTrue(portal.firstChild.docLoaded);
assertEquals(portal.name, 'some text');
}));
}.bind(this),
`${testRunnerParams.testServerBaseUrl}portal/portal-with-text.html`);
});

@ -0,0 +1,4 @@
<!DOCTYPE html>
<body>
<text>some text</text>
</body>

@ -0,0 +1,4 @@
<!DOCTYPE html>
<body>
<portal src="portal-with-text-portal.html"></portal>
</body>

@ -1151,6 +1151,25 @@ void AutomationInternalCustomBindings::AddRoutes() {
v8::NewStringType::kNormal)
.ToLocalChecked());
});
RouteNodeIDFunction("GetName", [this](v8::Isolate* isolate,
v8::ReturnValue<v8::Value> result,
AutomationAXTreeWrapper* tree_wrapper,
ui::AXNode* node) {
const ui::AXNodeData& node_data = node->data();
const char* name =
node_data.GetStringAttribute(ax::mojom::StringAttribute::kName).c_str();
if (node_data.role == ax::mojom::Role::kPortal &&
node_data.GetNameFrom() == ax::mojom::NameFrom::kNone) {
if (GetRootOfChildTree(&node, &tree_wrapper)) {
name = node->data()
.GetStringAttribute(ax::mojom::StringAttribute::kName)
.c_str();
}
}
result.Set(
v8::String::NewFromUtf8(isolate, name, v8::NewStringType::kNormal)
.ToLocalChecked());
});
RouteNodeIDFunction(
"GetDescriptionFrom",
[](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,

@ -262,6 +262,13 @@ var GetUnclippedLocation = natives.GetUnclippedLocation;
var GetLineStartOffsets = requireNative(
'automationInternal').GetLineStartOffsets;
/**
* @param {string} axTreeID The id of the accessibility tree.
* @param {number} nodeID The id of the node.
* @return {?string} The computed name of this node.
*/
var GetName = natives.GetName;
/**
* @param {string} axTreeID The id of the accessibility tree.
* @param {number} nodeID The id of a node.
@ -700,6 +707,9 @@ AutomationNodeImpl.prototype = {
return GetNameFrom(this.treeID, this.id);
},
get name() {
return GetName(this.treeID, this.id);
},
get descriptionFrom() {
return GetDescriptionFrom(this.treeID, this.id);
@ -1036,7 +1046,7 @@ AutomationNodeImpl.prototype = {
var childID = GetChildIDAtIndex(this.treeID, this.id, i).nodeId;
$Array.push(childIDs, childID);
}
var name = GetStringAttribute(this.treeID, this.id, 'name');
var name = GetName(this.treeID, this.id);
var result = 'node id=' + this.id +
' role=' + this.role +
@ -1231,7 +1241,6 @@ var stringAttributes = [
'language',
'liveRelevant',
'liveStatus',
'name',
'placeholder',
'roleDescription',
'textInputType',
@ -1815,6 +1824,7 @@ utils.expose(AutomationNode, AutomationNodeImpl, {
'lineThrough',
'location',
'markers',
'name',
'nameFrom',
'nextSibling',
'nonInlineTextWordEnds',