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 |