summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authordmazzoni <dmazzoni@chromium.org>2015-08-06 18:02:15 -0700
committerCommit bot <commit-bot@chromium.org>2015-08-07 01:03:09 +0000
commit1efe8793da85ee6e25185175047c077adfe8e55c (patch)
tree3da8b088c3c997fca1d8b4e652819f8db1e415d9 /content
parentf54108dd9aa8b43982c206442664cb325cd792d7 (diff)
downloadchromium_src-1efe8793da85ee6e25185175047c077adfe8e55c.zip
chromium_src-1efe8793da85ee6e25185175047c077adfe8e55c.tar.gz
chromium_src-1efe8793da85ee6e25185175047c077adfe8e55c.tar.bz2
Get rid of FrameAccessibility using AXTreeIDs
Depends on: https://codereview.chromium.org/1257093005/ Instead of keeping track of the relationship between frames in FrameAccessibility, create a subclass of AXNodeData that's only allowed to be used within the content module, and once an AX tree is received in the browser process, convert routing IDs to global AXTreeIDs that can be stored AXNodeData. BUG=368298 Review URL: https://codereview.chromium.org/1267663002 Cr-Commit-Position: refs/heads/master@{#342251}
Diffstat (limited to 'content')
-rw-r--r--content/browser/accessibility/accessibility_ipc_error_browsertest.cc6
-rw-r--r--content/browser/accessibility/ax_tree_id_registry.cc61
-rw-r--r--content/browser/accessibility/ax_tree_id_registry.h55
-rw-r--r--content/browser/accessibility/browser_accessibility.cc41
-rw-r--r--content/browser/accessibility/browser_accessibility.h5
-rw-r--r--content/browser/accessibility/browser_accessibility_auralinux.cc5
-rw-r--r--content/browser/accessibility/browser_accessibility_manager.cc120
-rw-r--r--content/browser/accessibility/browser_accessibility_manager.h24
-rw-r--r--content/browser/accessibility/browser_accessibility_manager_unittest.cc45
-rw-r--r--content/browser/accessibility/browser_accessibility_manager_win.cc46
-rw-r--r--content/browser/accessibility/browser_accessibility_manager_win.h4
-rw-r--r--content/browser/accessibility/browser_accessibility_win_unittest.cc16
-rw-r--r--content/browser/accessibility/site_per_process_accessibility_browsertest.cc33
-rw-r--r--content/browser/frame_host/frame_accessibility.cc229
-rw-r--r--content/browser/frame_host/frame_accessibility.h106
-rw-r--r--content/browser/frame_host/render_frame_host_impl.cc283
-rw-r--r--content/browser/frame_host/render_frame_host_impl.h36
-rw-r--r--content/common/accessibility_messages.h45
-rw-r--r--content/common/ax_content_node_data.cc93
-rw-r--r--content/common/ax_content_node_data.h51
-rw-r--r--content/content_browser.gypi4
-rw-r--r--content/content_common.gypi2
-rw-r--r--content/public/browser/ax_event_notification_details.cc20
-rw-r--r--content/public/browser/ax_event_notification_details.h20
-rw-r--r--content/public/browser/render_frame_host.h6
-rw-r--r--content/public/common/common_param_traits_macros.h20
-rw-r--r--content/renderer/accessibility/blink_ax_tree_source.cc57
-rw-r--r--content/renderer/accessibility/blink_ax_tree_source.h15
-rw-r--r--content/renderer/accessibility/renderer_accessibility.cc6
-rw-r--r--content/renderer/accessibility/renderer_accessibility.h8
-rw-r--r--content/renderer/accessibility/renderer_accessibility_browsertest.cc1
-rw-r--r--content/renderer/render_frame_impl.cc3
-rw-r--r--content/test/accessibility_browser_test_utils.cc7
-rw-r--r--content/test/accessibility_browser_test_utils.h2
34 files changed, 731 insertions, 744 deletions
diff --git a/content/browser/accessibility/accessibility_ipc_error_browsertest.cc b/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
index 7ff3d27..6c47f94 100644
--- a/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
+++ b/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
@@ -4,7 +4,7 @@
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/common/accessibility_messages.h"
+#include "content/public/browser/ax_event_notification_details.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
@@ -153,8 +153,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
// Construct a bad accessibility message that BrowserAccessibilityManager
// will reject.
- std::vector<AccessibilityHostMsg_EventParams> bad_accessibility_event_list;
- bad_accessibility_event_list.push_back(AccessibilityHostMsg_EventParams());
+ std::vector<AXEventNotificationDetails> bad_accessibility_event_list;
+ bad_accessibility_event_list.push_back(AXEventNotificationDetails());
bad_accessibility_event_list[0].update.node_id_to_clear = -2;
// We should be able to reset accessibility |max_iterations-1| times
diff --git a/content/browser/accessibility/ax_tree_id_registry.cc b/content/browser/accessibility/ax_tree_id_registry.cc
new file mode 100644
index 0000000..5973cbf
--- /dev/null
+++ b/content/browser/accessibility/ax_tree_id_registry.cc
@@ -0,0 +1,61 @@
+// 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.
+
+#include "content/browser/accessibility/ax_tree_id_registry.h"
+
+#include "base/memory/singleton.h"
+
+namespace content {
+
+// static
+const AXTreeIDRegistry::AXTreeID AXTreeIDRegistry::kNoAXTreeID = -1;
+
+// static
+AXTreeIDRegistry* AXTreeIDRegistry::GetInstance() {
+ return Singleton<AXTreeIDRegistry>::get();
+}
+
+AXTreeIDRegistry::AXTreeID AXTreeIDRegistry::GetOrCreateAXTreeID(
+ int process_id, int routing_id) {
+ FrameID frame_id(process_id, routing_id);
+ std::map<FrameID, AXTreeID>::iterator it;
+ it = frame_to_ax_tree_id_map_.find(frame_id);
+ if (it != frame_to_ax_tree_id_map_.end())
+ return it->second;
+
+ AXTreeID new_id = ++ax_tree_id_counter_;
+ frame_to_ax_tree_id_map_[frame_id] = new_id;
+ ax_tree_to_frame_id_map_[new_id] = frame_id;
+
+ return new_id;
+}
+
+AXTreeIDRegistry::FrameID AXTreeIDRegistry::GetFrameID(
+ AXTreeIDRegistry::AXTreeID ax_tree_id) {
+ std::map<AXTreeID, FrameID>::iterator it;
+ it = ax_tree_to_frame_id_map_.find(ax_tree_id);
+ if (it != ax_tree_to_frame_id_map_.end())
+ return it->second;
+
+ return FrameID(-1, -1);
+}
+
+void AXTreeIDRegistry::RemoveAXTreeID(AXTreeIDRegistry::AXTreeID ax_tree_id) {
+ std::map<AXTreeID, FrameID>::iterator it;
+ it = ax_tree_to_frame_id_map_.find(ax_tree_id);
+ if (it != ax_tree_to_frame_id_map_.end()) {
+ frame_to_ax_tree_id_map_.erase(it->second);
+ ax_tree_to_frame_id_map_.erase(it);
+ }
+}
+
+AXTreeIDRegistry::AXTreeIDRegistry() : ax_tree_id_counter_(-1) {
+ // Always populate default desktop tree value (0 -> 0, 0).
+ GetOrCreateAXTreeID(0, 0);
+}
+
+AXTreeIDRegistry::~AXTreeIDRegistry() {
+}
+
+} // namespace content
diff --git a/content/browser/accessibility/ax_tree_id_registry.h b/content/browser/accessibility/ax_tree_id_registry.h
new file mode 100644
index 0000000..e3ffca9
--- /dev/null
+++ b/content/browser/accessibility/ax_tree_id_registry.h
@@ -0,0 +1,55 @@
+// 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_BROWSER_ACCESSIBILITY_AX_TREE_ID_REGISTRY_H_
+#define CONTENT_BROWSER_ACCESSIBILITY_AX_TREE_ID_REGISTRY_H_
+
+#include <map>
+
+#include "base/stl_util.h"
+
+template <typename T>
+struct DefaultSingletonTraits;
+
+namespace content {
+
+// A class which generates a unique id given a process id and frame routing id.
+class AXTreeIDRegistry {
+ public:
+ typedef std::pair<int, int> FrameID;
+
+ typedef int AXTreeID;
+
+ static const AXTreeID kNoAXTreeID;
+
+ // Get the single instance of this class.
+ static AXTreeIDRegistry* GetInstance();
+
+ // Obtains a unique id given a |process_id| and |routing_id|. Placeholder
+ // for full implementation once out of process iframe accessibility finalizes.
+ AXTreeID GetOrCreateAXTreeID(int process_id, int routing_id);
+ FrameID GetFrameID(AXTreeID ax_tree_id);
+ void RemoveAXTreeID(AXTreeID ax_tree_id);
+
+ private:
+ friend struct DefaultSingletonTraits<AXTreeIDRegistry>;
+
+ AXTreeIDRegistry();
+ virtual ~AXTreeIDRegistry();
+
+ // Tracks the current unique ax frame id.
+ AXTreeID ax_tree_id_counter_;
+
+ // Maps an accessibility tree to its frame via ids.
+ std::map<AXTreeID, FrameID> ax_tree_to_frame_id_map_;
+
+ // Maps frames to an accessibility tree via ids.
+ std::map<FrameID, AXTreeID> frame_to_ax_tree_id_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(AXTreeIDRegistry);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ACCESSIBILITY_AX_TREE_ID_REGISTRY_H_
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc
index f3cf377..6b32ef2 100644
--- a/content/browser/accessibility/browser_accessibility.cc
+++ b/content/browser/accessibility/browser_accessibility.cc
@@ -61,9 +61,11 @@ bool BrowserAccessibility::PlatformIsLeaf() const {
}
uint32 BrowserAccessibility::PlatformChildCount() const {
- if (GetBoolAttribute(ui::AX_ATTR_IS_AX_TREE_HOST)) {
- // Check if the child frame currently exists.
- if (manager_->delegate()->AccessibilityGetChildFrame(GetId()))
+ if (HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)) {
+ BrowserAccessibilityManager* child_manager =
+ BrowserAccessibilityManager::FromID(
+ GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID));
+ if (child_manager)
return 1;
return 0;
@@ -92,9 +94,10 @@ BrowserAccessibility* BrowserAccessibility::PlatformGetChild(
DCHECK(child_index < PlatformChildCount());
BrowserAccessibility* result = nullptr;
- if (GetBoolAttribute(ui::AX_ATTR_IS_AX_TREE_HOST)) {
+ if (HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)) {
BrowserAccessibilityManager* child_manager =
- manager_->delegate()->AccessibilityGetChildFrame(GetId());
+ BrowserAccessibilityManager::FromID(
+ GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID));
if (child_manager)
result = child_manager->GetRoot();
} else {
@@ -153,15 +156,7 @@ BrowserAccessibility* BrowserAccessibility::GetParent() const {
if (parent)
return manager_->GetFromAXNode(parent);
- if (!manager_->delegate())
- return NULL;
-
- BrowserAccessibility* host_node =
- manager_->delegate()->AccessibilityGetParentFrame();
- if (!host_node)
- return NULL;
-
- return host_node;
+ return manager_->GetParentNodeFromParentTree();
}
int32 BrowserAccessibility::GetIndexInParent() const {
@@ -693,20 +688,6 @@ int BrowserAccessibility::GetStaticTextLenRecursive() const {
return len;
}
-BrowserAccessibility* BrowserAccessibility::GetParentForBoundsCalculation()
- const {
- if (!node_ || !manager_)
- return NULL;
- ui::AXNode* parent = node_->parent();
- if (parent)
- return manager_->GetFromAXNode(parent);
-
- if (!manager_->delegate())
- return NULL;
-
- return manager_->delegate()->AccessibilityGetParentFrame();
-}
-
void BrowserAccessibility::FixEmptyBounds(gfx::Rect* bounds) const
{
if (bounds->width() > 0 && bounds->height() > 0)
@@ -738,7 +719,7 @@ gfx::Rect BrowserAccessibility::ElementBoundsToLocalBounds(gfx::Rect bounds)
// Walk up the parent chain. Every time we encounter a Web Area, offset
// based on the scroll bars and then offset based on the origin of that
// nested web area.
- BrowserAccessibility* parent = GetParentForBoundsCalculation();
+ BrowserAccessibility* parent = GetParent();
bool need_to_offset_web_area =
(GetRole() == ui::AX_ROLE_WEB_AREA ||
GetRole() == ui::AX_ROLE_ROOT_WEB_AREA);
@@ -767,7 +748,7 @@ gfx::Rect BrowserAccessibility::ElementBoundsToLocalBounds(gfx::Rect bounds)
}
need_to_offset_web_area = true;
}
- parent = parent->GetParentForBoundsCalculation();
+ parent = parent->GetParent();
}
return bounds;
diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h
index 17297ba..679becf 100644
--- a/content/browser/accessibility/browser_accessibility.h
+++ b/content/browser/accessibility/browser_accessibility.h
@@ -282,11 +282,6 @@ class CONTENT_EXPORT BrowserAccessibility {
// including this object if it's static text.
int GetStaticTextLenRecursive() const;
- // Similar to GetParent(), but includes nodes that are the host of a
- // subtree rather than skipping over them - because they contain important
- // bounds offsets.
- BrowserAccessibility* GetParentForBoundsCalculation() const;
-
// If a bounding rectangle is empty, compute it based on the union of its
// children, since most accessibility APIs don't like elements with no
// bounds, but "virtual" elements in the accessibility tree that don't
diff --git a/content/browser/accessibility/browser_accessibility_auralinux.cc b/content/browser/accessibility/browser_accessibility_auralinux.cc
index c754880..9fb8e4b 100644
--- a/content/browser/accessibility/browser_accessibility_auralinux.cc
+++ b/content/browser/accessibility/browser_accessibility_auralinux.cc
@@ -763,6 +763,11 @@ void BrowserAccessibilityAuraLinux::OnDataChanged() {
if (!atk_object_) {
interface_mask_ = GetInterfaceMaskFromObject(this);
atk_object_ = ATK_OBJECT(browser_accessibility_new(this));
+ if (this->GetParent()) {
+ atk_object_set_parent(
+ atk_object_,
+ this->GetParent()->ToBrowserAccessibilityAuraLinux()->GetAtkObject());
+ }
}
}
diff --git a/content/browser/accessibility/browser_accessibility_manager.cc b/content/browser/accessibility/browser_accessibility_manager.cc
index f20cce9..4ccca0e 100644
--- a/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/content/browser/accessibility/browser_accessibility_manager.cc
@@ -11,6 +11,35 @@
namespace content {
+namespace {
+
+// Search the tree recursively from |node| and return any node that has
+// a child tree ID of |ax_tree_id|.
+BrowserAccessibility* FindNodeWithChildTreeId(BrowserAccessibility* node,
+ int ax_tree_id) {
+ if (!node)
+ return nullptr;
+
+ if (node->GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID) == ax_tree_id)
+ return node;
+
+ for (unsigned int i = 0; i < node->InternalChildCount(); ++i) {
+ BrowserAccessibility* child = node->InternalGetChild(i);
+ BrowserAccessibility* result = FindNodeWithChildTreeId(child, ax_tree_id);
+ if (result)
+ return result;
+ }
+
+ return nullptr;
+}
+
+} // namespace
+
+// Map from AXTreeID to BrowserAccessibilityManager
+using AXTreeIDMap =
+ base::hash_map<AXTreeIDRegistry::AXTreeID, BrowserAccessibilityManager*>;
+base::LazyInstance<AXTreeIDMap> g_ax_tree_id_map = LAZY_INSTANCE_INITIALIZER;
+
SimpleAXTreeUpdate MakeAXTreeUpdate(
const ui::AXNodeData& node1,
const ui::AXNodeData& node2 /* = ui::AXNodeData() */,
@@ -73,6 +102,14 @@ BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
}
#endif
+// static
+BrowserAccessibilityManager* BrowserAccessibilityManager::FromID(
+ AXTreeIDRegistry::AXTreeID ax_tree_id) {
+ AXTreeIDMap* ax_tree_id_map = g_ax_tree_id_map.Pointer();
+ auto iter = ax_tree_id_map->find(ax_tree_id);
+ return iter == ax_tree_id_map->end() ? nullptr : iter->second;
+}
+
BrowserAccessibilityManager::BrowserAccessibilityManager(
BrowserAccessibilityDelegate* delegate,
BrowserAccessibilityFactory* factory)
@@ -81,7 +118,9 @@ BrowserAccessibilityManager::BrowserAccessibilityManager(
tree_(new ui::AXSerializableTree()),
focus_(NULL),
user_is_navigating_away_(false),
- osk_state_(OSK_ALLOWED) {
+ osk_state_(OSK_ALLOWED),
+ ax_tree_id_(AXTreeIDRegistry::kNoAXTreeID),
+ parent_node_id_from_parent_tree_(0) {
tree_->SetDelegate(this);
}
@@ -148,6 +187,41 @@ BrowserAccessibility* BrowserAccessibilityManager::GetFromID(int32 id) {
return NULL;
}
+BrowserAccessibility*
+BrowserAccessibilityManager::GetParentNodeFromParentTree() {
+ if (!GetRoot())
+ return nullptr;
+
+ int parent_tree_id = GetRoot()->GetIntAttribute(ui::AX_ATTR_PARENT_TREE_ID);
+ BrowserAccessibilityManager* parent_manager =
+ BrowserAccessibilityManager::FromID(parent_tree_id);
+ if (!parent_manager)
+ return nullptr;
+
+ // Try to use the cached parent node from the most recent time this
+ // was called.
+ if (parent_node_id_from_parent_tree_) {
+ BrowserAccessibility* parent_node = parent_manager->GetFromID(
+ parent_node_id_from_parent_tree_);
+ if (parent_node) {
+ int parent_child_tree_id =
+ parent_node->GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID);
+ if (parent_child_tree_id == ax_tree_id_)
+ return parent_node;
+ }
+ }
+
+ // If that fails, search for it and cache it for next time.
+ BrowserAccessibility* parent_node = FindNodeWithChildTreeId(
+ parent_manager->GetRoot(), ax_tree_id_);
+ if (parent_node) {
+ parent_node_id_from_parent_tree_ = parent_node->GetId();
+ return parent_node;
+ }
+
+ return nullptr;
+}
+
void BrowserAccessibilityManager::OnWindowFocused() {
if (focus_)
NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, GetFromAXNode(focus_));
@@ -184,13 +258,13 @@ bool BrowserAccessibilityManager::UseRootScrollOffsetsWhenComputingBounds() {
}
void BrowserAccessibilityManager::OnAccessibilityEvents(
- const std::vector<AccessibilityHostMsg_EventParams>& params) {
+ const std::vector<AXEventNotificationDetails>& details) {
bool should_send_initial_focus = false;
// Process all changes to the accessibility tree first.
- for (uint32 index = 0; index < params.size(); index++) {
- const AccessibilityHostMsg_EventParams& param = params[index];
- if (!tree_->Unserialize(param.update)) {
+ for (uint32 index = 0; index < details.size(); ++index) {
+ const AXEventNotificationDetails& detail = details[index];
+ if (!tree_->Unserialize(detail.update)) {
if (delegate_) {
LOG(ERROR) << tree_->error();
delegate_->AccessibilityFatalError();
@@ -213,16 +287,16 @@ void BrowserAccessibilityManager::OnAccessibilityEvents(
}
// Now iterate over the events again and fire the events.
- for (uint32 index = 0; index < params.size(); index++) {
- const AccessibilityHostMsg_EventParams& param = params[index];
+ for (uint32 index = 0; index < details.size(); index++) {
+ const AXEventNotificationDetails& detail = details[index];
// Find the node corresponding to the id that's the target of the
// event (which may not be the root of the update tree).
- ui::AXNode* node = tree_->GetFromId(param.id);
+ ui::AXNode* node = tree_->GetFromId(detail.id);
if (!node)
continue;
- ui::AXEvent event_type = param.event_type;
+ ui::AXEvent event_type = detail.event_type;
if (event_type == ui::AX_EVENT_FOCUS ||
event_type == ui::AX_EVENT_BLUR) {
SetFocus(node, false);
@@ -317,9 +391,10 @@ BrowserAccessibility* BrowserAccessibilityManager::GetFocus(
return NULL;
BrowserAccessibility* obj = GetFromAXNode(focus_);
- if (delegate() && obj->HasBoolAttribute(ui::AX_ATTR_IS_AX_TREE_HOST)) {
+ if (obj->HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)) {
BrowserAccessibilityManager* child_manager =
- delegate()->AccessibilityGetChildFrame(obj->GetId());
+ BrowserAccessibilityManager::FromID(
+ obj->GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID));
if (child_manager)
return child_manager->GetFocus(child_manager->GetRoot());
}
@@ -464,19 +539,24 @@ void BrowserAccessibilityManager::OnAtomicUpdateFinished(
ui::AXTree* tree,
bool root_changed,
const std::vector<ui::AXTreeDelegate::Change>& changes) {
+ if (GetRoot()->HasIntAttribute(ui::AX_ATTR_TREE_ID) &&
+ GetRoot()->GetIntAttribute(ui::AX_ATTR_TREE_ID) != ax_tree_id_) {
+ g_ax_tree_id_map.Get().erase(ax_tree_id_);
+ ax_tree_id_ = GetRoot()->GetIntAttribute(ui::AX_ATTR_TREE_ID);
+ g_ax_tree_id_map.Get().insert(std::make_pair(ax_tree_id_, this));
+ }
}
BrowserAccessibilityDelegate*
BrowserAccessibilityManager::GetDelegateFromRootManager() {
- BrowserAccessibilityManager* manager = this;
- while (manager->delegate()) {
- BrowserAccessibility* host_node_in_parent_frame =
- manager->delegate()->AccessibilityGetParentFrame();
- if (!host_node_in_parent_frame)
- break;
- manager = host_node_in_parent_frame->manager();
- }
- return manager->delegate();
+ if (!GetRoot())
+ return nullptr;
+ int parent_tree_id = GetRoot()->GetIntAttribute(ui::AX_ATTR_PARENT_TREE_ID);
+ BrowserAccessibilityManager* parent_manager =
+ BrowserAccessibilityManager::FromID(parent_tree_id);
+ if (parent_manager)
+ return parent_manager->GetDelegateFromRootManager();
+ return delegate();
}
SimpleAXTreeUpdate
diff --git a/content/browser/accessibility/browser_accessibility_manager.h b/content/browser/accessibility/browser_accessibility_manager.h
index e04d757..865b51f 100644
--- a/content/browser/accessibility/browser_accessibility_manager.h
+++ b/content/browser/accessibility/browser_accessibility_manager.h
@@ -10,14 +10,15 @@
#include "base/containers/hash_tables.h"
#include "base/memory/scoped_ptr.h"
#include "build/build_config.h"
+#include "content/browser/accessibility/ax_tree_id_registry.h"
#include "content/common/content_export.h"
+#include "content/public/browser/ax_event_notification_details.h"
#include "third_party/WebKit/public/web/WebAXEnums.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_serializable_tree.h"
#include "ui/accessibility/ax_tree_update.h"
#include "ui/gfx/native_widget_types.h"
-struct AccessibilityHostMsg_EventParams;
struct AccessibilityHostMsg_LocationChangeParams;
namespace content {
@@ -78,11 +79,6 @@ class CONTENT_EXPORT BrowserAccessibilityDelegate {
virtual void AccessibilityFatalError() = 0;
virtual gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget() = 0;
virtual gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() = 0;
- virtual BrowserAccessibilityManager* AccessibilityGetChildFrame(
- int accessibility_node_id) = 0;
- virtual void AccessibilityGetAllChildFrames(
- std::vector<BrowserAccessibilityManager*>* child_frames) = 0;
- virtual BrowserAccessibility* AccessibilityGetParentFrame() = 0;
};
class CONTENT_EXPORT BrowserAccessibilityFactory {
@@ -124,6 +120,9 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
BrowserAccessibilityDelegate* delegate,
BrowserAccessibilityFactory* factory = new BrowserAccessibilityFactory());
+ static BrowserAccessibilityManager* FromID(
+ AXTreeIDRegistry::AXTreeID ax_tree_id);
+
~BrowserAccessibilityManager() override;
void Initialize(const SimpleAXTreeUpdate& initial_tree);
@@ -143,6 +142,9 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
// does not make a new reference.
BrowserAccessibility* GetFromID(int32 id);
+ // If this tree has a parent tree, return the parent node in that tree.
+ BrowserAccessibility* GetParentNodeFromParentTree();
+
// Called to notify the accessibility manager that its associated native
// view got focused.
virtual void OnWindowFocused();
@@ -203,7 +205,7 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
// Called when the renderer process has notified us of about tree changes.
void OnAccessibilityEvents(
- const std::vector<AccessibilityHostMsg_EventParams>& params);
+ const std::vector<AXEventNotificationDetails>& details);
// Called when the renderer process updates the location of accessibility
// objects.
@@ -333,6 +335,14 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
BrowserAccessibilityFindInPageInfo find_in_page_info_;
+ // The global ID of this accessibility tree.
+ AXTreeIDRegistry::AXTreeID ax_tree_id_;
+
+ // If this tree has a parent tree, this is the cached ID of the parent
+ // node within that parent tree. It's computed as needed and cached for
+ // speed so that it can be accessed quickly if it hasn't changed.
+ int parent_node_id_from_parent_tree_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityManager);
};
diff --git a/content/browser/accessibility/browser_accessibility_manager_unittest.cc b/content/browser/accessibility/browser_accessibility_manager_unittest.cc
index a5f89ff..1be3c64 100644
--- a/content/browser/accessibility/browser_accessibility_manager_unittest.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_unittest.cc
@@ -9,7 +9,7 @@
#if defined(OS_WIN)
#include "content/browser/accessibility/browser_accessibility_win.h"
#endif
-#include "content/common/accessibility_messages.h"
+#include "content/public/browser/ax_event_notification_details.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -92,15 +92,6 @@ class TestBrowserAccessibilityDelegate
gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() override {
return nullptr;
}
- BrowserAccessibilityManager* AccessibilityGetChildFrame(
- int accessibility_node_id) override {
- return nullptr;
- }
- BrowserAccessibility* AccessibilityGetParentFrame() override {
- return nullptr;
- }
- void AccessibilityGetAllChildFrames(
- std::vector<BrowserAccessibilityManager*>* child_frames) override {}
bool got_fatal_error() const { return got_fatal_error_; }
void reset_got_fatal_error() { got_fatal_error_ = false; }
@@ -275,9 +266,9 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects) {
EXPECT_EQ(2, child3_accessible->GetIndexInParent());
// Process a notification containing the changed subtree.
- std::vector<AccessibilityHostMsg_EventParams> params;
- params.push_back(AccessibilityHostMsg_EventParams());
- AccessibilityHostMsg_EventParams* msg = &params[0];
+ std::vector<AXEventNotificationDetails> params;
+ params.push_back(AXEventNotificationDetails());
+ AXEventNotificationDetails* msg = &params[0];
msg->event_type = ui::AX_EVENT_CHILDREN_CHANGED;
msg->update.nodes.push_back(tree2_root);
msg->update.nodes.push_back(tree2_child0);
@@ -451,9 +442,9 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects2) {
// Process a notification containing the changed subtree rooted at
// the container.
- std::vector<AccessibilityHostMsg_EventParams> params;
- params.push_back(AccessibilityHostMsg_EventParams());
- AccessibilityHostMsg_EventParams* msg = &params[0];
+ std::vector<AXEventNotificationDetails> params;
+ params.push_back(AXEventNotificationDetails());
+ AXEventNotificationDetails* msg = &params[0];
msg->event_type = ui::AX_EVENT_CHILDREN_CHANGED;
msg->update.nodes.push_back(tree2_container);
msg->update.nodes.push_back(tree2_child0);
@@ -557,9 +548,9 @@ TEST(BrowserAccessibilityManagerTest, TestMoveChildUp) {
ASSERT_EQ(4, CountedBrowserAccessibility::global_obj_count_);
// Process a notification containing the changed subtree.
- std::vector<AccessibilityHostMsg_EventParams> params;
- params.push_back(AccessibilityHostMsg_EventParams());
- AccessibilityHostMsg_EventParams* msg = &params[0];
+ std::vector<AXEventNotificationDetails> params;
+ params.push_back(AXEventNotificationDetails());
+ AXEventNotificationDetails* msg = &params[0];
msg->event_type = ui::AX_EVENT_CHILDREN_CHANGED;
msg->update.nodes.push_back(tree2_1);
msg->update.nodes.push_back(tree2_4);
@@ -1013,8 +1004,8 @@ TEST(BrowserAccessibilityManagerTest, DeletingFocusedNodeDoesNotCrash) {
ASSERT_EQ(1, manager->GetFocus(manager->GetRoot())->GetId());
// Send the focus event for node 2.
- std::vector<AccessibilityHostMsg_EventParams> events;
- events.push_back(AccessibilityHostMsg_EventParams());
+ std::vector<AXEventNotificationDetails> events;
+ events.push_back(AXEventNotificationDetails());
events[0].update = MakeAXTreeUpdate(node2);
events[0].id = 2;
events[0].event_type = ui::AX_EVENT_FOCUS;
@@ -1029,8 +1020,8 @@ TEST(BrowserAccessibilityManagerTest, DeletingFocusedNodeDoesNotCrash) {
root2.role = ui::AX_ROLE_ROOT_WEB_AREA;
root2.state = 0;
- std::vector<AccessibilityHostMsg_EventParams> events2;
- events2.push_back(AccessibilityHostMsg_EventParams());
+ std::vector<AXEventNotificationDetails> events2;
+ events2.push_back(AXEventNotificationDetails());
events2[0].update = MakeAXTreeUpdate(root2);
events2[0].id = -1;
events2[0].event_type = ui::AX_EVENT_NONE;
@@ -1074,8 +1065,8 @@ TEST(BrowserAccessibilityManagerTest, DeletingFocusedNodeDoesNotCrash2) {
ASSERT_EQ(1, manager->GetFocus(manager->GetRoot())->GetId());
// Send the focus event for node 2.
- std::vector<AccessibilityHostMsg_EventParams> events;
- events.push_back(AccessibilityHostMsg_EventParams());
+ std::vector<AXEventNotificationDetails> events;
+ events.push_back(AXEventNotificationDetails());
events[0].update = MakeAXTreeUpdate(node2);
events[0].id = 2;
events[0].event_type = ui::AX_EVENT_FOCUS;
@@ -1091,8 +1082,8 @@ TEST(BrowserAccessibilityManagerTest, DeletingFocusedNodeDoesNotCrash2) {
root2.state = 0;
// Make an update the explicitly clears the previous root.
- std::vector<AccessibilityHostMsg_EventParams> events2;
- events2.push_back(AccessibilityHostMsg_EventParams());
+ std::vector<AXEventNotificationDetails> events2;
+ events2.push_back(AXEventNotificationDetails());
events2[0].update = MakeAXTreeUpdate(root2);
events2[0].update.node_id_to_clear = 1;
events2[0].id = -1;
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.cc b/content/browser/accessibility/browser_accessibility_manager_win.cc
index dcc60bf..d28423b 100644
--- a/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -298,6 +298,7 @@ void BrowserAccessibilityManagerWin::OnNodeCreated(ui::AXTree* tree,
return;
LONG unique_id_win = obj->ToBrowserAccessibilityWin()->unique_id_win();
unique_id_to_ax_id_map_[unique_id_win] = obj->GetId();
+ unique_id_to_ax_tree_id_map_[unique_id_win] = ax_tree_id_;
}
void BrowserAccessibilityManagerWin::OnNodeWillBeDeleted(ui::AXTree* tree,
@@ -310,6 +311,8 @@ void BrowserAccessibilityManagerWin::OnNodeWillBeDeleted(ui::AXTree* tree,
return;
unique_id_to_ax_id_map_.erase(
obj->ToBrowserAccessibilityWin()->unique_id_win());
+ unique_id_to_ax_tree_id_map_.erase(
+ obj->ToBrowserAccessibilityWin()->unique_id_win());
if (obj == tracked_scroll_object_) {
tracked_scroll_object_->Release();
tracked_scroll_object_ = NULL;
@@ -375,30 +378,31 @@ void BrowserAccessibilityManagerWin::TrackScrollingObject(
BrowserAccessibilityWin* BrowserAccessibilityManagerWin::GetFromUniqueIdWin(
LONG unique_id_win) {
- base::hash_map<LONG, int32>::iterator iter =
- unique_id_to_ax_id_map_.find(unique_id_win);
- if (iter != unique_id_to_ax_id_map_.end()) {
- BrowserAccessibility* result = GetFromID(iter->second);
- if (result && result->IsNative())
- return result->ToBrowserAccessibilityWin();
+ auto tree_iter = unique_id_to_ax_tree_id_map_.find(unique_id_win);
+ if (tree_iter == unique_id_to_ax_tree_id_map_.end())
+ return nullptr;
+
+ int tree_id = tree_iter->second;
+ if (tree_id != ax_tree_id_) {
+ BrowserAccessibilityManagerWin* manager =
+ BrowserAccessibilityManager::FromID(tree_id)
+ ->ToBrowserAccessibilityManagerWin();
+ if (!manager)
+ return nullptr;
+ if (manager != this)
+ return manager->GetFromUniqueIdWin(unique_id_win);
+ return nullptr;
}
- // Also search all child frames, such as out-of-process iframes or
- // guest browser plugins.
- if (delegate()) {
- std::vector<BrowserAccessibilityManager*> child_frames;
- delegate()->AccessibilityGetAllChildFrames(&child_frames);
- for (size_t i = 0; i < child_frames.size(); ++i) {
- BrowserAccessibilityManagerWin* child_manager =
- child_frames[i]->ToBrowserAccessibilityManagerWin();
- BrowserAccessibilityWin* result =
- child_manager->GetFromUniqueIdWin(unique_id_win);
- if (result)
- return result;
- }
- }
+ auto iter = unique_id_to_ax_id_map_.find(unique_id_win);
+ if (iter == unique_id_to_ax_id_map_.end())
+ return nullptr;
+
+ BrowserAccessibility* result = GetFromID(iter->second);
+ if (result && result->IsNative())
+ return result->ToBrowserAccessibilityWin();
- return NULL;
+ return nullptr;
}
} // namespace content
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.h b/content/browser/accessibility/browser_accessibility_manager_win.h
index 1fdf486..f1cb688 100644
--- a/content/browser/accessibility/browser_accessibility_manager_win.h
+++ b/content/browser/accessibility/browser_accessibility_manager_win.h
@@ -76,6 +76,10 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin
// browser process) to accessibility ids within this page.
base::hash_map<long, int32> unique_id_to_ax_id_map_;
+ // A mapping from the Windows-specific unique IDs (unique within the
+ // browser process) to the AXTreeID that contains this unique ID.
+ base::hash_map<long, AXTreeIDRegistry::AXTreeID> unique_id_to_ax_tree_id_map_;
+
// Set to true if we need to fire a focus event on the root as soon as
// possible.
bool focus_event_on_root_needed_;
diff --git a/content/browser/accessibility/browser_accessibility_win_unittest.cc b/content/browser/accessibility/browser_accessibility_win_unittest.cc
index 501490e..2a3ebde 100644
--- a/content/browser/accessibility/browser_accessibility_win_unittest.cc
+++ b/content/browser/accessibility/browser_accessibility_win_unittest.cc
@@ -231,16 +231,16 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChange) {
text_accessible.Release();
// Notify the BrowserAccessibilityManager that the text child has changed.
- ui::AXNodeData text2;
+ AXContentNodeData text2;
text2.id = 2;
text2.role = ui::AX_ROLE_STATIC_TEXT;
text2.SetName("new text");
text2.SetName("old text");
- AccessibilityHostMsg_EventParams param;
+ AXEventNotificationDetails param;
param.event_type = ui::AX_EVENT_CHILDREN_CHANGED;
param.update.nodes.push_back(text2);
param.id = text2.id;
- std::vector<AccessibilityHostMsg_EventParams> events;
+ std::vector<AXEventNotificationDetails> events;
events.push_back(param);
manager->OnAccessibilityEvents(events);
@@ -308,11 +308,11 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChangeNoLeaks) {
// Notify the BrowserAccessibilityManager that the div node and its children
// were removed and ensure that only one BrowserAccessibility instance exists.
root.child_ids.clear();
- AccessibilityHostMsg_EventParams param;
+ AXEventNotificationDetails param;
param.event_type = ui::AX_EVENT_CHILDREN_CHANGED;
param.update.nodes.push_back(root);
param.id = root.id;
- std::vector<AccessibilityHostMsg_EventParams> events;
+ std::vector<AXEventNotificationDetails> events;
events.push_back(param);
manager->OnAccessibilityEvents(events);
ASSERT_EQ(1, CountedBrowserAccessibility::num_instances());
@@ -693,9 +693,9 @@ TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
tree1_2.role = ui::AX_ROLE_TEXT_FIELD;
// Process a load complete.
- std::vector<AccessibilityHostMsg_EventParams> params;
- params.push_back(AccessibilityHostMsg_EventParams());
- AccessibilityHostMsg_EventParams* msg = &params[0];
+ std::vector<AXEventNotificationDetails> params;
+ params.push_back(AXEventNotificationDetails());
+ AXEventNotificationDetails* msg = &params[0];
msg->event_type = ui::AX_EVENT_LOAD_COMPLETE;
msg->update.nodes.push_back(tree1_1);
msg->update.nodes.push_back(tree1_2);
diff --git a/content/browser/accessibility/site_per_process_accessibility_browsertest.cc b/content/browser/accessibility/site_per_process_accessibility_browsertest.cc
index 75abf1a..192b11c 100644
--- a/content/browser/accessibility/site_per_process_accessibility_browsertest.cc
+++ b/content/browser/accessibility/site_per_process_accessibility_browsertest.cc
@@ -38,6 +38,18 @@ class SitePerProcessAccessibilityBrowserTest
SitePerProcessAccessibilityBrowserTest() {}
};
+bool AccessibilityTreeContainsDocTitle(
+ BrowserAccessibility* node,
+ const std::string& title) {
+ if (node->GetStringAttribute(ui::AX_ATTR_DOC_TITLE) == title)
+ return true;
+ for (unsigned i = 0; i < node->PlatformChildCount(); i++) {
+ if (AccessibilityTreeContainsDocTitle(node->PlatformGetChild(i), title))
+ return true;
+ }
+ return false;
+}
+
// Utility function to determine if an accessibility tree has finished loading
// or if the tree represents a page that hasn't finished loading yet.
bool AccessibilityTreeIsLoaded(BrowserAccessibilityManager* manager) {
@@ -96,25 +108,16 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessAccessibilityBrowserTest,
main_frame->browser_accessibility_manager();
VLOG(1) << "Main frame accessibility tree:\n"
<< main_frame_manager->SnapshotAXTreeForTesting().ToString();
- EXPECT_TRUE(AccessibilityTreeIsLoaded(main_frame_manager));
- // Next, wait for the accessibility tree from the cross-process iframe
- // to load. Since accessibility was enabled at the time this frame was
- // created, we need to check to see if it's already loaded first, and
- // only create an AccessibilityNotificationWaiter if it's not.
RenderFrameHostImpl* child_frame = static_cast<RenderFrameHostImpl*>(
child->current_frame_host());
- BrowserAccessibilityManager* child_frame_manager =
- child_frame->browser_accessibility_manager();
- if (!AccessibilityTreeIsLoaded(child_frame_manager)) {
- VLOG(1) << "Child frame accessibility tree is not loaded, waiting...";
- AccessibilityNotificationWaiter child_frame_accessibility_waiter(
- child_frame, ui::AX_EVENT_LOAD_COMPLETE);
- child_frame_accessibility_waiter.WaitForNotification();
+ while (!AccessibilityTreeContainsDocTitle(main_frame_manager->GetRoot(),
+ "Title Of Awesomeness")) {
+ AccessibilityNotificationWaiter accessibility_waiter(main_frame,
+ ui::AX_EVENT_NONE);
+ accessibility_waiter.ListenToAdditionalFrame(child_frame);
+ accessibility_waiter.WaitForNotification();
}
- EXPECT_TRUE(AccessibilityTreeIsLoaded(child_frame_manager));
- VLOG(1) << "Child frame accessibility tree:\n"
- << child_frame_manager->SnapshotAXTreeForTesting().ToString();
// Assert that we can walk from the main frame down into the child frame
// directly, getting correct roles and data along the way.
diff --git a/content/browser/frame_host/frame_accessibility.cc b/content/browser/frame_host/frame_accessibility.cc
deleted file mode 100644
index b046167..0000000
--- a/content/browser/frame_host/frame_accessibility.cc
+++ /dev/null
@@ -1,229 +0,0 @@
-// 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.
-
-#include "content/browser/frame_host/frame_accessibility.h"
-
-#include "content/browser/frame_host/frame_tree.h"
-#include "content/browser/frame_host/frame_tree_node.h"
-#include "content/browser/frame_host/render_frame_host_delegate.h"
-#include "content/browser/frame_host/render_frame_host_impl.h"
-#include "content/public/browser/browser_context.h"
-
-namespace content {
-
-// static
-FrameAccessibility* FrameAccessibility::GetInstance() {
- return Singleton<FrameAccessibility>::get();
-}
-
-FrameAccessibility::ChildFrameMapping::ChildFrameMapping()
- : parent_frame_host(nullptr),
- accessibility_node_id(0),
- child_frame_tree_node_id(0),
- browser_plugin_instance_id(0) {}
-
-FrameAccessibility::FrameAccessibility() {}
-
-FrameAccessibility::~FrameAccessibility() {}
-
-void FrameAccessibility::AddChildFrame(
- RenderFrameHostImpl* parent_frame_host,
- int accessibility_node_id,
- int child_frame_tree_node_id) {
- for (std::vector<ChildFrameMapping>::iterator iter = mappings_.begin();
- iter != mappings_.end();
- ++iter) {
- // TODO(dmazzoni): the renderer should keep track of these mappings
- // and clear an existing mapping before setting a new one, that would
- // be safer than just updating existing mappings. http://crbug.com/413464
- if (iter->parent_frame_host == parent_frame_host &&
- (iter->accessibility_node_id == accessibility_node_id ||
- iter->child_frame_tree_node_id == child_frame_tree_node_id)) {
- iter->accessibility_node_id = accessibility_node_id;
- iter->child_frame_tree_node_id = child_frame_tree_node_id;
- return;
- }
- }
-
- ChildFrameMapping new_mapping;
- new_mapping.parent_frame_host = parent_frame_host;
- new_mapping.accessibility_node_id = accessibility_node_id;
- new_mapping.child_frame_tree_node_id = child_frame_tree_node_id;
- mappings_.push_back(new_mapping);
-}
-
-void FrameAccessibility::AddGuestWebContents(
- RenderFrameHostImpl* parent_frame_host,
- int accessibility_node_id,
- int browser_plugin_instance_id) {
- for (std::vector<ChildFrameMapping>::iterator iter = mappings_.begin();
- iter != mappings_.end();
- ++iter) {
- // TODO(dmazzoni): the renderer should keep track of these mappings
- // and clear an existing mapping before setting a new one, that would
- // be safer than just updating existing mappings. http://crbug.com/413464
- if (iter->parent_frame_host == parent_frame_host &&
- (iter->accessibility_node_id == accessibility_node_id ||
- iter->browser_plugin_instance_id == browser_plugin_instance_id)) {
- iter->accessibility_node_id = accessibility_node_id;
- iter->browser_plugin_instance_id = browser_plugin_instance_id;
- return;
- }
- }
-
- ChildFrameMapping new_mapping;
- new_mapping.parent_frame_host = parent_frame_host;
- new_mapping.accessibility_node_id = accessibility_node_id;
- new_mapping.browser_plugin_instance_id = browser_plugin_instance_id;
- mappings_.push_back(new_mapping);
-}
-
-void FrameAccessibility::OnRenderFrameHostDestroyed(
- RenderFrameHostImpl* render_frame_host) {
- // Since the order doesn't matter, the fastest way to remove all items
- // with this render_frame_host is to iterate over the vector backwards,
- // swapping each one with the back element if we need to delete it.
- int initial_len = static_cast<int>(mappings_.size());
- for (int i = initial_len - 1; i >= 0; i--) {
- if (mappings_[i].parent_frame_host == render_frame_host) {
- mappings_[i] = mappings_.back();
- mappings_.pop_back();
- }
- }
-}
-
-RenderFrameHostImpl* FrameAccessibility::GetChild(
- RenderFrameHostImpl* parent_frame_host,
- int accessibility_node_id) {
- for (std::vector<ChildFrameMapping>::iterator iter = mappings_.begin();
- iter != mappings_.end();
- ++iter) {
- if (iter->parent_frame_host != parent_frame_host ||
- iter->accessibility_node_id != accessibility_node_id) {
- continue;
- }
-
- if (iter->child_frame_tree_node_id) {
- return GetRFHIFromFrameTreeNodeId(
- parent_frame_host, iter->child_frame_tree_node_id);
- }
-
- if (iter->browser_plugin_instance_id) {
- RenderFrameHost* guest =
- parent_frame_host->delegate()->GetGuestByInstanceID(
- iter->parent_frame_host,
- iter->browser_plugin_instance_id);
- if (guest)
- return static_cast<RenderFrameHostImpl*>(guest);
- }
- }
-
- return nullptr;
-}
-
-void FrameAccessibility::GetAllChildFrames(
- RenderFrameHostImpl* parent_frame_host,
- std::vector<RenderFrameHostImpl*>* child_frame_hosts) {
- CHECK(child_frame_hosts);
-
- for (std::vector<ChildFrameMapping>::iterator iter = mappings_.begin();
- iter != mappings_.end();
- ++iter) {
- if (iter->parent_frame_host != parent_frame_host)
- continue;
-
- if (iter->child_frame_tree_node_id) {
- RenderFrameHostImpl* child_frame_host = GetRFHIFromFrameTreeNodeId(
- parent_frame_host, iter->child_frame_tree_node_id);
- if (child_frame_host)
- child_frame_hosts->push_back(child_frame_host);
- }
-
- if (iter->browser_plugin_instance_id) {
- RenderFrameHost* guest =
- parent_frame_host->delegate()->GetGuestByInstanceID(
- iter->parent_frame_host,
- iter->browser_plugin_instance_id);
- if (guest)
- child_frame_hosts->push_back(static_cast<RenderFrameHostImpl*>(guest));
- }
- }
-}
-
-bool FrameAccessibility::GetParent(
- RenderFrameHostImpl* child_frame_host,
- RenderFrameHostImpl** out_parent_frame_host,
- int* out_accessibility_node_id) {
- for (std::vector<ChildFrameMapping>::iterator iter = mappings_.begin();
- iter != mappings_.end();
- ++iter) {
- if (iter->child_frame_tree_node_id) {
- FrameTreeNode* child_node =
- FrameTreeNode::GloballyFindByID(iter->child_frame_tree_node_id);
- if (child_node &&
- child_node->current_frame_host() == child_frame_host) {
- // Assert that the child node is a descendant of the parent frame in
- // the frame tree. It may not be a direct descendant because the
- // parent frame's accessibility tree may span multiple frames from the
- // same origin.
- FrameTreeNode* parent_node = iter->parent_frame_host->frame_tree_node();
- FrameTreeNode* child_node_ancestor = child_node->parent();
- while (child_node_ancestor && child_node_ancestor != parent_node)
- child_node_ancestor = child_node_ancestor->parent();
- if (child_node_ancestor != parent_node) {
- NOTREACHED();
- return false;
- }
-
- if (out_parent_frame_host)
- *out_parent_frame_host = iter->parent_frame_host;
- if (out_accessibility_node_id)
- *out_accessibility_node_id = iter->accessibility_node_id;
- return true;
- }
- }
-
- if (iter->browser_plugin_instance_id) {
- RenderFrameHost* guest =
- iter->parent_frame_host->delegate()->GetGuestByInstanceID(
- iter->parent_frame_host,
- iter->browser_plugin_instance_id);
- if (guest == child_frame_host) {
- if (out_parent_frame_host)
- *out_parent_frame_host = iter->parent_frame_host;
- if (out_accessibility_node_id)
- *out_accessibility_node_id = iter->accessibility_node_id;
- return true;
- }
- }
- }
-
- return false;
-}
-
-RenderFrameHostImpl* FrameAccessibility::GetRFHIFromFrameTreeNodeId(
- RenderFrameHostImpl* parent_frame_host,
- int child_frame_tree_node_id) {
- FrameTreeNode* child_node =
- FrameTreeNode::GloballyFindByID(child_frame_tree_node_id);
- if (!child_node)
- return nullptr;
-
- // Assert that the child node is a descendant of the parent frame in
- // the frame tree. It may not be a direct descendant because the
- // parent frame's accessibility tree may span multiple frames from the
- // same origin.
- FrameTreeNode* parent_node = parent_frame_host->frame_tree_node();
- FrameTreeNode* child_node_ancestor = child_node->parent();
- while (child_node_ancestor && child_node_ancestor != parent_node)
- child_node_ancestor = child_node_ancestor->parent();
- if (child_node_ancestor != parent_node) {
- NOTREACHED();
- return nullptr;
- }
-
- return child_node->current_frame_host();
-}
-
-} // namespace content
diff --git a/content/browser/frame_host/frame_accessibility.h b/content/browser/frame_host/frame_accessibility.h
deleted file mode 100644
index d97a5c0..0000000
--- a/content/browser/frame_host/frame_accessibility.h
+++ /dev/null
@@ -1,106 +0,0 @@
-// 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_BROWSER_FRAME_HOST_FRAME_ACCESSIBILITY_H_
-#define CONTENT_BROWSER_FRAME_HOST_FRAME_ACCESSIBILITY_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/memory/singleton.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-class RenderFrameHostImpl;
-
-// This singleton class maintains the mappings necessary to link child frames
-// and guest frames into a single tree for accessibility. This class is only
-// used if accessibility is enabled.
-class CONTENT_EXPORT FrameAccessibility {
- public:
- static FrameAccessibility* GetInstance();
-
- // Add a mapping between an accessibility node of |parent_frame_host|
- // and the child frame with the given frame tree node id, in the same
- // frame tree.
- void AddChildFrame(RenderFrameHostImpl* parent_frame_host,
- int accessibility_node_id,
- int child_frame_tree_node_id);
-
- // Add a mapping between an accessibility node of |parent_frame_host|
- // and the main frame of the guest Webcontents with the given
- // browser plugin instance id.
- void AddGuestWebContents(RenderFrameHostImpl* parent_frame_host,
- int accessibility_node_id,
- int browser_plugin_instance_id);
-
- // This is called when a RenderFrameHostImpl is deleted, so invalid
- // mappings can be removed from this data structure.
- void OnRenderFrameHostDestroyed(RenderFrameHostImpl* render_frame_host);
-
- // Given a parent RenderFrameHostImpl and an accessibility node id, look up
- // a child frame or guest frame that was previously associated with this
- // frame and node id. If a mapping exists, return the resulting frame if
- // it's valid. If it doesn't resolve to a valid RenderFrameHostImpl,
- // returns NULL.
- RenderFrameHostImpl* GetChild(RenderFrameHostImpl* parent_frame_host,
- int accessibility_node_id);
-
- // Given a parent RenderFrameHostImpl and an accessibility node id, look up
- // all child frames or guest frames that were previously associated with this
- // frame, and populate |child_frame_hosts| with all of them that resolve
- // to a valid RenderFrameHostImpl.
- void GetAllChildFrames(RenderFrameHostImpl* parent_frame_host,
- std::vector<RenderFrameHostImpl*>* child_frame_hosts);
-
- // Given a RenderFrameHostImpl, check the mapping table to see if it's
- // the child of a node in some other frame. If so, return true and
- // set the parent frame and accessibility node id in the parent frame,
- // otherwise return false.
- bool GetParent(RenderFrameHostImpl* child_frame_host,
- RenderFrameHostImpl** out_parent_frame_host,
- int* out_accessibility_node_id);
-
- private:
- FrameAccessibility();
- virtual ~FrameAccessibility();
-
- RenderFrameHostImpl* GetRFHIFromFrameTreeNodeId(
- RenderFrameHostImpl* parent_frame_host,
- int child_frame_tree_node_id);
-
- // This structure stores the parent-child relationship between an
- // accessibility node in a parent frame and its child frame, where the
- // child frame may be an iframe or the main frame of a guest browser
- // plugin. It allows the accessibility code to walk both down and up
- // the "composed" accessibility tree.
- struct ChildFrameMapping {
- ChildFrameMapping();
-
- // The parent frame host. Required.
- RenderFrameHostImpl* parent_frame_host;
-
- // The id of the accessibility node that's the host of the child frame,
- // for example the accessibility node for the <iframe> element or the
- // <embed> element.
- int accessibility_node_id;
-
- // If the child frame is an iframe, this is the iframe's FrameTreeNode id,
- // otherwise 0.
- int child_frame_tree_node_id;
-
- // If the child frame is a browser plugin, this is its instance id,
- // otherwise 0.
- int browser_plugin_instance_id;
- };
-
- std::vector<ChildFrameMapping> mappings_;
-
- friend struct DefaultSingletonTraits<FrameAccessibility>;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_FRAME_HOST_FRAME_ACCESSIBILITY_H_
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 331f152..a25fc59 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -12,13 +12,13 @@
#include "base/process/kill.h"
#include "base/time/time.h"
#include "content/browser/accessibility/accessibility_mode_helper.h"
+#include "content/browser/accessibility/ax_tree_id_registry.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/bad_message.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/frame_host/cross_process_frame_connector.h"
#include "content/browser/frame_host/cross_site_transferring_request.h"
-#include "content/browser/frame_host/frame_accessibility.h"
#include "content/browser/frame_host/frame_mojo_shell.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
@@ -147,6 +147,21 @@ RenderFrameHostImpl* RenderFrameHostImpl::FromID(int process_id,
return it == frames->end() ? NULL : it->second;
}
+// static
+RenderFrameHost* RenderFrameHost::FromAXTreeID(
+ int ax_tree_id) {
+ return RenderFrameHostImpl::FromAXTreeID(ax_tree_id);
+}
+
+// static
+RenderFrameHostImpl* RenderFrameHostImpl::FromAXTreeID(
+ AXTreeIDRegistry::AXTreeID ax_tree_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ AXTreeIDRegistry::FrameID frame_id =
+ AXTreeIDRegistry::GetInstance()->GetFrameID(ax_tree_id);
+ return RenderFrameHostImpl::FromID(frame_id.first, frame_id.second);
+}
+
RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
RenderViewHostImpl* render_view_host,
RenderFrameHostDelegate* delegate,
@@ -209,8 +224,6 @@ RenderFrameHostImpl::~RenderFrameHostImpl() {
if (delegate_ && render_frame_created_)
delegate_->RenderFrameDeleted(this);
- FrameAccessibility::GetInstance()->OnRenderFrameHostDestroyed(this);
-
// If this was swapped out, it already decremented the active frame count of
// the SiteInstance it belongs to.
if (IsRFHStateActive(rfh_state_))
@@ -238,6 +251,11 @@ int RenderFrameHostImpl::GetRoutingID() {
return routing_id_;
}
+AXTreeIDRegistry::AXTreeID RenderFrameHostImpl::GetAXTreeID() {
+ return AXTreeIDRegistry::GetInstance()->GetOrCreateAXTreeID(
+ GetProcess()->GetID(), routing_id_);
+}
+
SiteInstanceImpl* RenderFrameHostImpl::GetSiteInstance() {
return site_instance_.get();
}
@@ -580,57 +598,6 @@ gfx::NativeViewAccessible
return NULL;
}
-BrowserAccessibilityManager* RenderFrameHostImpl::AccessibilityGetChildFrame(
- int accessibility_node_id) {
- RenderFrameHostImpl* child_frame =
- FrameAccessibility::GetInstance()->GetChild(this, accessibility_node_id);
- if (!child_frame || IsSameSiteInstance(child_frame))
- return nullptr;
-
- return child_frame->GetOrCreateBrowserAccessibilityManager();
-}
-
-void RenderFrameHostImpl::AccessibilityGetAllChildFrames(
- std::vector<BrowserAccessibilityManager*>* child_frames) {
- std::vector<RenderFrameHostImpl*> child_frame_hosts;
- FrameAccessibility::GetInstance()->GetAllChildFrames(
- this, &child_frame_hosts);
- for (size_t i = 0; i < child_frame_hosts.size(); ++i) {
- RenderFrameHostImpl* child_frame_host = child_frame_hosts[i];
- if (!child_frame_host || IsSameSiteInstance(child_frame_host))
- continue;
-
- BrowserAccessibilityManager* manager =
- child_frame_host->GetOrCreateBrowserAccessibilityManager();
- if (manager)
- child_frames->push_back(manager);
- }
-}
-
-BrowserAccessibility* RenderFrameHostImpl::AccessibilityGetParentFrame() {
- RenderFrameHostImpl* parent_frame = NULL;
- int parent_node_id = 0;
- if (!FrameAccessibility::GetInstance()->GetParent(
- this, &parent_frame, &parent_node_id)) {
- return NULL;
- }
-
- // As a sanity check, make sure the frame we're going to return belongs
- // to the same BrowserContext.
- if (GetSiteInstance()->GetBrowserContext() !=
- parent_frame->GetSiteInstance()->GetBrowserContext()) {
- NOTREACHED();
- return NULL;
- }
-
- BrowserAccessibilityManager* manager =
- parent_frame->browser_accessibility_manager();
- if (!manager)
- return NULL;
-
- return manager->GetFromID(parent_node_id);
-}
-
bool RenderFrameHostImpl::CreateRenderFrame(int parent_routing_id,
int previous_sibling_routing_id,
int proxy_routing_id) {
@@ -1425,72 +1392,61 @@ void RenderFrameHostImpl::OnAccessibilityEvents(
AccessibilityMode accessibility_mode = delegate_->GetAccessibilityMode();
if ((accessibility_mode != AccessibilityModeOff) && view &&
RenderFrameHostImpl::IsRFHStateActive(rfh_state())) {
- if (browser_accessibility_manager_) {
- // Get the frame routing ids from out-of-process iframes and
- // browser plugin instance ids from guests and update the mappings in
- // FrameAccessibility.
- for (size_t i = 0; i < params.size(); ++i) {
- const AccessibilityHostMsg_EventParams& param = params[i];
- UpdateCrossProcessIframeAccessibility(
- param.node_to_frame_routing_id_map);
- UpdateGuestFrameAccessibility(
- param.node_to_browser_plugin_instance_id_map);
- }
- }
-
- if (accessibility_mode & AccessibilityModeFlagPlatform) {
+ if (accessibility_mode & AccessibilityModeFlagPlatform)
GetOrCreateBrowserAccessibilityManager();
- if (browser_accessibility_manager_)
- browser_accessibility_manager_->OnAccessibilityEvents(params);
- }
- // Send the updates to the automation extension API.
std::vector<AXEventNotificationDetails> details;
details.reserve(params.size());
for (size_t i = 0; i < params.size(); ++i) {
const AccessibilityHostMsg_EventParams& param = params[i];
- AXEventNotificationDetails detail(
- param.update.node_id_to_clear,
- param.update.nodes,
- param.event_type,
- param.id,
- param.node_to_browser_plugin_instance_id_map,
- GetProcess()->GetID(),
- routing_id_);
+ AXEventNotificationDetails detail;
+ detail.event_type = param.event_type;
+ detail.id = param.id;
+ detail.ax_tree_id = GetAXTreeID();
+ detail.update.node_id_to_clear = param.update.node_id_to_clear;
+ detail.update.nodes.resize(param.update.nodes.size());
+ for (size_t i = 0; i < param.update.nodes.size(); ++i) {
+ AXContentNodeDataToAXNodeData(param.update.nodes[i],
+ &detail.update.nodes[i]);
+ }
details.push_back(detail);
}
- delegate_->AccessibilityEventReceived(details);
- }
-
- // Always send an ACK or the renderer can be in a bad state.
- Send(new AccessibilityMsg_Events_ACK(routing_id_));
-
- // The rest of this code is just for testing; bail out if we're not
- // in that mode.
- if (accessibility_testing_callback_.is_null())
- return;
+ if (accessibility_mode & AccessibilityModeFlagPlatform) {
+ if (browser_accessibility_manager_)
+ browser_accessibility_manager_->OnAccessibilityEvents(details);
+ }
- for (size_t i = 0; i < params.size(); i++) {
- const AccessibilityHostMsg_EventParams& param = params[i];
- if (static_cast<int>(param.event_type) < 0)
- continue;
+ // Send the updates to the automation extension API.
+ delegate_->AccessibilityEventReceived(details);
- if (!ax_tree_for_testing_) {
- if (browser_accessibility_manager_) {
- ax_tree_for_testing_.reset(new ui::AXTree(
- browser_accessibility_manager_->SnapshotAXTreeForTesting()));
- } else {
- ax_tree_for_testing_.reset(new ui::AXTree());
- CHECK(ax_tree_for_testing_->Unserialize(param.update))
- << ax_tree_for_testing_->error();
+ // For testing only.
+ if (!accessibility_testing_callback_.is_null()) {
+ for (size_t i = 0; i < details.size(); i++) {
+ const AXEventNotificationDetails& detail = details[i];
+ if (static_cast<int>(detail.event_type) < 0)
+ continue;
+
+ if (!ax_tree_for_testing_) {
+ if (browser_accessibility_manager_) {
+ ax_tree_for_testing_.reset(new ui::AXTree(
+ browser_accessibility_manager_->SnapshotAXTreeForTesting()));
+ } else {
+ ax_tree_for_testing_.reset(new ui::AXTree());
+ CHECK(ax_tree_for_testing_->Unserialize(detail.update))
+ << ax_tree_for_testing_->error();
+ }
+ } else {
+ CHECK(ax_tree_for_testing_->Unserialize(detail.update))
+ << ax_tree_for_testing_->error();
+ }
+ accessibility_testing_callback_.Run(detail.event_type, detail.id);
}
- } else {
- CHECK(ax_tree_for_testing_->Unserialize(param.update))
- << ax_tree_for_testing_->error();
}
- accessibility_testing_callback_.Run(param.event_type, param.id);
}
+
+ // Always send an ACK or the renderer can be in a bad state.
+ Send(new AccessibilityMsg_Events_ACK(routing_id_));
}
void RenderFrameHostImpl::OnAccessibilityLocationChanges(
@@ -1528,10 +1484,16 @@ void RenderFrameHostImpl::OnAccessibilityFindInPageResult(
void RenderFrameHostImpl::OnAccessibilitySnapshotResponse(
int callback_id,
- const ui::AXTreeUpdate<ui::AXNodeData>& snapshot) {
+ const ui::AXTreeUpdate<AXContentNodeData>& snapshot) {
const auto& it = ax_tree_snapshot_callbacks_.find(callback_id);
if (it != ax_tree_snapshot_callbacks_.end()) {
- it->second.Run(snapshot);
+ ui::AXTreeUpdate<ui::AXNodeData> dst_snapshot;
+ dst_snapshot.nodes.resize(snapshot.nodes.size());
+ for (size_t i = 0; i < snapshot.nodes.size(); ++i) {
+ AXContentNodeDataToAXNodeData(snapshot.nodes[i],
+ &dst_snapshot.nodes[i]);
+ }
+ it->second.Run(dst_snapshot);
ax_tree_snapshot_callbacks_.erase(it);
} else {
NOTREACHED() << "Received AX tree snapshot response for unknown id";
@@ -1972,37 +1934,6 @@ RenderFrameHostImpl::GetMojoImageDownloader() {
return mojo_image_downloader_;
}
-void RenderFrameHostImpl::UpdateCrossProcessIframeAccessibility(
- const std::map<int32, int>& node_to_frame_routing_id_map) {
- for (const auto& iter : node_to_frame_routing_id_map) {
- // This is the id of the accessibility node that has a child frame.
- int32 node_id = iter.first;
- // The routing id from either a RenderFrame or a RenderFrameProxy.
- int frame_routing_id = iter.second;
-
- FrameTree* frame_tree = frame_tree_node()->frame_tree();
- FrameTreeNode* child_frame_tree_node = frame_tree->FindByRoutingID(
- GetProcess()->GetID(), frame_routing_id);
-
- if (child_frame_tree_node) {
- FrameAccessibility::GetInstance()->AddChildFrame(
- this, node_id, child_frame_tree_node->frame_tree_node_id());
- }
- }
-}
-
-void RenderFrameHostImpl::UpdateGuestFrameAccessibility(
- const std::map<int32, int>& node_to_browser_plugin_instance_id_map) {
- for (const auto& iter : node_to_browser_plugin_instance_id_map) {
- // This is the id of the accessibility node that hosts a plugin.
- int32 node_id = iter.first;
- // The id of the browser plugin.
- int browser_plugin_instance_id = iter.second;
- FrameAccessibility::GetInstance()->AddGuestWebContents(
- this, node_id, browser_plugin_instance_id);
- }
-}
-
bool RenderFrameHostImpl::IsSameSiteInstance(
RenderFrameHostImpl* other_render_frame_host) {
// As a sanity check, make sure the frame belongs to the same BrowserContext.
@@ -2216,4 +2147,78 @@ bool RenderFrameHostImpl::CanExecuteJavaScript() {
(delegate_->GetAsWebContents() == nullptr);
}
+AXTreeIDRegistry::AXTreeID RenderFrameHostImpl::RoutingIDToAXTreeID(
+ int routing_id) {
+ RenderFrameHostImpl* rfh = nullptr;
+ RenderFrameProxyHost* rfph = RenderFrameProxyHost::FromID(
+ GetProcess()->GetID(), routing_id);
+ if (rfph) {
+ FrameTree* frame_tree = frame_tree_node()->frame_tree();
+ FrameTreeNode* frame_tree_node = frame_tree->FindByRoutingID(
+ GetProcess()->GetID(), routing_id);
+ rfh = frame_tree_node->render_manager()->current_frame_host();
+ } else {
+ rfh = RenderFrameHostImpl::FromID(GetProcess()->GetID(), routing_id);
+ }
+
+ if (!rfh)
+ return AXTreeIDRegistry::kNoAXTreeID;
+
+ // As a sanity check, make sure we're within the same frame tree and
+ // crash the renderer if not.
+ if (rfh->frame_tree_node()->frame_tree() != frame_tree_node()->frame_tree()) {
+ AccessibilityFatalError();
+ return AXTreeIDRegistry::kNoAXTreeID;
+ }
+
+ return rfh->GetAXTreeID();
+}
+
+AXTreeIDRegistry::AXTreeID
+RenderFrameHostImpl::BrowserPluginInstanceIDToAXTreeID(
+ int instance_id) {
+ RenderFrameHost* guest = delegate()->GetGuestByInstanceID(
+ this, instance_id);
+ if (!guest)
+ return AXTreeIDRegistry::kNoAXTreeID;
+
+ return guest->GetAXTreeID();
+}
+
+void RenderFrameHostImpl::AXContentNodeDataToAXNodeData(
+ const AXContentNodeData& src,
+ ui::AXNodeData* dst) {
+ // Copy the common fields.
+ *dst = src;
+
+ // Map content-specific attributes based on routing IDs or browser plugin
+ // instance IDs to generic attributes with global AXTreeIDs.
+ for (auto iter : src.content_int_attributes) {
+ AXContentIntAttribute attr = iter.first;
+ int32 value = iter.second;
+ switch (attr) {
+ case AX_CONTENT_ATTR_ROUTING_ID:
+ dst->int_attributes.push_back(std::make_pair(
+ ui::AX_ATTR_TREE_ID, RoutingIDToAXTreeID(value)));
+ break;
+ case AX_CONTENT_ATTR_PARENT_ROUTING_ID:
+ dst->int_attributes.push_back(std::make_pair(
+ ui::AX_ATTR_PARENT_TREE_ID, RoutingIDToAXTreeID(value)));
+ break;
+ case AX_CONTENT_ATTR_CHILD_ROUTING_ID:
+ dst->int_attributes.push_back(std::make_pair(
+ ui::AX_ATTR_CHILD_TREE_ID, RoutingIDToAXTreeID(value)));
+ break;
+ case AX_CONTENT_ATTR_CHILD_BROWSER_PLUGIN_INSTANCE_ID:
+ dst->int_attributes.push_back(std::make_pair(
+ ui::AX_ATTR_CHILD_TREE_ID,
+ BrowserPluginInstanceIDToAXTreeID(value)));
+ break;
+ case AX_CONTENT_INT_ATTRIBUTE_LAST:
+ NOTREACHED();
+ break;
+ }
+ }
+}
+
} // namespace content
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 772cdeb..a36899d 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -17,6 +17,7 @@
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/site_instance_impl.h"
#include "content/common/accessibility_mode_enums.h"
+#include "content/common/ax_content_node_data.h"
#include "content/common/content_export.h"
#include "content/common/frame_message_enums.h"
#include "content/common/frame_replication_state.h"
@@ -123,11 +124,14 @@ class CONTENT_EXPORT RenderFrameHostImpl
static const int kMaxAccessibilityResets = 5;
static RenderFrameHostImpl* FromID(int process_id, int routing_id);
+ static RenderFrameHostImpl* FromAXTreeID(
+ AXTreeIDRegistry::AXTreeID ax_tree_id);
~RenderFrameHostImpl() override;
// RenderFrameHost
int GetRoutingID() override;
+ AXTreeIDRegistry::AXTreeID GetAXTreeID() override;
SiteInstanceImpl* GetSiteInstance() override;
RenderProcessHost* GetProcess() override;
RenderFrameHost* GetParent() override;
@@ -188,11 +192,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
void AccessibilityFatalError() override;
gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget() override;
gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() override;
- BrowserAccessibilityManager* AccessibilityGetChildFrame(
- int accessibility_node_id) override;
- void AccessibilityGetAllChildFrames(
- std::vector<BrowserAccessibilityManager*>* child_frames) override;
- BrowserAccessibility* AccessibilityGetParentFrame() override;
// Creates a RenderFrame in the renderer process. Only called for
// cross-process subframe navigations in --site-per-process.
@@ -559,7 +558,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
const AccessibilityHostMsg_FindInPageResultParams& params);
void OnAccessibilitySnapshotResponse(
int callback_id,
- const ui::AXTreeUpdate<ui::AXNodeData>& snapshot);
+ const ui::AXTreeUpdate<AXContentNodeData>& snapshot);
void OnToggleFullscreen(bool enter_fullscreen);
void OnDidStartLoading(bool to_different_document);
void OnDidStopLoading();
@@ -582,18 +581,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
// it will be used to kill processes that commit unauthorized URLs.
bool CanCommitURL(const GURL& url);
- // Update the the singleton FrameAccessibility instance with a map
- // from accessibility node id to the frame routing id of a cross-process
- // iframe.
- void UpdateCrossProcessIframeAccessibility(
- const std::map<int32, int>& node_to_frame_routing_id_map);
-
- // Update the the singleton FrameAccessibility instance with a map
- // from accessibility node id to the browser plugin instance id of a
- // guest WebContents.
- void UpdateGuestFrameAccessibility(
- const std::map<int32, int>& node_to_browser_plugin_instance_id_map);
-
// Asserts that the given RenderFrameHostImpl is part of the same browser
// context (and crashes if not), then returns whether the given frame is
// part of the same site instance.
@@ -609,6 +596,19 @@ class CONTENT_EXPORT RenderFrameHostImpl
// Returns true if the ExecuteJavaScript() API can be used on this host.
bool CanExecuteJavaScript();
+ // Map a routing ID from a frame in the same frame tree to a globally
+ // unique AXTreeID.
+ AXTreeIDRegistry::AXTreeID RoutingIDToAXTreeID(int routing_id);
+
+ // Map a browser plugin instance ID to the AXTreeID of the plugin's
+ // main frame.
+ AXTreeIDRegistry::AXTreeID BrowserPluginInstanceIDToAXTreeID(int routing_id);
+
+ // Convert the content-layer-specific AXContentNodeData to a general-purpose
+ // AXNodeData structure.
+ void AXContentNodeDataToAXNodeData(const AXContentNodeData& src,
+ ui::AXNodeData* dst);
+
// For now, RenderFrameHosts indirectly keep RenderViewHosts alive via a
// refcount that calls Shutdown when it reaches zero. This allows each
// RenderFrameHostManager to just care about RenderFrameHosts, while ensuring
diff --git a/content/common/accessibility_messages.h b/content/common/accessibility_messages.h
index badcaee..b9ffe90 100644
--- a/content/common/accessibility_messages.h
+++ b/content/common/accessibility_messages.h
@@ -6,6 +6,7 @@
// Multiply-included message file, hence no include guard.
#include "base/basictypes.h"
+#include "content/common/ax_content_node_data.h"
#include "content/common/content_export.h"
#include "content/common/view_message_enums.h"
#include "content/public/common/common_param_traits.h"
@@ -17,31 +18,37 @@
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_tree_update.h"
-// Singly-included section for custom types.
-#ifndef CONTENT_COMMON_ACCESSIBILITY_MESSAGES_H_
-#define CONTENT_COMMON_ACCESSIBILITY_MESSAGES_H_
-
-typedef std::map<int32, int> FrameIDMap;
-
-#endif // CONTENT_COMMON_ACCESSIBILITY_MESSAGES_H_
-
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
#define IPC_MESSAGE_START AccessibilityMsgStart
+IPC_ENUM_TRAITS_MAX_VALUE(content::AXContentIntAttribute,
+ content::AX_CONTENT_INT_ATTRIBUTE_LAST)
+
+IPC_STRUCT_TRAITS_BEGIN(content::AXContentNodeData)
+ IPC_STRUCT_TRAITS_MEMBER(id)
+ IPC_STRUCT_TRAITS_MEMBER(role)
+ IPC_STRUCT_TRAITS_MEMBER(state)
+ IPC_STRUCT_TRAITS_MEMBER(location)
+ IPC_STRUCT_TRAITS_MEMBER(string_attributes)
+ IPC_STRUCT_TRAITS_MEMBER(int_attributes)
+ IPC_STRUCT_TRAITS_MEMBER(float_attributes)
+ IPC_STRUCT_TRAITS_MEMBER(bool_attributes)
+ IPC_STRUCT_TRAITS_MEMBER(intlist_attributes)
+ IPC_STRUCT_TRAITS_MEMBER(html_attributes)
+ IPC_STRUCT_TRAITS_MEMBER(child_ids)
+ IPC_STRUCT_TRAITS_MEMBER(content_int_attributes)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(ui::AXTreeUpdate<content::AXContentNodeData>)
+ IPC_STRUCT_TRAITS_MEMBER(node_id_to_clear)
+ IPC_STRUCT_TRAITS_MEMBER(nodes)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_BEGIN(AccessibilityHostMsg_EventParams)
// The tree update.
- IPC_STRUCT_MEMBER(ui::AXTreeUpdate<ui::AXNodeData>, update)
-
- // Mapping from node id to routing id of its child frame - either the
- // routing id of a RenderFrame or a RenderFrameProxy for an out-of-process
- // iframe.
- IPC_STRUCT_MEMBER(FrameIDMap, node_to_frame_routing_id_map)
-
- // Mapping from node id to the browser plugin instance id of a child
- // browser plugin.
- IPC_STRUCT_MEMBER(FrameIDMap, node_to_browser_plugin_instance_id_map)
+ IPC_STRUCT_MEMBER(ui::AXTreeUpdate<content::AXContentNodeData>, update)
// Type of event.
IPC_STRUCT_MEMBER(ui::AXEvent, event_type)
@@ -194,4 +201,4 @@ IPC_MESSAGE_ROUTED1(
// a standalone snapshot of the accessibility tree.
IPC_MESSAGE_ROUTED2(AccessibilityHostMsg_SnapshotResponse,
int /* callback_id */,
- ui::AXTreeUpdate<ui::AXNodeData>)
+ ui::AXTreeUpdate<content::AXContentNodeData>)
diff --git a/content/common/ax_content_node_data.cc b/content/common/ax_content_node_data.cc
new file mode 100644
index 0000000..677503c
--- /dev/null
+++ b/content/common/ax_content_node_data.cc
@@ -0,0 +1,93 @@
+// Copyright 2015 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 "base/strings/string_number_conversions.h"
+#include "content/common/ax_content_node_data.h"
+
+using base::IntToString;
+
+namespace content {
+
+namespace {
+
+// Helper function that finds a key in a vector of pairs by matching on the
+// first value, and returns an iterator.
+template<typename FirstType, typename SecondType>
+typename std::vector<std::pair<FirstType, SecondType>>::const_iterator
+ FindInVectorOfPairs(
+ FirstType first,
+ const std::vector<std::pair<FirstType, SecondType>>& vector) {
+ return std::find_if(vector.begin(),
+ vector.end(),
+ [first](std::pair<FirstType, SecondType> const& p) {
+ return p.first == first;
+ });
+}
+
+} // namespace
+
+AXContentNodeData::AXContentNodeData() {
+}
+
+AXContentNodeData::~AXContentNodeData() {
+}
+
+bool AXContentNodeData::HasContentIntAttribute(
+ AXContentIntAttribute attribute) const {
+ auto iter = FindInVectorOfPairs(attribute, content_int_attributes);
+ return iter != content_int_attributes.end();
+}
+
+int AXContentNodeData::GetContentIntAttribute(
+ AXContentIntAttribute attribute) const {
+ int result;
+ if (GetContentIntAttribute(attribute, &result))
+ return result;
+ return 0;
+}
+
+bool AXContentNodeData::GetContentIntAttribute(
+ AXContentIntAttribute attribute, int* value) const {
+ auto iter = FindInVectorOfPairs(attribute, content_int_attributes);
+ if (iter != content_int_attributes.end()) {
+ *value = iter->second;
+ return true;
+ }
+
+ return false;
+}
+
+void AXContentNodeData::AddContentIntAttribute(
+ AXContentIntAttribute attribute, int32 value) {
+ content_int_attributes.push_back(std::make_pair(attribute, value));
+}
+
+std::string AXContentNodeData::ToString() const {
+ std::string result = AXNodeData::ToString();
+
+ for (auto iter : content_int_attributes) {
+ std::string value = IntToString(iter.second);
+ switch (iter.first) {
+ case AX_CONTENT_ATTR_ROUTING_ID:
+ result += " routing_id=" + value;
+ break;
+ case AX_CONTENT_ATTR_PARENT_ROUTING_ID:
+ result += " parent_routing_id=" + value;
+ break;
+ case AX_CONTENT_ATTR_CHILD_ROUTING_ID:
+ result += " child_routing_id=" + value;
+ break;
+ case AX_CONTENT_ATTR_CHILD_BROWSER_PLUGIN_INSTANCE_ID:
+ result += " child_browser_plugin_instance_id=" + value;
+ break;
+ case AX_CONTENT_INT_ATTRIBUTE_LAST:
+ NOTREACHED();
+ break;
+ }
+ }
+
+ return result;
+}
+
+} // namespace ui
diff --git a/content/common/ax_content_node_data.h b/content/common/ax_content_node_data.h
new file mode 100644
index 0000000..8441173
--- /dev/null
+++ b/content/common/ax_content_node_data.h
@@ -0,0 +1,51 @@
+// Copyright 2015 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_COMMON_AX_CONTENT_NODE_DATA_H_
+#define CONTENT_COMMON_AX_CONTENT_NODE_DATA_H_
+
+#include "content/common/content_export.h"
+#include "ui/accessibility/ax_node_data.h"
+
+namespace content {
+
+enum AXContentIntAttribute {
+ // The routing ID of this root node.
+ AX_CONTENT_ATTR_ROUTING_ID,
+
+ // The routing ID of this tree's parent.
+ AX_CONTENT_ATTR_PARENT_ROUTING_ID,
+
+ // The routing ID of this node's child tree.
+ AX_CONTENT_ATTR_CHILD_ROUTING_ID,
+
+ // The browser plugin instance ID of this node's child tree.
+ AX_CONTENT_ATTR_CHILD_BROWSER_PLUGIN_INSTANCE_ID,
+
+ AX_CONTENT_INT_ATTRIBUTE_LAST
+};
+
+// A subclass of AXNodeData that contains extra fields for
+// content-layer-specific AX attributes.
+struct CONTENT_EXPORT AXContentNodeData : public ui::AXNodeData {
+ AXContentNodeData();
+ ~AXContentNodeData() override;
+
+ bool HasContentIntAttribute(AXContentIntAttribute attribute) const;
+ int GetContentIntAttribute(AXContentIntAttribute attribute) const;
+ bool GetContentIntAttribute(AXContentIntAttribute attribute,
+ int* value) const;
+ void AddContentIntAttribute(AXContentIntAttribute attribute, int value);
+
+ // Return a string representation of this data, for debugging.
+ std::string ToString() const override;
+
+ // This is a simple serializable struct. All member variables should be
+ // public and copyable.
+ std::vector<std::pair<AXContentIntAttribute, int32> > content_int_attributes;
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_AX_CONTENT_NODE_DATA_H_
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 4a6e7b6..687171b 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -316,6 +316,8 @@
'browser/accessibility/accessibility_tree_formatter_win.cc',
'browser/accessibility/accessibility_ui.cc',
'browser/accessibility/accessibility_ui.h',
+ 'browser/accessibility/ax_tree_id_registry.cc',
+ 'browser/accessibility/ax_tree_id_registry.h',
'browser/accessibility/browser_accessibility.cc',
'browser/accessibility/browser_accessibility.h',
'browser/accessibility/browser_accessibility_android.cc',
@@ -721,8 +723,6 @@
'browser/frame_host/cross_site_transferring_request.h',
'browser/frame_host/debug_urls.cc',
'browser/frame_host/debug_urls.h',
- 'browser/frame_host/frame_accessibility.cc',
- 'browser/frame_host/frame_accessibility.h',
'browser/frame_host/frame_mojo_shell.cc',
'browser/frame_host/frame_mojo_shell.h',
'browser/frame_host/frame_navigation_entry.cc',
diff --git a/content/content_common.gypi b/content/content_common.gypi
index 87d2574..5ba296f 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -180,6 +180,8 @@
'common/appcache_interfaces.cc',
'common/appcache_interfaces.h',
'common/appcache_messages.h',
+ 'common/ax_content_node_data.cc',
+ 'common/ax_content_node_data.h',
'common/bluetooth/bluetooth_device.cc',
'common/bluetooth/bluetooth_device.h',
'common/bluetooth/bluetooth_messages.h',
diff --git a/content/public/browser/ax_event_notification_details.cc b/content/public/browser/ax_event_notification_details.cc
index 8944f57..ead942c 100644
--- a/content/public/browser/ax_event_notification_details.cc
+++ b/content/public/browser/ax_event_notification_details.cc
@@ -6,22 +6,10 @@
namespace content {
-AXEventNotificationDetails::AXEventNotificationDetails(
- int node_id_to_clear,
- const std::vector<ui::AXNodeData>& nodes,
- ui::AXEvent event_type,
- int id,
- std::map<int32, int> node_to_browser_plugin_instance_id_map,
- int process_id,
- int routing_id)
- : node_id_to_clear(node_id_to_clear),
- nodes(nodes),
- event_type(event_type),
- id(id),
- node_to_browser_plugin_instance_id_map(
- node_to_browser_plugin_instance_id_map),
- process_id(process_id),
- routing_id(routing_id) {
+AXEventNotificationDetails::AXEventNotificationDetails()
+ : event_type(ui::AX_EVENT_NONE),
+ id(-1),
+ ax_tree_id(-1) {
}
AXEventNotificationDetails::~AXEventNotificationDetails() {}
diff --git a/content/public/browser/ax_event_notification_details.h b/content/public/browser/ax_event_notification_details.h
index 4173b82..d4ee1d0 100644
--- a/content/public/browser/ax_event_notification_details.h
+++ b/content/public/browser/ax_event_notification_details.h
@@ -8,8 +8,7 @@
#include <vector>
#include "content/common/content_export.h"
-#include "ui/accessibility/ax_enums.h"
-#include "ui/accessibility/ax_node_data.h"
+#include "ui/accessibility/ax_tree_update.h"
namespace content {
@@ -17,24 +16,13 @@ namespace content {
// |WebContentsObserver::AccessibilityEventReceived| method.
struct CONTENT_EXPORT AXEventNotificationDetails {
public:
- AXEventNotificationDetails(
- int node_id_to_clear,
- const std::vector<ui::AXNodeData>& nodes,
- ui::AXEvent event_type,
- int id,
- std::map<int32, int> node_to_browser_plugin_instance_id_map,
- int process_id,
- int routing_id);
-
+ AXEventNotificationDetails();
~AXEventNotificationDetails();
- int node_id_to_clear;
- std::vector<ui::AXNodeData> nodes;
+ ui::AXTreeUpdate<ui::AXNodeData> update;
ui::AXEvent event_type;
int id;
- std::map<int32, int> node_to_browser_plugin_instance_id_map;
- int process_id;
- int routing_id;
+ int ax_tree_id;
};
} // namespace content
diff --git a/content/public/browser/render_frame_host.h b/content/public/browser/render_frame_host.h
index e47441d..0424979 100644
--- a/content/public/browser/render_frame_host.h
+++ b/content/public/browser/render_frame_host.h
@@ -40,11 +40,17 @@ class CONTENT_EXPORT RenderFrameHost : public IPC::Listener,
// configurations.
static void AllowInjectingJavaScriptForAndroidWebView();
+ // Returns a RenderFrameHost given its accessibility tree ID.
+ static RenderFrameHost* FromAXTreeID(int ax_tree_id);
+
~RenderFrameHost() override {}
// Returns the route id for this frame.
virtual int GetRoutingID() = 0;
+ // Returns the accessibility tree ID for this RenderFrameHost.
+ virtual int GetAXTreeID() = 0;
+
// Returns the SiteInstance grouping all RenderFrameHosts that have script
// access to this RenderFrameHost, and must therefore live in the same
// process.
diff --git a/content/public/common/common_param_traits_macros.h b/content/public/common/common_param_traits_macros.h
index 128044a..3c0c982 100644
--- a/content/public/common/common_param_traits_macros.h
+++ b/content/public/common/common_param_traits_macros.h
@@ -250,7 +250,6 @@ IPC_STRUCT_TRAITS_END()
IPC_ENUM_TRAITS_MAX_VALUE(ui::AXEvent, ui::AX_EVENT_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(ui::AXRole, ui::AX_ROLE_LAST)
-
IPC_ENUM_TRAITS_MAX_VALUE(ui::AXBoolAttribute, ui::AX_BOOL_ATTRIBUTE_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(ui::AXFloatAttribute, ui::AX_FLOAT_ATTRIBUTE_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(ui::AXIntAttribute, ui::AX_INT_ATTRIBUTE_LAST)
@@ -258,23 +257,4 @@ IPC_ENUM_TRAITS_MAX_VALUE(ui::AXIntListAttribute,
ui::AX_INT_LIST_ATTRIBUTE_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(ui::AXStringAttribute, ui::AX_STRING_ATTRIBUTE_LAST)
-IPC_STRUCT_TRAITS_BEGIN(ui::AXNodeData)
- IPC_STRUCT_TRAITS_MEMBER(id)
- IPC_STRUCT_TRAITS_MEMBER(role)
- IPC_STRUCT_TRAITS_MEMBER(state)
- IPC_STRUCT_TRAITS_MEMBER(location)
- IPC_STRUCT_TRAITS_MEMBER(string_attributes)
- IPC_STRUCT_TRAITS_MEMBER(int_attributes)
- IPC_STRUCT_TRAITS_MEMBER(float_attributes)
- IPC_STRUCT_TRAITS_MEMBER(bool_attributes)
- IPC_STRUCT_TRAITS_MEMBER(intlist_attributes)
- IPC_STRUCT_TRAITS_MEMBER(html_attributes)
- IPC_STRUCT_TRAITS_MEMBER(child_ids)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(ui::AXTreeUpdate<ui::AXNodeData>)
- IPC_STRUCT_TRAITS_MEMBER(node_id_to_clear)
- IPC_STRUCT_TRAITS_MEMBER(nodes)
-IPC_STRUCT_TRAITS_END()
-
#endif // CONTENT_PUBLIC_COMMON_COMMON_PARAM_TRAITS_MACROS_H_
diff --git a/content/renderer/accessibility/blink_ax_tree_source.cc b/content/renderer/accessibility/blink_ax_tree_source.cc
index e72cd6e..6f24a81 100644
--- a/content/renderer/accessibility/blink_ax_tree_source.cc
+++ b/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -9,7 +9,9 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/common/accessibility_messages.h"
#include "content/renderer/accessibility/blink_ax_enum_conversion.h"
+#include "content/renderer/accessibility/renderer_accessibility.h"
#include "content/renderer/browser_plugin/browser_plugin.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_frame_proxy.h"
@@ -38,6 +40,7 @@ using blink::WebDocument;
using blink::WebDocumentType;
using blink::WebElement;
using blink::WebFrame;
+using blink::WebLocalFrame;
using blink::WebNode;
using blink::WebPlugin;
using blink::WebPluginContainer;
@@ -97,7 +100,7 @@ std::string GetEquivalentAriaRoleString(const ui::AXRole role) {
void AddIntListAttributeFromWebObjects(ui::AXIntListAttribute attr,
WebVector<WebAXObject> objects,
- ui::AXNodeData* dst) {
+ AXContentNodeData* dst) {
std::vector<int32> ids;
for(size_t i = 0; i < objects.size(); i++)
ids.push_back(objects[i].axID());
@@ -109,8 +112,6 @@ void AddIntListAttributeFromWebObjects(ui::AXIntListAttribute attr,
BlinkAXTreeSource::BlinkAXTreeSource(RenderFrameImpl* render_frame)
: render_frame_(render_frame),
- node_to_frame_routing_id_map_(NULL),
- node_to_browser_plugin_instance_id_map_(NULL),
accessibility_focus_id_(-1) {
}
@@ -131,14 +132,6 @@ bool BlinkAXTreeSource::IsInTree(blink::WebAXObject node) const {
return false;
}
-void BlinkAXTreeSource::CollectChildFrameIdMapping(
- std::map<int32, int>* node_to_frame_routing_id_map,
- std::map<int32, int>* node_to_browser_plugin_instance_id_map) {
- node_to_frame_routing_id_map_ = node_to_frame_routing_id_map;
- node_to_browser_plugin_instance_id_map_ =
- node_to_browser_plugin_instance_id_map;
-}
-
blink::WebAXObject BlinkAXTreeSource::GetRoot() const {
if (!root_.isNull())
return root_;
@@ -219,7 +212,7 @@ blink::WebAXObject BlinkAXTreeSource::GetNull() const {
}
void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
- ui::AXNodeData* dst) const {
+ AXContentNodeData* dst) const {
dst->role = AXRoleFromBlink(src.role());
dst->state = AXStateFromBlink(src);
dst->location = src.boundingBoxRect();
@@ -428,27 +421,24 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
}
// Browser plugin (used in a <webview>).
- if (node_to_browser_plugin_instance_id_map_) {
- BrowserPlugin* browser_plugin = BrowserPlugin::GetFromNode(element);
- if (browser_plugin) {
- (*node_to_browser_plugin_instance_id_map_)[dst->id] =
- browser_plugin->browser_plugin_instance_id();
- dst->AddBoolAttribute(ui::AX_ATTR_IS_AX_TREE_HOST, true);
- }
+ BrowserPlugin* browser_plugin = BrowserPlugin::GetFromNode(element);
+ if (browser_plugin) {
+ dst->AddContentIntAttribute(
+ AX_CONTENT_ATTR_CHILD_BROWSER_PLUGIN_INSTANCE_ID,
+ browser_plugin->browser_plugin_instance_id());
}
// Out-of-process iframe.
- if (is_iframe && node_to_frame_routing_id_map_) {
+ if (is_iframe) {
WebFrame* frame = WebFrame::fromFrameOwnerElement(element);
if (frame && frame->isWebRemoteFrame()) {
RenderFrameProxy* render_frame_proxy =
RenderFrameProxy::FromWebFrame(frame);
-
DCHECK(render_frame_proxy);
- (*node_to_frame_routing_id_map_)[dst->id] =
- render_frame_proxy->routing_id();
- dst->AddBoolAttribute(ui::AX_ATTR_IS_AX_TREE_HOST, true);
+ dst->AddContentIntAttribute(
+ AX_CONTENT_ATTR_CHILD_ROUTING_ID,
+ render_frame_proxy->routing_id());
}
}
}
@@ -513,6 +503,25 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
UTF16ToUTF8(base::StringPiece16(doctype.name())));
}
+ // Get the tree ID for this frame and possibly the parent frame.
+ WebLocalFrame* web_frame = document.frame();
+ if (web_frame) {
+ RenderFrame* render_frame = RenderFrame::FromWebFrame(web_frame);
+ dst->AddContentIntAttribute(
+ AX_CONTENT_ATTR_ROUTING_ID,
+ render_frame->GetRoutingID());
+
+ // Get the tree ID for the parent frame, if it's remote.
+ // (If it's local, it's already part of this same tree.)
+ blink::WebFrame* parent_web_frame = web_frame->parent();
+ if (parent_web_frame && parent_web_frame->isWebRemoteFrame()) {
+ RenderFrameProxy* parent_render_frame_proxy =
+ RenderFrameProxy::FromWebFrame(parent_web_frame);
+ dst->AddContentIntAttribute(
+ AX_CONTENT_ATTR_PARENT_ROUTING_ID,
+ parent_render_frame_proxy->routing_id());
+ }
+ }
}
if (dst->role == ui::AX_ROLE_TABLE) {
diff --git a/content/renderer/accessibility/blink_ax_tree_source.h b/content/renderer/accessibility/blink_ax_tree_source.h
index f226270..d7265f2 100644
--- a/content/renderer/accessibility/blink_ax_tree_source.h
+++ b/content/renderer/accessibility/blink_ax_tree_source.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_RENDERER_ACCESSIBILITY_BLINK_AX_TREE_SOURCE_H_
#define CONTENT_RENDERER_ACCESSIBILITY_BLINK_AX_TREE_SOURCE_H_
+#include "content/common/ax_content_node_data.h"
#include "third_party/WebKit/public/web/WebAXObject.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_tree_source.h"
@@ -14,7 +15,7 @@ namespace content {
class RenderFrameImpl;
class BlinkAXTreeSource
- : public ui::AXTreeSource<blink::WebAXObject, ui::AXNodeData> {
+ : public ui::AXTreeSource<blink::WebAXObject, AXContentNodeData> {
public:
BlinkAXTreeSource(RenderFrameImpl* render_frame);
~BlinkAXTreeSource() override;
@@ -24,13 +25,6 @@ class BlinkAXTreeSource
// WebDocument if accessibility isn't enabled globally.
void SetRoot(blink::WebAXObject root);
- // Call this to have BlinkAXTreeSource collect a mapping from
- // node ids to the frame routing id for an out-of-process iframe during
- // calls to SerializeNode.
- void CollectChildFrameIdMapping(
- std::map<int32, int>* node_to_frame_routing_id_map,
- std::map<int32, int>* node_to_browser_plugin_instance_id_map);
-
// Walks up the ancestor chain to see if this is a descendant of the root.
bool IsInTree(blink::WebAXObject node) const;
@@ -49,7 +43,7 @@ class BlinkAXTreeSource
std::vector<blink::WebAXObject>* out_children) const override;
blink::WebAXObject GetParent(blink::WebAXObject node) const override;
void SerializeNode(blink::WebAXObject node,
- ui::AXNodeData* out_data) const override;
+ AXContentNodeData* out_data) const override;
bool IsValid(blink::WebAXObject node) const override;
bool IsEqual(blink::WebAXObject node1,
blink::WebAXObject node2) const override;
@@ -60,8 +54,7 @@ class BlinkAXTreeSource
private:
RenderFrameImpl* render_frame_;
blink::WebAXObject root_;
- std::map<int32, int>* node_to_frame_routing_id_map_;
- std::map<int32, int>* node_to_browser_plugin_instance_id_map_;
+
int accessibility_focus_id_;
};
diff --git a/content/renderer/accessibility/renderer_accessibility.cc b/content/renderer/accessibility/renderer_accessibility.cc
index 3b56597..86ce7c6 100644
--- a/content/renderer/accessibility/renderer_accessibility.cc
+++ b/content/renderer/accessibility/renderer_accessibility.cc
@@ -11,6 +11,7 @@
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/thread_task_runner_handle.h"
+#include "content/common/accessibility_messages.h"
#include "content/renderer/accessibility/blink_ax_enum_conversion.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_view_impl.h"
@@ -41,7 +42,7 @@ const size_t kMaxSnapshotNodeCount = 5000;
// static
void RendererAccessibility::SnapshotAccessibilityTree(
RenderFrameImpl* render_frame,
- ui::AXTreeUpdate<ui::AXNodeData>* response) {
+ ui::AXTreeUpdate<content::AXContentNodeData>* response) {
DCHECK(render_frame);
DCHECK(response);
if (!render_frame->GetWebFrame())
@@ -264,9 +265,6 @@ void RendererAccessibility::SendPendingAccessibilityEvents() {
continue;
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);
diff --git a/content/renderer/accessibility/renderer_accessibility.h b/content/renderer/accessibility/renderer_accessibility.h
index 4975018..6605aa8 100644
--- a/content/renderer/accessibility/renderer_accessibility.h
+++ b/content/renderer/accessibility/renderer_accessibility.h
@@ -9,12 +9,14 @@
#include "base/containers/hash_tables.h"
#include "base/memory/weak_ptr.h"
-#include "content/common/accessibility_messages.h"
+#include "content/common/ax_content_node_data.h"
#include "content/public/renderer/render_frame_observer.h"
#include "content/renderer/accessibility/blink_ax_tree_source.h"
#include "third_party/WebKit/public/web/WebAXObject.h"
#include "ui/accessibility/ax_tree_serializer.h"
+struct AccessibilityHostMsg_EventParams;
+
namespace blink {
class WebDocument;
class WebNode;
@@ -50,7 +52,7 @@ class CONTENT_EXPORT RendererAccessibility : public RenderFrameObserver {
// enabling accessibility if it wasn't already enabled.
static void SnapshotAccessibilityTree(
RenderFrameImpl* render_frame,
- ui::AXTreeUpdate<ui::AXNodeData>* response);
+ ui::AXTreeUpdate<AXContentNodeData>* response);
explicit RendererAccessibility(RenderFrameImpl* render_frame);
~RendererAccessibility() override;
@@ -121,7 +123,7 @@ class CONTENT_EXPORT RendererAccessibility : public RenderFrameObserver {
// The serializer that sends accessibility messages to the browser process.
using BlinkAXTreeSerializer =
- ui::AXTreeSerializer<blink::WebAXObject, ui::AXNodeData>;
+ ui::AXTreeSerializer<blink::WebAXObject, AXContentNodeData>;
BlinkAXTreeSerializer serializer_;
// Current location of every object, so we can detect when it moves.
diff --git a/content/renderer/accessibility/renderer_accessibility_browsertest.cc b/content/renderer/accessibility/renderer_accessibility_browsertest.cc
index a4fa171..a0b6550 100644
--- a/content/renderer/accessibility/renderer_accessibility_browsertest.cc
+++ b/content/renderer/accessibility/renderer_accessibility_browsertest.cc
@@ -4,6 +4,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
+#include "content/common/accessibility_messages.h"
#include "content/common/frame_messages.h"
#include "content/common/site_isolation_policy.h"
#include "content/common/view_message_enums.h"
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index c56c958..d1672fc 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -35,6 +35,7 @@
#include "content/child/webmessageportchannel_impl.h"
#include "content/child/websocket_bridge.h"
#include "content/child/weburlresponse_extradata_impl.h"
+#include "content/common/accessibility_messages.h"
#include "content/common/clipboard_messages.h"
#include "content/common/frame_messages.h"
#include "content/common/frame_replication_state.h"
@@ -1595,7 +1596,7 @@ void RenderFrameImpl::OnSetAccessibilityMode(AccessibilityMode new_mode) {
}
void RenderFrameImpl::OnSnapshotAccessibilityTree(int callback_id) {
- ui::AXTreeUpdate<ui::AXNodeData> response;
+ ui::AXTreeUpdate<AXContentNodeData> response;
RendererAccessibility::SnapshotAccessibilityTree(this, &response);
Send(new AccessibilityHostMsg_SnapshotResponse(
routing_id_, callback_id, response));
diff --git a/content/test/accessibility_browser_test_utils.cc b/content/test/accessibility_browser_test_utils.cc
index 94245ec..58ff89c 100644
--- a/content/test/accessibility_browser_test_utils.cc
+++ b/content/test/accessibility_browser_test_utils.cc
@@ -67,6 +67,13 @@ AccessibilityNotificationWaiter::AccessibilityNotificationWaiter(
AccessibilityNotificationWaiter::~AccessibilityNotificationWaiter() {
}
+void AccessibilityNotificationWaiter::ListenToAdditionalFrame(
+ RenderFrameHostImpl* frame_host) {
+ frame_host->SetAccessibilityCallbackForTesting(
+ base::Bind(&AccessibilityNotificationWaiter::OnAccessibilityEvent,
+ weak_factory_.GetWeakPtr()));
+}
+
void AccessibilityNotificationWaiter::WaitForNotification() {
loop_runner_->Run();
diff --git a/content/test/accessibility_browser_test_utils.h b/content/test/accessibility_browser_test_utils.h
index 52e2b18..1d06b5f 100644
--- a/content/test/accessibility_browser_test_utils.h
+++ b/content/test/accessibility_browser_test_utils.h
@@ -33,6 +33,8 @@ class AccessibilityNotificationWaiter {
ui::AXEvent event);
~AccessibilityNotificationWaiter();
+ void ListenToAdditionalFrame(RenderFrameHostImpl* frame_host);
+
// Blocks until the specific accessibility notification registered in
// AccessibilityNotificationWaiter is received. Ignores notifications for
// "about:blank".