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

Side by Side Diff: chrome/renderer/extensions/automation_internal_custom_bindings.cc

Issue 1457683009: Complete live region support in ChromeVox Next. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed last feedback Created 5 years 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 unified diff | Download patch
OLDNEW
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 "base/bind.h" 7 #include "base/bind.h"
8 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
9 #include "base/thread_task_runner_handle.h" 9 #include "base/thread_task_runner_handle.h"
10 #include "base/values.h" 10 #include "base/values.h"
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 386
387 AutomationInternalCustomBindings* owner_; 387 AutomationInternalCustomBindings* owner_;
388 bool removed_; 388 bool removed_;
389 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 389 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
390 390
391 DISALLOW_COPY_AND_ASSIGN(AutomationMessageFilter); 391 DISALLOW_COPY_AND_ASSIGN(AutomationMessageFilter);
392 }; 392 };
393 393
394 AutomationInternalCustomBindings::AutomationInternalCustomBindings( 394 AutomationInternalCustomBindings::AutomationInternalCustomBindings(
395 ScriptContext* context) 395 ScriptContext* context)
396 : ObjectBackedNativeHandler(context), is_active_profile_(true) { 396 : ObjectBackedNativeHandler(context),
397 is_active_profile_(true),
398 tree_change_observer_overall_filter_(
399 api::automation::TREE_CHANGE_OBSERVER_FILTER_NOTREECHANGES) {
397 // It's safe to use base::Unretained(this) here because these bindings 400 // It's safe to use base::Unretained(this) here because these bindings
398 // will only be called on a valid AutomationInternalCustomBindings instance 401 // will only be called on a valid AutomationInternalCustomBindings instance
399 // and none of the functions have any side effects. 402 // and none of the functions have any side effects.
400 #define ROUTE_FUNCTION(FN) \ 403 #define ROUTE_FUNCTION(FN) \
401 RouteFunction(#FN, \ 404 RouteFunction(#FN, \
402 base::Bind(&AutomationInternalCustomBindings::FN, \ 405 base::Bind(&AutomationInternalCustomBindings::FN, \
403 base::Unretained(this))) 406 base::Unretained(this)))
404 ROUTE_FUNCTION(IsInteractPermitted); 407 ROUTE_FUNCTION(IsInteractPermitted);
405 ROUTE_FUNCTION(GetSchemaAdditions); 408 ROUTE_FUNCTION(GetSchemaAdditions);
406 ROUTE_FUNCTION(GetRoutingID); 409 ROUTE_FUNCTION(GetRoutingID);
407 ROUTE_FUNCTION(StartCachingAccessibilityTrees); 410 ROUTE_FUNCTION(StartCachingAccessibilityTrees);
408 ROUTE_FUNCTION(DestroyAccessibilityTree); 411 ROUTE_FUNCTION(DestroyAccessibilityTree);
412 ROUTE_FUNCTION(AddTreeChangeObserver);
413 ROUTE_FUNCTION(RemoveTreeChangeObserver);
409 ROUTE_FUNCTION(GetChildIDAtIndex); 414 ROUTE_FUNCTION(GetChildIDAtIndex);
410 #undef ROUTE_FUNCTION 415 #undef ROUTE_FUNCTION
411 416
412 // Bindings that take a Tree ID and return a property of the tree. 417 // Bindings that take a Tree ID and return a property of the tree.
413 418
414 RouteTreeIDFunction( 419 RouteTreeIDFunction(
415 "GetRootID", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, 420 "GetRootID", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
416 TreeCache* cache) { 421 TreeCache* cache) {
417 result.Set(v8::Integer::New(isolate, cache->tree.root()->id())); 422 result.Set(v8::Integer::New(isolate, cache->tree.root()->id()));
418 }); 423 });
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
725 auto iter = tree_id_to_tree_cache_map_.find(tree_id); 730 auto iter = tree_id_to_tree_cache_map_.find(tree_id);
726 if (iter == tree_id_to_tree_cache_map_.end()) 731 if (iter == tree_id_to_tree_cache_map_.end())
727 return; 732 return;
728 733
729 TreeCache* cache = iter->second; 734 TreeCache* cache = iter->second;
730 tree_id_to_tree_cache_map_.erase(tree_id); 735 tree_id_to_tree_cache_map_.erase(tree_id);
731 axtree_to_tree_cache_map_.erase(&cache->tree); 736 axtree_to_tree_cache_map_.erase(&cache->tree);
732 delete cache; 737 delete cache;
733 } 738 }
734 739
740 void AutomationInternalCustomBindings::AddTreeChangeObserver(
741 const v8::FunctionCallbackInfo<v8::Value>& args) {
742 if (args.Length() != 2 || !args[0]->IsNumber() || !args[1]->IsString()) {
743 ThrowInvalidArgumentsException(this);
744 return;
745 }
746
747 TreeChangeObserver observer;
748 observer.id = args[0]->Int32Value();
749 std::string filter_str = *v8::String::Utf8Value(args[1]);
750 observer.filter = api::automation::ParseTreeChangeObserverFilter(filter_str);
751
752 tree_change_observers_.push_back(observer);
753 UpdateOverallTreeChangeObserverFilter();
754 }
755
756 void AutomationInternalCustomBindings::RemoveTreeChangeObserver(
757 const v8::FunctionCallbackInfo<v8::Value>& args) {
758 if (args.Length() != 1 || !args[0]->IsNumber()) {
759 ThrowInvalidArgumentsException(this);
760 return;
761 }
762
763 int observer_id = args[0]->Int32Value();
764
765 for (auto iter = tree_change_observers_.begin();
766 iter != tree_change_observers_.end(); ++iter) {
767 if (iter->id == observer_id) {
768 tree_change_observers_.erase(iter);
769 break;
770 }
771 }
772
773 UpdateOverallTreeChangeObserverFilter();
774 }
775
776 void AutomationInternalCustomBindings::UpdateOverallTreeChangeObserverFilter() {
777 tree_change_observer_overall_filter_ =
778 api::automation::TREE_CHANGE_OBSERVER_FILTER_NOTREECHANGES;
779 for (const auto& observer : tree_change_observers_) {
780 tree_change_observer_overall_filter_ =
781 std::max(observer.filter, tree_change_observer_overall_filter_);
782 }
783 }
784
735 void AutomationInternalCustomBindings::RouteTreeIDFunction( 785 void AutomationInternalCustomBindings::RouteTreeIDFunction(
736 const std::string& name, 786 const std::string& name,
737 TreeIDFunction callback) { 787 TreeIDFunction callback) {
738 scoped_refptr<TreeIDWrapper> wrapper = new TreeIDWrapper(this, callback); 788 scoped_refptr<TreeIDWrapper> wrapper = new TreeIDWrapper(this, callback);
739 RouteFunction(name, base::Bind(&TreeIDWrapper::Run, wrapper)); 789 RouteFunction(name, base::Bind(&TreeIDWrapper::Run, wrapper));
740 } 790 }
741 791
742 void AutomationInternalCustomBindings::RouteNodeIDFunction( 792 void AutomationInternalCustomBindings::RouteNodeIDFunction(
743 const std::string& name, 793 const std::string& name,
744 NodeIDFunction callback) { 794 NodeIDFunction callback) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
809 cache->tree_id = params.tree_id; 859 cache->tree_id = params.tree_id;
810 cache->tree.SetDelegate(this); 860 cache->tree.SetDelegate(this);
811 tree_id_to_tree_cache_map_.insert(std::make_pair(tree_id, cache)); 861 tree_id_to_tree_cache_map_.insert(std::make_pair(tree_id, cache));
812 axtree_to_tree_cache_map_.insert(std::make_pair(&cache->tree, cache)); 862 axtree_to_tree_cache_map_.insert(std::make_pair(&cache->tree, cache));
813 } else { 863 } else {
814 cache = iter->second; 864 cache = iter->second;
815 } 865 }
816 866
817 // Update the internal state whether it's the active profile or not. 867 // Update the internal state whether it's the active profile or not.
818 cache->location_offset = params.location_offset; 868 cache->location_offset = params.location_offset;
869 deleted_node_ids_.clear();
819 if (!cache->tree.Unserialize(params.update)) { 870 if (!cache->tree.Unserialize(params.update)) {
820 LOG(ERROR) << cache->tree.error(); 871 LOG(ERROR) << cache->tree.error();
821 return; 872 return;
822 } 873 }
823 874
824 // Don't send the event if it's not the active profile. 875 // Don't send any events if it's not the active profile.
825 if (!is_active_profile) 876 if (!is_active_profile)
826 return; 877 return;
827 878
879 SendNodesRemovedEvent(&cache->tree, deleted_node_ids_);
880 deleted_node_ids_.clear();
881
828 v8::Isolate* isolate = GetIsolate(); 882 v8::Isolate* isolate = GetIsolate();
829 v8::HandleScope handle_scope(isolate); 883 v8::HandleScope handle_scope(isolate);
830 v8::Context::Scope context_scope(context()->v8_context()); 884 v8::Context::Scope context_scope(context()->v8_context());
831 v8::Local<v8::Array> args(v8::Array::New(GetIsolate(), 1U)); 885 v8::Local<v8::Array> args(v8::Array::New(GetIsolate(), 1U));
832 v8::Local<v8::Object> event_params(v8::Object::New(GetIsolate())); 886 v8::Local<v8::Object> event_params(v8::Object::New(GetIsolate()));
833 event_params->Set(CreateV8String(isolate, "treeID"), 887 event_params->Set(CreateV8String(isolate, "treeID"),
834 v8::Integer::New(GetIsolate(), params.tree_id)); 888 v8::Integer::New(GetIsolate(), params.tree_id));
835 event_params->Set(CreateV8String(isolate, "targetID"), 889 event_params->Set(CreateV8String(isolate, "targetID"),
836 v8::Integer::New(GetIsolate(), params.id)); 890 v8::Integer::New(GetIsolate(), params.id));
837 event_params->Set(CreateV8String(isolate, "eventType"), 891 event_params->Set(CreateV8String(isolate, "eventType"),
838 CreateV8String(isolate, ToString(params.event_type))); 892 CreateV8String(isolate, ToString(params.event_type)));
839 args->Set(0U, event_params); 893 args->Set(0U, event_params);
840 context()->DispatchEvent("automationInternal.onAccessibilityEvent", args); 894 context()->DispatchEvent("automationInternal.onAccessibilityEvent", args);
841 } 895 }
842 896
843 void AutomationInternalCustomBindings::OnTreeDataChanged(ui::AXTree* tree) {} 897 void AutomationInternalCustomBindings::OnTreeDataChanged(ui::AXTree* tree) {}
844 898
845 void AutomationInternalCustomBindings::OnNodeWillBeDeleted(ui::AXTree* tree, 899 void AutomationInternalCustomBindings::OnNodeWillBeDeleted(ui::AXTree* tree,
846 ui::AXNode* node) { 900 ui::AXNode* node) {
847 SendTreeChangeEvent( 901 SendTreeChangeEvent(
848 api::automation::TREE_CHANGE_TYPE_NODEREMOVED, 902 api::automation::TREE_CHANGE_TYPE_NODEREMOVED,
849 tree, node); 903 tree, node);
904 deleted_node_ids_.push_back(node->id());
850 } 905 }
851 906
852 void AutomationInternalCustomBindings::OnSubtreeWillBeDeleted( 907 void AutomationInternalCustomBindings::OnSubtreeWillBeDeleted(
853 ui::AXTree* tree, 908 ui::AXTree* tree,
854 ui::AXNode* node) { 909 ui::AXNode* node) {
855 // This isn't strictly needed, as OnNodeWillBeDeleted will already be 910 // This isn't strictly needed, as OnNodeWillBeDeleted will already be
856 // called. We could send a JS event for this only if it turns out to 911 // called. We could send a JS event for this only if it turns out to
857 // be needed for something. 912 // be needed for something.
858 } 913 }
859 914
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
902 } 957 }
903 958
904 void AutomationInternalCustomBindings::SendTreeChangeEvent( 959 void AutomationInternalCustomBindings::SendTreeChangeEvent(
905 api::automation::TreeChangeType change_type, 960 api::automation::TreeChangeType change_type,
906 ui::AXTree* tree, 961 ui::AXTree* tree,
907 ui::AXNode* node) { 962 ui::AXNode* node) {
908 // Don't send tree change events when it's not the active profile. 963 // Don't send tree change events when it's not the active profile.
909 if (!is_active_profile_) 964 if (!is_active_profile_)
910 return; 965 return;
911 966
967 // Always notify the custom bindings when there's a node with a child tree
968 // ID that might need to be loaded.
969 if (node->data().HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID))
970 SendChildTreeIDEvent(tree, node);
971
972 switch (tree_change_observer_overall_filter_) {
973 case api::automation::TREE_CHANGE_OBSERVER_FILTER_NOTREECHANGES:
974 default:
975 return;
976 case api::automation::TREE_CHANGE_OBSERVER_FILTER_LIVEREGIONTREECHANGES:
977 if (!node->data().HasStringAttribute(ui::AX_ATTR_CONTAINER_LIVE_STATUS) &&
978 node->data().role != ui::AX_ROLE_ALERT) {
979 return;
980 }
981 break;
982 case api::automation::TREE_CHANGE_OBSERVER_FILTER_ALLTREECHANGES:
983 break;
984 }
985
912 auto iter = axtree_to_tree_cache_map_.find(tree); 986 auto iter = axtree_to_tree_cache_map_.find(tree);
913 if (iter == axtree_to_tree_cache_map_.end()) 987 if (iter == axtree_to_tree_cache_map_.end())
914 return; 988 return;
989
990 int tree_id = iter->second->tree_id;
991
992 v8::Isolate* isolate = GetIsolate();
993 v8::HandleScope handle_scope(isolate);
994 v8::Context::Scope context_scope(context()->v8_context());
995
996 for (const auto& observer : tree_change_observers_) {
997 switch (observer.filter) {
998 case api::automation::TREE_CHANGE_OBSERVER_FILTER_NOTREECHANGES:
999 default:
1000 continue;
1001 case api::automation::TREE_CHANGE_OBSERVER_FILTER_LIVEREGIONTREECHANGES:
1002 if (!node->data().HasStringAttribute(
1003 ui::AX_ATTR_CONTAINER_LIVE_STATUS) &&
1004 node->data().role != ui::AX_ROLE_ALERT) {
1005 continue;
1006 }
1007 break;
1008 case api::automation::TREE_CHANGE_OBSERVER_FILTER_ALLTREECHANGES:
1009 break;
1010 }
1011
1012 v8::Local<v8::Array> args(v8::Array::New(GetIsolate(), 4U));
1013 args->Set(0U, v8::Integer::New(GetIsolate(), observer.id));
1014 args->Set(1U, v8::Integer::New(GetIsolate(), tree_id));
1015 args->Set(2U, v8::Integer::New(GetIsolate(), node->id()));
1016 args->Set(3U, CreateV8String(isolate, ToString(change_type)));
1017 context()->DispatchEvent("automationInternal.onTreeChange", args);
1018 }
1019 }
1020
1021 void AutomationInternalCustomBindings::SendChildTreeIDEvent(ui::AXTree* tree,
1022 ui::AXNode* node) {
1023 auto iter = axtree_to_tree_cache_map_.find(tree);
1024 if (iter == axtree_to_tree_cache_map_.end())
1025 return;
915 1026
916 int tree_id = iter->second->tree_id; 1027 int tree_id = iter->second->tree_id;
917 1028
918 v8::Isolate* isolate = GetIsolate(); 1029 v8::Isolate* isolate = GetIsolate();
919 v8::HandleScope handle_scope(isolate); 1030 v8::HandleScope handle_scope(isolate);
920 v8::Context::Scope context_scope(context()->v8_context()); 1031 v8::Context::Scope context_scope(context()->v8_context());
921 v8::Local<v8::Array> args(v8::Array::New(GetIsolate(), 3U)); 1032 v8::Local<v8::Array> args(v8::Array::New(GetIsolate(), 2U));
922 args->Set(0U, v8::Integer::New(GetIsolate(), tree_id)); 1033 args->Set(0U, v8::Integer::New(GetIsolate(), tree_id));
923 args->Set(1U, v8::Integer::New(GetIsolate(), node->id())); 1034 args->Set(1U, v8::Integer::New(GetIsolate(), node->id()));
924 args->Set(2U, CreateV8String(isolate, ToString(change_type))); 1035 context()->DispatchEvent("automationInternal.onChildTreeID", args);
925 context()->DispatchEvent("automationInternal.onTreeChange", args); 1036 }
1037
1038 void AutomationInternalCustomBindings::SendNodesRemovedEvent(
1039 ui::AXTree* tree,
1040 const std::vector<int>& ids) {
1041 auto iter = axtree_to_tree_cache_map_.find(tree);
1042 if (iter == axtree_to_tree_cache_map_.end())
1043 return;
1044
1045 int tree_id = iter->second->tree_id;
1046
1047 v8::Isolate* isolate = GetIsolate();
1048 v8::HandleScope handle_scope(isolate);
1049 v8::Context::Scope context_scope(context()->v8_context());
1050 v8::Local<v8::Array> args(v8::Array::New(GetIsolate(), 2U));
1051 args->Set(0U, v8::Integer::New(GetIsolate(), tree_id));
1052 v8::Local<v8::Array> nodes(v8::Array::New(GetIsolate(), ids.size()));
1053 args->Set(1U, nodes);
1054 for (size_t i = 0; i < ids.size(); ++i)
1055 nodes->Set(i, v8::Integer::New(GetIsolate(), ids[i]));
1056 context()->DispatchEvent("automationInternal.onNodesRemoved", args);
926 } 1057 }
927 1058
928 } // namespace extensions 1059 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698