Index: content/renderer/accessibility/renderer_accessibility_complete.cc |
diff --git a/content/renderer/accessibility/renderer_accessibility_complete.cc b/content/renderer/accessibility/renderer_accessibility_complete.cc |
deleted file mode 100644 |
index e09021138999317c0fb66e9b24aef6dee5a3bef1..0000000000000000000000000000000000000000 |
--- a/content/renderer/accessibility/renderer_accessibility_complete.cc |
+++ /dev/null |
@@ -1,454 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "content/renderer/accessibility/renderer_accessibility_complete.h" |
- |
-#include <queue> |
- |
-#include "base/bind.h" |
-#include "base/message_loop/message_loop.h" |
-#include "content/renderer/accessibility/blink_ax_enum_conversion.h" |
-#include "content/renderer/render_frame_impl.h" |
-#include "content/renderer/render_view_impl.h" |
-#include "third_party/WebKit/public/web/WebAXObject.h" |
-#include "third_party/WebKit/public/web/WebDocument.h" |
-#include "third_party/WebKit/public/web/WebFrame.h" |
-#include "third_party/WebKit/public/web/WebInputElement.h" |
-#include "third_party/WebKit/public/web/WebLocalFrame.h" |
-#include "third_party/WebKit/public/web/WebNode.h" |
-#include "third_party/WebKit/public/web/WebSettings.h" |
-#include "third_party/WebKit/public/web/WebView.h" |
-#include "ui/accessibility/ax_tree.h" |
- |
-using blink::WebAXObject; |
-using blink::WebDocument; |
-using blink::WebFrame; |
-using blink::WebNode; |
-using blink::WebPoint; |
-using blink::WebRect; |
-using blink::WebSettings; |
-using blink::WebView; |
- |
-namespace content { |
- |
-RendererAccessibilityComplete::RendererAccessibilityComplete( |
- RenderFrameImpl* render_frame) |
- : RendererAccessibility(render_frame), |
- tree_source_(render_frame), |
- serializer_(&tree_source_), |
- last_scroll_offset_(gfx::Size()), |
- ack_pending_(false), |
- reset_token_(0), |
- weak_factory_(this) { |
- WebView* web_view = render_frame_->GetRenderView()->GetWebView(); |
- WebSettings* settings = web_view->settings(); |
- settings->setAccessibilityEnabled(true); |
- |
-#if !defined(OS_ANDROID) |
- // Skip inline text boxes on Android - since there are no native Android |
- // APIs that compute the bounds of a range of text, it's a waste to |
- // include these in the AX tree. |
- settings->setInlineTextBoxAccessibilityEnabled(true); |
-#endif |
- |
- const WebDocument& document = GetMainDocument(); |
- if (!document.isNull()) { |
- // It's possible that the webview has already loaded a webpage without |
- // accessibility being enabled. Initialize the browser's cached |
- // accessibility tree by sending it a notification. |
- HandleAXEvent(document.accessibilityObject(), |
- ui::AX_EVENT_LAYOUT_COMPLETE); |
- } |
-} |
- |
-RendererAccessibilityComplete::~RendererAccessibilityComplete() { |
-} |
- |
-bool RendererAccessibilityComplete::OnMessageReceived( |
- const IPC::Message& message) { |
- bool handled = true; |
- IPC_BEGIN_MESSAGE_MAP(RendererAccessibilityComplete, message) |
- IPC_MESSAGE_HANDLER(AccessibilityMsg_SetFocus, OnSetFocus) |
- IPC_MESSAGE_HANDLER(AccessibilityMsg_DoDefaultAction, |
- OnDoDefaultAction) |
- IPC_MESSAGE_HANDLER(AccessibilityMsg_Events_ACK, |
- OnEventsAck) |
- IPC_MESSAGE_HANDLER(AccessibilityMsg_ScrollToMakeVisible, |
- OnScrollToMakeVisible) |
- IPC_MESSAGE_HANDLER(AccessibilityMsg_ScrollToPoint, |
- OnScrollToPoint) |
- IPC_MESSAGE_HANDLER(AccessibilityMsg_SetTextSelection, |
- OnSetTextSelection) |
- IPC_MESSAGE_HANDLER(AccessibilityMsg_HitTest, OnHitTest) |
- IPC_MESSAGE_HANDLER(AccessibilityMsg_Reset, OnReset) |
- IPC_MESSAGE_HANDLER(AccessibilityMsg_FatalError, OnFatalError) |
- IPC_MESSAGE_UNHANDLED(handled = false) |
- IPC_END_MESSAGE_MAP() |
- return handled; |
-} |
- |
-void RendererAccessibilityComplete::FocusedNodeChanged(const WebNode& node) { |
- const WebDocument& document = GetMainDocument(); |
- if (document.isNull()) |
- return; |
- |
- if (node.isNull()) { |
- // When focus is cleared, implicitly focus the document. |
- // TODO(dmazzoni): Make Blink send this notification instead. |
- HandleAXEvent(document.accessibilityObject(), ui::AX_EVENT_BLUR); |
- } |
-} |
- |
-void RendererAccessibilityComplete::DisableAccessibility() { |
- RenderView* render_view = render_frame_->GetRenderView(); |
- if (!render_view) |
- return; |
- |
- WebView* web_view = render_view->GetWebView(); |
- if (!web_view) |
- return; |
- |
- WebSettings* settings = web_view->settings(); |
- if (!settings) |
- return; |
- |
- settings->setAccessibilityEnabled(false); |
-} |
- |
-void RendererAccessibilityComplete::HandleWebAccessibilityEvent( |
- const blink::WebAXObject& obj, blink::WebAXEvent event) { |
- HandleAXEvent(obj, AXEventFromBlink(event)); |
-} |
- |
-void RendererAccessibilityComplete::HandleAXEvent( |
- const blink::WebAXObject& obj, ui::AXEvent event) { |
- const WebDocument& document = GetMainDocument(); |
- if (document.isNull()) |
- return; |
- |
- gfx::Size scroll_offset = document.frame()->scrollOffset(); |
- if (scroll_offset != last_scroll_offset_) { |
- // Make sure the browser is always aware of the scroll position of |
- // the root document element by posting a generic notification that |
- // will update it. |
- // TODO(dmazzoni): remove this as soon as |
- // https://bugs.webkit.org/show_bug.cgi?id=73460 is fixed. |
- last_scroll_offset_ = scroll_offset; |
- if (!obj.equals(document.accessibilityObject())) { |
- HandleAXEvent(document.accessibilityObject(), |
- ui::AX_EVENT_LAYOUT_COMPLETE); |
- } |
- } |
- |
- // Add the accessibility object to our cache and ensure it's valid. |
- AccessibilityHostMsg_EventParams acc_event; |
- acc_event.id = obj.axID(); |
- acc_event.event_type = event; |
- |
- // Discard duplicate accessibility events. |
- for (uint32 i = 0; i < pending_events_.size(); ++i) { |
- if (pending_events_[i].id == acc_event.id && |
- pending_events_[i].event_type == |
- acc_event.event_type) { |
- return; |
- } |
- } |
- pending_events_.push_back(acc_event); |
- |
- if (!ack_pending_ && !weak_factory_.HasWeakPtrs()) { |
- // When no accessibility events are in-flight post a task to send |
- // the events to the browser. We use PostTask so that we can queue |
- // up additional events. |
- base::MessageLoop::current()->PostTask( |
- FROM_HERE, |
- base::Bind(&RendererAccessibilityComplete:: |
- SendPendingAccessibilityEvents, |
- weak_factory_.GetWeakPtr())); |
- } |
-} |
- |
-RendererAccessibilityType RendererAccessibilityComplete::GetType() { |
- return RendererAccessibilityTypeComplete; |
-} |
- |
-void RendererAccessibilityComplete::SendPendingAccessibilityEvents() { |
- const WebDocument& document = GetMainDocument(); |
- if (document.isNull()) |
- return; |
- |
- if (pending_events_.empty()) |
- return; |
- |
- if (render_frame_->is_swapped_out()) |
- return; |
- |
- ack_pending_ = true; |
- |
- // Make a copy of the events, because it's possible that |
- // actions inside this loop will cause more events to be |
- // queued up. |
- std::vector<AccessibilityHostMsg_EventParams> src_events = |
- pending_events_; |
- pending_events_.clear(); |
- |
- // Generate an event message from each Blink event. |
- std::vector<AccessibilityHostMsg_EventParams> event_msgs; |
- |
- // If there's a layout complete message, we need to send location changes. |
- bool had_layout_complete_messages = false; |
- |
- // Loop over each event and generate an updated event message. |
- for (size_t i = 0; i < src_events.size(); ++i) { |
- AccessibilityHostMsg_EventParams& event = src_events[i]; |
- if (event.event_type == ui::AX_EVENT_LAYOUT_COMPLETE) |
- had_layout_complete_messages = true; |
- |
- WebAXObject obj = document.accessibilityObjectFromID(event.id); |
- |
- // Make sure the object still exists. |
- if (!obj.updateLayoutAndCheckValidity()) |
- continue; |
- |
- // If it's ignored, find the first ancestor that's not ignored. |
- while (!obj.isDetached() && obj.accessibilityIsIgnored()) |
- obj = obj.parentObject(); |
- |
- // Make sure it's a descendant of our root node - exceptions include the |
- // scroll area that's the parent of the main document (we ignore it), and |
- // possibly nodes attached to a different document. |
- if (!tree_source_.IsInTree(obj)) |
- continue; |
- |
- // When we get a "selected children changed" event, Blink |
- // doesn't also send us events for each child that changed |
- // selection state, so make sure we re-send that whole subtree. |
- if (event.event_type == |
- ui::AX_EVENT_SELECTED_CHILDREN_CHANGED) { |
- serializer_.DeleteClientSubtree(obj); |
- } |
- |
- AccessibilityHostMsg_EventParams event_msg; |
- tree_source_.CollectChildFrameIdMapping( |
- &event_msg.node_to_frame_routing_id_map, |
- &event_msg.node_to_browser_plugin_instance_id_map); |
- event_msg.event_type = event.event_type; |
- event_msg.id = event.id; |
- serializer_.SerializeChanges(obj, &event_msg.update); |
- event_msgs.push_back(event_msg); |
- |
- // For each node in the update, set the location in our map from |
- // ids to locations. |
- for (size_t i = 0; i < event_msg.update.nodes.size(); ++i) { |
- locations_[event_msg.update.nodes[i].id] = |
- event_msg.update.nodes[i].location; |
- } |
- |
- VLOG(0) << "Accessibility event: " << ui::ToString(event.event_type) |
- << " on node id " << event_msg.id |
- << "\n" << event_msg.update.ToString(); |
- } |
- |
- Send(new AccessibilityHostMsg_Events(routing_id(), event_msgs, reset_token_)); |
- reset_token_ = 0; |
- |
- if (had_layout_complete_messages) |
- SendLocationChanges(); |
-} |
- |
-void RendererAccessibilityComplete::SendLocationChanges() { |
- std::vector<AccessibilityHostMsg_LocationChangeParams> messages; |
- |
- // Do a breadth-first explore of the whole blink AX tree. |
- base::hash_map<int, gfx::Rect> new_locations; |
- std::queue<WebAXObject> objs_to_explore; |
- objs_to_explore.push(tree_source_.GetRoot()); |
- while (objs_to_explore.size()) { |
- WebAXObject obj = objs_to_explore.front(); |
- objs_to_explore.pop(); |
- |
- // See if we had a previous location. If not, this whole subtree must |
- // be new, so don't continue to explore this branch. |
- int id = obj.axID(); |
- base::hash_map<int, gfx::Rect>::iterator iter = locations_.find(id); |
- if (iter == locations_.end()) |
- continue; |
- |
- // If the location has changed, append it to the IPC message. |
- gfx::Rect new_location = obj.boundingBoxRect(); |
- if (iter != locations_.end() && iter->second != new_location) { |
- AccessibilityHostMsg_LocationChangeParams message; |
- message.id = id; |
- message.new_location = new_location; |
- messages.push_back(message); |
- } |
- |
- // Save the new location. |
- new_locations[id] = new_location; |
- |
- // Explore children of this object. |
- std::vector<blink::WebAXObject> children; |
- tree_source_.GetChildren(obj, &children); |
- for (size_t i = 0; i < children.size(); ++i) |
- objs_to_explore.push(children[i]); |
- } |
- locations_.swap(new_locations); |
- |
- Send(new AccessibilityHostMsg_LocationChanges(routing_id(), messages)); |
-} |
- |
-void RendererAccessibilityComplete::OnDoDefaultAction(int acc_obj_id) { |
- const WebDocument& document = GetMainDocument(); |
- if (document.isNull()) |
- return; |
- |
- WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id); |
- if (obj.isDetached()) { |
-#ifndef NDEBUG |
- LOG(WARNING) << "DoDefaultAction on invalid object id " << acc_obj_id; |
-#endif |
- return; |
- } |
- |
- obj.performDefaultAction(); |
-} |
- |
-void RendererAccessibilityComplete::OnScrollToMakeVisible( |
- int acc_obj_id, gfx::Rect subfocus) { |
- const WebDocument& document = GetMainDocument(); |
- if (document.isNull()) |
- return; |
- |
- WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id); |
- if (obj.isDetached()) { |
-#ifndef NDEBUG |
- LOG(WARNING) << "ScrollToMakeVisible on invalid object id " << acc_obj_id; |
-#endif |
- return; |
- } |
- |
- obj.scrollToMakeVisibleWithSubFocus( |
- WebRect(subfocus.x(), subfocus.y(), |
- subfocus.width(), subfocus.height())); |
- |
- // Make sure the browser gets an event when the scroll |
- // position actually changes. |
- // TODO(dmazzoni): remove this once this bug is fixed: |
- // https://bugs.webkit.org/show_bug.cgi?id=73460 |
- HandleAXEvent(document.accessibilityObject(), |
- ui::AX_EVENT_LAYOUT_COMPLETE); |
-} |
- |
-void RendererAccessibilityComplete::OnScrollToPoint( |
- int acc_obj_id, gfx::Point point) { |
- const WebDocument& document = GetMainDocument(); |
- if (document.isNull()) |
- return; |
- |
- WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id); |
- if (obj.isDetached()) { |
-#ifndef NDEBUG |
- LOG(WARNING) << "ScrollToPoint on invalid object id " << acc_obj_id; |
-#endif |
- return; |
- } |
- |
- obj.scrollToGlobalPoint(WebPoint(point.x(), point.y())); |
- |
- // Make sure the browser gets an event when the scroll |
- // position actually changes. |
- // TODO(dmazzoni): remove this once this bug is fixed: |
- // https://bugs.webkit.org/show_bug.cgi?id=73460 |
- HandleAXEvent(document.accessibilityObject(), |
- ui::AX_EVENT_LAYOUT_COMPLETE); |
-} |
- |
-void RendererAccessibilityComplete::OnSetTextSelection( |
- int acc_obj_id, int start_offset, int end_offset) { |
- const WebDocument& document = GetMainDocument(); |
- if (document.isNull()) |
- return; |
- |
- WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id); |
- if (obj.isDetached()) { |
-#ifndef NDEBUG |
- LOG(WARNING) << "SetTextSelection on invalid object id " << acc_obj_id; |
-#endif |
- return; |
- } |
- |
- // TODO(dmazzoni): support elements other than <input>. |
- blink::WebNode node = obj.node(); |
- if (!node.isNull() && node.isElementNode()) { |
- blink::WebElement element = node.to<blink::WebElement>(); |
- blink::WebInputElement* input_element = |
- blink::toWebInputElement(&element); |
- if (input_element && input_element->isTextField()) |
- input_element->setSelectionRange(start_offset, end_offset); |
- } |
-} |
- |
-void RendererAccessibilityComplete::OnHitTest(gfx::Point point) { |
- const WebDocument& document = GetMainDocument(); |
- if (document.isNull()) |
- return; |
- WebAXObject root_obj = document.accessibilityObject(); |
- if (!root_obj.updateLayoutAndCheckValidity()) |
- return; |
- |
- WebAXObject obj = root_obj.hitTest(point); |
- if (!obj.isDetached()) |
- HandleAXEvent(obj, ui::AX_EVENT_HOVER); |
-} |
- |
-void RendererAccessibilityComplete::OnEventsAck() { |
- DCHECK(ack_pending_); |
- ack_pending_ = false; |
- SendPendingAccessibilityEvents(); |
-} |
- |
-void RendererAccessibilityComplete::OnSetFocus(int acc_obj_id) { |
- const WebDocument& document = GetMainDocument(); |
- if (document.isNull()) |
- return; |
- |
- WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id); |
- if (obj.isDetached()) { |
-#ifndef NDEBUG |
- LOG(WARNING) << "OnSetAccessibilityFocus on invalid object id " |
- << acc_obj_id; |
-#endif |
- return; |
- } |
- |
- WebAXObject root = document.accessibilityObject(); |
- if (root.isDetached()) { |
-#ifndef NDEBUG |
- LOG(WARNING) << "OnSetAccessibilityFocus but root is invalid"; |
-#endif |
- return; |
- } |
- |
- // By convention, calling SetFocus on the root of the tree should clear the |
- // current focus. Otherwise set the focus to the new node. |
- if (acc_obj_id == root.axID()) |
- render_frame_->GetRenderView()->GetWebView()->clearFocusedElement(); |
- else |
- obj.setFocused(true); |
-} |
- |
-void RendererAccessibilityComplete::OnReset(int reset_token) { |
- reset_token_ = reset_token; |
- serializer_.Reset(); |
- pending_events_.clear(); |
- |
- const WebDocument& document = GetMainDocument(); |
- if (!document.isNull()) |
- HandleAXEvent(document.accessibilityObject(), ui::AX_EVENT_LAYOUT_COMPLETE); |
-} |
- |
-void RendererAccessibilityComplete::OnFatalError() { |
- CHECK(false) << "Invalid accessibility tree."; |
-} |
- |
-} // namespace content |