Commit 949df1cc authored by dmazzoni@chromium.org's avatar dmazzoni@chromium.org

Refactor content/renderer/accessibility to use AXTreeSerializer (re-land).

This removes the confusing code in content/renderer/accessibility that
serializes updates from Blink's accessibility tree, and replaces it with
calls to the new cleaner and fully-unit-tested AXTreeSerializer class.

BUG=316726

Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=261099

Review URL: https://codereview.chromium.org/125763003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@261408 0039d316-1c4b-4281-b951-d872f2087c98
parent 87b9bf1b
......@@ -131,7 +131,7 @@ void BrowserAccessibilityManager::OnAccessibilityEvents(
// Process all changes to the accessibility tree first.
for (uint32 index = 0; index < params.size(); index++) {
const AccessibilityHostMsg_EventParams& param = params[index];
if (!UpdateNodes(param.nodes))
if (!UpdateNodes(param.update.nodes))
return;
// Set initial focus when a page is loaded.
......
......@@ -267,8 +267,8 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects) {
params.push_back(AccessibilityHostMsg_EventParams());
AccessibilityHostMsg_EventParams* msg = &params[0];
msg->event_type = ui::AX_EVENT_CHILDREN_CHANGED;
msg->nodes.push_back(tree2_root);
msg->nodes.push_back(tree2_child0);
msg->update.nodes.push_back(tree2_root);
msg->update.nodes.push_back(tree2_child0);
msg->id = tree2_root.id;
manager->OnAccessibilityEvents(params);
......@@ -444,9 +444,9 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects2) {
params.push_back(AccessibilityHostMsg_EventParams());
AccessibilityHostMsg_EventParams* msg = &params[0];
msg->event_type = ui::AX_EVENT_CHILDREN_CHANGED;
msg->nodes.push_back(tree2_container);
msg->nodes.push_back(tree2_child0);
msg->nodes.push_back(tree2_grandchild0);
msg->update.nodes.push_back(tree2_container);
msg->update.nodes.push_back(tree2_child0);
msg->update.nodes.push_back(tree2_grandchild0);
msg->id = tree2_container.id;
manager->OnAccessibilityEvents(params);
......@@ -551,10 +551,10 @@ TEST(BrowserAccessibilityManagerTest, TestMoveChildUp) {
params.push_back(AccessibilityHostMsg_EventParams());
AccessibilityHostMsg_EventParams* msg = &params[0];
msg->event_type = ui::AX_EVENT_CHILDREN_CHANGED;
msg->nodes.push_back(tree2_1);
msg->nodes.push_back(tree2_4);
msg->nodes.push_back(tree2_5);
msg->nodes.push_back(tree2_6);
msg->update.nodes.push_back(tree2_1);
msg->update.nodes.push_back(tree2_4);
msg->update.nodes.push_back(tree2_5);
msg->update.nodes.push_back(tree2_6);
msg->id = tree2_1.id;
manager->OnAccessibilityEvents(params);
......
......@@ -235,7 +235,7 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChange) {
text2.SetName("old text");
AccessibilityHostMsg_EventParams param;
param.event_type = ui::AX_EVENT_CHILDREN_CHANGED;
param.nodes.push_back(text2);
param.update.nodes.push_back(text2);
param.id = text2.id;
std::vector<AccessibilityHostMsg_EventParams> events;
events.push_back(param);
......@@ -307,7 +307,7 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChangeNoLeaks) {
root.child_ids.clear();
AccessibilityHostMsg_EventParams param;
param.event_type = ui::AX_EVENT_CHILDREN_CHANGED;
param.nodes.push_back(root);
param.update.nodes.push_back(root);
param.id = root.id;
std::vector<AccessibilityHostMsg_EventParams> events;
events.push_back(param);
......@@ -637,8 +637,8 @@ TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
params.push_back(AccessibilityHostMsg_EventParams());
AccessibilityHostMsg_EventParams* msg = &params[0];
msg->event_type = ui::AX_EVENT_LOAD_COMPLETE;
msg->nodes.push_back(tree1_1);
msg->nodes.push_back(tree1_2);
msg->update.nodes.push_back(tree1_1);
msg->update.nodes.push_back(tree1_2);
msg->id = tree1_1.id;
manager->OnAccessibilityEvents(params);
......@@ -662,9 +662,9 @@ TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
tree2_2.id = 3;
tree2_2.role = ui::AX_ROLE_BUTTON;
msg->nodes.clear();
msg->nodes.push_back(tree2_1);
msg->nodes.push_back(tree2_2);
msg->update.nodes.clear();
msg->update.nodes.push_back(tree2_1);
msg->update.nodes.push_back(tree2_2);
msg->id = tree2_1.id;
// Fire another load complete.
......
......@@ -1728,7 +1728,7 @@ void RenderViewHostImpl::OnAccessibilityEvents(
for (unsigned int i = 0; i < params.size(); ++i) {
const AccessibilityHostMsg_EventParams& param = params[i];
AXEventNotificationDetails detail(
param.nodes, param.event_type, param.id, GetRoutingID());
param.update.nodes, param.event_type, param.id, GetRoutingID());
details.push_back(detail);
}
......@@ -1747,12 +1747,10 @@ void RenderViewHostImpl::OnAccessibilityEvents(
const AccessibilityHostMsg_EventParams& param = params[i];
if (static_cast<int>(param.event_type) < 0)
continue;
ui::AXTreeUpdate update;
update.nodes = param.nodes;
if (!ax_tree_)
ax_tree_.reset(new ui::AXTree(update));
ax_tree_.reset(new ui::AXTree(param.update));
else
CHECK(ax_tree_->Unserialize(update)) << ax_tree_->error();
CHECK(ax_tree_->Unserialize(param.update)) << ax_tree_->error();
accessibility_testing_callback_.Run(param.event_type);
}
}
......
......@@ -15,6 +15,7 @@
#include "ipc/param_traits_macros.h"
#include "third_party/WebKit/public/web/WebAXEnums.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_tree_update.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
......@@ -45,10 +46,14 @@ IPC_STRUCT_TRAITS_BEGIN(ui::AXNodeData)
IPC_STRUCT_TRAITS_MEMBER(child_ids)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(ui::AXTreeUpdate)
IPC_STRUCT_TRAITS_MEMBER(node_id_to_clear)
IPC_STRUCT_TRAITS_MEMBER(nodes)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_BEGIN(AccessibilityHostMsg_EventParams)
// Vector of nodes in the tree that need to be updated before
// sending the event.
IPC_STRUCT_MEMBER(std::vector<ui::AXNodeData>, nodes)
// The tree update.
IPC_STRUCT_MEMBER(ui::AXTreeUpdate, update)
// Type of event.
IPC_STRUCT_MEMBER(ui::AXEvent, event_type)
......
......@@ -65,10 +65,10 @@
'public/renderer/video_encode_accelerator.cc',
'public/renderer/video_encode_accelerator.h',
'public/renderer/web_preferences.h',
'renderer/accessibility/accessibility_node_serializer.cc',
'renderer/accessibility/accessibility_node_serializer.h',
'renderer/accessibility/blink_ax_enum_conversion.cc',
'renderer/accessibility/blink_ax_enum_conversion.h',
'renderer/accessibility/blink_ax_tree_source.cc',
'renderer/accessibility/blink_ax_tree_source.h',
'renderer/accessibility/renderer_accessibility.cc',
'renderer/accessibility/renderer_accessibility.h',
'renderer/accessibility/renderer_accessibility_complete.cc',
......
// Copyright 2014 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.
#ifndef CONTENT_RENDERER_ACCESSIBILITY_ACCESSIBILITY_NODE_SERIALIZER_H_
#define CONTENT_RENDERER_ACCESSIBILITY_ACCESSIBILITY_NODE_SERIALIZER_H_
#include "third_party/WebKit/public/web/WebAXObject.h"
#include "ui/accessibility/ax_node_data.h"
namespace content {
void SerializeAccessibilityNode(
const blink::WebAXObject& src,
ui::AXNodeData* dst);
bool ShouldIncludeChildNode(
const blink::WebAXObject& parent,
const blink::WebAXObject& child);
} // namespace content
#endif // CONTENT_RENDERER_ACCESSIBILITY_ACCESSIBILITY_NODE_SERIALIZER_H_
// Copyright 2014 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.
#ifndef CONTENT_RENDERER_ACCESSIBILITY_BLINK_AX_TREE_SOURCE_H_
#define CONTENT_RENDERER_ACCESSIBILITY_BLINK_AX_TREE_SOURCE_H_
#include "third_party/WebKit/public/web/WebAXObject.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_tree_source.h"
namespace content {
class RenderViewImpl;
class BlinkAXTreeSource
: public ui::AXTreeSource<blink::WebAXObject> {
public:
BlinkAXTreeSource(RenderViewImpl* render_view);
virtual ~BlinkAXTreeSource();
// AXTreeSource implementation.
virtual blink::WebAXObject GetRoot() const OVERRIDE;
virtual blink::WebAXObject GetFromId(int32 id) const OVERRIDE;
virtual int32 GetId(blink::WebAXObject node) const OVERRIDE;
virtual void GetChildren(
blink::WebAXObject node,
std::vector<blink::WebAXObject>* out_children) const OVERRIDE;
virtual blink::WebAXObject GetParent(blink::WebAXObject node) const
OVERRIDE;
virtual void SerializeNode(blink::WebAXObject node,
ui::AXNodeData* out_data) const OVERRIDE;
virtual bool IsValid(blink::WebAXObject node) const OVERRIDE;
virtual bool IsEqual(blink::WebAXObject node1,
blink::WebAXObject node2) const OVERRIDE;
virtual blink::WebAXObject GetNull() const OVERRIDE;
blink::WebDocument GetMainDocument() const;
private:
RenderViewImpl* render_view_;
};
} // namespace content
#endif // CONTENT_RENDERER_ACCESSIBILITY_BLINK_AX_TREE_SOURCE_H_
......@@ -11,10 +11,12 @@
#include "base/containers/hash_tables.h"
#include "base/memory/weak_ptr.h"
#include "content/public/renderer/render_view_observer.h"
#include "content/renderer/accessibility/blink_ax_tree_source.h"
#include "content/renderer/accessibility/renderer_accessibility.h"
#include "third_party/WebKit/public/web/WebAXEnums.h"
#include "third_party/WebKit/public/web/WebAXObject.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_tree_serializer.h"
namespace blink {
class WebDocument;
......@@ -50,20 +52,6 @@ class CONTENT_EXPORT RendererAccessibilityComplete
void HandleAXEvent(const blink::WebAXObject& obj, ui::AXEvent event);
// In order to keep track of what nodes the browser knows about, we keep a
// representation of the browser tree - just IDs and parent/child
// relationships.
struct CONTENT_EXPORT BrowserTreeNode {
BrowserTreeNode();
virtual ~BrowserTreeNode();
int32 id;
gfx::Rect location;
BrowserTreeNode* parent;
std::vector<BrowserTreeNode*> children;
};
virtual BrowserTreeNode* CreateBrowserTreeNode();
protected:
// Send queued events from the renderer to the browser.
void SendPendingAccessibilityEvents();
......@@ -74,19 +62,6 @@ class CONTENT_EXPORT RendererAccessibilityComplete
void SendLocationChanges();
private:
// Serialize the given accessibility object |obj| and append it to
// |dst|, and then recursively also serialize any *new* children of
// |obj|, based on what object ids we know the browser already has.
// The set of ids serialized is added to |ids_serialized|, and any
// ids previously in that set are not serialized again.
void SerializeChangedNodes(const blink::WebAXObject& obj,
std::vector<ui::AXNodeData>* dst,
std::set<int>* ids_serialized);
// Clear the given node and recursively delete all of its descendants
// from the browser tree. (Does not delete |browser_node|).
void ClearBrowserTreeNode(BrowserTreeNode* browser_node);
// Handlers for messages from the browser to the renderer.
void OnDoDefaultAction(int acc_obj_id);
void OnEventsAck();
......@@ -107,13 +82,6 @@ class CONTENT_EXPORT RendererAccessibilityComplete
const blink::WebAXObject& src,
ui::AXNodeData* dst);
// Build a tree of serializable ui::AXNodeData nodes to send to the
// browser process, given a WebAXObject node from Blink.
// Modifies |dst| in-place, it's assumed to be empty.
void BuildAccessibilityTree(const blink::WebAXObject& src,
bool include_children,
ui::AXNodeData* dst);
// So we can queue up tasks to be executed later.
base::WeakPtrFactory<RendererAccessibilityComplete> weak_factory_;
......@@ -121,11 +89,14 @@ class CONTENT_EXPORT RendererAccessibilityComplete
// sent to the browser.
std::vector<AccessibilityHostMsg_EventParams> pending_events_;
// Our representation of the browser tree.
BrowserTreeNode* browser_root_;
// The adapter that exposes Blink's accessibility tree to AXTreeSerializer.
BlinkAXTreeSource tree_source_;
// The serializer that sends accessibility messages to the browser process.
ui::AXTreeSerializer<blink::WebAXObject> serializer_;
// A map from IDs to nodes in the browser tree.
base::hash_map<int32, BrowserTreeNode*> browser_id_map_;
// Current location of every object, so we can detect when it moves.
base::hash_map<int, gfx::Rect> locations_;
// The most recently observed scroll offset of the root document element.
// TODO(dmazzoni): remove once https://bugs.webkit.org/show_bug.cgi?id=73460
......
......@@ -97,9 +97,9 @@ void RendererAccessibilityFocusOnly::HandleFocusedNodeChanged(
// has focus, otherwise the focused node.
event.id = node_has_focus ? next_id_ : 1;
event.nodes.resize(2);
ui::AXNodeData& root = event.nodes[0];
ui::AXNodeData& child = event.nodes[1];
event.update.nodes.resize(2);
ui::AXNodeData& root = event.update.nodes[0];
ui::AXNodeData& child = event.update.nodes[1];
// Always include the root of the tree, the document. It always has id 1.
root.id = 1;
......
......@@ -172,10 +172,13 @@ AXTreeSerializer<AXSourceNode>::~AXTreeSerializer() {
template<typename AXSourceNode>
void AXTreeSerializer<AXSourceNode>::Reset() {
if (client_root_) {
DeleteClientSubtree(client_root_);
client_root_ = NULL;
}
if (!client_root_)
return;
DeleteClientSubtree(client_root_);
client_id_map_.erase(client_root_->id);
delete client_root_;
client_root_ = NULL;
}
template<typename AXSourceNode>
......@@ -305,9 +308,7 @@ void AXTreeSerializer<AXSourceNode>::SerializeChanges(
// If there's no LCA, just tell the client to destroy the whole
// tree and then we'll serialize everything from the new root.
out_update->node_id_to_clear = client_root_->id;
DeleteClientSubtree(client_root_);
client_id_map_.erase(client_root_->id);
client_root_ = NULL;
Reset();
} else if (need_delete) {
// Otherwise, if we need to reserialize a subtree, first we need
// to delete those nodes in our client tree so that
......@@ -318,6 +319,7 @@ void AXTreeSerializer<AXSourceNode>::SerializeChanges(
for (size_t i = 0; i < client_lca->children.size(); ++i) {
client_id_map_.erase(client_lca->children[i]->id);
DeleteClientSubtree(client_lca->children[i]);
delete client_lca->children[i];
}
client_lca->children.clear();
}
......@@ -342,6 +344,7 @@ void AXTreeSerializer<AXSourceNode>::DeleteClientSubtree(
for (size_t i = 0; i < client_node->children.size(); ++i) {
client_id_map_.erase(client_node->children[i]->id);
DeleteClientSubtree(client_node->children[i]);
delete client_node->children[i];
}
client_node->children.clear();
}
......@@ -365,10 +368,7 @@ void AXTreeSerializer<AXSourceNode>::SerializeChangedNodes(
int id = tree_->GetId(node);
ClientTreeNode* client_node = ClientTreeNodeById(id);
if (!client_node) {
if (client_root_) {
client_id_map_.erase(client_root_->id);
DeleteClientSubtree(client_root_);
}
Reset();
client_root_ = new ClientTreeNode();
client_node = client_root_;
client_node->id = id;
......@@ -408,6 +408,7 @@ void AXTreeSerializer<AXSourceNode>::SerializeChangedNodes(
if (new_child_ids.find(old_child_id) == new_child_ids.end()) {
client_id_map_.erase(old_child_id);
DeleteClientSubtree(old_child);
delete old_child;
} else {
client_child_id_map[old_child_id] = old_child;
}
......
......@@ -20,7 +20,7 @@ namespace ui {
// an accessibility tree will be sent over an IPC before being
// consumed.
template<typename AXNodeSource>
class AX_EXPORT AXTreeSource {
class AXTreeSource {
public:
virtual ~AXTreeSource() {}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment