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..431a3823643b17454cde5d48e7fc75c57180b259 100644 |
--- a/chrome/renderer/extensions/automation_internal_custom_bindings.cc |
+++ b/chrome/renderer/extensions/automation_internal_custom_bindings.cc |
@@ -416,6 +416,7 @@ AutomationInternalCustomBindings::AutomationInternalCustomBindings( |
ROUTE_FUNCTION(AddTreeChangeObserver); |
ROUTE_FUNCTION(RemoveTreeChangeObserver); |
ROUTE_FUNCTION(GetChildIDAtIndex); |
+ ROUTE_FUNCTION(GetFocus); |
#undef ROUTE_FUNCTION |
// Bindings that take a Tree ID and return a property of the tree. |
@@ -777,6 +778,54 @@ void AutomationInternalCustomBindings::RemoveTreeChangeObserver( |
UpdateOverallTreeChangeObserverFilter(); |
} |
+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(); |
+ ui::AXNode* focus = nullptr; |
+ TreeCache* cache = GetTreeCacheFromTreeID(tree_id); |
+ if (!cache) |
+ return; |
+ |
+ int focus_id = cache->tree.data().focus_id; |
+ focus = cache->tree.GetFromId(focus_id); |
+ if (!focus) |
+ return; |
+ |
+ 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 = cache->tree.GetFromId(focus_id); |
+ if (!child_focus) |
+ break; |
+ |
+ focus = child_focus; |
+ tree_id = child_tree_id; |
+ focus_id = child_focus_id; |
+ } |
+ |
+ v8::Isolate* isolate = GetIsolate(); |
+ v8::Local<v8::Object> result(v8::Object::New(isolate)); |
+ result->Set(CreateV8String(isolate, "treeId"), |
+ v8::Integer::New(isolate, tree_id)); |
+ result->Set(CreateV8String(isolate, "nodeId"), |
+ v8::Integer::New(isolate, focus_id)); |
+ args.GetReturnValue().Set(result); |
+} |
+ |
void AutomationInternalCustomBindings::UpdateOverallTreeChangeObserverFilter() { |
tree_change_observer_overall_filter_ = |
api::automation::TREE_CHANGE_OBSERVER_FILTER_NOTREECHANGES; |