| Index: chrome/renderer/extensions/automation_internal_custom_bindings.cc
|
| diff --git a/chrome/renderer/extensions/automation_internal_custom_bindings.cc b/chrome/renderer/extensions/automation_internal_custom_bindings.cc
|
| index 5c8dc7fa754e26d1226a369c9dd12fb42a777e3c..225d68d4a01b6a150cdd15c93da95797a0ea6b17 100644
|
| --- a/chrome/renderer/extensions/automation_internal_custom_bindings.cc
|
| +++ b/chrome/renderer/extensions/automation_internal_custom_bindings.cc
|
| @@ -112,11 +112,13 @@ static gfx::RectF ComputeLocalNodeBounds(TreeCache* cache, ui::AXNode* node) {
|
| return bounds;
|
| }
|
|
|
| -// Compute the bounding box of a node in global coordinates, walking up the
|
| -// parent hierarchy to offset by frame offsets and scroll offsets.
|
| -static gfx::Rect ComputeGlobalNodeBounds(TreeCache* cache, ui::AXNode* node) {
|
| - gfx::RectF bounds = ComputeLocalNodeBounds(cache, node);
|
| -
|
| +// Adjust the bounding box of a node from local to global coordinates,
|
| +// walking up the parent hierarchy to offset by frame offsets and
|
| +// scroll offsets.
|
| +static gfx::Rect ComputeGlobalNodeBounds(TreeCache* cache,
|
| + ui::AXNode* node,
|
| + gfx::RectF local_bounds) {
|
| + gfx::RectF bounds = local_bounds;
|
| while (node) {
|
| if (node->data().transform)
|
| node->data().transform->TransformRect(&bounds);
|
| @@ -523,9 +525,11 @@ AutomationInternalCustomBindings::AutomationInternalCustomBindings(
|
| RouteNodeIDFunction(
|
| "GetLocation", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
|
| TreeCache* cache, ui::AXNode* node) {
|
| - gfx::Rect location = ComputeGlobalNodeBounds(cache, node);
|
| - location.Offset(cache->location_offset);
|
| - result.Set(RectToV8Object(isolate, location));
|
| + gfx::RectF local_bounds = ComputeLocalNodeBounds(cache, node);
|
| + gfx::Rect global_bounds =
|
| + ComputeGlobalNodeBounds(cache, node, local_bounds);
|
| + global_bounds.Offset(cache->location_offset);
|
| + result.Set(RectToV8Object(isolate, global_bounds));
|
| });
|
| RouteNodeIDFunction(
|
| "GetLineStartOffsets",
|
| @@ -560,40 +564,54 @@ AutomationInternalCustomBindings::AutomationInternalCustomBindings(
|
| "GetBoundsForRange",
|
| [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
|
| TreeCache* cache, ui::AXNode* node, int start, int end) {
|
| - gfx::Rect location = ComputeGlobalNodeBounds(cache, node);
|
| - location.Offset(cache->location_offset);
|
| - if (node->data().role == ui::AX_ROLE_INLINE_TEXT_BOX) {
|
| - std::string name = node->data().GetStringAttribute(ui::AX_ATTR_NAME);
|
| - std::vector<int> character_offsets =
|
| - node->data().GetIntListAttribute(ui::AX_ATTR_CHARACTER_OFFSETS);
|
| - int len =
|
| - static_cast<int>(std::min(name.size(), character_offsets.size()));
|
| - if (start >= 0 && start <= end && end <= len) {
|
| - int start_offset = start > 0 ? character_offsets[start - 1] : 0;
|
| - int end_offset = end > 0 ? character_offsets[end - 1] : 0;
|
| -
|
| - switch (node->data().GetIntAttribute(ui::AX_ATTR_TEXT_DIRECTION)) {
|
| - case ui::AX_TEXT_DIRECTION_LTR:
|
| - default:
|
| - location.set_x(location.x() + start_offset);
|
| - location.set_width(end_offset - start_offset);
|
| - break;
|
| - case ui::AX_TEXT_DIRECTION_RTL:
|
| - location.set_x(location.x() + location.width() - end_offset);
|
| - location.set_width(end_offset - start_offset);
|
| - break;
|
| - case ui::AX_TEXT_DIRECTION_TTB:
|
| - location.set_y(location.y() + start_offset);
|
| - location.set_height(end_offset - start_offset);
|
| - break;
|
| - case ui::AX_TEXT_DIRECTION_BTT:
|
| - location.set_y(location.y() + location.height() - end_offset);
|
| - location.set_height(end_offset - start_offset);
|
| - break;
|
| - }
|
| + gfx::RectF local_bounds = ComputeLocalNodeBounds(cache, node);
|
| + if (node->data().role != ui::AX_ROLE_INLINE_TEXT_BOX) {
|
| + gfx::Rect global_bounds =
|
| + ComputeGlobalNodeBounds(cache, node, local_bounds);
|
| + global_bounds.Offset(cache->location_offset);
|
| + result.Set(RectToV8Object(isolate, global_bounds));
|
| + }
|
| +
|
| + // Use character offsets to compute the local bounds of this subrange.
|
| + std::string name = node->data().GetStringAttribute(ui::AX_ATTR_NAME);
|
| + std::vector<int> character_offsets =
|
| + node->data().GetIntListAttribute(ui::AX_ATTR_CHARACTER_OFFSETS);
|
| + int len =
|
| + static_cast<int>(std::min(name.size(), character_offsets.size()));
|
| + if (start >= 0 && start <= end && end <= len) {
|
| + int start_offset = start > 0 ? character_offsets[start - 1] : 0;
|
| + int end_offset = end > 0 ? character_offsets[end - 1] : 0;
|
| +
|
| + switch (node->data().GetIntAttribute(ui::AX_ATTR_TEXT_DIRECTION)) {
|
| + case ui::AX_TEXT_DIRECTION_LTR:
|
| + default:
|
| + local_bounds.set_x(local_bounds.x() + start_offset);
|
| + local_bounds.set_width(end_offset - start_offset);
|
| + break;
|
| + case ui::AX_TEXT_DIRECTION_RTL:
|
| + local_bounds.set_x(local_bounds.x() + local_bounds.width() -
|
| + end_offset);
|
| + local_bounds.set_width(end_offset - start_offset);
|
| + break;
|
| + case ui::AX_TEXT_DIRECTION_TTB:
|
| + local_bounds.set_y(local_bounds.y() + start_offset);
|
| + local_bounds.set_height(end_offset - start_offset);
|
| + break;
|
| + case ui::AX_TEXT_DIRECTION_BTT:
|
| + local_bounds.set_y(local_bounds.y() + local_bounds.height() -
|
| + end_offset);
|
| + local_bounds.set_height(end_offset - start_offset);
|
| + break;
|
| }
|
| }
|
| - result.Set(RectToV8Object(isolate, location));
|
| +
|
| + // Convert from local to global coordinates second, after subsetting,
|
| + // because the local to global conversion might involve matrix
|
| + // transformations.
|
| + gfx::Rect global_bounds =
|
| + ComputeGlobalNodeBounds(cache, node, local_bounds);
|
| + global_bounds.Offset(cache->location_offset);
|
| + result.Set(RectToV8Object(isolate, global_bounds));
|
| });
|
|
|
| // Bindings that take a Tree ID and Node ID and string attribute name
|
|
|