Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7823)

Unified Diff: chrome/renderer/extensions/automation_internal_custom_bindings.cc

Issue 1589623002: Keep track of accessibility focus across windows. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Final suggestions Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/renderer/extensions/automation_internal_custom_bindings.cc
diff --git a/chrome/renderer/extensions/automation_internal_custom_bindings.cc b/chrome/renderer/extensions/automation_internal_custom_bindings.cc
index 3a05d188a739a69f1cb5d5ffedf60d255fdde848..826859edb42390cdf33ddb20fa405a2085ebf4ae 100644
--- a/chrome/renderer/extensions/automation_internal_custom_bindings.cc
+++ b/chrome/renderer/extensions/automation_internal_custom_bindings.cc
@@ -416,6 +416,8 @@ AutomationInternalCustomBindings::AutomationInternalCustomBindings(
ROUTE_FUNCTION(AddTreeChangeObserver);
ROUTE_FUNCTION(RemoveTreeChangeObserver);
ROUTE_FUNCTION(GetChildIDAtIndex);
+ ROUTE_FUNCTION(GetFocus);
+ ROUTE_FUNCTION(GetState);
#undef ROUTE_FUNCTION
// Bindings that take a Tree ID and return a property of the tree.
@@ -491,22 +493,6 @@ AutomationInternalCustomBindings::AutomationInternalCustomBindings(
result.Set(v8::Integer::New(isolate, node->index_in_parent()));
});
RouteNodeIDFunction(
- "GetState", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
- TreeCache* cache, ui::AXNode* node) {
- v8::Local<v8::Object> state(v8::Object::New(isolate));
- uint32_t state_pos = 0, state_shifter = node->data().state;
- while (state_shifter) {
- if (state_shifter & 1) {
- std::string key = ToString(static_cast<ui::AXState>(state_pos));
- state->Set(CreateV8String(isolate, key),
- v8::Boolean::New(isolate, true));
- }
- state_shifter = state_shifter >> 1;
- state_pos++;
- }
- result.Set(state);
- });
- RouteNodeIDFunction(
"GetRole", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
TreeCache* cache, ui::AXNode* node) {
std::string role_name = ui::ToString(node->data().role);
@@ -777,6 +763,112 @@ void AutomationInternalCustomBindings::RemoveTreeChangeObserver(
UpdateOverallTreeChangeObserverFilter();
}
+bool AutomationInternalCustomBindings::GetFocusInternal(TreeCache* cache,
+ TreeCache** out_cache,
+ ui::AXNode** out_node) {
+ int focus_id = cache->tree.data().focus_id;
+ ui::AXNode* focus = cache->tree.GetFromId(focus_id);
+ if (!focus)
+ return false;
+
+ while (focus->data().HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)) {
+ // Try to keep following focus recursively, by letting |tree_id| be the
+ // new subtree to search in, while keeping |focus_tree_id| set to the tree
+ // where we know we found a focused node.
+ int child_tree_id =
+ focus->data().GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID);
+
+ TreeCache* child_cache = GetTreeCacheFromTreeID(child_tree_id);
+ if (!child_cache)
+ break;
+
+ int child_focus_id = child_cache->tree.data().focus_id;
+ ui::AXNode* child_focus = child_cache->tree.GetFromId(child_focus_id);
+ if (!child_focus)
+ break;
+
+ focus = child_focus;
+ cache = child_cache;
+ }
+
+ *out_cache = cache;
+ *out_node = focus;
+ return true;
+}
+
+void AutomationInternalCustomBindings::GetFocus(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ if (args.Length() != 1 || !args[0]->IsNumber()) {
+ ThrowInvalidArgumentsException(this);
+ return;
+ }
+
+ int tree_id = args[0]->Int32Value();
+ TreeCache* cache = GetTreeCacheFromTreeID(tree_id);
+ if (!cache)
+ return;
+
+ TreeCache* focused_tree_cache = nullptr;
+ ui::AXNode* focused_node = nullptr;
+ if (!GetFocusInternal(cache, &focused_tree_cache, &focused_node))
+ return;
+
+ v8::Isolate* isolate = GetIsolate();
+ v8::Local<v8::Object> result(v8::Object::New(isolate));
+ result->Set(CreateV8String(isolate, "treeId"),
+ v8::Integer::New(isolate, focused_tree_cache->tree_id));
+ result->Set(CreateV8String(isolate, "nodeId"),
+ v8::Integer::New(isolate, focused_node->id()));
+ args.GetReturnValue().Set(result);
+}
+
+void AutomationInternalCustomBindings::GetState(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ v8::Isolate* isolate = GetIsolate();
+ if (args.Length() < 2 || !args[0]->IsNumber() || !args[1]->IsNumber())
+ ThrowInvalidArgumentsException(this);
+
+ int tree_id = args[0]->Int32Value();
+ int node_id = args[1]->Int32Value();
+
+ TreeCache* cache = GetTreeCacheFromTreeID(tree_id);
+ if (!cache)
+ return;
+
+ ui::AXNode* node = cache->tree.GetFromId(node_id);
+ if (!node)
+ return;
+
+ v8::Local<v8::Object> state(v8::Object::New(isolate));
+ uint32_t state_pos = 0, state_shifter = node->data().state;
+ while (state_shifter) {
+ if (state_shifter & 1) {
+ std::string key = ToString(static_cast<ui::AXState>(state_pos));
+ state->Set(CreateV8String(isolate, key), v8::Boolean::New(isolate, true));
+ }
+ state_shifter = state_shifter >> 1;
+ state_pos++;
+ }
+
+ TreeCache* top_cache = GetTreeCacheFromTreeID(0);
+ if (!top_cache)
+ top_cache = cache;
+ TreeCache* focused_cache = nullptr;
+ ui::AXNode* focused_node = nullptr;
+ if (GetFocusInternal(top_cache, &focused_cache, &focused_node)) {
+ if (focused_cache == cache && focused_node == node) {
+ state->Set(CreateV8String(isolate, "focused"),
+ v8::Boolean::New(isolate, true));
+ }
+ }
+ if (cache->tree.data().focus_id == node->id()) {
+ state->Set(CreateV8String(isolate, "focused"),
+ v8::Boolean::New(isolate, true));
+ }
+
+ args.GetReturnValue().Set(state);
+}
+
void AutomationInternalCustomBindings::UpdateOverallTreeChangeObserverFilter() {
tree_change_observer_overall_filter_ =
api::automation::TREE_CHANGE_OBSERVER_FILTER_NOTREECHANGES;

Powered by Google App Engine
This is Rietveld 408576698