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 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 base::Bind(&AutomationInternalCustomBindings::FN, \ | 409 base::Bind(&AutomationInternalCustomBindings::FN, \ |
410 base::Unretained(this))) | 410 base::Unretained(this))) |
411 ROUTE_FUNCTION(IsInteractPermitted); | 411 ROUTE_FUNCTION(IsInteractPermitted); |
412 ROUTE_FUNCTION(GetSchemaAdditions); | 412 ROUTE_FUNCTION(GetSchemaAdditions); |
413 ROUTE_FUNCTION(GetRoutingID); | 413 ROUTE_FUNCTION(GetRoutingID); |
414 ROUTE_FUNCTION(StartCachingAccessibilityTrees); | 414 ROUTE_FUNCTION(StartCachingAccessibilityTrees); |
415 ROUTE_FUNCTION(DestroyAccessibilityTree); | 415 ROUTE_FUNCTION(DestroyAccessibilityTree); |
416 ROUTE_FUNCTION(AddTreeChangeObserver); | 416 ROUTE_FUNCTION(AddTreeChangeObserver); |
417 ROUTE_FUNCTION(RemoveTreeChangeObserver); | 417 ROUTE_FUNCTION(RemoveTreeChangeObserver); |
418 ROUTE_FUNCTION(GetChildIDAtIndex); | 418 ROUTE_FUNCTION(GetChildIDAtIndex); |
| 419 ROUTE_FUNCTION(GetFocus); |
| 420 ROUTE_FUNCTION(GetState); |
419 #undef ROUTE_FUNCTION | 421 #undef ROUTE_FUNCTION |
420 | 422 |
421 // Bindings that take a Tree ID and return a property of the tree. | 423 // Bindings that take a Tree ID and return a property of the tree. |
422 | 424 |
423 RouteTreeIDFunction( | 425 RouteTreeIDFunction( |
424 "GetRootID", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, | 426 "GetRootID", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, |
425 TreeCache* cache) { | 427 TreeCache* cache) { |
426 result.Set(v8::Integer::New(isolate, cache->tree.root()->id())); | 428 result.Set(v8::Integer::New(isolate, cache->tree.root()->id())); |
427 }); | 429 }); |
428 RouteTreeIDFunction( | 430 RouteTreeIDFunction( |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
484 TreeCache* cache, ui::AXNode* node) { | 486 TreeCache* cache, ui::AXNode* node) { |
485 result.Set(v8::Integer::New(isolate, node->child_count())); | 487 result.Set(v8::Integer::New(isolate, node->child_count())); |
486 }); | 488 }); |
487 RouteNodeIDFunction( | 489 RouteNodeIDFunction( |
488 "GetIndexInParent", | 490 "GetIndexInParent", |
489 [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, | 491 [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, |
490 TreeCache* cache, ui::AXNode* node) { | 492 TreeCache* cache, ui::AXNode* node) { |
491 result.Set(v8::Integer::New(isolate, node->index_in_parent())); | 493 result.Set(v8::Integer::New(isolate, node->index_in_parent())); |
492 }); | 494 }); |
493 RouteNodeIDFunction( | 495 RouteNodeIDFunction( |
494 "GetState", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, | |
495 TreeCache* cache, ui::AXNode* node) { | |
496 v8::Local<v8::Object> state(v8::Object::New(isolate)); | |
497 uint32_t state_pos = 0, state_shifter = node->data().state; | |
498 while (state_shifter) { | |
499 if (state_shifter & 1) { | |
500 std::string key = ToString(static_cast<ui::AXState>(state_pos)); | |
501 state->Set(CreateV8String(isolate, key), | |
502 v8::Boolean::New(isolate, true)); | |
503 } | |
504 state_shifter = state_shifter >> 1; | |
505 state_pos++; | |
506 } | |
507 result.Set(state); | |
508 }); | |
509 RouteNodeIDFunction( | |
510 "GetRole", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, | 496 "GetRole", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, |
511 TreeCache* cache, ui::AXNode* node) { | 497 TreeCache* cache, ui::AXNode* node) { |
512 std::string role_name = ui::ToString(node->data().role); | 498 std::string role_name = ui::ToString(node->data().role); |
513 result.Set(v8::String::NewFromUtf8(isolate, role_name.c_str())); | 499 result.Set(v8::String::NewFromUtf8(isolate, role_name.c_str())); |
514 }); | 500 }); |
515 RouteNodeIDFunction( | 501 RouteNodeIDFunction( |
516 "GetLocation", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, | 502 "GetLocation", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, |
517 TreeCache* cache, ui::AXNode* node) { | 503 TreeCache* cache, ui::AXNode* node) { |
518 gfx::Rect location = ComputeGlobalNodeBounds(cache, node); | 504 gfx::Rect location = ComputeGlobalNodeBounds(cache, node); |
519 location.Offset(cache->location_offset); | 505 location.Offset(cache->location_offset); |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
770 iter != tree_change_observers_.end(); ++iter) { | 756 iter != tree_change_observers_.end(); ++iter) { |
771 if (iter->id == observer_id) { | 757 if (iter->id == observer_id) { |
772 tree_change_observers_.erase(iter); | 758 tree_change_observers_.erase(iter); |
773 break; | 759 break; |
774 } | 760 } |
775 } | 761 } |
776 | 762 |
777 UpdateOverallTreeChangeObserverFilter(); | 763 UpdateOverallTreeChangeObserverFilter(); |
778 } | 764 } |
779 | 765 |
| 766 bool AutomationInternalCustomBindings::GetFocusInternal(TreeCache* cache, |
| 767 TreeCache** out_cache, |
| 768 ui::AXNode** out_node) { |
| 769 int focus_id = cache->tree.data().focus_id; |
| 770 ui::AXNode* focus = cache->tree.GetFromId(focus_id); |
| 771 if (!focus) |
| 772 return false; |
| 773 |
| 774 while (focus->data().HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)) { |
| 775 // 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 |
| 777 // where we know we found a focused node. |
| 778 int child_tree_id = |
| 779 focus->data().GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID); |
| 780 |
| 781 TreeCache* child_cache = GetTreeCacheFromTreeID(child_tree_id); |
| 782 if (!child_cache) |
| 783 break; |
| 784 |
| 785 int child_focus_id = child_cache->tree.data().focus_id; |
| 786 ui::AXNode* child_focus = child_cache->tree.GetFromId(child_focus_id); |
| 787 if (!child_focus) |
| 788 break; |
| 789 |
| 790 focus = child_focus; |
| 791 cache = child_cache; |
| 792 } |
| 793 |
| 794 *out_cache = cache; |
| 795 *out_node = focus; |
| 796 return true; |
| 797 } |
| 798 |
| 799 void AutomationInternalCustomBindings::GetFocus( |
| 800 const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 801 if (args.Length() != 1 || !args[0]->IsNumber()) { |
| 802 ThrowInvalidArgumentsException(this); |
| 803 return; |
| 804 } |
| 805 |
| 806 int tree_id = args[0]->Int32Value(); |
| 807 TreeCache* cache = GetTreeCacheFromTreeID(tree_id); |
| 808 if (!cache) |
| 809 return; |
| 810 |
| 811 TreeCache* focused_tree_cache = nullptr; |
| 812 ui::AXNode* focused_node = nullptr; |
| 813 if (!GetFocusInternal(cache, &focused_tree_cache, &focused_node)) |
| 814 return; |
| 815 |
| 816 v8::Isolate* isolate = GetIsolate(); |
| 817 v8::Local<v8::Object> result(v8::Object::New(isolate)); |
| 818 result->Set(CreateV8String(isolate, "treeId"), |
| 819 v8::Integer::New(isolate, focused_tree_cache->tree_id)); |
| 820 result->Set(CreateV8String(isolate, "nodeId"), |
| 821 v8::Integer::New(isolate, focused_node->id())); |
| 822 args.GetReturnValue().Set(result); |
| 823 } |
| 824 |
| 825 void AutomationInternalCustomBindings::GetState( |
| 826 const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 827 v8::Isolate* isolate = GetIsolate(); |
| 828 if (args.Length() < 2 || !args[0]->IsNumber() || !args[1]->IsNumber()) |
| 829 ThrowInvalidArgumentsException(this); |
| 830 |
| 831 int tree_id = args[0]->Int32Value(); |
| 832 int node_id = args[1]->Int32Value(); |
| 833 |
| 834 TreeCache* cache = GetTreeCacheFromTreeID(tree_id); |
| 835 if (!cache) |
| 836 return; |
| 837 |
| 838 ui::AXNode* node = cache->tree.GetFromId(node_id); |
| 839 if (!node) |
| 840 return; |
| 841 |
| 842 v8::Local<v8::Object> state(v8::Object::New(isolate)); |
| 843 uint32_t state_pos = 0, state_shifter = node->data().state; |
| 844 while (state_shifter) { |
| 845 if (state_shifter & 1) { |
| 846 std::string key = ToString(static_cast<ui::AXState>(state_pos)); |
| 847 state->Set(CreateV8String(isolate, key), v8::Boolean::New(isolate, true)); |
| 848 } |
| 849 state_shifter = state_shifter >> 1; |
| 850 state_pos++; |
| 851 } |
| 852 |
| 853 TreeCache* top_cache = GetTreeCacheFromTreeID(0); |
| 854 if (!top_cache) |
| 855 top_cache = cache; |
| 856 TreeCache* focused_cache = nullptr; |
| 857 ui::AXNode* focused_node = nullptr; |
| 858 if (GetFocusInternal(top_cache, &focused_cache, &focused_node)) { |
| 859 if (focused_cache == cache && focused_node == node) { |
| 860 state->Set(CreateV8String(isolate, "focused"), |
| 861 v8::Boolean::New(isolate, true)); |
| 862 } |
| 863 } |
| 864 if (cache->tree.data().focus_id == node->id()) { |
| 865 state->Set(CreateV8String(isolate, "focused"), |
| 866 v8::Boolean::New(isolate, true)); |
| 867 } |
| 868 |
| 869 args.GetReturnValue().Set(state); |
| 870 } |
| 871 |
780 void AutomationInternalCustomBindings::UpdateOverallTreeChangeObserverFilter() { | 872 void AutomationInternalCustomBindings::UpdateOverallTreeChangeObserverFilter() { |
781 tree_change_observer_overall_filter_ = | 873 tree_change_observer_overall_filter_ = |
782 api::automation::TREE_CHANGE_OBSERVER_FILTER_NOTREECHANGES; | 874 api::automation::TREE_CHANGE_OBSERVER_FILTER_NOTREECHANGES; |
783 for (const auto& observer : tree_change_observers_) { | 875 for (const auto& observer : tree_change_observers_) { |
784 tree_change_observer_overall_filter_ = | 876 tree_change_observer_overall_filter_ = |
785 std::max(observer.filter, tree_change_observer_overall_filter_); | 877 std::max(observer.filter, tree_change_observer_overall_filter_); |
786 } | 878 } |
787 } | 879 } |
788 | 880 |
789 void AutomationInternalCustomBindings::RouteTreeIDFunction( | 881 void AutomationInternalCustomBindings::RouteTreeIDFunction( |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1054 v8::Local<v8::Array> args(v8::Array::New(GetIsolate(), 2U)); | 1146 v8::Local<v8::Array> args(v8::Array::New(GetIsolate(), 2U)); |
1055 args->Set(0U, v8::Integer::New(GetIsolate(), tree_id)); | 1147 args->Set(0U, v8::Integer::New(GetIsolate(), tree_id)); |
1056 v8::Local<v8::Array> nodes(v8::Array::New(GetIsolate(), ids.size())); | 1148 v8::Local<v8::Array> nodes(v8::Array::New(GetIsolate(), ids.size())); |
1057 args->Set(1U, nodes); | 1149 args->Set(1U, nodes); |
1058 for (size_t i = 0; i < ids.size(); ++i) | 1150 for (size_t i = 0; i < ids.size(); ++i) |
1059 nodes->Set(i, v8::Integer::New(GetIsolate(), ids[i])); | 1151 nodes->Set(i, v8::Integer::New(GetIsolate(), ids[i])); |
1060 context()->DispatchEvent("automationInternal.onNodesRemoved", args); | 1152 context()->DispatchEvent("automationInternal.onNodesRemoved", args); |
1061 } | 1153 } |
1062 | 1154 |
1063 } // namespace extensions | 1155 } // namespace extensions |
OLD | NEW |