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

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

Issue 1407413002: Move some AX attrs from AXNodeData to AXTreeData. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 5 years, 2 months 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"
11 #include "chrome/common/extensions/chrome_extension_messages.h" 11 #include "chrome/common/extensions/chrome_extension_messages.h"
12 #include "chrome/common/extensions/manifest_handlers/automation.h" 12 #include "chrome/common/extensions/manifest_handlers/automation.h"
13 #include "content/public/renderer/render_frame.h" 13 #include "content/public/renderer/render_frame.h"
14 #include "content/public/renderer/render_thread.h" 14 #include "content/public/renderer/render_thread.h"
15 #include "content/public/renderer/render_view.h" 15 #include "content/public/renderer/render_view.h"
16 #include "extensions/common/extension.h" 16 #include "extensions/common/extension.h"
17 #include "extensions/common/manifest.h" 17 #include "extensions/common/manifest.h"
18 #include "extensions/renderer/script_context.h" 18 #include "extensions/renderer/script_context.h"
19 #include "ipc/message_filter.h" 19 #include "ipc/message_filter.h"
20 #include "ui/accessibility/ax_enums.h" 20 #include "ui/accessibility/ax_enums.h"
21 #include "ui/accessibility/ax_node.h" 21 #include "ui/accessibility/ax_node.h"
22 22
23 namespace extensions {
24
23 namespace { 25 namespace {
24 26
25 // Helper to convert an enum to a V8 object. 27 // Helper to convert an enum to a V8 object.
26 template <typename EnumType> 28 template <typename EnumType>
27 v8::Local<v8::Object> ToEnumObject(v8::Isolate* isolate, 29 v8::Local<v8::Object> ToEnumObject(v8::Isolate* isolate,
28 EnumType start_after, 30 EnumType start_after,
29 EnumType end_at) { 31 EnumType end_at) {
30 v8::Local<v8::Object> object = v8::Object::New(isolate); 32 v8::Local<v8::Object> object = v8::Object::New(isolate);
31 for (int i = start_after + 1; i <= end_at; ++i) { 33 for (int i = start_after + 1; i <= end_at; ++i) {
32 v8::Local<v8::String> value = v8::String::NewFromUtf8( 34 v8::Local<v8::String> value = v8::String::NewFromUtf8(
33 isolate, ui::ToString(static_cast<EnumType>(i)).c_str()); 35 isolate, ui::ToString(static_cast<EnumType>(i)).c_str());
34 object->Set(value, value); 36 object->Set(value, value);
35 } 37 }
36 return object; 38 return object;
37 } 39 }
38 40
41 void ThrowInvalidArgumentsException(
42 AutomationInternalCustomBindings* automation_bindings) {
43 v8::Isolate* isolate = automation_bindings->GetIsolate();
44 automation_bindings->GetIsolate()->ThrowException(
45 v8::String::NewFromUtf8(
46 isolate,
47 "Invalid arguments to AutomationInternalCustomBindings function",
48 v8::NewStringType::kNormal)
49 .ToLocalChecked());
50
51 LOG(FATAL) << "Invalid arguments to AutomationInternalCustomBindings function"
52 << automation_bindings->context()->GetStackTraceAsString();
53 }
54
55 v8::Local<v8::Value> CreateV8String(v8::Isolate* isolate, const char* str) {
56 return v8::String::NewFromUtf8(isolate, str, v8::String::kNormalString,
57 strlen(str));
58 }
59
60 v8::Local<v8::Value> CreateV8String(v8::Isolate* isolate,
61 const std::string& str) {
62 return v8::String::NewFromUtf8(isolate, str.c_str(),
63 v8::String::kNormalString, str.length());
64 }
65
66 //
67 // Helper class that helps implement bindings for a JavaScript function
68 // that takes a single input argument consisting of a Tree ID. Looks up
69 // the TreeCache and passes it to the function passed to the constructor.
70 //
71
72 typedef void (*TreeIDFunction)(v8::Isolate* isolate,
73 v8::ReturnValue<v8::Value> result,
74 TreeCache* cache);
75
76 class TreeIDWrapper : public base::RefCountedThreadSafe<TreeIDWrapper> {
77 public:
78 TreeIDWrapper(AutomationInternalCustomBindings* automation_bindings,
79 TreeIDFunction function)
80 : automation_bindings_(automation_bindings), function_(function) {}
81
82 void Run(const v8::FunctionCallbackInfo<v8::Value>& args) {
83 v8::Isolate* isolate = automation_bindings_->GetIsolate();
84 if (args.Length() != 1 || !args[0]->IsNumber())
85 ThrowInvalidArgumentsException(automation_bindings_);
86
87 int tree_id = args[0]->Int32Value();
88 TreeCache* cache = automation_bindings_->GetTreeCacheFromTreeID(tree_id);
89 if (!cache)
90 return;
91
92 // The root can be null if this is called from an onTreeChange callback.
93 if (!cache->tree.root())
94 return;
95
96 function_(isolate, args.GetReturnValue(), cache);
97 }
98
99 private:
100 virtual ~TreeIDWrapper() {}
101
102 friend class base::RefCountedThreadSafe<TreeIDWrapper>;
103
104 AutomationInternalCustomBindings* automation_bindings_;
105 TreeIDFunction function_;
106 };
107
108 //
109 // Helper class that helps implement bindings for a JavaScript function
110 // that takes two input arguments: a tree ID and node ID. Looks up the
111 // TreeCache and the AXNode and passes them to the function passed to
112 // the constructor.
113 //
114
115 typedef void (*NodeIDFunction)(v8::Isolate* isolate,
116 v8::ReturnValue<v8::Value> result,
117 TreeCache* cache,
118 ui::AXNode* node);
119
120 class NodeIDWrapper : public base::RefCountedThreadSafe<NodeIDWrapper> {
121 public:
122 NodeIDWrapper(AutomationInternalCustomBindings* automation_bindings,
123 NodeIDFunction function)
124 : automation_bindings_(automation_bindings), function_(function) {}
125
126 void Run(const v8::FunctionCallbackInfo<v8::Value>& args) {
127 v8::Isolate* isolate = automation_bindings_->GetIsolate();
128 if (args.Length() < 2 || !args[0]->IsNumber() || !args[1]->IsNumber())
129 ThrowInvalidArgumentsException(automation_bindings_);
130
131 int tree_id = args[0]->Int32Value();
132 int node_id = args[1]->Int32Value();
133
134 TreeCache* cache = automation_bindings_->GetTreeCacheFromTreeID(tree_id);
135 if (!cache)
136 return;
137
138 ui::AXNode* node = cache->tree.GetFromId(node_id);
139 if (!node)
140 return;
141
142 function_(isolate, args.GetReturnValue(), cache, node);
143 }
144
145 private:
146 virtual ~NodeIDWrapper() {}
147
148 friend class base::RefCountedThreadSafe<NodeIDWrapper>;
149
150 AutomationInternalCustomBindings* automation_bindings_;
151 NodeIDFunction function_;
152 };
153
154 //
155 // Helper class that helps implement bindings for a JavaScript function
156 // that takes three input arguments: a tree ID, node ID, and string
157 // argument. Looks up the TreeCache and the AXNode and passes them to the
158 // function passed to the constructor.
159 //
160
161 typedef void (*NodeIDPlusAttributeFunction)(v8::Isolate* isolate,
162 v8::ReturnValue<v8::Value> result,
163 ui::AXNode* node,
164 const std::string& attribute);
165
166 class NodeIDPlusAttributeWrapper
167 : public base::RefCountedThreadSafe<NodeIDPlusAttributeWrapper> {
168 public:
169 NodeIDPlusAttributeWrapper(
170 AutomationInternalCustomBindings* automation_bindings,
171 NodeIDPlusAttributeFunction function)
172 : automation_bindings_(automation_bindings), function_(function) {}
173
174 void Run(const v8::FunctionCallbackInfo<v8::Value>& args) {
175 v8::Isolate* isolate = automation_bindings_->GetIsolate();
176 if (args.Length() < 3 || !args[0]->IsNumber() || !args[1]->IsNumber() ||
177 !args[2]->IsString()) {
178 ThrowInvalidArgumentsException(automation_bindings_);
179 }
180
181 int tree_id = args[0]->Int32Value();
182 int node_id = args[1]->Int32Value();
183 std::string attribute = *v8::String::Utf8Value(args[2]);
184
185 TreeCache* cache = automation_bindings_->GetTreeCacheFromTreeID(tree_id);
186 if (!cache)
187 return;
188
189 ui::AXNode* node = cache->tree.GetFromId(node_id);
190 if (!node)
191 return;
192
193 function_(isolate, args.GetReturnValue(), node, attribute);
194 }
195
196 private:
197 virtual ~NodeIDPlusAttributeWrapper() {}
198
199 friend class base::RefCountedThreadSafe<NodeIDPlusAttributeWrapper>;
200
201 AutomationInternalCustomBindings* automation_bindings_;
202 NodeIDPlusAttributeFunction function_;
203 };
204
39 } // namespace 205 } // namespace
40 206
41 namespace extensions {
42
43 TreeCache::TreeCache() {} 207 TreeCache::TreeCache() {}
44 TreeCache::~TreeCache() {} 208 TreeCache::~TreeCache() {}
45 209
46 class AutomationMessageFilter : public IPC::MessageFilter { 210 class AutomationMessageFilter : public IPC::MessageFilter {
47 public: 211 public:
48 explicit AutomationMessageFilter(AutomationInternalCustomBindings* owner) 212 explicit AutomationMessageFilter(AutomationInternalCustomBindings* owner)
49 : owner_(owner), 213 : owner_(owner),
50 removed_(false) { 214 removed_(false) {
51 DCHECK(owner); 215 DCHECK(owner);
52 content::RenderThread::Get()->AddFilter(this); 216 content::RenderThread::Get()->AddFilter(this);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 AutomationInternalCustomBindings::AutomationInternalCustomBindings( 266 AutomationInternalCustomBindings::AutomationInternalCustomBindings(
103 ScriptContext* context) 267 ScriptContext* context)
104 : ObjectBackedNativeHandler(context), is_active_profile_(true) { 268 : ObjectBackedNativeHandler(context), is_active_profile_(true) {
105 // It's safe to use base::Unretained(this) here because these bindings 269 // It's safe to use base::Unretained(this) here because these bindings
106 // will only be called on a valid AutomationInternalCustomBindings instance 270 // will only be called on a valid AutomationInternalCustomBindings instance
107 // and none of the functions have any side effects. 271 // and none of the functions have any side effects.
108 #define ROUTE_FUNCTION(FN) \ 272 #define ROUTE_FUNCTION(FN) \
109 RouteFunction(#FN, \ 273 RouteFunction(#FN, \
110 base::Bind(&AutomationInternalCustomBindings::FN, \ 274 base::Bind(&AutomationInternalCustomBindings::FN, \
111 base::Unretained(this))) 275 base::Unretained(this)))
112
113 ROUTE_FUNCTION(IsInteractPermitted); 276 ROUTE_FUNCTION(IsInteractPermitted);
114 ROUTE_FUNCTION(GetSchemaAdditions); 277 ROUTE_FUNCTION(GetSchemaAdditions);
115 ROUTE_FUNCTION(GetRoutingID); 278 ROUTE_FUNCTION(GetRoutingID);
116 ROUTE_FUNCTION(StartCachingAccessibilityTrees); 279 ROUTE_FUNCTION(StartCachingAccessibilityTrees);
117 ROUTE_FUNCTION(DestroyAccessibilityTree); 280 ROUTE_FUNCTION(DestroyAccessibilityTree);
118 ROUTE_FUNCTION(GetRootID);
119 ROUTE_FUNCTION(GetParentID);
120 ROUTE_FUNCTION(GetChildCount);
121 ROUTE_FUNCTION(GetChildIDAtIndex); 281 ROUTE_FUNCTION(GetChildIDAtIndex);
122 ROUTE_FUNCTION(GetIndexInParent);
123 ROUTE_FUNCTION(GetState);
124 ROUTE_FUNCTION(GetRole);
125 ROUTE_FUNCTION(GetLocation);
126 ROUTE_FUNCTION(GetStringAttribute);
127 ROUTE_FUNCTION(GetBoolAttribute);
128 ROUTE_FUNCTION(GetIntAttribute);
129 ROUTE_FUNCTION(GetFloatAttribute);
130 ROUTE_FUNCTION(GetIntListAttribute);
131 ROUTE_FUNCTION(GetHtmlAttribute);
132
133 #undef ROUTE_FUNCTION 282 #undef ROUTE_FUNCTION
283
284 // Bindings that take a Tree ID and return a property of the tree.
285
286 RouteTreeIDFunction(
287 "GetRootID", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
288 TreeCache* cache) {
289 result.Set(v8::Integer::New(isolate, cache->tree.root()->id()));
290 });
291 RouteTreeIDFunction(
292 "GetDocURL", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
293 TreeCache* cache) {
294 result.Set(
295 v8::String::NewFromUtf8(isolate, cache->tree.data().url.c_str()));
296 });
297 RouteTreeIDFunction(
298 "GetDocTitle", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
299 TreeCache* cache) {
300 result.Set(
301 v8::String::NewFromUtf8(isolate, cache->tree.data().title.c_str()));
302 });
303 RouteTreeIDFunction(
304 "GetDocLoaded", [](v8::Isolate* isolate,
305 v8::ReturnValue<v8::Value> result, TreeCache* cache) {
306 result.Set(v8::Boolean::New(isolate, cache->tree.data().loaded));
307 });
308 RouteTreeIDFunction("GetDocLoadingProgress",
309 [](v8::Isolate* isolate,
310 v8::ReturnValue<v8::Value> result, TreeCache* cache) {
311 result.Set(v8::Number::New(
312 isolate, cache->tree.data().loading_progress));
313 });
314 RouteTreeIDFunction("GetAnchorObjectID",
315 [](v8::Isolate* isolate,
316 v8::ReturnValue<v8::Value> result, TreeCache* cache) {
317 result.Set(v8::Number::New(
318 isolate, cache->tree.data().sel_anchor_object_id));
319 });
320 RouteTreeIDFunction("GetAnchorOffset", [](v8::Isolate* isolate,
321 v8::ReturnValue<v8::Value> result,
322 TreeCache* cache) {
323 result.Set(v8::Number::New(isolate, cache->tree.data().sel_anchor_offset));
324 });
325 RouteTreeIDFunction("GetFocusObjectID",
326 [](v8::Isolate* isolate,
327 v8::ReturnValue<v8::Value> result, TreeCache* cache) {
328 result.Set(v8::Number::New(
329 isolate, cache->tree.data().sel_focus_object_id));
330 });
331 RouteTreeIDFunction("GetFocusOffset", [](v8::Isolate* isolate,
332 v8::ReturnValue<v8::Value> result,
333 TreeCache* cache) {
334 result.Set(v8::Number::New(isolate, cache->tree.data().sel_focus_offset));
335 });
336
337 // Bindings that take a Tree ID and Node ID and return a property of the node.
338
339 RouteNodeIDFunction(
340 "GetParentID", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
341 TreeCache* cache, ui::AXNode* node) {
342 if (node->parent())
343 result.Set(v8::Integer::New(isolate, node->parent()->id()));
344 });
345 RouteNodeIDFunction("GetChildCount", [](v8::Isolate* isolate,
346 v8::ReturnValue<v8::Value> result,
347 TreeCache* cache, ui::AXNode* node) {
348 result.Set(v8::Integer::New(isolate, node->child_count()));
349 });
350 RouteNodeIDFunction(
351 "GetIndexInParent",
352 [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
353 TreeCache* cache, ui::AXNode* node) {
354 result.Set(v8::Integer::New(isolate, node->index_in_parent()));
355 });
356 RouteNodeIDFunction(
357 "GetState", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
358 TreeCache* cache, ui::AXNode* node) {
359 v8::Local<v8::Object> state(v8::Object::New(isolate));
360 uint32 state_pos = 0, state_shifter = node->data().state;
361 while (state_shifter) {
362 if (state_shifter & 1) {
363 std::string key = ToString(static_cast<ui::AXState>(state_pos));
364 state->Set(CreateV8String(isolate, key),
365 v8::Boolean::New(isolate, true));
366 }
367 state_shifter = state_shifter >> 1;
368 state_pos++;
369 }
370 result.Set(state);
371 });
372 RouteNodeIDFunction(
373 "GetRole", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
374 TreeCache* cache, ui::AXNode* node) {
375 std::string role_name = ui::ToString(node->data().role);
376 result.Set(v8::String::NewFromUtf8(isolate, role_name.c_str()));
377 });
378 RouteNodeIDFunction(
379 "GetLocation", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
380 TreeCache* cache, ui::AXNode* node) {
381 v8::Local<v8::Object> location_obj(v8::Object::New(isolate));
382 gfx::Rect location = node->data().location;
383 location.Offset(cache->location_offset);
384 location_obj->Set(CreateV8String(isolate, "left"),
385 v8::Integer::New(isolate, location.x()));
386 location_obj->Set(CreateV8String(isolate, "top"),
387 v8::Integer::New(isolate, location.y()));
388 location_obj->Set(CreateV8String(isolate, "width"),
389 v8::Integer::New(isolate, location.width()));
390 location_obj->Set(CreateV8String(isolate, "height"),
391 v8::Integer::New(isolate, location.height()));
392 result.Set(location_obj);
393 });
394
395 // Bindings that take a Tree ID and Node ID and string attribute name
396 // and return a property of the node.
397
398 RouteNodeIDPlusAttributeFunction(
399 "GetStringAttribute",
400 [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
401 ui::AXNode* node, const std::string& attribute_name) {
402 ui::AXStringAttribute attribute =
403 ui::ParseAXStringAttribute(attribute_name);
404 std::string attr_value;
405 if (!node->data().GetStringAttribute(attribute, &attr_value))
406 return;
407
408 result.Set(v8::String::NewFromUtf8(isolate, attr_value.c_str()));
409 });
410 RouteNodeIDPlusAttributeFunction(
411 "GetBoolAttribute",
412 [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
413 ui::AXNode* node, const std::string& attribute_name) {
414 ui::AXBoolAttribute attribute =
415 ui::ParseAXBoolAttribute(attribute_name);
416 bool attr_value;
417 if (!node->data().GetBoolAttribute(attribute, &attr_value))
418 return;
419
420 result.Set(v8::Boolean::New(isolate, attr_value));
421 });
422 RouteNodeIDPlusAttributeFunction(
423 "GetIntAttribute",
424 [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
425 ui::AXNode* node, const std::string& attribute_name) {
426 ui::AXIntAttribute attribute = ui::ParseAXIntAttribute(attribute_name);
427 int attr_value;
428 if (!node->data().GetIntAttribute(attribute, &attr_value))
429 return;
430
431 result.Set(v8::Integer::New(isolate, attr_value));
432 });
433 RouteNodeIDPlusAttributeFunction(
434 "GetFloatAttribute",
435 [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
436 ui::AXNode* node, const std::string& attribute_name) {
437 ui::AXFloatAttribute attribute =
438 ui::ParseAXFloatAttribute(attribute_name);
439 float attr_value;
440
441 if (!node->data().GetFloatAttribute(attribute, &attr_value))
442 return;
443
444 result.Set(v8::Number::New(isolate, attr_value));
445 });
446 RouteNodeIDPlusAttributeFunction(
447 "GetIntListAttribute",
448 [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
449 ui::AXNode* node, const std::string& attribute_name) {
450 ui::AXIntListAttribute attribute =
451 ui::ParseAXIntListAttribute(attribute_name);
452 if (!node->data().HasIntListAttribute(attribute))
453 return;
454 const std::vector<int32>& attr_value =
455 node->data().GetIntListAttribute(attribute);
456
457 v8::Local<v8::Array> array_result(
458 v8::Array::New(isolate, attr_value.size()));
459 for (size_t i = 0; i < attr_value.size(); ++i)
460 array_result->Set(static_cast<uint32>(i),
461 v8::Integer::New(isolate, attr_value[i]));
462 result.Set(array_result);
463 });
464 RouteNodeIDPlusAttributeFunction(
465 "GetHtmlAttribute",
466 [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
467 ui::AXNode* node, const std::string& attribute_name) {
468 std::string attr_value;
469 if (!node->data().GetHtmlAttribute(attribute_name.c_str(), &attr_value))
470 return;
471
472 result.Set(v8::String::NewFromUtf8(isolate, attr_value.c_str()));
473 });
134 } 474 }
135 475
136 AutomationInternalCustomBindings::~AutomationInternalCustomBindings() { 476 AutomationInternalCustomBindings::~AutomationInternalCustomBindings() {
137 if (message_filter_) 477 if (message_filter_)
138 message_filter_->Detach(); 478 message_filter_->Detach();
139 STLDeleteContainerPairSecondPointers(tree_id_to_tree_cache_map_.begin(), 479 STLDeleteContainerPairSecondPointers(tree_id_to_tree_cache_map_.begin(),
140 tree_id_to_tree_cache_map_.end()); 480 tree_id_to_tree_cache_map_.end());
141 } 481 }
142 482
143 void AutomationInternalCustomBindings::OnMessageReceived( 483 void AutomationInternalCustomBindings::OnMessageReceived(
144 const IPC::Message& message) { 484 const IPC::Message& message) {
145 IPC_BEGIN_MESSAGE_MAP(AutomationInternalCustomBindings, message) 485 IPC_BEGIN_MESSAGE_MAP(AutomationInternalCustomBindings, message)
146 IPC_MESSAGE_HANDLER(ExtensionMsg_AccessibilityEvent, OnAccessibilityEvent) 486 IPC_MESSAGE_HANDLER(ExtensionMsg_AccessibilityEvent, OnAccessibilityEvent)
147 IPC_END_MESSAGE_MAP() 487 IPC_END_MESSAGE_MAP()
148 } 488 }
149 489
490 TreeCache* AutomationInternalCustomBindings::GetTreeCacheFromTreeID(
491 int tree_id) {
492 const auto iter = tree_id_to_tree_cache_map_.find(tree_id);
493 if (iter == tree_id_to_tree_cache_map_.end())
494 return nullptr;
495
496 return iter->second;
497 }
498
150 void AutomationInternalCustomBindings::IsInteractPermitted( 499 void AutomationInternalCustomBindings::IsInteractPermitted(
151 const v8::FunctionCallbackInfo<v8::Value>& args) { 500 const v8::FunctionCallbackInfo<v8::Value>& args) {
152 const Extension* extension = context()->extension(); 501 const Extension* extension = context()->extension();
153 CHECK(extension); 502 CHECK(extension);
154 const AutomationInfo* automation_info = AutomationInfo::Get(extension); 503 const AutomationInfo* automation_info = AutomationInfo::Get(extension);
155 CHECK(automation_info); 504 CHECK(automation_info);
156 args.GetReturnValue().Set( 505 args.GetReturnValue().Set(
157 v8::Boolean::New(GetIsolate(), automation_info->interact)); 506 v8::Boolean::New(GetIsolate(), automation_info->interact));
158 } 507 }
159 508
(...skipping 28 matching lines...) Expand all
188 additions->Set( 537 additions->Set(
189 v8::String::NewFromUtf8(GetIsolate(), "TreeChangeType"), 538 v8::String::NewFromUtf8(GetIsolate(), "TreeChangeType"),
190 ToEnumObject(GetIsolate(), ui::AX_MUTATION_NONE, ui::AX_MUTATION_LAST)); 539 ToEnumObject(GetIsolate(), ui::AX_MUTATION_NONE, ui::AX_MUTATION_LAST));
191 540
192 args.GetReturnValue().Set(additions); 541 args.GetReturnValue().Set(additions);
193 } 542 }
194 543
195 void AutomationInternalCustomBindings::DestroyAccessibilityTree( 544 void AutomationInternalCustomBindings::DestroyAccessibilityTree(
196 const v8::FunctionCallbackInfo<v8::Value>& args) { 545 const v8::FunctionCallbackInfo<v8::Value>& args) {
197 if (args.Length() != 1 || !args[0]->IsNumber()) { 546 if (args.Length() != 1 || !args[0]->IsNumber()) {
198 ThrowInvalidArgumentsException(args); 547 ThrowInvalidArgumentsException(this);
199 return; 548 return;
200 } 549 }
201 550
202 int tree_id = args[0]->Int32Value(); 551 int tree_id = args[0]->Int32Value();
203 auto iter = tree_id_to_tree_cache_map_.find(tree_id); 552 auto iter = tree_id_to_tree_cache_map_.find(tree_id);
204 if (iter == tree_id_to_tree_cache_map_.end()) 553 if (iter == tree_id_to_tree_cache_map_.end())
205 return; 554 return;
206 555
207 TreeCache* cache = iter->second; 556 TreeCache* cache = iter->second;
208 tree_id_to_tree_cache_map_.erase(tree_id); 557 tree_id_to_tree_cache_map_.erase(tree_id);
209 axtree_to_tree_cache_map_.erase(&cache->tree); 558 axtree_to_tree_cache_map_.erase(&cache->tree);
210 delete cache; 559 delete cache;
211 } 560 }
212 561
213 // 562 void AutomationInternalCustomBindings::RouteTreeIDFunction(
214 // Access the cached accessibility trees and properties of their nodes. 563 const std::string& name,
215 // 564 TreeIDFunction callback) {
216 565 scoped_refptr<TreeIDWrapper> wrapper = new TreeIDWrapper(this, callback);
217 void AutomationInternalCustomBindings::GetRootID( 566 RouteFunction(name, base::Bind(&TreeIDWrapper::Run, wrapper));
218 const v8::FunctionCallbackInfo<v8::Value>& args) {
219 if (args.Length() != 1 || !args[0]->IsNumber()) {
220 ThrowInvalidArgumentsException(args);
221 return;
222 }
223
224 int tree_id = args[0]->Int32Value();
225 const auto iter = tree_id_to_tree_cache_map_.find(tree_id);
226 if (iter == tree_id_to_tree_cache_map_.end())
227 return;
228
229 TreeCache* cache = iter->second;
230 ui::AXNode* root = cache->tree.root();
231
232 // The root can be null if this is called from an onTreeChange callback.
233 if (!root)
234 return;
235
236 int root_id = root->id();
237 args.GetReturnValue().Set(v8::Integer::New(GetIsolate(), root_id));
238 } 567 }
239 568
240 void AutomationInternalCustomBindings::GetParentID( 569 void AutomationInternalCustomBindings::RouteNodeIDFunction(
241 const v8::FunctionCallbackInfo<v8::Value>& args) { 570 const std::string& name,
242 ui::AXNode* node = nullptr; 571 NodeIDFunction callback) {
243 if (!GetNodeHelper(args, nullptr, &node)) 572 scoped_refptr<NodeIDWrapper> wrapper = new NodeIDWrapper(this, callback);
244 return; 573 RouteFunction(name, base::Bind(&NodeIDWrapper::Run, wrapper));
245
246 if (!node->parent())
247 return;
248
249 int parent_id = node->parent()->id();
250 args.GetReturnValue().Set(v8::Integer::New(GetIsolate(), parent_id));
251 } 574 }
252 575
253 void AutomationInternalCustomBindings::GetChildCount( 576 void AutomationInternalCustomBindings::RouteNodeIDPlusAttributeFunction(
254 const v8::FunctionCallbackInfo<v8::Value>& args) { 577 const std::string& name,
255 ui::AXNode* node = nullptr; 578 NodeIDPlusAttributeFunction callback) {
256 if (!GetNodeHelper(args, nullptr, &node)) 579 scoped_refptr<NodeIDPlusAttributeWrapper> wrapper =
257 return; 580 new NodeIDPlusAttributeWrapper(this, callback);
258 581 RouteFunction(name, base::Bind(&NodeIDPlusAttributeWrapper::Run, wrapper));
259 int child_count = node->child_count();
260 args.GetReturnValue().Set(v8::Integer::New(GetIsolate(), child_count));
261 } 582 }
262 583
263 void AutomationInternalCustomBindings::GetChildIDAtIndex( 584 void AutomationInternalCustomBindings::GetChildIDAtIndex(
264 const v8::FunctionCallbackInfo<v8::Value>& args) { 585 const v8::FunctionCallbackInfo<v8::Value>& args) {
265 if (args.Length() < 3 || !args[2]->IsNumber()) { 586 if (args.Length() < 3 || !args[2]->IsNumber()) {
266 ThrowInvalidArgumentsException(args); 587 ThrowInvalidArgumentsException(this);
267 return; 588 return;
268 } 589 }
269 590
270 ui::AXNode* node = nullptr;
271 if (!GetNodeHelper(args, nullptr, &node))
272 return;
273
274 int index = args[2]->Int32Value();
275 if (index < 0 || index >= node->child_count())
276 return;
277
278 int child_id = node->children()[index]->id();
279 args.GetReturnValue().Set(v8::Integer::New(GetIsolate(), child_id));
280 }
281
282 void AutomationInternalCustomBindings::GetIndexInParent(
283 const v8::FunctionCallbackInfo<v8::Value>& args) {
284 ui::AXNode* node = nullptr;
285 if (!GetNodeHelper(args, nullptr, &node))
286 return;
287
288 int index_in_parent = node->index_in_parent();
289 args.GetReturnValue().Set(v8::Integer::New(GetIsolate(), index_in_parent));
290 }
291
292 void AutomationInternalCustomBindings::GetState(
293 const v8::FunctionCallbackInfo<v8::Value>& args) {
294 ui::AXNode* node = nullptr;
295 if (!GetNodeHelper(args, nullptr, &node))
296 return;
297
298 v8::Local<v8::Object> state(v8::Object::New(GetIsolate()));
299 uint32 state_pos = 0, state_shifter = node->data().state;
300 while (state_shifter) {
301 if (state_shifter & 1) {
302 std::string key = ToString(static_cast<ui::AXState>(state_pos));
303 state->Set(CreateV8String(key),
304 v8::Boolean::New(GetIsolate(), true));
305 }
306 state_shifter = state_shifter >> 1;
307 state_pos++;
308 }
309
310 args.GetReturnValue().Set(state);
311 }
312
313 void AutomationInternalCustomBindings::GetRole(
314 const v8::FunctionCallbackInfo<v8::Value>& args) {
315 ui::AXNode* node = nullptr;
316 if (!GetNodeHelper(args, nullptr, &node))
317 return;
318
319 std::string role_name = ui::ToString(node->data().role);
320 args.GetReturnValue().Set(
321 v8::String::NewFromUtf8(GetIsolate(), role_name.c_str()));
322 }
323
324 void AutomationInternalCustomBindings::GetLocation(
325 const v8::FunctionCallbackInfo<v8::Value>& args) {
326 TreeCache* cache;
327 ui::AXNode* node = nullptr;
328 if (!GetNodeHelper(args, &cache, &node))
329 return;
330
331 v8::Local<v8::Object> location_obj(v8::Object::New(GetIsolate()));
332 gfx::Rect location = node->data().location;
333 location.Offset(cache->location_offset);
334 location_obj->Set(CreateV8String("left"),
335 v8::Integer::New(GetIsolate(), location.x()));
336 location_obj->Set(CreateV8String("top"),
337 v8::Integer::New(GetIsolate(), location.y()));
338 location_obj->Set(CreateV8String("width"),
339 v8::Integer::New(GetIsolate(), location.width()));
340 location_obj->Set(CreateV8String("height"),
341 v8::Integer::New(GetIsolate(), location.height()));
342 args.GetReturnValue().Set(location_obj);
343 }
344
345 void AutomationInternalCustomBindings::GetStringAttribute(
346 const v8::FunctionCallbackInfo<v8::Value>& args) {
347 ui::AXNode* node = nullptr;
348 std::string attribute_name;
349 if (!GetAttributeHelper(args, &node, &attribute_name))
350 return;
351
352 ui::AXStringAttribute attribute = ui::ParseAXStringAttribute(attribute_name);
353 std::string attr_value;
354 if (!node->data().GetStringAttribute(attribute, &attr_value))
355 return;
356
357 args.GetReturnValue().Set(
358 v8::String::NewFromUtf8(GetIsolate(), attr_value.c_str()));
359 }
360
361 void AutomationInternalCustomBindings::GetBoolAttribute(
362 const v8::FunctionCallbackInfo<v8::Value>& args) {
363 ui::AXNode* node = nullptr;
364 std::string attribute_name;
365 if (!GetAttributeHelper(args, &node, &attribute_name))
366 return;
367
368 ui::AXBoolAttribute attribute = ui::ParseAXBoolAttribute(attribute_name);
369 bool attr_value;
370 if (!node->data().GetBoolAttribute(attribute, &attr_value))
371 return;
372
373 args.GetReturnValue().Set(v8::Boolean::New(GetIsolate(), attr_value));
374 }
375
376 void AutomationInternalCustomBindings::GetIntAttribute(
377 const v8::FunctionCallbackInfo<v8::Value>& args) {
378 ui::AXNode* node = nullptr;
379 std::string attribute_name;
380 if (!GetAttributeHelper(args, &node, &attribute_name))
381 return;
382
383 ui::AXIntAttribute attribute = ui::ParseAXIntAttribute(attribute_name);
384 int attr_value;
385 if (!node->data().GetIntAttribute(attribute, &attr_value))
386 return;
387
388 args.GetReturnValue().Set(v8::Integer::New(GetIsolate(), attr_value));
389 }
390
391 void AutomationInternalCustomBindings::GetFloatAttribute(
392 const v8::FunctionCallbackInfo<v8::Value>& args) {
393 ui::AXNode* node = nullptr;
394 std::string attribute_name;
395 if (!GetAttributeHelper(args, &node, &attribute_name))
396 return;
397
398 ui::AXFloatAttribute attribute = ui::ParseAXFloatAttribute(attribute_name);
399 float attr_value;
400
401 if (!node->data().GetFloatAttribute(attribute, &attr_value))
402 return;
403
404 args.GetReturnValue().Set(v8::Number::New(GetIsolate(), attr_value));
405 }
406
407 void AutomationInternalCustomBindings::GetIntListAttribute(
408 const v8::FunctionCallbackInfo<v8::Value>& args) {
409 ui::AXNode* node = nullptr;
410 std::string attribute_name;
411 if (!GetAttributeHelper(args, &node, &attribute_name))
412 return;
413
414 ui::AXIntListAttribute attribute =
415 ui::ParseAXIntListAttribute(attribute_name);
416 if (!node->data().HasIntListAttribute(attribute))
417 return;
418 const std::vector<int32>& attr_value =
419 node->data().GetIntListAttribute(attribute);
420
421 v8::Local<v8::Array> result(v8::Array::New(GetIsolate(), attr_value.size()));
422 for (size_t i = 0; i < attr_value.size(); ++i)
423 result->Set(static_cast<uint32>(i),
424 v8::Integer::New(GetIsolate(), attr_value[i]));
425 args.GetReturnValue().Set(result);
426 }
427
428 void AutomationInternalCustomBindings::GetHtmlAttribute(
429 const v8::FunctionCallbackInfo<v8::Value>& args) {
430 ui::AXNode* node = nullptr;
431 std::string attribute_name;
432 if (!GetAttributeHelper(args, &node, &attribute_name))
433 return;
434
435 std::string attr_value;
436 if (!node->data().GetHtmlAttribute(attribute_name.c_str(), &attr_value))
437 return;
438
439 args.GetReturnValue().Set(
440 v8::String::NewFromUtf8(GetIsolate(), attr_value.c_str()));
441 }
442
443 //
444 // Helper functions.
445 //
446
447 void AutomationInternalCustomBindings::ThrowInvalidArgumentsException(
448 const v8::FunctionCallbackInfo<v8::Value>& args) {
449 GetIsolate()->ThrowException(
450 v8::String::NewFromUtf8(
451 GetIsolate(),
452 "Invalid arguments to AutomationInternalCustomBindings function",
453 v8::NewStringType::kNormal).ToLocalChecked());
454
455 LOG(FATAL)
456 << "Invalid arguments to AutomationInternalCustomBindings function"
457 << context()->GetStackTraceAsString();
458 }
459
460 bool AutomationInternalCustomBindings::GetNodeHelper(
461 const v8::FunctionCallbackInfo<v8::Value>& args,
462 TreeCache** out_cache,
463 ui::AXNode** out_node) {
464 if (args.Length() < 2 || !args[0]->IsNumber() || !args[1]->IsNumber()) {
465 ThrowInvalidArgumentsException(args);
466 return false;
467 }
468
469 int tree_id = args[0]->Int32Value(); 591 int tree_id = args[0]->Int32Value();
470 int node_id = args[1]->Int32Value(); 592 int node_id = args[1]->Int32Value();
471 593
472 const auto iter = tree_id_to_tree_cache_map_.find(tree_id); 594 const auto iter = tree_id_to_tree_cache_map_.find(tree_id);
473 if (iter == tree_id_to_tree_cache_map_.end()) 595 if (iter == tree_id_to_tree_cache_map_.end())
474 return false; 596 return;
475 597
476 TreeCache* cache = iter->second; 598 TreeCache* cache = iter->second;
599 if (!cache)
600 return;
601
477 ui::AXNode* node = cache->tree.GetFromId(node_id); 602 ui::AXNode* node = cache->tree.GetFromId(node_id);
603 if (!node)
604 return;
478 605
479 if (out_cache) 606 int index = args[2]->Int32Value();
480 *out_cache = cache; 607 if (index < 0 || index >= node->child_count())
481 if (out_node) 608 return;
482 *out_node = node;
483 609
484 return node != nullptr; 610 int child_id = node->children()[index]->id();
485 } 611 args.GetReturnValue().Set(v8::Integer::New(GetIsolate(), child_id));
486
487 bool AutomationInternalCustomBindings::GetAttributeHelper(
488 const v8::FunctionCallbackInfo<v8::Value>& args,
489 ui::AXNode** out_node,
490 std::string* out_attribute_name) {
491 if (args.Length() != 3 ||
492 !args[2]->IsString()) {
493 ThrowInvalidArgumentsException(args);
494 return false;
495 }
496
497 TreeCache* cache = nullptr;
498 if (!GetNodeHelper(args, &cache, out_node))
499 return false;
500
501 *out_attribute_name = *v8::String::Utf8Value(args[2]);
502 return true;
503 }
504
505 v8::Local<v8::Value> AutomationInternalCustomBindings::CreateV8String(
506 const char* str) {
507 return v8::String::NewFromUtf8(
508 GetIsolate(), str, v8::String::kNormalString, strlen(str));
509 }
510
511 v8::Local<v8::Value> AutomationInternalCustomBindings::CreateV8String(
512 const std::string& str) {
513 return v8::String::NewFromUtf8(
514 GetIsolate(), str.c_str(), v8::String::kNormalString, str.length());
515 } 612 }
516 613
517 // 614 //
518 // Handle accessibility events from the browser process. 615 // Handle accessibility events from the browser process.
519 // 616 //
520 617
521 void AutomationInternalCustomBindings::OnAccessibilityEvent( 618 void AutomationInternalCustomBindings::OnAccessibilityEvent(
522 const ExtensionMsg_AccessibilityEventParams& params, 619 const ExtensionMsg_AccessibilityEventParams& params,
523 bool is_active_profile) { 620 bool is_active_profile) {
524 is_active_profile_ = is_active_profile; 621 is_active_profile_ = is_active_profile;
(...skipping 15 matching lines...) Expand all
540 cache->location_offset = params.location_offset; 637 cache->location_offset = params.location_offset;
541 if (!cache->tree.Unserialize(params.update)) { 638 if (!cache->tree.Unserialize(params.update)) {
542 LOG(ERROR) << cache->tree.error(); 639 LOG(ERROR) << cache->tree.error();
543 return; 640 return;
544 } 641 }
545 642
546 // Don't send the event if it's not the active profile. 643 // Don't send the event if it's not the active profile.
547 if (!is_active_profile) 644 if (!is_active_profile)
548 return; 645 return;
549 646
550 v8::HandleScope handle_scope(GetIsolate()); 647 v8::Isolate* isolate = GetIsolate();
648 v8::HandleScope handle_scope(isolate);
551 v8::Context::Scope context_scope(context()->v8_context()); 649 v8::Context::Scope context_scope(context()->v8_context());
552 v8::Local<v8::Array> args(v8::Array::New(GetIsolate(), 1U)); 650 v8::Local<v8::Array> args(v8::Array::New(GetIsolate(), 1U));
553 v8::Local<v8::Object> event_params(v8::Object::New(GetIsolate())); 651 v8::Local<v8::Object> event_params(v8::Object::New(GetIsolate()));
554 event_params->Set(CreateV8String("treeID"), 652 event_params->Set(CreateV8String(isolate, "treeID"),
555 v8::Integer::New(GetIsolate(), params.tree_id)); 653 v8::Integer::New(GetIsolate(), params.tree_id));
556 event_params->Set(CreateV8String("targetID"), 654 event_params->Set(CreateV8String(isolate, "targetID"),
557 v8::Integer::New(GetIsolate(), params.id)); 655 v8::Integer::New(GetIsolate(), params.id));
558 event_params->Set(CreateV8String("eventType"), 656 event_params->Set(CreateV8String(isolate, "eventType"),
559 CreateV8String(ToString(params.event_type))); 657 CreateV8String(isolate, ToString(params.event_type)));
560 args->Set(0U, event_params); 658 args->Set(0U, event_params);
561 context()->DispatchEvent("automationInternal.onAccessibilityEvent", args); 659 context()->DispatchEvent("automationInternal.onAccessibilityEvent", args);
562 } 660 }
563 661
662 void AutomationInternalCustomBindings::OnTreeDataChanged(ui::AXTree* tree) {}
663
564 void AutomationInternalCustomBindings::OnNodeWillBeDeleted(ui::AXTree* tree, 664 void AutomationInternalCustomBindings::OnNodeWillBeDeleted(ui::AXTree* tree,
565 ui::AXNode* node) { 665 ui::AXNode* node) {
566 SendTreeChangeEvent( 666 SendTreeChangeEvent(
567 api::automation::TREE_CHANGE_TYPE_NODEREMOVED, 667 api::automation::TREE_CHANGE_TYPE_NODEREMOVED,
568 tree, node); 668 tree, node);
569 } 669 }
570 670
571 void AutomationInternalCustomBindings::OnSubtreeWillBeDeleted( 671 void AutomationInternalCustomBindings::OnSubtreeWillBeDeleted(
572 ui::AXTree* tree, 672 ui::AXTree* tree,
573 ui::AXNode* node) { 673 ui::AXNode* node) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
627 // Don't send tree change events when it's not the active profile. 727 // Don't send tree change events when it's not the active profile.
628 if (!is_active_profile_) 728 if (!is_active_profile_)
629 return; 729 return;
630 730
631 auto iter = axtree_to_tree_cache_map_.find(tree); 731 auto iter = axtree_to_tree_cache_map_.find(tree);
632 if (iter == axtree_to_tree_cache_map_.end()) 732 if (iter == axtree_to_tree_cache_map_.end())
633 return; 733 return;
634 734
635 int tree_id = iter->second->tree_id; 735 int tree_id = iter->second->tree_id;
636 736
637 v8::HandleScope handle_scope(GetIsolate()); 737 v8::Isolate* isolate = GetIsolate();
738 v8::HandleScope handle_scope(isolate);
638 v8::Context::Scope context_scope(context()->v8_context()); 739 v8::Context::Scope context_scope(context()->v8_context());
639 v8::Local<v8::Array> args(v8::Array::New(GetIsolate(), 3U)); 740 v8::Local<v8::Array> args(v8::Array::New(GetIsolate(), 3U));
640 args->Set(0U, v8::Integer::New(GetIsolate(), tree_id)); 741 args->Set(0U, v8::Integer::New(GetIsolate(), tree_id));
641 args->Set(1U, v8::Integer::New(GetIsolate(), node->id())); 742 args->Set(1U, v8::Integer::New(GetIsolate(), node->id()));
642 args->Set(2U, CreateV8String(ToString(change_type))); 743 args->Set(2U, CreateV8String(isolate, ToString(change_type)));
643 context()->DispatchEvent("automationInternal.onTreeChange", args); 744 context()->DispatchEvent("automationInternal.onTreeChange", args);
644 } 745 }
645 746
646 } // namespace extensions 747 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698