Chromium Code Reviews| 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 "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/values.h" | 9 #include "base/values.h" |
| 10 #include "chrome/common/extensions/chrome_extension_messages.h" | 10 #include "chrome/common/extensions/chrome_extension_messages.h" |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 32 isolate, ui::ToString(static_cast<EnumType>(i)).c_str()); | 32 isolate, ui::ToString(static_cast<EnumType>(i)).c_str()); |
| 33 object->Set(value, value); | 33 object->Set(value, value); |
| 34 } | 34 } |
| 35 return object; | 35 return object; |
| 36 } | 36 } |
| 37 | 37 |
| 38 } // namespace | 38 } // namespace |
| 39 | 39 |
| 40 namespace extensions { | 40 namespace extensions { |
| 41 | 41 |
| 42 TreeCache::TreeCache() {} | |
| 43 TreeCache::~TreeCache() {} | |
| 44 | |
| 42 class AutomationMessageFilter : public IPC::MessageFilter { | 45 class AutomationMessageFilter : public IPC::MessageFilter { |
| 43 public: | 46 public: |
| 44 explicit AutomationMessageFilter(AutomationInternalCustomBindings* owner) | 47 explicit AutomationMessageFilter(AutomationInternalCustomBindings* owner) |
| 45 : owner_(owner) { | 48 : owner_(owner) { |
| 46 DCHECK(owner); | 49 DCHECK(owner); |
| 47 content::RenderThread::Get()->AddFilter(this); | 50 content::RenderThread::Get()->AddFilter(this); |
| 51 task_runner_ = content::RenderThread::Get()->GetTaskRunner(); | |
| 48 } | 52 } |
| 49 | 53 |
| 50 void Detach() { | 54 void Detach() { |
| 51 owner_ = nullptr; | 55 owner_ = nullptr; |
| 52 } | 56 } |
| 53 | 57 |
| 54 // IPC::MessageFilter | 58 // IPC::MessageFilter |
| 55 bool OnMessageReceived(const IPC::Message& message) override { | 59 bool OnMessageReceived(const IPC::Message& message) override { |
| 56 if (owner_) | 60 task_runner_->PostTask( |
| 57 return owner_->OnMessageReceived(message); | 61 FROM_HERE, |
| 58 else | 62 base::Bind( |
| 59 return false; | 63 &AutomationMessageFilter::OnMessageReceivedOnRenderThread, |
| 64 this, message)); | |
| 65 return false; | |
| 60 } | 66 } |
| 61 | 67 |
| 62 private: | 68 private: |
| 69 void OnMessageReceivedOnRenderThread(const IPC::Message& message) { | |
| 70 if (owner_) | |
| 71 owner_->OnMessageReceived(message); | |
| 72 } | |
| 73 | |
| 63 ~AutomationMessageFilter() override { | 74 ~AutomationMessageFilter() override { |
| 64 content::RenderThread::Get()->RemoveFilter(this); | 75 content::RenderThread::Get()->RemoveFilter(this); |
| 65 } | 76 } |
| 66 | 77 |
| 67 AutomationInternalCustomBindings* owner_; | 78 AutomationInternalCustomBindings* owner_; |
| 79 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | |
| 68 | 80 |
| 69 DISALLOW_COPY_AND_ASSIGN(AutomationMessageFilter); | 81 DISALLOW_COPY_AND_ASSIGN(AutomationMessageFilter); |
| 70 }; | 82 }; |
| 71 | 83 |
| 72 AutomationInternalCustomBindings::AutomationInternalCustomBindings( | 84 AutomationInternalCustomBindings::AutomationInternalCustomBindings( |
| 73 ScriptContext* context) : ObjectBackedNativeHandler(context) { | 85 ScriptContext* context) : ObjectBackedNativeHandler(context) { |
| 74 // It's safe to use base::Unretained(this) here because these bindings | 86 // It's safe to use base::Unretained(this) here because these bindings |
| 75 // will only be called on a valid AutomationInternalCustomBindings instance | 87 // will only be called on a valid AutomationInternalCustomBindings instance |
| 76 // and none of the functions have any side effects. | 88 // and none of the functions have any side effects. |
| 77 RouteFunction( | 89 #define ROUTE_FUNCTION(FN) \ |
| 78 "IsInteractPermitted", | 90 RouteFunction(#FN, \ |
| 79 base::Bind(&AutomationInternalCustomBindings::IsInteractPermitted, | 91 base::Bind(&AutomationInternalCustomBindings::FN, \ |
| 80 base::Unretained(this))); | 92 base::Unretained(this))) |
| 81 RouteFunction( | 93 |
| 82 "GetSchemaAdditions", | 94 ROUTE_FUNCTION(IsInteractPermitted); |
| 83 base::Bind(&AutomationInternalCustomBindings::GetSchemaAdditions, | 95 ROUTE_FUNCTION(GetSchemaAdditions); |
| 84 base::Unretained(this))); | 96 ROUTE_FUNCTION(GetRoutingID); |
| 85 RouteFunction( | 97 ROUTE_FUNCTION(DestroyAccessibilityTree); |
| 86 "GetRoutingID", | 98 ROUTE_FUNCTION(GetRootID); |
| 87 base::Bind(&AutomationInternalCustomBindings::GetRoutingID, | 99 ROUTE_FUNCTION(GetParentID); |
| 88 base::Unretained(this))); | 100 ROUTE_FUNCTION(GetChildCount); |
| 101 ROUTE_FUNCTION(GetChildIDAtIndex); | |
| 102 ROUTE_FUNCTION(GetIndexInParent); | |
| 103 ROUTE_FUNCTION(GetState); | |
| 104 ROUTE_FUNCTION(GetRole); | |
| 105 ROUTE_FUNCTION(GetLocation); | |
| 106 ROUTE_FUNCTION(GetStringAttribute); | |
| 107 ROUTE_FUNCTION(GetBoolAttribute); | |
| 108 ROUTE_FUNCTION(GetIntAttribute); | |
| 109 ROUTE_FUNCTION(GetFloatAttribute); | |
| 110 ROUTE_FUNCTION(GetIntListAttribute); | |
| 89 | 111 |
| 90 message_filter_ = new AutomationMessageFilter(this); | 112 message_filter_ = new AutomationMessageFilter(this); |
| 91 } | 113 } |
| 92 | 114 |
| 93 AutomationInternalCustomBindings::~AutomationInternalCustomBindings() { | 115 AutomationInternalCustomBindings::~AutomationInternalCustomBindings() { |
| 94 message_filter_->Detach(); | 116 message_filter_->Detach(); |
| 95 } | 117 } |
| 96 | 118 |
| 97 bool AutomationInternalCustomBindings::OnMessageReceived( | 119 bool AutomationInternalCustomBindings::OnMessageReceived( |
| 98 const IPC::Message& message) { | 120 const IPC::Message& message) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 137 v8::String::NewFromUtf8(GetIsolate(), "StateType"), | 159 v8::String::NewFromUtf8(GetIsolate(), "StateType"), |
| 138 ToEnumObject(GetIsolate(), ui::AX_STATE_NONE, ui::AX_STATE_LAST)); | 160 ToEnumObject(GetIsolate(), ui::AX_STATE_NONE, ui::AX_STATE_LAST)); |
| 139 | 161 |
| 140 additions->Set( | 162 additions->Set( |
| 141 v8::String::NewFromUtf8(GetIsolate(), "TreeChangeType"), | 163 v8::String::NewFromUtf8(GetIsolate(), "TreeChangeType"), |
| 142 ToEnumObject(GetIsolate(), ui::AX_MUTATION_NONE, ui::AX_MUTATION_LAST)); | 164 ToEnumObject(GetIsolate(), ui::AX_MUTATION_NONE, ui::AX_MUTATION_LAST)); |
| 143 | 165 |
| 144 args.GetReturnValue().Set(additions); | 166 args.GetReturnValue().Set(additions); |
| 145 } | 167 } |
| 146 | 168 |
| 169 void AutomationInternalCustomBindings::DestroyAccessibilityTree( | |
| 170 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 171 if (args.Length() != 1) | |
| 172 return; | |
| 173 if (!args[0]->IsNumber()) | |
| 174 return; | |
| 175 | |
| 176 int tree_id = args[0]->Int32Value(); | |
| 177 auto iter = tree_id_to_tree_cache_map_.find(tree_id); | |
| 178 if (iter == tree_id_to_tree_cache_map_.end()) | |
| 179 return; | |
| 180 | |
| 181 TreeCache* cache = iter->second; | |
| 182 tree_id_to_tree_cache_map_.erase(tree_id); | |
| 183 axtree_to_tree_cache_map_.erase(&cache->tree); | |
| 184 delete cache; | |
| 185 } | |
| 186 | |
| 187 void AutomationInternalCustomBindings::GetRootID( | |
| 188 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 189 if (args.Length() != 1) | |
|
David Tseng
2015/06/10 17:48:16
Seems like these cases throughout should cause an
dmazzoni
2015/06/11 19:09:12
Done. I have it throw an exception for invalid arg
aboxhall
2015/06/11 20:32:42
Looks like other custom bindings code uses CHECKs
dmazzoni
2015/06/12 17:51:35
That's pretty hard to debug, though - there's no w
aboxhall
2015/06/12 20:43:10
With a CHECK, it'll be super obvious that somethin
dmazzoni
2015/06/16 18:19:48
OK, solved both problems. Now it grabs a JS stack
aboxhall
2015/06/16 18:22:44
Nice one :)
| |
| 190 return; | |
| 191 if (!args[0]->IsNumber()) | |
| 192 return; | |
| 193 | |
| 194 int tree_id = args[0]->Int32Value(); | |
| 195 const auto& iter = tree_id_to_tree_cache_map_.find(tree_id); | |
| 196 if (iter == tree_id_to_tree_cache_map_.end()) | |
| 197 return; | |
| 198 | |
| 199 TreeCache* cache = iter->second; | |
| 200 int root_id = cache->tree.root()->id(); | |
| 201 args.GetReturnValue().Set(v8::Integer::New(GetIsolate(), root_id)); | |
| 202 } | |
| 203 | |
| 204 bool AutomationInternalCustomBindings::GetNodeHelper( | |
| 205 const v8::FunctionCallbackInfo<v8::Value>& args, | |
| 206 TreeCache** out_cache, | |
| 207 ui::AXNode** out_node) { | |
| 208 if (args.Length() < 2) | |
| 209 return false; | |
| 210 if (!args[0]->IsNumber() || !args[1]->IsNumber()) | |
| 211 return false; | |
| 212 | |
| 213 int tree_id = args[0]->Int32Value(); | |
| 214 int node_id = args[1]->Int32Value(); | |
| 215 | |
| 216 const auto& iter = tree_id_to_tree_cache_map_.find(tree_id); | |
| 217 if (iter == tree_id_to_tree_cache_map_.end()) | |
| 218 return false; | |
| 219 | |
| 220 TreeCache* cache = iter->second; | |
| 221 ui::AXNode* node = cache->tree.GetFromId(node_id); | |
| 222 | |
| 223 if (out_cache) | |
| 224 *out_cache = cache; | |
| 225 if (out_node) | |
| 226 *out_node = node; | |
| 227 | |
| 228 return node != nullptr; | |
| 229 } | |
| 230 | |
| 231 void AutomationInternalCustomBindings::SetReturnValueFromBaseValue( | |
| 232 const v8::FunctionCallbackInfo<v8::Value>& args, | |
| 233 base::Value* value) { | |
| 234 v8::Isolate* isolate = context()->isolate(); | |
| 235 v8::HandleScope handle_scope(isolate); | |
| 236 v8::Context::Scope context_scope(context()->v8_context()); | |
| 237 scoped_ptr<content::V8ValueConverter> converter( | |
| 238 content::V8ValueConverter::create()); | |
| 239 v8::Local<v8::Value> v8_value = | |
| 240 converter->ToV8Value(value, context()->v8_context()); | |
| 241 args.GetReturnValue().Set(v8_value); | |
| 242 } | |
| 243 | |
| 244 void AutomationInternalCustomBindings::GetParentID( | |
| 245 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 246 ui::AXNode* node; | |
| 247 if (!GetNodeHelper(args, nullptr, &node)) | |
| 248 return; | |
| 249 | |
| 250 if (!node->parent()) | |
| 251 return; | |
| 252 | |
| 253 int parent_id = node->parent()->id(); | |
| 254 args.GetReturnValue().Set(v8::Integer::New(GetIsolate(), parent_id)); | |
| 255 } | |
| 256 | |
| 257 void AutomationInternalCustomBindings::GetChildCount( | |
| 258 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 259 ui::AXNode* node; | |
| 260 if (!GetNodeHelper(args, nullptr, &node)) | |
| 261 return; | |
| 262 | |
| 263 int child_count = node->child_count(); | |
| 264 args.GetReturnValue().Set(v8::Integer::New(GetIsolate(), child_count)); | |
| 265 } | |
| 266 | |
| 267 void AutomationInternalCustomBindings::GetChildIDAtIndex( | |
|
David Tseng
2015/06/10 17:48:16
These functions should probably get docs; maybe js
dmazzoni
2015/06/11 19:09:11
Added concise docs to the header file now. Does th
| |
| 268 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 269 ui::AXNode* node; | |
| 270 if (!GetNodeHelper(args, nullptr, &node)) | |
| 271 return; | |
| 272 | |
| 273 if (args.Length() < 3 || !args[2]->IsNumber()) | |
|
aboxhall
2015/06/11 15:05:38
Do args validation before getting the node?
dmazzoni
2015/06/11 19:09:12
Done.
| |
| 274 return; | |
| 275 | |
| 276 int index = args[2]->Int32Value(); | |
| 277 if (index < 0 || index >= node->child_count()) | |
| 278 return; | |
| 279 | |
| 280 int child_id = node->children()[index]->id(); | |
| 281 args.GetReturnValue().Set(v8::Integer::New(GetIsolate(), child_id)); | |
| 282 } | |
| 283 | |
| 284 void AutomationInternalCustomBindings::GetIndexInParent( | |
| 285 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 286 ui::AXNode* node; | |
| 287 if (!GetNodeHelper(args, nullptr, &node)) | |
| 288 return; | |
| 289 | |
| 290 int index_in_parent = node->index_in_parent(); | |
| 291 args.GetReturnValue().Set(v8::Integer::New(GetIsolate(), index_in_parent)); | |
| 292 } | |
| 293 | |
| 294 void AutomationInternalCustomBindings::GetState( | |
| 295 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 296 ui::AXNode* node; | |
| 297 if (!GetNodeHelper(args, nullptr, &node)) | |
| 298 return; | |
| 299 | |
| 300 scoped_ptr<base::DictionaryValue> state_dict(new base::DictionaryValue()); | |
| 301 uint32 state_pos = 0, state_shifter = node->data().state; | |
| 302 while (state_shifter) { | |
| 303 if (state_shifter & 1) { | |
| 304 state_dict->SetBoolean( | |
| 305 ToString(static_cast<ui::AXState>(state_pos)), true); | |
| 306 } | |
| 307 state_shifter = state_shifter >> 1; | |
| 308 state_pos++; | |
| 309 } | |
| 310 | |
| 311 SetReturnValueFromBaseValue(args, state_dict.get()); | |
| 312 } | |
| 313 | |
| 314 void AutomationInternalCustomBindings::GetRole( | |
| 315 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 316 ui::AXNode* node; | |
| 317 if (!GetNodeHelper(args, nullptr, &node)) | |
| 318 return; | |
| 319 | |
| 320 std::string role_name = ui::ToString(node->data().role); | |
| 321 args.GetReturnValue().Set( | |
| 322 v8::String::NewFromUtf8(GetIsolate(), role_name.c_str())); | |
| 323 } | |
| 324 | |
| 325 void AutomationInternalCustomBindings::GetLocation( | |
| 326 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 327 TreeCache* cache; | |
| 328 ui::AXNode* node; | |
| 329 if (!GetNodeHelper(args, &cache, &node)) | |
| 330 return; | |
| 331 | |
| 332 scoped_ptr<base::DictionaryValue> location_dict(new base::DictionaryValue()); | |
| 333 gfx::Rect location = node->data().location; | |
| 334 location.Offset(cache->location_offset); | |
| 335 location_dict->SetInteger("left", location.x()); | |
| 336 location_dict->SetInteger("top", location.y()); | |
| 337 location_dict->SetInteger("width", location.width()); | |
| 338 location_dict->SetInteger("height", location.height()); | |
| 339 | |
| 340 SetReturnValueFromBaseValue(args, location_dict.get()); | |
| 341 } | |
| 342 | |
| 343 bool AutomationInternalCustomBindings::GetAttributeHelper( | |
| 344 const v8::FunctionCallbackInfo<v8::Value>& args, | |
| 345 ui::AXNode** out_node, | |
| 346 std::string* out_attribute_name) { | |
| 347 if (args.Length() != 3) | |
| 348 return false; | |
| 349 if (!args[0]->IsNumber() || | |
| 350 !args[1]->IsNumber() || | |
| 351 !args[2]->IsString()) { | |
| 352 return false; | |
| 353 } | |
| 354 | |
| 355 int tree_id = args[0]->Int32Value(); | |
| 356 int node_id = args[1]->Int32Value(); | |
| 357 *out_attribute_name = *v8::String::Utf8Value(args[2]); | |
| 358 | |
| 359 const auto& iter = tree_id_to_tree_cache_map_.find(tree_id); | |
| 360 if (iter == tree_id_to_tree_cache_map_.end()) | |
| 361 return false; | |
| 362 | |
| 363 TreeCache* cache = iter->second; | |
| 364 *out_node = cache->tree.GetFromId(node_id); | |
| 365 if (!*out_node) | |
|
David Tseng
2015/06/10 17:48:16
GetNodeHelper?
dmazzoni
2015/06/11 19:09:12
Done.
| |
| 366 return false; | |
| 367 | |
| 368 return true; | |
| 369 } | |
| 370 | |
| 371 void AutomationInternalCustomBindings::GetStringAttribute( | |
| 372 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 373 ui::AXNode* node; | |
| 374 std::string attribute_name; | |
| 375 if (!GetAttributeHelper(args, &node, &attribute_name)) | |
| 376 return; | |
| 377 | |
| 378 ui::AXStringAttribute attribute = ui::ParseAXStringAttribute(attribute_name); | |
| 379 std::string attr_value; | |
| 380 if (!node->data().GetStringAttribute(attribute, &attr_value)) | |
| 381 return; | |
| 382 | |
| 383 args.GetReturnValue().Set( | |
| 384 v8::String::NewFromUtf8(GetIsolate(), attr_value.c_str())); | |
| 385 } | |
| 386 | |
| 387 void AutomationInternalCustomBindings::GetBoolAttribute( | |
| 388 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 389 ui::AXNode* node; | |
| 390 std::string attribute_name; | |
| 391 if (!GetAttributeHelper(args, &node, &attribute_name)) | |
| 392 return; | |
| 393 | |
| 394 ui::AXBoolAttribute attribute = ui::ParseAXBoolAttribute(attribute_name); | |
| 395 bool attr_value; | |
| 396 if (!node->data().GetBoolAttribute(attribute, &attr_value)) | |
| 397 return; | |
|
David Tseng
2015/06/10 17:48:16
Is return value here undefined in js?
dmazzoni
2015/06/11 19:09:11
Yes, the default will be undefined.
| |
| 398 | |
| 399 args.GetReturnValue().Set(v8::Boolean::New(GetIsolate(), attr_value)); | |
| 400 } | |
| 401 | |
| 402 void AutomationInternalCustomBindings::GetIntAttribute( | |
| 403 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 404 ui::AXNode* node; | |
| 405 std::string attribute_name; | |
| 406 if (!GetAttributeHelper(args, &node, &attribute_name)) | |
| 407 return; | |
| 408 | |
| 409 ui::AXIntAttribute attribute = ui::ParseAXIntAttribute(attribute_name); | |
| 410 int attr_value; | |
| 411 if (!node->data().GetIntAttribute(attribute, &attr_value)) | |
| 412 return; | |
| 413 | |
| 414 args.GetReturnValue().Set(v8::Integer::New(GetIsolate(), attr_value)); | |
| 415 } | |
| 416 | |
| 417 void AutomationInternalCustomBindings::GetFloatAttribute( | |
| 418 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 419 ui::AXNode* node; | |
| 420 std::string attribute_name; | |
| 421 if (!GetAttributeHelper(args, &node, &attribute_name)) | |
| 422 return; | |
| 423 | |
| 424 ui::AXFloatAttribute attribute = ui::ParseAXFloatAttribute(attribute_name); | |
| 425 float attr_value; | |
| 426 | |
| 427 if (!node->data().GetFloatAttribute(attribute, &attr_value)) | |
| 428 return; | |
| 429 | |
| 430 args.GetReturnValue().Set(v8::Number::New(GetIsolate(), attr_value)); | |
| 431 } | |
| 432 | |
| 433 void AutomationInternalCustomBindings::GetIntListAttribute( | |
| 434 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 435 ui::AXNode* node; | |
| 436 std::string attribute_name; | |
| 437 if (!GetAttributeHelper(args, &node, &attribute_name)) | |
| 438 return; | |
| 439 | |
| 440 ui::AXIntListAttribute attribute = | |
| 441 ui::ParseAXIntListAttribute(attribute_name); | |
| 442 if (!node->data().HasIntListAttribute(attribute)) | |
| 443 return; | |
| 444 const std::vector<int32>& attr_value = | |
| 445 node->data().GetIntListAttribute(attribute); | |
| 446 | |
| 447 scoped_ptr<base::ListValue> list(new base::ListValue()); | |
| 448 for (int32 i : attr_value) | |
| 449 list->AppendInteger(i); | |
| 450 SetReturnValueFromBaseValue(args, list.get()); | |
| 451 } | |
| 452 | |
| 147 void AutomationInternalCustomBindings::OnAccessibilityEvent( | 453 void AutomationInternalCustomBindings::OnAccessibilityEvent( |
|
aboxhall
2015/06/11 15:05:38
I can't figure out how this event gets dispatched.
dmazzoni
2015/06/11 19:09:11
It gets called from AutomationWebContentsObserver:
| |
| 148 const ExtensionMsg_AccessibilityEventParams& params) { | 454 const ExtensionMsg_AccessibilityEventParams& params) { |
| 149 // TODO(dmazzoni): finish implementing this. | 455 int tree_id = params.tree_id; |
| 456 TreeCache* cache; | |
| 457 auto iter = tree_id_to_tree_cache_map_.find(tree_id); | |
| 458 if (iter == tree_id_to_tree_cache_map_.end()) { | |
|
aboxhall
2015/06/11 15:05:38
I was trying to figure out where this got called s
dmazzoni
2015/06/11 19:09:11
Yeah, AutomationEventRouter keeps track of exactly
aboxhall
2015/06/11 20:32:42
Ah, I see it now. Technically the permissions chec
dmazzoni
2015/06/12 17:51:35
I'm not sure how to do that because AutomationEven
aboxhall
2015/06/12 20:43:10
Right, I see. I misunderstood the 'has permission
| |
| 459 cache = new TreeCache(); | |
| 460 cache->tab_id = -1; | |
| 461 cache->tree_id = params.tree_id; | |
| 462 cache->tree.SetDelegate(this); | |
| 463 tree_id_to_tree_cache_map_.insert(std::make_pair(tree_id, cache)); | |
| 464 axtree_to_tree_cache_map_.insert(std::make_pair(&cache->tree, cache)); | |
| 465 } else { | |
| 466 cache = iter->second; | |
| 467 } | |
| 468 | |
| 469 cache->location_offset = params.location_offset; | |
| 470 CHECK(cache->tree.Unserialize(params.update)); | |
| 471 api::automation_internal::AXEventParams event_params; | |
| 472 event_params.tree_id = params.tree_id; | |
| 473 event_params.target_id = params.id; | |
| 474 event_params.event_type = ToString(params.event_type); | |
| 475 scoped_ptr<base::ListValue> args(new base::ListValue()); | |
| 476 args->Append(event_params.ToValue()); | |
| 477 | |
| 478 v8::Isolate* isolate = context()->isolate(); | |
| 479 v8::HandleScope handle_scope(isolate); | |
| 480 v8::Context::Scope context_scope(context()->v8_context()); | |
| 481 scoped_ptr<content::V8ValueConverter> converter( | |
| 482 content::V8ValueConverter::create()); | |
| 483 v8::Local<v8::Value> v8_args = | |
| 484 converter->ToV8Value(args.get(), context()->v8_context()); | |
| 485 | |
| 486 CHECK(v8_args->IsArray()); | |
| 487 v8::Local<v8::Array> v8_args_array = v8_args.As<v8::Array>(); | |
| 488 context()->DispatchEvent("automationInternal.onAccessibilityEvent", | |
| 489 v8_args_array); | |
| 490 } | |
| 491 | |
| 492 void AutomationInternalCustomBindings::OnNodeWillBeDeleted(ui::AXTree* tree, | |
| 493 ui::AXNode* node) { | |
| 494 SendTreeChangeEvent("nodeRemoved", tree, node); | |
| 495 } | |
| 496 | |
| 497 void AutomationInternalCustomBindings::OnSubtreeWillBeDeleted( | |
| 498 ui::AXTree* tree, | |
| 499 ui::AXNode* node) { | |
| 500 } | |
|
David Tseng
2015/06/10 17:48:15
TODO?
dmazzoni
2015/06/11 19:09:12
Not necessarily needed? This was needed to impleme
aboxhall
2015/06/11 20:32:42
Could these null implementations be moved up into
dmazzoni
2015/06/12 17:51:35
To be clear, these are pure virtual functions in A
aboxhall
2015/06/12 20:43:10
Makes sense - I wasn't sure to what extent we gene
| |
| 501 | |
| 502 void AutomationInternalCustomBindings::OnNodeCreated(ui::AXTree* tree, | |
| 503 ui::AXNode* node) { | |
| 504 | |
|
David Tseng
2015/06/10 17:48:16
TODO?
dmazzoni
2015/06/11 19:09:11
Not needed, added a comment.
| |
| 505 } | |
| 506 | |
| 507 void AutomationInternalCustomBindings::OnNodeChanged(ui::AXTree* tree, | |
| 508 ui::AXNode* node) { | |
| 509 } | |
|
David Tseng
2015/06/10 17:48:15
TODO?
dmazzoni
2015/06/11 19:09:11
Done.
| |
| 510 | |
| 511 void AutomationInternalCustomBindings::OnAtomicUpdateFinished( | |
|
David Tseng
2015/06/10 17:48:16
What calls this function?
dmazzoni
2015/06/11 19:09:11
AXTree calls this because we implement AXTreeDeleg
| |
| 512 ui::AXTree* tree, | |
| 513 bool root_changed, | |
| 514 const std::vector<ui::AXTreeDelegate::Change>& changes) { | |
| 515 auto iter = axtree_to_tree_cache_map_.find(tree); | |
| 516 if (iter == axtree_to_tree_cache_map_.end()) | |
| 517 return; | |
| 518 | |
| 519 for (auto change : changes) { | |
| 520 ui::AXNode* node = change.node; | |
| 521 switch (change.type) { | |
| 522 case NODE_CREATED: | |
| 523 SendTreeChangeEvent("nodeCreated", tree, node); | |
| 524 break; | |
| 525 case SUBTREE_CREATED: | |
| 526 SendTreeChangeEvent("subtreeCreated", tree, node); | |
| 527 break; | |
| 528 case NODE_CHANGED: | |
| 529 SendTreeChangeEvent("nodeChanged", tree, node); | |
|
David Tseng
2015/06/10 17:48:16
Define/document these literals.
dmazzoni
2015/06/11 19:09:12
Switched to use the enum and ToString function aut
| |
| 530 break; | |
| 531 } | |
| 532 } | |
| 533 } | |
| 534 | |
| 535 void AutomationInternalCustomBindings::SendTreeChangeEvent( | |
| 536 const char *change_type, | |
| 537 ui::AXTree* tree, | |
| 538 ui::AXNode* node) { | |
| 539 auto iter = axtree_to_tree_cache_map_.find(tree); | |
| 540 if (iter == axtree_to_tree_cache_map_.end()) | |
| 541 return; | |
| 542 | |
| 543 int tree_id = iter->second->tree_id; | |
| 544 scoped_ptr<base::ListValue> args(new base::ListValue()); | |
| 545 args->AppendInteger(tree_id); | |
| 546 args->AppendInteger(node->id()); | |
| 547 args->AppendString(change_type); | |
| 548 | |
| 549 v8::Isolate* isolate = context()->isolate(); | |
| 550 v8::HandleScope handle_scope(isolate); | |
| 551 v8::Context::Scope context_scope(context()->v8_context()); | |
| 552 scoped_ptr<content::V8ValueConverter> converter( | |
| 553 content::V8ValueConverter::create()); | |
| 554 v8::Local<v8::Value> v8_args = | |
| 555 converter->ToV8Value(args.get(), context()->v8_context()); | |
| 556 | |
| 557 CHECK(v8_args->IsArray()); | |
| 558 v8::Local<v8::Array> v8_args_array = v8_args.As<v8::Array>(); | |
| 559 context()->DispatchEvent("automationInternal.onTreeChange", | |
| 560 v8_args_array); | |
| 150 } | 561 } |
| 151 | 562 |
| 152 } // namespace extensions | 563 } // namespace extensions |
| OLD | NEW |