OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/renderer/extensions/automation_internal_custom_bindings.h" | 5 #include "chrome/renderer/extensions/automation_internal_custom_bindings.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 if (parent->data().role == ui::AX_ROLE_WEB_AREA || | 129 if (parent->data().role == ui::AX_ROLE_WEB_AREA || |
130 parent->data().role == ui::AX_ROLE_ROOT_WEB_AREA) { | 130 parent->data().role == ui::AX_ROLE_ROOT_WEB_AREA) { |
131 int sx = 0; | 131 int sx = 0; |
132 int sy = 0; | 132 int sy = 0; |
133 if (parent->data().GetIntAttribute(ui::AX_ATTR_SCROLL_X, &sx) && | 133 if (parent->data().GetIntAttribute(ui::AX_ATTR_SCROLL_X, &sx) && |
134 parent->data().GetIntAttribute(ui::AX_ATTR_SCROLL_Y, &sy)) { | 134 parent->data().GetIntAttribute(ui::AX_ATTR_SCROLL_Y, &sy)) { |
135 bounds.Offset(-sx, -sy); | 135 bounds.Offset(-sx, -sy); |
136 } | 136 } |
137 need_to_offset_web_area = true; | 137 need_to_offset_web_area = true; |
138 } | 138 } |
139 parent = parent->parent(); | 139 parent = cache->owner->GetParent(parent, &cache); |
140 } | 140 } |
141 | 141 |
142 return bounds; | 142 return bounds; |
143 } | 143 } |
144 | 144 |
| 145 ui::AXNode* FindNodeWithChildTreeId(ui::AXNode* node, int child_tree_id) { |
| 146 if (child_tree_id == node->data().GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)) |
| 147 return node; |
| 148 |
| 149 for (int i = 0; i < node->child_count(); ++i) { |
| 150 ui::AXNode* result = |
| 151 FindNodeWithChildTreeId(node->ChildAtIndex(i), child_tree_id); |
| 152 if (result) |
| 153 return result; |
| 154 } |
| 155 |
| 156 return nullptr; |
| 157 } |
| 158 |
145 // | 159 // |
146 // Helper class that helps implement bindings for a JavaScript function | 160 // Helper class that helps implement bindings for a JavaScript function |
147 // that takes a single input argument consisting of a Tree ID. Looks up | 161 // that takes a single input argument consisting of a Tree ID. Looks up |
148 // the TreeCache and passes it to the function passed to the constructor. | 162 // the TreeCache and passes it to the function passed to the constructor. |
149 // | 163 // |
150 | 164 |
151 typedef void (*TreeIDFunction)(v8::Isolate* isolate, | 165 typedef void (*TreeIDFunction)(v8::Isolate* isolate, |
152 v8::ReturnValue<v8::Value> result, | 166 v8::ReturnValue<v8::Value> result, |
153 TreeCache* cache); | 167 TreeCache* cache); |
154 | 168 |
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
764 } | 778 } |
765 | 779 |
766 bool AutomationInternalCustomBindings::GetFocusInternal(TreeCache* cache, | 780 bool AutomationInternalCustomBindings::GetFocusInternal(TreeCache* cache, |
767 TreeCache** out_cache, | 781 TreeCache** out_cache, |
768 ui::AXNode** out_node) { | 782 ui::AXNode** out_node) { |
769 int focus_id = cache->tree.data().focus_id; | 783 int focus_id = cache->tree.data().focus_id; |
770 ui::AXNode* focus = cache->tree.GetFromId(focus_id); | 784 ui::AXNode* focus = cache->tree.GetFromId(focus_id); |
771 if (!focus) | 785 if (!focus) |
772 return false; | 786 return false; |
773 | 787 |
| 788 // If the focused node is the owner of a child tree, that indicates |
| 789 // a node within the child tree is the one that actually has focus. |
774 while (focus->data().HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)) { | 790 while (focus->data().HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)) { |
775 // Try to keep following focus recursively, by letting |tree_id| be the | 791 // Try to keep following focus recursively, by letting |tree_id| be the |
776 // new subtree to search in, while keeping |focus_tree_id| set to the tree | 792 // new subtree to search in, while keeping |focus_tree_id| set to the tree |
777 // where we know we found a focused node. | 793 // where we know we found a focused node. |
778 int child_tree_id = | 794 int child_tree_id = |
779 focus->data().GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID); | 795 focus->data().GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID); |
780 | 796 |
781 TreeCache* child_cache = GetTreeCacheFromTreeID(child_tree_id); | 797 TreeCache* child_cache = GetTreeCacheFromTreeID(child_tree_id); |
782 if (!child_cache) | 798 if (!child_cache) |
783 break; | 799 break; |
784 | 800 |
| 801 // If the child cache is a frame tree that indicates a focused frame, |
| 802 // jump to that frame if possible. |
| 803 if (child_cache->tree.data().focused_tree_id > 0) { |
| 804 TreeCache* focused_cache = |
| 805 GetTreeCacheFromTreeID(child_cache->tree.data().focused_tree_id); |
| 806 if (focused_cache) |
| 807 child_cache = focused_cache; |
| 808 } |
| 809 |
785 int child_focus_id = child_cache->tree.data().focus_id; | 810 int child_focus_id = child_cache->tree.data().focus_id; |
786 ui::AXNode* child_focus = child_cache->tree.GetFromId(child_focus_id); | 811 ui::AXNode* child_focus = child_cache->tree.GetFromId(child_focus_id); |
787 if (!child_focus) | 812 if (!child_focus) |
788 break; | 813 break; |
789 | 814 |
790 focus = child_focus; | 815 focus = child_focus; |
791 cache = child_cache; | 816 cache = child_cache; |
792 } | 817 } |
793 | 818 |
794 *out_cache = cache; | 819 *out_cache = cache; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
871 | 896 |
872 void AutomationInternalCustomBindings::UpdateOverallTreeChangeObserverFilter() { | 897 void AutomationInternalCustomBindings::UpdateOverallTreeChangeObserverFilter() { |
873 tree_change_observer_overall_filter_ = | 898 tree_change_observer_overall_filter_ = |
874 api::automation::TREE_CHANGE_OBSERVER_FILTER_NOTREECHANGES; | 899 api::automation::TREE_CHANGE_OBSERVER_FILTER_NOTREECHANGES; |
875 for (const auto& observer : tree_change_observers_) { | 900 for (const auto& observer : tree_change_observers_) { |
876 tree_change_observer_overall_filter_ = | 901 tree_change_observer_overall_filter_ = |
877 std::max(observer.filter, tree_change_observer_overall_filter_); | 902 std::max(observer.filter, tree_change_observer_overall_filter_); |
878 } | 903 } |
879 } | 904 } |
880 | 905 |
| 906 ui::AXNode* AutomationInternalCustomBindings::GetParent( |
| 907 ui::AXNode* node, |
| 908 TreeCache** in_out_cache) { |
| 909 if (node->parent()) |
| 910 return node->parent(); |
| 911 |
| 912 int parent_tree_id = (*in_out_cache)->tree.data().parent_tree_id; |
| 913 if (parent_tree_id < 0) |
| 914 return nullptr; |
| 915 |
| 916 TreeCache* parent_cache = GetTreeCacheFromTreeID(parent_tree_id); |
| 917 if (!parent_cache) |
| 918 return nullptr; |
| 919 |
| 920 // Try to use the cached parent node from the most recent time this |
| 921 // was called. |
| 922 if (parent_cache->parent_node_id_from_parent_tree > 0) { |
| 923 ui::AXNode* parent = parent_cache->tree.GetFromId( |
| 924 parent_cache->parent_node_id_from_parent_tree); |
| 925 if (parent) { |
| 926 int parent_child_tree_id = |
| 927 parent->data().GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID); |
| 928 if (parent_child_tree_id == (*in_out_cache)->tree_id) { |
| 929 *in_out_cache = parent_cache; |
| 930 return parent; |
| 931 } |
| 932 } |
| 933 } |
| 934 |
| 935 // If that fails, search for it and cache it for next time. |
| 936 ui::AXNode* parent = FindNodeWithChildTreeId(parent_cache->tree.root(), |
| 937 (*in_out_cache)->tree_id); |
| 938 if (parent) { |
| 939 (*in_out_cache)->parent_node_id_from_parent_tree = parent->id(); |
| 940 *in_out_cache = parent_cache; |
| 941 return parent; |
| 942 } |
| 943 |
| 944 return nullptr; |
| 945 } |
| 946 |
881 void AutomationInternalCustomBindings::RouteTreeIDFunction( | 947 void AutomationInternalCustomBindings::RouteTreeIDFunction( |
882 const std::string& name, | 948 const std::string& name, |
883 TreeIDFunction callback) { | 949 TreeIDFunction callback) { |
884 scoped_refptr<TreeIDWrapper> wrapper = new TreeIDWrapper(this, callback); | 950 scoped_refptr<TreeIDWrapper> wrapper = new TreeIDWrapper(this, callback); |
885 RouteFunction(name, base::Bind(&TreeIDWrapper::Run, wrapper)); | 951 RouteFunction(name, base::Bind(&TreeIDWrapper::Run, wrapper)); |
886 } | 952 } |
887 | 953 |
888 void AutomationInternalCustomBindings::RouteNodeIDFunction( | 954 void AutomationInternalCustomBindings::RouteNodeIDFunction( |
889 const std::string& name, | 955 const std::string& name, |
890 NodeIDFunction callback) { | 956 NodeIDFunction callback) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
946 const ExtensionMsg_AccessibilityEventParams& params, | 1012 const ExtensionMsg_AccessibilityEventParams& params, |
947 bool is_active_profile) { | 1013 bool is_active_profile) { |
948 is_active_profile_ = is_active_profile; | 1014 is_active_profile_ = is_active_profile; |
949 int tree_id = params.tree_id; | 1015 int tree_id = params.tree_id; |
950 TreeCache* cache; | 1016 TreeCache* cache; |
951 auto iter = tree_id_to_tree_cache_map_.find(tree_id); | 1017 auto iter = tree_id_to_tree_cache_map_.find(tree_id); |
952 if (iter == tree_id_to_tree_cache_map_.end()) { | 1018 if (iter == tree_id_to_tree_cache_map_.end()) { |
953 cache = new TreeCache(); | 1019 cache = new TreeCache(); |
954 cache->tab_id = -1; | 1020 cache->tab_id = -1; |
955 cache->tree_id = params.tree_id; | 1021 cache->tree_id = params.tree_id; |
| 1022 cache->parent_node_id_from_parent_tree = -1; |
956 cache->tree.SetDelegate(this); | 1023 cache->tree.SetDelegate(this); |
| 1024 cache->owner = this; |
957 tree_id_to_tree_cache_map_.insert(std::make_pair(tree_id, cache)); | 1025 tree_id_to_tree_cache_map_.insert(std::make_pair(tree_id, cache)); |
958 axtree_to_tree_cache_map_.insert(std::make_pair(&cache->tree, cache)); | 1026 axtree_to_tree_cache_map_.insert(std::make_pair(&cache->tree, cache)); |
959 } else { | 1027 } else { |
960 cache = iter->second; | 1028 cache = iter->second; |
961 } | 1029 } |
962 | 1030 |
963 // Update the internal state whether it's the active profile or not. | 1031 // Update the internal state whether it's the active profile or not. |
964 cache->location_offset = params.location_offset; | 1032 cache->location_offset = params.location_offset; |
965 deleted_node_ids_.clear(); | 1033 deleted_node_ids_.clear(); |
966 if (!cache->tree.Unserialize(params.update)) { | 1034 if (!cache->tree.Unserialize(params.update)) { |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1160 v8::Local<v8::Array> args(v8::Array::New(GetIsolate(), 2U)); | 1228 v8::Local<v8::Array> args(v8::Array::New(GetIsolate(), 2U)); |
1161 args->Set(0U, v8::Integer::New(GetIsolate(), tree_id)); | 1229 args->Set(0U, v8::Integer::New(GetIsolate(), tree_id)); |
1162 v8::Local<v8::Array> nodes(v8::Array::New(GetIsolate(), ids.size())); | 1230 v8::Local<v8::Array> nodes(v8::Array::New(GetIsolate(), ids.size())); |
1163 args->Set(1U, nodes); | 1231 args->Set(1U, nodes); |
1164 for (size_t i = 0; i < ids.size(); ++i) | 1232 for (size_t i = 0; i < ids.size(); ++i) |
1165 nodes->Set(i, v8::Integer::New(GetIsolate(), ids[i])); | 1233 nodes->Set(i, v8::Integer::New(GetIsolate(), ids[i])); |
1166 context()->DispatchEvent("automationInternal.onNodesRemoved", args); | 1234 context()->DispatchEvent("automationInternal.onNodesRemoved", args); |
1167 } | 1235 } |
1168 | 1236 |
1169 } // namespace extensions | 1237 } // namespace extensions |
OLD | NEW |