| 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 |