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 <memory> | 10 #include <memory> |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 continue; | 105 continue; |
106 } | 106 } |
107 | 107 |
108 // Union each additional child's bounds. | 108 // Union each additional child's bounds. |
109 bounds.Union(child_bounds); | 109 bounds.Union(child_bounds); |
110 } | 110 } |
111 | 111 |
112 return bounds; | 112 return bounds; |
113 } | 113 } |
114 | 114 |
115 // Compute the bounding box of a node in global coordinates, walking up the | 115 // Adjust the bounding box of a node from local to global coordinates, |
116 // parent hierarchy to offset by frame offsets and scroll offsets. | 116 // walking up the parent hierarchy to offset by frame offsets and |
117 static gfx::Rect ComputeGlobalNodeBounds(TreeCache* cache, ui::AXNode* node) { | 117 // scroll offsets. |
118 gfx::RectF bounds = ComputeLocalNodeBounds(cache, node); | 118 static gfx::Rect ComputeGlobalNodeBounds(TreeCache* cache, |
119 | 119 ui::AXNode* node, |
| 120 gfx::RectF local_bounds) { |
| 121 gfx::RectF bounds = local_bounds; |
120 while (node) { | 122 while (node) { |
121 if (node->data().transform) | 123 if (node->data().transform) |
122 node->data().transform->TransformRect(&bounds); | 124 node->data().transform->TransformRect(&bounds); |
123 | 125 |
124 ui::AXNode* container = | 126 ui::AXNode* container = |
125 cache->tree.GetFromId(node->data().offset_container_id); | 127 cache->tree.GetFromId(node->data().offset_container_id); |
126 if (!container) { | 128 if (!container) { |
127 if (node == cache->tree.root()) { | 129 if (node == cache->tree.root()) { |
128 container = cache->owner->GetParent(node, &cache); | 130 container = cache->owner->GetParent(node, &cache); |
129 } else { | 131 } else { |
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 }); | 518 }); |
517 RouteNodeIDFunction( | 519 RouteNodeIDFunction( |
518 "GetRole", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, | 520 "GetRole", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, |
519 TreeCache* cache, ui::AXNode* node) { | 521 TreeCache* cache, ui::AXNode* node) { |
520 std::string role_name = ui::ToString(node->data().role); | 522 std::string role_name = ui::ToString(node->data().role); |
521 result.Set(v8::String::NewFromUtf8(isolate, role_name.c_str())); | 523 result.Set(v8::String::NewFromUtf8(isolate, role_name.c_str())); |
522 }); | 524 }); |
523 RouteNodeIDFunction( | 525 RouteNodeIDFunction( |
524 "GetLocation", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, | 526 "GetLocation", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, |
525 TreeCache* cache, ui::AXNode* node) { | 527 TreeCache* cache, ui::AXNode* node) { |
526 gfx::Rect location = ComputeGlobalNodeBounds(cache, node); | 528 gfx::RectF local_bounds = ComputeLocalNodeBounds(cache, node); |
527 location.Offset(cache->location_offset); | 529 gfx::Rect global_bounds = |
528 result.Set(RectToV8Object(isolate, location)); | 530 ComputeGlobalNodeBounds(cache, node, local_bounds); |
| 531 global_bounds.Offset(cache->location_offset); |
| 532 result.Set(RectToV8Object(isolate, global_bounds)); |
529 }); | 533 }); |
530 RouteNodeIDFunction( | 534 RouteNodeIDFunction( |
531 "GetLineStartOffsets", | 535 "GetLineStartOffsets", |
532 [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, | 536 [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, |
533 TreeCache* cache, ui::AXNode* node) { | 537 TreeCache* cache, ui::AXNode* node) { |
534 const std::vector<int> line_starts = | 538 const std::vector<int> line_starts = |
535 node->GetOrComputeLineStartOffsets(); | 539 node->GetOrComputeLineStartOffsets(); |
536 v8::Local<v8::Array> array_result( | 540 v8::Local<v8::Array> array_result( |
537 v8::Array::New(isolate, line_starts.size())); | 541 v8::Array::New(isolate, line_starts.size())); |
538 for (size_t i = 0; i < line_starts.size(); ++i) { | 542 for (size_t i = 0; i < line_starts.size(); ++i) { |
(...skipping 14 matching lines...) Expand all Loading... |
553 result.Set(array_result); | 557 result.Set(array_result); |
554 }); | 558 }); |
555 | 559 |
556 // Bindings that take a Tree ID and Node ID and string attribute name | 560 // Bindings that take a Tree ID and Node ID and string attribute name |
557 // and return a property of the node. | 561 // and return a property of the node. |
558 | 562 |
559 RouteNodeIDPlusRangeFunction( | 563 RouteNodeIDPlusRangeFunction( |
560 "GetBoundsForRange", | 564 "GetBoundsForRange", |
561 [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, | 565 [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, |
562 TreeCache* cache, ui::AXNode* node, int start, int end) { | 566 TreeCache* cache, ui::AXNode* node, int start, int end) { |
563 gfx::Rect location = ComputeGlobalNodeBounds(cache, node); | 567 gfx::RectF local_bounds = ComputeLocalNodeBounds(cache, node); |
564 location.Offset(cache->location_offset); | 568 if (node->data().role != ui::AX_ROLE_INLINE_TEXT_BOX) { |
565 if (node->data().role == ui::AX_ROLE_INLINE_TEXT_BOX) { | 569 gfx::Rect global_bounds = |
566 std::string name = node->data().GetStringAttribute(ui::AX_ATTR_NAME); | 570 ComputeGlobalNodeBounds(cache, node, local_bounds); |
567 std::vector<int> character_offsets = | 571 global_bounds.Offset(cache->location_offset); |
568 node->data().GetIntListAttribute(ui::AX_ATTR_CHARACTER_OFFSETS); | 572 result.Set(RectToV8Object(isolate, global_bounds)); |
569 int len = | 573 } |
570 static_cast<int>(std::min(name.size(), character_offsets.size())); | |
571 if (start >= 0 && start <= end && end <= len) { | |
572 int start_offset = start > 0 ? character_offsets[start - 1] : 0; | |
573 int end_offset = end > 0 ? character_offsets[end - 1] : 0; | |
574 | 574 |
575 switch (node->data().GetIntAttribute(ui::AX_ATTR_TEXT_DIRECTION)) { | 575 // Use character offsets to compute the local bounds of this subrange. |
576 case ui::AX_TEXT_DIRECTION_LTR: | 576 std::string name = node->data().GetStringAttribute(ui::AX_ATTR_NAME); |
577 default: | 577 std::vector<int> character_offsets = |
578 location.set_x(location.x() + start_offset); | 578 node->data().GetIntListAttribute(ui::AX_ATTR_CHARACTER_OFFSETS); |
579 location.set_width(end_offset - start_offset); | 579 int len = |
580 break; | 580 static_cast<int>(std::min(name.size(), character_offsets.size())); |
581 case ui::AX_TEXT_DIRECTION_RTL: | 581 if (start >= 0 && start <= end && end <= len) { |
582 location.set_x(location.x() + location.width() - end_offset); | 582 int start_offset = start > 0 ? character_offsets[start - 1] : 0; |
583 location.set_width(end_offset - start_offset); | 583 int end_offset = end > 0 ? character_offsets[end - 1] : 0; |
584 break; | 584 |
585 case ui::AX_TEXT_DIRECTION_TTB: | 585 switch (node->data().GetIntAttribute(ui::AX_ATTR_TEXT_DIRECTION)) { |
586 location.set_y(location.y() + start_offset); | 586 case ui::AX_TEXT_DIRECTION_LTR: |
587 location.set_height(end_offset - start_offset); | 587 default: |
588 break; | 588 local_bounds.set_x(local_bounds.x() + start_offset); |
589 case ui::AX_TEXT_DIRECTION_BTT: | 589 local_bounds.set_width(end_offset - start_offset); |
590 location.set_y(location.y() + location.height() - end_offset); | 590 break; |
591 location.set_height(end_offset - start_offset); | 591 case ui::AX_TEXT_DIRECTION_RTL: |
592 break; | 592 local_bounds.set_x(local_bounds.x() + local_bounds.width() - |
593 } | 593 end_offset); |
| 594 local_bounds.set_width(end_offset - start_offset); |
| 595 break; |
| 596 case ui::AX_TEXT_DIRECTION_TTB: |
| 597 local_bounds.set_y(local_bounds.y() + start_offset); |
| 598 local_bounds.set_height(end_offset - start_offset); |
| 599 break; |
| 600 case ui::AX_TEXT_DIRECTION_BTT: |
| 601 local_bounds.set_y(local_bounds.y() + local_bounds.height() - |
| 602 end_offset); |
| 603 local_bounds.set_height(end_offset - start_offset); |
| 604 break; |
594 } | 605 } |
595 } | 606 } |
596 result.Set(RectToV8Object(isolate, location)); | 607 |
| 608 // Convert from local to global coordinates second, after subsetting, |
| 609 // because the local to global conversion might involve matrix |
| 610 // transformations. |
| 611 gfx::Rect global_bounds = |
| 612 ComputeGlobalNodeBounds(cache, node, local_bounds); |
| 613 global_bounds.Offset(cache->location_offset); |
| 614 result.Set(RectToV8Object(isolate, global_bounds)); |
597 }); | 615 }); |
598 | 616 |
599 // Bindings that take a Tree ID and Node ID and string attribute name | 617 // Bindings that take a Tree ID and Node ID and string attribute name |
600 // and return a property of the node. | 618 // and return a property of the node. |
601 | 619 |
602 RouteNodeIDPlusAttributeFunction( | 620 RouteNodeIDPlusAttributeFunction( |
603 "GetStringAttribute", | 621 "GetStringAttribute", |
604 [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, | 622 [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, |
605 ui::AXNode* node, const std::string& attribute_name) { | 623 ui::AXNode* node, const std::string& attribute_name) { |
606 ui::AXStringAttribute attribute = | 624 ui::AXStringAttribute attribute = |
(...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1366 v8::Local<v8::Array> args(v8::Array::New(GetIsolate(), 2U)); | 1384 v8::Local<v8::Array> args(v8::Array::New(GetIsolate(), 2U)); |
1367 args->Set(0U, v8::Integer::New(GetIsolate(), tree_id)); | 1385 args->Set(0U, v8::Integer::New(GetIsolate(), tree_id)); |
1368 v8::Local<v8::Array> nodes(v8::Array::New(GetIsolate(), ids.size())); | 1386 v8::Local<v8::Array> nodes(v8::Array::New(GetIsolate(), ids.size())); |
1369 args->Set(1U, nodes); | 1387 args->Set(1U, nodes); |
1370 for (size_t i = 0; i < ids.size(); ++i) | 1388 for (size_t i = 0; i < ids.size(); ++i) |
1371 nodes->Set(i, v8::Integer::New(GetIsolate(), ids[i])); | 1389 nodes->Set(i, v8::Integer::New(GetIsolate(), ids[i])); |
1372 context()->DispatchEvent("automationInternal.onNodesRemoved", args); | 1390 context()->DispatchEvent("automationInternal.onNodesRemoved", args); |
1373 } | 1391 } |
1374 | 1392 |
1375 } // namespace extensions | 1393 } // namespace extensions |
OLD | NEW |