| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "content/renderer/accessibility/render_accessibility_impl.h" | 5 #include "content/renderer/accessibility/render_accessibility_impl.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <queue> | 10 #include <queue> |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 BlinkAXTreeSerializer serializer(&tree_source); | 74 BlinkAXTreeSerializer serializer(&tree_source); |
| 75 serializer.set_max_node_count(kMaxSnapshotNodeCount); | 75 serializer.set_max_node_count(kMaxSnapshotNodeCount); |
| 76 serializer.SerializeChanges(context.root(), response); | 76 serializer.SerializeChanges(context.root(), response); |
| 77 } | 77 } |
| 78 | 78 |
| 79 RenderAccessibilityImpl::RenderAccessibilityImpl(RenderFrameImpl* render_frame) | 79 RenderAccessibilityImpl::RenderAccessibilityImpl(RenderFrameImpl* render_frame) |
| 80 : RenderFrameObserver(render_frame), | 80 : RenderFrameObserver(render_frame), |
| 81 render_frame_(render_frame), | 81 render_frame_(render_frame), |
| 82 tree_source_(render_frame), | 82 tree_source_(render_frame), |
| 83 serializer_(&tree_source_), | 83 serializer_(&tree_source_), |
| 84 pdf_tree_source_(nullptr), | 84 plugin_tree_source_(nullptr), |
| 85 last_scroll_offset_(gfx::Size()), | 85 last_scroll_offset_(gfx::Size()), |
| 86 ack_pending_(false), | 86 ack_pending_(false), |
| 87 reset_token_(0), | 87 reset_token_(0), |
| 88 during_action_(false), | 88 during_action_(false), |
| 89 weak_factory_(this) { | 89 weak_factory_(this) { |
| 90 ack_token_ = g_next_ack_token++; | 90 ack_token_ = g_next_ack_token++; |
| 91 WebView* web_view = render_frame_->GetRenderView()->GetWebView(); | 91 WebView* web_view = render_frame_->GetRenderView()->GetWebView(); |
| 92 WebSettings* settings = web_view->settings(); | 92 WebSettings* settings = web_view->settings(); |
| 93 settings->setAccessibilityEnabled(true); | 93 settings->setAccessibilityEnabled(true); |
| 94 | 94 |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 base::Bind(&RenderAccessibilityImpl::SendPendingAccessibilityEvents, | 247 base::Bind(&RenderAccessibilityImpl::SendPendingAccessibilityEvents, |
| 248 weak_factory_.GetWeakPtr())); | 248 weak_factory_.GetWeakPtr())); |
| 249 } | 249 } |
| 250 } | 250 } |
| 251 | 251 |
| 252 int RenderAccessibilityImpl::GenerateAXID() { | 252 int RenderAccessibilityImpl::GenerateAXID() { |
| 253 WebAXObject root = tree_source_.GetRoot(); | 253 WebAXObject root = tree_source_.GetRoot(); |
| 254 return root.generateAXID(); | 254 return root.generateAXID(); |
| 255 } | 255 } |
| 256 | 256 |
| 257 void RenderAccessibilityImpl::SetPdfTreeSource( | 257 void RenderAccessibilityImpl::SetPluginTreeSource( |
| 258 RenderAccessibilityImpl::PdfAXTreeSource* pdf_tree_source) { | 258 RenderAccessibilityImpl::PluginAXTreeSource* plugin_tree_source) { |
| 259 pdf_tree_source_ = pdf_tree_source; | 259 plugin_tree_source_ = plugin_tree_source; |
| 260 pdf_serializer_.reset(new PdfAXTreeSerializer(pdf_tree_source_)); | 260 plugin_serializer_.reset(new PluginAXTreeSerializer(plugin_tree_source_)); |
| 261 |
| 262 OnPluginRootNodeUpdated(); |
| 263 } |
| 264 |
| 265 void RenderAccessibilityImpl::OnPluginRootNodeUpdated() { |
| 266 // Search the accessibility tree for an EMBED element and post a |
| 267 // children changed notification on it to force it to update the |
| 268 // plugin accessibility tree. |
| 261 | 269 |
| 262 ScopedFreezeBlinkAXTreeSource freeze(&tree_source_); | 270 ScopedFreezeBlinkAXTreeSource freeze(&tree_source_); |
| 263 WebAXObject root = tree_source_.GetRoot(); | 271 WebAXObject root = tree_source_.GetRoot(); |
| 264 if (!root.updateLayoutAndCheckValidity()) | 272 if (!root.updateLayoutAndCheckValidity()) |
| 265 return; | 273 return; |
| 266 | 274 |
| 267 std::queue<WebAXObject> objs_to_explore; | 275 std::queue<WebAXObject> objs_to_explore; |
| 268 objs_to_explore.push(root); | 276 objs_to_explore.push(root); |
| 269 while (objs_to_explore.size()) { | 277 while (objs_to_explore.size()) { |
| 270 WebAXObject obj = objs_to_explore.front(); | 278 WebAXObject obj = objs_to_explore.front(); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 | 349 |
| 342 AccessibilityHostMsg_EventParams event_msg; | 350 AccessibilityHostMsg_EventParams event_msg; |
| 343 event_msg.event_type = event.event_type; | 351 event_msg.event_type = event.event_type; |
| 344 event_msg.id = event.id; | 352 event_msg.id = event.id; |
| 345 event_msg.event_from = event.event_from; | 353 event_msg.event_from = event.event_from; |
| 346 if (!serializer_.SerializeChanges(obj, &event_msg.update)) { | 354 if (!serializer_.SerializeChanges(obj, &event_msg.update)) { |
| 347 LOG(ERROR) << "Failed to serialize one accessibility event."; | 355 LOG(ERROR) << "Failed to serialize one accessibility event."; |
| 348 continue; | 356 continue; |
| 349 } | 357 } |
| 350 | 358 |
| 351 if (pdf_tree_source_) | 359 if (plugin_tree_source_) |
| 352 AddPdfTreeToUpdate(&event_msg.update); | 360 AddPluginTreeToUpdate(&event_msg.update); |
| 353 | 361 |
| 354 event_msgs.push_back(event_msg); | 362 event_msgs.push_back(event_msg); |
| 355 | 363 |
| 356 // For each node in the update, set the location in our map from | 364 // For each node in the update, set the location in our map from |
| 357 // ids to locations. | 365 // ids to locations. |
| 358 for (size_t i = 0; i < event_msg.update.nodes.size(); ++i) { | 366 for (size_t i = 0; i < event_msg.update.nodes.size(); ++i) { |
| 359 ui::AXNodeData& src = event_msg.update.nodes[i]; | 367 ui::AXNodeData& src = event_msg.update.nodes[i]; |
| 360 ui::AXRelativeBounds& dst = locations_[event_msg.update.nodes[i].id]; | 368 ui::AXRelativeBounds& dst = locations_[event_msg.update.nodes[i].id]; |
| 361 dst.offset_container_id = src.offset_container_id; | 369 dst.offset_container_id = src.offset_container_id; |
| 362 dst.bounds = src.location; | 370 dst.bounds = src.location; |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 526 // Tree-only mode gets used by the automation extension API which requires a | 534 // Tree-only mode gets used by the automation extension API which requires a |
| 527 // load complete event to invoke listener callbacks. | 535 // load complete event to invoke listener callbacks. |
| 528 ui::AXEvent evt = document.accessibilityObject().isLoaded() | 536 ui::AXEvent evt = document.accessibilityObject().isLoaded() |
| 529 ? ui::AX_EVENT_LOAD_COMPLETE : ui::AX_EVENT_LAYOUT_COMPLETE; | 537 ? ui::AX_EVENT_LOAD_COMPLETE : ui::AX_EVENT_LAYOUT_COMPLETE; |
| 530 HandleAXEvent(document.accessibilityObject(), evt); | 538 HandleAXEvent(document.accessibilityObject(), evt); |
| 531 } | 539 } |
| 532 } | 540 } |
| 533 | 541 |
| 534 void RenderAccessibilityImpl::OnScrollToMakeVisible( | 542 void RenderAccessibilityImpl::OnScrollToMakeVisible( |
| 535 int acc_obj_id, gfx::Rect subfocus) { | 543 int acc_obj_id, gfx::Rect subfocus) { |
| 536 if (pdf_tree_source_ && pdf_tree_source_->GetFromId(acc_obj_id)) { | 544 if (plugin_tree_source_ && plugin_tree_source_->GetFromId(acc_obj_id)) { |
| 537 ScrollPdf(acc_obj_id); | 545 ScrollPlugin(acc_obj_id); |
| 538 return; | 546 return; |
| 539 } | 547 } |
| 540 | 548 |
| 541 const WebDocument& document = GetMainDocument(); | 549 const WebDocument& document = GetMainDocument(); |
| 542 if (document.isNull()) | 550 if (document.isNull()) |
| 543 return; | 551 return; |
| 544 | 552 |
| 545 WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id); | 553 WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id); |
| 546 if (obj.isDetached()) { | 554 if (obj.isDetached()) { |
| 547 #ifndef NDEBUG | 555 #ifndef NDEBUG |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 696 return; | 704 return; |
| 697 } | 705 } |
| 698 | 706 |
| 699 obj.showContextMenu(); | 707 obj.showContextMenu(); |
| 700 } | 708 } |
| 701 | 709 |
| 702 void RenderAccessibilityImpl::OnDestruct() { | 710 void RenderAccessibilityImpl::OnDestruct() { |
| 703 delete this; | 711 delete this; |
| 704 } | 712 } |
| 705 | 713 |
| 706 void RenderAccessibilityImpl::AddPdfTreeToUpdate(AXContentTreeUpdate* update) { | 714 void RenderAccessibilityImpl::AddPluginTreeToUpdate( |
| 715 AXContentTreeUpdate* update) { |
| 707 for (size_t i = 0; i < update->nodes.size(); ++i) { | 716 for (size_t i = 0; i < update->nodes.size(); ++i) { |
| 708 if (update->nodes[i].role == ui::AX_ROLE_EMBEDDED_OBJECT) { | 717 if (update->nodes[i].role == ui::AX_ROLE_EMBEDDED_OBJECT) { |
| 709 const ui::AXNode* root = pdf_tree_source_->GetRoot(); | 718 const ui::AXNode* root = plugin_tree_source_->GetRoot(); |
| 710 update->nodes[i].child_ids.push_back(root->id()); | 719 update->nodes[i].child_ids.push_back(root->id()); |
| 711 | 720 |
| 712 ui::AXTreeUpdate pdf_update; | 721 ui::AXTreeUpdate plugin_update; |
| 713 pdf_serializer_->SerializeChanges(root, &pdf_update); | 722 plugin_serializer_->SerializeChanges(root, &plugin_update); |
| 714 | 723 |
| 715 // We have to copy the updated nodes using a loop because we're | 724 // We have to copy the updated nodes using a loop because we're |
| 716 // converting from a generic ui::AXNodeData to a vector of its | 725 // converting from a generic ui::AXNodeData to a vector of its |
| 717 // content-specific subclass AXContentNodeData. | 726 // content-specific subclass AXContentNodeData. |
| 718 size_t old_count = update->nodes.size(); | 727 size_t old_count = update->nodes.size(); |
| 719 size_t new_count = pdf_update.nodes.size(); | 728 size_t new_count = plugin_update.nodes.size(); |
| 720 update->nodes.resize(old_count + new_count); | 729 update->nodes.resize(old_count + new_count); |
| 721 for (size_t i = 0; i < new_count; ++i) | 730 for (size_t i = 0; i < new_count; ++i) |
| 722 update->nodes[old_count + i] = pdf_update.nodes[i]; | 731 update->nodes[old_count + i] = plugin_update.nodes[i]; |
| 723 break; | 732 break; |
| 724 } | 733 } |
| 725 } | 734 } |
| 726 } | 735 } |
| 727 | 736 |
| 728 void RenderAccessibilityImpl::ScrollPdf(int id_to_make_visible) { | 737 void RenderAccessibilityImpl::ScrollPlugin(int id_to_make_visible) { |
| 729 // The PDF content doesn't scroll itself, rather it's just one big document | 738 // Plugin content doesn't scroll itself, so when we're requested to |
| 730 // and the embedding page scrolls. So, when we're requested to scroll to make | 739 // scroll to make a particular plugin node visible, get the |
| 731 // a particular PDF node visible, get the coordinates of the target PDF node | 740 // coordinates of the target plugin node and then tell the document |
| 732 // and then tell the document node to scroll to those coordinates. | 741 // node to scroll to those coordinates. |
| 733 // | 742 // |
| 734 // Note that calling scrollToMakeVisibleWithSubFocus() is preferable to | 743 // Note that calling scrollToMakeVisibleWithSubFocus() is preferable to |
| 735 // telling the document to scroll to a specific coordinate because it will | 744 // telling the document to scroll to a specific coordinate because it will |
| 736 // first compute whether that rectangle is visible and do nothing if it is. | 745 // first compute whether that rectangle is visible and do nothing if it is. |
| 737 // If it's not visible, it will automatically center it. | 746 // If it's not visible, it will automatically center it. |
| 738 | 747 |
| 739 DCHECK(pdf_tree_source_); | 748 DCHECK(plugin_tree_source_); |
| 740 ui::AXNodeData root_data = pdf_tree_source_->GetRoot()->data(); | 749 ui::AXNodeData root_data = plugin_tree_source_->GetRoot()->data(); |
| 741 ui::AXNodeData target_data = | 750 ui::AXNodeData target_data = |
| 742 pdf_tree_source_->GetFromId(id_to_make_visible)->data(); | 751 plugin_tree_source_->GetFromId(id_to_make_visible)->data(); |
| 743 | 752 |
| 744 gfx::RectF bounds = target_data.location; | 753 gfx::RectF bounds = target_data.location; |
| 745 if (root_data.transform) | 754 if (root_data.transform) |
| 746 root_data.transform->TransformRect(&bounds); | 755 root_data.transform->TransformRect(&bounds); |
| 747 | 756 |
| 748 const WebDocument& document = GetMainDocument(); | 757 const WebDocument& document = GetMainDocument(); |
| 749 if (document.isNull()) | 758 if (document.isNull()) |
| 750 return; | 759 return; |
| 751 | 760 |
| 752 document.accessibilityObject().scrollToMakeVisibleWithSubFocus( | 761 document.accessibilityObject().scrollToMakeVisibleWithSubFocus( |
| 753 WebRect(bounds.x(), bounds.y(), bounds.width(), bounds.height())); | 762 WebRect(bounds.x(), bounds.y(), bounds.width(), bounds.height())); |
| 754 } | 763 } |
| 755 | 764 |
| 756 } // namespace content | 765 } // namespace content |
| OLD | NEW |