Commit a656928e authored by dmazzoni's avatar dmazzoni Committed by Commit bot

Hook up guest browser plugins to the accessibility tree.

This change refactors the existing support for cross-process iframe
accessibility and extends it to make guest browser plugins, for example
the <webview> element in apps, accessible too.

In this change, a new class, FrameAccessibility, manages all links
from one frame's accessibility tree to either a child iframe's tree,
or a guest web contents' tree. This is cleaner than storing ids in
BrowserAccessibility nodes - now the accessibility tree just needs a
single bit indicating which nodes in one tree are acting as a host of
another tree.

FrameAccessibility doesn't try to be efficient yet, it scans its list
for every operation - the goal is for it to be simple and safe first.
Hash maps could make it much faster later if needed.

None of the APIs needed to test this are available outside of content
yet. Once http://crbug.com/396137 is finished we'll have a clean way
to test this. In the meantime, this can be tested by visiting
chrome://accessibility on Windows or Mac, and observing that the
accessibility tree for an app includes all nodes within <webview>
elements now. Also tested with VoiceOver on Mac; there are some bugs
but the <webview> is definitely part of the accessibility tree now.

BUG=330307,368298

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

Cr-Commit-Position: refs/heads/master@{#294883}
parent 09599b6d
...@@ -26,8 +26,7 @@ BrowserAccessibility* BrowserAccessibility::Create() { ...@@ -26,8 +26,7 @@ BrowserAccessibility* BrowserAccessibility::Create() {
BrowserAccessibility::BrowserAccessibility() BrowserAccessibility::BrowserAccessibility()
: manager_(NULL), : manager_(NULL),
node_(NULL), node_(NULL) {
child_frame_tree_node_id_(0) {
} }
BrowserAccessibility::~BrowserAccessibility() { BrowserAccessibility::~BrowserAccessibility() {
...@@ -64,15 +63,6 @@ bool BrowserAccessibility::PlatformIsLeaf() const { ...@@ -64,15 +63,6 @@ bool BrowserAccessibility::PlatformIsLeaf() const {
} }
uint32 BrowserAccessibility::PlatformChildCount() const { uint32 BrowserAccessibility::PlatformChildCount() const {
if (child_frame_tree_node_id_ &&
manager_ && manager_->delegate()) {
BrowserAccessibilityManager* child_manager =
manager_->delegate()->AccessibilityGetChildFrame(
child_frame_tree_node_id_);
if (child_manager)
return 1;
}
return PlatformIsLeaf() ? 0 : InternalChildCount(); return PlatformIsLeaf() ? 0 : InternalChildCount();
} }
...@@ -93,18 +83,17 @@ bool BrowserAccessibility::IsDescendantOf( ...@@ -93,18 +83,17 @@ bool BrowserAccessibility::IsDescendantOf(
BrowserAccessibility* BrowserAccessibility::PlatformGetChild( BrowserAccessibility* BrowserAccessibility::PlatformGetChild(
uint32 child_index) const { uint32 child_index) const {
if (child_index == 0 && child_frame_tree_node_id_ && DCHECK(child_index < InternalChildCount());
manager_ && BrowserAccessibility* result = InternalGetChild(child_index);
manager_->delegate()) {
if (result->HasBoolAttribute(ui::AX_ATTR_IS_AX_TREE_HOST)) {
BrowserAccessibilityManager* child_manager = BrowserAccessibilityManager* child_manager =
manager_->delegate()->AccessibilityGetChildFrame( manager_->delegate()->AccessibilityGetChildFrame(result->GetId());
child_frame_tree_node_id_);
if (child_manager) if (child_manager)
return child_manager->GetRoot(); result = child_manager->GetRoot();
} }
DCHECK(child_index < InternalChildCount()); return result;
return InternalGetChild(child_index);
} }
BrowserAccessibility* BrowserAccessibility::GetPreviousSibling() { BrowserAccessibility* BrowserAccessibility::GetPreviousSibling() {
...@@ -144,7 +133,16 @@ BrowserAccessibility* BrowserAccessibility::GetParent() const { ...@@ -144,7 +133,16 @@ BrowserAccessibility* BrowserAccessibility::GetParent() const {
ui::AXNode* parent = node_->parent(); ui::AXNode* parent = node_->parent();
if (parent) if (parent)
return manager_->GetFromAXNode(parent); return manager_->GetFromAXNode(parent);
return manager_->GetCrossFrameParent();
if (!manager_->delegate())
return NULL;
BrowserAccessibility* host_node =
manager_->delegate()->AccessibilityGetParentFrame();
if (!host_node)
return NULL;
return host_node->GetParent();
} }
int32 BrowserAccessibility::GetIndexInParent() const { int32 BrowserAccessibility::GetIndexInParent() const {
...@@ -702,10 +700,4 @@ int BrowserAccessibility::GetStaticTextLenRecursive() const { ...@@ -702,10 +700,4 @@ int BrowserAccessibility::GetStaticTextLenRecursive() const {
return len; return len;
} }
void BrowserAccessibility::SetChildFrameTreeNodeId(
int64 child_frame_tree_node_id) {
child_frame_tree_node_id_ = child_frame_tree_node_id;
manager_->NotifyAccessibilityEvent(ui::AX_EVENT_CHILDREN_CHANGED, this);
}
} // namespace content } // namespace content
...@@ -246,15 +246,6 @@ class CONTENT_EXPORT BrowserAccessibility { ...@@ -246,15 +246,6 @@ class CONTENT_EXPORT BrowserAccessibility {
// Append the text from this node and its children. // Append the text from this node and its children.
std::string GetTextRecursive() const; std::string GetTextRecursive() const;
// Identifies the given frame tree node id as the only child of this node,
// so any call to PlatformChildCount/PlatformGetChild will use
// BrowserAccessibilityDelegate::AccessibilityGetChildFrame to retrieve
// the BrowserAccessibilityManager of the child frame and return its root
// node as this node's child.
void SetChildFrameTreeNodeId(int64 child_frame_tree_node_id);
int64 child_frame_tree_node_id() const { return child_frame_tree_node_id_; }
protected: protected:
BrowserAccessibility(); BrowserAccessibility();
...@@ -272,9 +263,6 @@ class CONTENT_EXPORT BrowserAccessibility { ...@@ -272,9 +263,6 @@ class CONTENT_EXPORT BrowserAccessibility {
std::string name_; std::string name_;
std::string value_; std::string value_;
// If nonzero, the frame tree node id of the child frame of this node.
int64 child_frame_tree_node_id_;
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibility); DISALLOW_COPY_AND_ASSIGN(BrowserAccessibility);
}; };
......
...@@ -11,34 +11,6 @@ ...@@ -11,34 +11,6 @@
namespace content { namespace content {
namespace {
// Recursively searches |ancestor_node| and its descendants for a
// BrowserAccessibility with |child| as its immediate and only child.
// Searches only the frame that |ancestor_node| belongs to, does not descend
// into child frames (but |child| can be the root of another frame).
BrowserAccessibility* FindParentOfNode(
BrowserAccessibility* ancestor_node, BrowserAccessibility* child) {
if (ancestor_node->PlatformChildCount() == 1 &&
ancestor_node->PlatformGetChild(0) == child) {
return ancestor_node;
}
if (ancestor_node->InternalChildCount() == 0)
return NULL;
for (uint32 i = 0; i < ancestor_node->PlatformChildCount(); ++i) {
BrowserAccessibility* result = FindParentOfNode(
ancestor_node->PlatformGetChild(i), child);
if (result)
return result;
}
return NULL;
}
} // namespace.
ui::AXTreeUpdate MakeAXTreeUpdate( ui::AXTreeUpdate MakeAXTreeUpdate(
const ui::AXNodeData& node1, const ui::AXNodeData& node1,
const ui::AXNodeData& node2 /* = ui::AXNodeData() */, const ui::AXNodeData& node2 /* = ui::AXNodeData() */,
...@@ -401,31 +373,4 @@ ui::AXTreeUpdate BrowserAccessibilityManager::SnapshotAXTreeForTesting() { ...@@ -401,31 +373,4 @@ ui::AXTreeUpdate BrowserAccessibilityManager::SnapshotAXTreeForTesting() {
return update; return update;
} }
void BrowserAccessibilityManager::SetChildFrameTreeNodeId(
int32 node_id, int64 child_frame_tree_node_id) {
BrowserAccessibility* node = GetFromID(node_id);
if (node) {
// The node id passed to us is the web area for the proxy frame.
// In order to replace this node with the child frame, set the
// child frame id on its parent.
BrowserAccessibility* node_parent = node->GetParent();
if (node_parent)
node_parent->SetChildFrameTreeNodeId(child_frame_tree_node_id);
}
}
BrowserAccessibility* BrowserAccessibilityManager::GetCrossFrameParent() {
if (!delegate_)
return NULL;
BrowserAccessibilityManager* parent_frame =
delegate_->AccessibilityGetParentFrame();
if (!parent_frame)
return NULL;
// Recursively search the parent frame to find the node that has this
// frame as its child.
return FindParentOfNode(parent_frame->GetRoot(), GetRoot());
}
} // namespace content } // namespace content
...@@ -71,8 +71,8 @@ class CONTENT_EXPORT BrowserAccessibilityDelegate { ...@@ -71,8 +71,8 @@ class CONTENT_EXPORT BrowserAccessibilityDelegate {
virtual gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget() = 0; virtual gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget() = 0;
virtual gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() = 0; virtual gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() = 0;
virtual BrowserAccessibilityManager* AccessibilityGetChildFrame( virtual BrowserAccessibilityManager* AccessibilityGetChildFrame(
int64 frame_tree_node_id) = 0; int accessibility_node_id) = 0;
virtual BrowserAccessibilityManager* AccessibilityGetParentFrame() = 0; virtual BrowserAccessibility* AccessibilityGetParentFrame() = 0;
}; };
class CONTENT_EXPORT BrowserAccessibilityFactory { class CONTENT_EXPORT BrowserAccessibilityFactory {
...@@ -202,10 +202,6 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate { ...@@ -202,10 +202,6 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
// Get a snapshot of the current tree as an AXTreeUpdate. // Get a snapshot of the current tree as an AXTreeUpdate.
ui::AXTreeUpdate SnapshotAXTreeForTesting(); ui::AXTreeUpdate SnapshotAXTreeForTesting();
// Frame tree support.
void SetChildFrameTreeNodeId(int32 node_id, int64 child_frame_tree_node_id);
BrowserAccessibility* GetCrossFrameParent();
protected: protected:
BrowserAccessibilityManager( BrowserAccessibilityManager(
BrowserAccessibilityDelegate* delegate, BrowserAccessibilityDelegate* delegate,
......
...@@ -98,10 +98,10 @@ class TestBrowserAccessibilityDelegate ...@@ -98,10 +98,10 @@ class TestBrowserAccessibilityDelegate
return NULL; return NULL;
} }
virtual BrowserAccessibilityManager* AccessibilityGetChildFrame( virtual BrowserAccessibilityManager* AccessibilityGetChildFrame(
int64 frame_tree_node_id) OVERRIDE { int accessibility_node_id) OVERRIDE {
return NULL; return NULL;
} }
virtual BrowserAccessibilityManager* AccessibilityGetParentFrame() OVERRIDE { virtual BrowserAccessibility* AccessibilityGetParentFrame() OVERRIDE {
return NULL; return NULL;
} }
......
// 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(NULL),
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,
int64 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) {
FrameTreeNode* child_node =
FrameTree::GloballyFindByID(iter->child_frame_tree_node_id);
if (!child_node)
return NULL;
// We should have gotten a node in the same frame tree.
if (child_node->frame_tree() !=
parent_frame_host->frame_tree_node()->frame_tree()) {
NOTREACHED();
return NULL;
}
return child_node->current_frame_host();
}
if (iter->browser_plugin_instance_id) {
RenderFrameHost* guest =
parent_frame_host->delegate()->GetGuestByInstanceID(
iter->browser_plugin_instance_id);
if (guest)
return static_cast<RenderFrameHostImpl*>(guest);
}
}
return NULL;
}
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 =
FrameTree::GloballyFindByID(iter->child_frame_tree_node_id);
if (child_node &&
child_node->current_frame_host() == child_frame_host) {
// We should have gotten a node in the same frame tree.
if (child_node->frame_tree() !=
iter->parent_frame_host->frame_tree_node()->frame_tree()) {
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->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;
}
} // namespace content
// 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,
int64 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 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();
struct ChildFrameMapping {
ChildFrameMapping();
RenderFrameHostImpl* parent_frame_host;
int accessibility_node_id;
int64 child_frame_tree_node_id;
int browser_plugin_instance_id;
};
std::vector<ChildFrameMapping> mappings_;
friend struct DefaultSingletonTraits<FrameAccessibility>;
};
} // namespace content
#endif // CONTENT_BROWSER_FRAME_HOST_FRAME_ACCESSIBILITY_H_
...@@ -48,6 +48,11 @@ AccessibilityMode RenderFrameHostDelegate::GetAccessibilityMode() const { ...@@ -48,6 +48,11 @@ AccessibilityMode RenderFrameHostDelegate::GetAccessibilityMode() const {
return AccessibilityModeOff; return AccessibilityModeOff;
} }
RenderFrameHost* RenderFrameHostDelegate::GetGuestByInstanceID(
int browser_plugin_instance_id) {
return NULL;
}
#if defined(OS_WIN) #if defined(OS_WIN)
gfx::NativeViewAccessible gfx::NativeViewAccessible
RenderFrameHostDelegate::GetParentNativeViewAccessible() { RenderFrameHostDelegate::GetParentNativeViewAccessible() {
......
...@@ -137,6 +137,10 @@ class CONTENT_EXPORT RenderFrameHostDelegate { ...@@ -137,6 +137,10 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
virtual void AccessibilityEventReceived( virtual void AccessibilityEventReceived(
const std::vector<AXEventNotificationDetails>& details) {} const std::vector<AXEventNotificationDetails>& details) {}
// Find a guest RenderFrameHost by its browser plugin instance id.
virtual RenderFrameHost* GetGuestByInstanceID(
int browser_plugin_instance_id);
#if defined(OS_WIN) #if defined(OS_WIN)
// Returns the frame's parent's NativeViewAccessible. // Returns the frame's parent's NativeViewAccessible.
virtual gfx::NativeViewAccessible GetParentNativeViewAccessible(); virtual gfx::NativeViewAccessible GetParentNativeViewAccessible();
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "content/browser/child_process_security_policy_impl.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_process_frame_connector.h"
#include "content/browser/frame_host/cross_site_transferring_request.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_tree.h" #include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h" #include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/navigator.h" #include "content/browser/frame_host/navigator.h"
...@@ -42,6 +43,8 @@ ...@@ -42,6 +43,8 @@
#include "content/common/swapped_out_messages.h" #include "content/common/swapped_out_messages.h"
#include "content/public/browser/ax_event_notification_details.h" #include "content/public/browser/ax_event_notification_details.h"
#include "content/public/browser/browser_accessibility_state.h" #include "content/public/browser/browser_accessibility_state.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_plugin_guest_manager.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h" #include "content/public/browser/content_browser_client.h"
#include "content/public/browser/desktop_notification_delegate.h" #include "content/public/browser/desktop_notification_delegate.h"
...@@ -203,6 +206,8 @@ RenderFrameHostImpl::~RenderFrameHostImpl() { ...@@ -203,6 +206,8 @@ RenderFrameHostImpl::~RenderFrameHostImpl() {
if (delegate_) if (delegate_)
delegate_->RenderFrameDeleted(this); delegate_->RenderFrameDeleted(this);
FrameAccessibility::GetInstance()->OnRenderFrameHostDestroyed(this);
// Notify the FrameTree that this RFH is going away, allowing it to shut down // Notify the FrameTree that this RFH is going away, allowing it to shut down
// the corresponding RenderViewHost if it is no longer needed. // the corresponding RenderViewHost if it is no longer needed.
frame_tree_->UnregisterRenderFrameHost(this); frame_tree_->UnregisterRenderFrameHost(this);
...@@ -473,35 +478,50 @@ gfx::NativeViewAccessible ...@@ -473,35 +478,50 @@ gfx::NativeViewAccessible
} }
BrowserAccessibilityManager* RenderFrameHostImpl::AccessibilityGetChildFrame( BrowserAccessibilityManager* RenderFrameHostImpl::AccessibilityGetChildFrame(
int64 frame_tree_node_id) { int accessibility_node_id) {
FrameTreeNode* child_node = FrameTree::GloballyFindByID(frame_tree_node_id); RenderFrameHostImpl* child_frame =
if (!child_node) FrameAccessibility::GetInstance()->GetChild(this, accessibility_node_id);
if (!child_frame)
return NULL; return NULL;
// We should have gotten a node in the same frame tree.
CHECK(child_node->frame_tree() == frame_tree_node()->frame_tree());
RenderFrameHostImpl* child_rfhi = child_node->current_frame_host();
// Return NULL if this isn't an out-of-process iframe. Same-process iframes // Return NULL if this isn't an out-of-process iframe. Same-process iframes
// are already part of the accessibility tree. // are already part of the accessibility tree.
if (child_rfhi->GetProcess()->GetID() == GetProcess()->GetID()) if (child_frame->GetProcess()->GetID() == GetProcess()->GetID())
return NULL; return NULL;
return child_rfhi->GetOrCreateBrowserAccessibilityManager(); // As a sanity check, make sure the frame we're going to return belongs
// to the same BrowserContext.
if (GetSiteInstance()->GetBrowserContext() !=
child_frame->GetSiteInstance()->GetBrowserContext()) {
NOTREACHED();
return NULL;
}
return child_frame->GetOrCreateBrowserAccessibilityManager();
} }
BrowserAccessibilityManager* BrowserAccessibility* RenderFrameHostImpl::AccessibilityGetParentFrame() {
RenderFrameHostImpl::AccessibilityGetParentFrame() { RenderFrameHostImpl* parent_frame = NULL;
FrameTreeNode* parent_node = frame_tree_node()->parent(); int parent_node_id = 0;
if (!parent_node) if (!FrameAccessibility::GetInstance()->GetParent(
this, &parent_frame, &parent_node_id)) {
return NULL; return NULL;
}
RenderFrameHostImpl* parent_frame = parent_node->current_frame_host(); // As a sanity check, make sure the frame we're going to return belongs
if (!parent_frame) // 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 NULL;
return parent_frame->GetOrCreateBrowserAccessibilityManager(); return manager->GetFromID(parent_node_id);
} }
bool RenderFrameHostImpl::CreateRenderFrame(int parent_routing_id) { bool RenderFrameHostImpl::CreateRenderFrame(int parent_routing_id) {
...@@ -1012,28 +1032,15 @@ void RenderFrameHostImpl::OnAccessibilityEvents( ...@@ -1012,28 +1032,15 @@ void RenderFrameHostImpl::OnAccessibilityEvents(
} }
if (browser_accessibility_manager_) { if (browser_accessibility_manager_) {
// Get the frame routing ids from out-of-process iframes and use them // Get the frame routing ids from out-of-process iframes and
// to notify our BrowserAccessibilityManager of the frame tree node id of // browser plugin instance ids from guests and update the mappings in
// any of its child frames. // FrameAccessibility.
for (unsigned int i = 0; i < params.size(); ++i) { for (unsigned int i = 0; i < params.size(); ++i) {
const AccessibilityHostMsg_EventParams& param = params[i]; const AccessibilityHostMsg_EventParams& param = params[i];
std::map<int32, int>::const_iterator iter; UpdateCrossProcessIframeAccessibility(
for (iter = param.node_to_frame_routing_id_map.begin(); param.node_to_frame_routing_id_map);
iter != param.node_to_frame_routing_id_map.end(); UpdateGuestFrameAccessibility(
++iter) { param.node_to_browser_plugin_instance_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) {
browser_accessibility_manager_->SetChildFrameTreeNodeId(
node_id, child_frame_tree_node->frame_tree_node_id());
}
}
} }
} }
...@@ -1304,6 +1311,42 @@ void RenderFrameHostImpl::PlatformNotificationPermissionRequestDone( ...@@ -1304,6 +1311,42 @@ void RenderFrameHostImpl::PlatformNotificationPermissionRequestDone(
routing_id_, request_id, permission)); routing_id_, request_id, permission));
} }
void RenderFrameHostImpl::UpdateCrossProcessIframeAccessibility(
const std::map<int32, int> node_to_frame_routing_id_map) {
std::map<int32, int>::const_iterator iter;
for (iter = node_to_frame_routing_id_map.begin();
iter != node_to_frame_routing_id_map.end();
++iter) {
// 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) {
std::map<int32, int>::const_iterator iter;
for (iter = node_to_browser_plugin_instance_id_map.begin();
iter != node_to_browser_plugin_instance_id_map.end();
++iter) {
// 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);
}
}
void RenderFrameHostImpl::SetAccessibilityMode(AccessibilityMode mode) { void RenderFrameHostImpl::SetAccessibilityMode(AccessibilityMode mode) {
Send(new FrameMsg_SetAccessibilityMode(routing_id_, mode)); Send(new FrameMsg_SetAccessibilityMode(routing_id_, mode));
} }
......
...@@ -111,8 +111,8 @@ class CONTENT_EXPORT RenderFrameHostImpl ...@@ -111,8 +111,8 @@ class CONTENT_EXPORT RenderFrameHostImpl
virtual gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() virtual gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible()
OVERRIDE; OVERRIDE;
virtual BrowserAccessibilityManager* AccessibilityGetChildFrame( virtual BrowserAccessibilityManager* AccessibilityGetChildFrame(
int64 frame_tree_node_id) OVERRIDE; int accessibility_node_id) OVERRIDE;
virtual BrowserAccessibilityManager* AccessibilityGetParentFrame() OVERRIDE; virtual BrowserAccessibility* AccessibilityGetParentFrame() OVERRIDE;
bool CreateRenderFrame(int parent_routing_id); bool CreateRenderFrame(int parent_routing_id);
bool IsRenderFrameLive(); bool IsRenderFrameLive();
...@@ -379,6 +379,18 @@ class CONTENT_EXPORT RenderFrameHostImpl ...@@ -379,6 +379,18 @@ class CONTENT_EXPORT RenderFrameHostImpl
void PlatformNotificationPermissionRequestDone( void PlatformNotificationPermissionRequestDone(
int request_id, blink::WebNotificationPermission permission); int request_id, blink::WebNotificationPermission permission);
// 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);
// For now, RenderFrameHosts indirectly keep RenderViewHosts alive via a // For now, RenderFrameHosts indirectly keep RenderViewHosts alive via a
// refcount that calls Shutdown when it reaches zero. This allows each // refcount that calls Shutdown when it reaches zero. This allows each
// RenderFrameHostManager to just care about RenderFrameHosts, while ensuring // RenderFrameHostManager to just care about RenderFrameHosts, while ensuring
......
...@@ -1796,6 +1796,17 @@ void WebContentsImpl::AccessibilityEventReceived( ...@@ -1796,6 +1796,17 @@ void WebContentsImpl::AccessibilityEventReceived(
WebContentsObserver, observers_, AccessibilityEventReceived(details)); WebContentsObserver, observers_, AccessibilityEventReceived(details));
} }
RenderFrameHost* WebContentsImpl::GetGuestByInstanceID(
int browser_plugin_instance_id) {
BrowserPluginGuestManager* guest_manager =
GetBrowserContext()->GetGuestManager();
WebContents* guest = guest_manager->GetGuestByInstanceID(
this, browser_plugin_instance_id);
if (!guest)
return NULL;
return guest->GetMainFrame();
}
void WebContentsImpl::OnShowValidationMessage( void WebContentsImpl::OnShowValidationMessage(
const gfx::Rect& anchor_in_root_view, const gfx::Rect& anchor_in_root_view,
const base::string16& main_text, const base::string16& main_text,
......
...@@ -386,6 +386,8 @@ class CONTENT_EXPORT WebContentsImpl ...@@ -386,6 +386,8 @@ class CONTENT_EXPORT WebContentsImpl
virtual AccessibilityMode GetAccessibilityMode() const OVERRIDE; virtual AccessibilityMode GetAccessibilityMode() const OVERRIDE;
virtual void AccessibilityEventReceived( virtual void AccessibilityEventReceived(
const std::vector<AXEventNotificationDetails>& details) OVERRIDE; const std::vector<AXEventNotificationDetails>& details) OVERRIDE;
virtual RenderFrameHost* GetGuestByInstanceID(int browser_plugin_instance_id)
OVERRIDE;
#if defined(OS_WIN) #if defined(OS_WIN)
virtual gfx::NativeViewAccessible GetParentNativeViewAccessible() OVERRIDE; virtual gfx::NativeViewAccessible GetParentNativeViewAccessible() OVERRIDE;
#endif #endif
......
...@@ -68,6 +68,10 @@ IPC_STRUCT_BEGIN(AccessibilityHostMsg_EventParams) ...@@ -68,6 +68,10 @@ IPC_STRUCT_BEGIN(AccessibilityHostMsg_EventParams)
// iframe. // iframe.
IPC_STRUCT_MEMBER(FrameIDMap, node_to_frame_routing_id_map) 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)
// Type of event. // Type of event.
IPC_STRUCT_MEMBER(ui::AXEvent, event_type) IPC_STRUCT_MEMBER(ui::AXEvent, event_type)
......
...@@ -581,6 +581,8 @@ ...@@ -581,6 +581,8 @@
'browser/frame_host/cross_site_transferring_request.h', 'browser/frame_host/cross_site_transferring_request.h',
'browser/frame_host/debug_urls.cc', 'browser/frame_host/debug_urls.cc',
'browser/frame_host/debug_urls.h', 'browser/frame_host/debug_urls.h',
'browser/frame_host/frame_accessibility.cc',
'browser/frame_host/frame_accessibility.h',
'browser/frame_host/frame_tree.cc', 'browser/frame_host/frame_tree.cc',
'browser/frame_host/frame_tree.h', 'browser/frame_host/frame_tree.h',
'browser/frame_host/frame_tree_node.cc', 'browser/frame_host/frame_tree_node.cc',
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "content/renderer/accessibility/blink_ax_enum_conversion.h" #include "content/renderer/accessibility/blink_ax_enum_conversion.h"
#include "content/renderer/browser_plugin/browser_plugin.h"
#include "content/renderer/render_frame_impl.h" #include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_frame_proxy.h" #include "content/renderer/render_frame_proxy.h"
#include "content/renderer/render_view_impl.h" #include "content/renderer/render_view_impl.h"
...@@ -25,8 +26,9 @@ ...@@ -25,8 +26,9 @@
#include "third_party/WebKit/public/web/WebFormControlElement.h" #include "third_party/WebKit/public/web/WebFormControlElement.h"
#include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h" #include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebInputElement.h"
#include "third_party/WebKit/public/web/WebNode.h" #include "third_party/WebKit/public/web/WebNode.h"
#include "third_party/WebKit/public/web/WebPlugin.h"
#include "third_party/WebKit/public/web/WebPluginContainer.h"
#include "third_party/WebKit/public/web/WebView.h" #include "third_party/WebKit/public/web/WebView.h"
using base::ASCIIToUTF16; using base::ASCIIToUTF16;
...@@ -37,6 +39,8 @@ using blink::WebDocumentType; ...@@ -37,6 +39,8 @@ using blink::WebDocumentType;
using blink::WebElement; using blink::WebElement;
using blink::WebLocalFrame; using blink::WebLocalFrame;
using blink::WebNode; using blink::WebNode;
using blink::WebPlugin;
using blink::WebPluginContainer;
using blink::WebVector; using blink::WebVector;
using blink::WebView; using blink::WebView;
...@@ -97,7 +101,9 @@ void AddIntListAttributeFromWebObjects(ui::AXIntListAttribute attr, ...@@ -97,7 +101,9 @@ void AddIntListAttributeFromWebObjects(ui::AXIntListAttribute attr,
} // Anonymous namespace } // Anonymous namespace
BlinkAXTreeSource::BlinkAXTreeSource(RenderFrameImpl* render_frame) BlinkAXTreeSource::BlinkAXTreeSource(RenderFrameImpl* render_frame)
: render_frame_(render_frame) { : render_frame_(render_frame),
node_to_frame_routing_id_map_(NULL),
node_to_browser_plugin_instance_id_map_(NULL) {
} }
BlinkAXTreeSource::~BlinkAXTreeSource() { BlinkAXTreeSource::~BlinkAXTreeSource() {
...@@ -114,8 +120,11 @@ bool BlinkAXTreeSource::IsInTree(blink::WebAXObject node) const { ...@@ -114,8 +120,11 @@ bool BlinkAXTreeSource::IsInTree(blink::WebAXObject node) const {
} }
void BlinkAXTreeSource::CollectChildFrameIdMapping( void BlinkAXTreeSource::CollectChildFrameIdMapping(
std::map<int32, int>* node_to_frame_routing_id_map) { 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_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 { blink::WebAXObject BlinkAXTreeSource::GetRoot() const {
...@@ -350,6 +359,16 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src, ...@@ -350,6 +359,16 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
live_busy = UTF16ToUTF8(element.getAttribute("aria-busy")); live_busy = UTF16ToUTF8(element.getAttribute("aria-busy"));
live_status = UTF16ToUTF8(element.getAttribute("aria-live")); live_status = UTF16ToUTF8(element.getAttribute("aria-live"));
live_relevant = UTF16ToUTF8(element.getAttribute("aria-relevant")); live_relevant = UTF16ToUTF8(element.getAttribute("aria-relevant"));
// 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);
}
}
} }
// Walk up the parent chain to set live region attributes of containers // Walk up the parent chain to set live region attributes of containers
...@@ -461,14 +480,16 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src, ...@@ -461,14 +480,16 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
WebLocalFrame* frame = document.frame(); WebLocalFrame* frame = document.frame();
RenderFrameImpl* render_frame = RenderFrameImpl::FromWebFrame(frame); RenderFrameImpl* render_frame = RenderFrameImpl::FromWebFrame(frame);
if (render_frame) { if (render_frame) {
node_to_frame_routing_id_map_->insert(std::pair<int32, int>( (*node_to_frame_routing_id_map_)[dst->id] =
dst->id, render_frame->GetRoutingID())); render_frame->GetRoutingID();
dst->AddBoolAttribute(ui::AX_ATTR_IS_AX_TREE_HOST, true);
} else { } else {
RenderFrameProxy* render_frame_proxy = RenderFrameProxy* render_frame_proxy =
RenderFrameProxy::FromWebFrame(frame); RenderFrameProxy::FromWebFrame(frame);
if (render_frame_proxy) { if (render_frame_proxy) {
node_to_frame_routing_id_map_->insert(std::pair<int32, int>( (*node_to_frame_routing_id_map_)[dst->id] =
dst->id, render_frame_proxy->routing_id())); render_frame_proxy->routing_id();
dst->AddBoolAttribute(ui::AX_ATTR_IS_AX_TREE_HOST, true);
} }
} }
} }
......
...@@ -23,7 +23,8 @@ class BlinkAXTreeSource ...@@ -23,7 +23,8 @@ class BlinkAXTreeSource
// node ids to the frame routing id for an out-of-process iframe during // node ids to the frame routing id for an out-of-process iframe during
// calls to SerializeNode. // calls to SerializeNode.
void CollectChildFrameIdMapping( void CollectChildFrameIdMapping(
std::map<int32, int>* node_to_frame_routing_id_map); 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. // Walks up the ancestor chain to see if this is a descendant of the root.
bool IsInTree(blink::WebAXObject node) const; bool IsInTree(blink::WebAXObject node) const;
...@@ -49,7 +50,7 @@ class BlinkAXTreeSource ...@@ -49,7 +50,7 @@ class BlinkAXTreeSource
private: private:
RenderFrameImpl* render_frame_; RenderFrameImpl* render_frame_;
std::map<int32, int>* node_to_frame_routing_id_map_; std::map<int32, int>* node_to_frame_routing_id_map_;
std::map<int32, int>* node_to_browser_plugin_instance_id_map_;
}; };
} // namespace content } // namespace content
......
...@@ -208,7 +208,8 @@ void RendererAccessibilityComplete::SendPendingAccessibilityEvents() { ...@@ -208,7 +208,8 @@ void RendererAccessibilityComplete::SendPendingAccessibilityEvents() {
AccessibilityHostMsg_EventParams event_msg; AccessibilityHostMsg_EventParams event_msg;
tree_source_.CollectChildFrameIdMapping( tree_source_.CollectChildFrameIdMapping(
&event_msg.node_to_frame_routing_id_map); &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.event_type = event.event_type;
event_msg.id = event.id; event_msg.id = event.id;
serializer_.SerializeChanges(obj, &event_msg.update); serializer_.SerializeChanges(obj, &event_msg.update);
......
...@@ -41,8 +41,26 @@ using blink::WebRect; ...@@ -41,8 +41,26 @@ using blink::WebRect;
using blink::WebURL; using blink::WebURL;
using blink::WebVector; using blink::WebVector;
namespace {
typedef std::map<blink::WebPluginContainer*, content::BrowserPlugin*>
PluginContainerMap;
static base::LazyInstance<PluginContainerMap> g_plugin_container_map =
LAZY_INSTANCE_INITIALIZER;
} // namespace
namespace content { namespace content {
// static
BrowserPlugin* BrowserPlugin::GetFromNode(blink::WebNode& node) {
blink::WebPluginContainer* container = node.pluginContainer();
if (!container)
return NULL;
PluginContainerMap* browser_plugins = g_plugin_container_map.Pointer();
PluginContainerMap::iterator it = browser_plugins->find(container);
return it == browser_plugins->end() ? NULL : it->second;
}
BrowserPlugin::BrowserPlugin(RenderViewImpl* render_view, BrowserPlugin::BrowserPlugin(RenderViewImpl* render_view,
blink::WebFrame* frame, blink::WebFrame* frame,
scoped_ptr<BrowserPluginDelegate> delegate) scoped_ptr<BrowserPluginDelegate> delegate)
...@@ -378,6 +396,8 @@ bool BrowserPlugin::initialize(WebPluginContainer* container) { ...@@ -378,6 +396,8 @@ bool BrowserPlugin::initialize(WebPluginContainer* container) {
container_ = container; container_ = container;
container_->setWantsWheelEvents(true); container_->setWantsWheelEvents(true);
g_plugin_container_map.Get().insert(std::make_pair(container_, this));
// This is a way to notify observers of our attributes that this plugin is // This is a way to notify observers of our attributes that this plugin is
// available in render tree. // available in render tree.
// TODO(lazyboy): This should be done through the delegate instead. Perhaps // TODO(lazyboy): This should be done through the delegate instead. Perhaps
...@@ -418,6 +438,10 @@ void BrowserPlugin::destroy() { ...@@ -418,6 +438,10 @@ void BrowserPlugin::destroy() {
if (container_) if (container_)
container_->clearScriptObjects(); container_->clearScriptObjects();
// The BrowserPlugin's WebPluginContainer is deleted immediately after this
// call returns, so let's not keep a reference to it around.
g_plugin_container_map.Get().erase(container_);
if (compositing_helper_.get()) if (compositing_helper_.get())
compositing_helper_->OnContainerDestroy(); compositing_helper_->OnContainerDestroy();
container_ = NULL; container_ = NULL;
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "content/renderer/render_view_impl.h" #include "content/renderer/render_view_impl.h"
#include "third_party/WebKit/public/web/WebCompositionUnderline.h" #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
#include "third_party/WebKit/public/web/WebDragStatus.h" #include "third_party/WebKit/public/web/WebDragStatus.h"
#include "third_party/WebKit/public/web/WebNode.h"
#include "third_party/WebKit/public/web/WebWidget.h" #include "third_party/WebKit/public/web/WebWidget.h"
struct BrowserPluginHostMsg_ResizeGuest_Params; struct BrowserPluginHostMsg_ResizeGuest_Params;
...@@ -32,6 +33,8 @@ class CONTENT_EXPORT BrowserPlugin : ...@@ -32,6 +33,8 @@ class CONTENT_EXPORT BrowserPlugin :
NON_EXPORTED_BASE(public blink::WebPlugin), NON_EXPORTED_BASE(public blink::WebPlugin),
public MouseLockDispatcher::LockTarget { public MouseLockDispatcher::LockTarget {
public: public:
static BrowserPlugin* GetFromNode(blink::WebNode& node);
RenderViewImpl* render_view() const { return render_view_.get(); } RenderViewImpl* render_view() const { return render_view_.get(); }
int render_view_routing_id() const { return render_view_routing_id_; } int render_view_routing_id() const { return render_view_routing_id_; }
int browser_plugin_instance_id() const { return browser_plugin_instance_id_; } int browser_plugin_instance_id() const { return browser_plugin_instance_id_; }
......
...@@ -19,6 +19,7 @@ namespace content { ...@@ -19,6 +19,7 @@ namespace content {
// static // static
BrowserPluginManagerFactory* BrowserPluginManager::factory_ = NULL; BrowserPluginManagerFactory* BrowserPluginManager::factory_ = NULL;
// static
BrowserPluginManager* BrowserPluginManager::Create( BrowserPluginManager* BrowserPluginManager::Create(
RenderViewImpl* render_view) { RenderViewImpl* render_view) {
if (factory_) if (factory_)
......
...@@ -319,7 +319,12 @@ ...@@ -319,7 +319,12 @@
update_location_only, update_location_only,
// Set on a canvas element if it has fallback content. // Set on a canvas element if it has fallback content.
canvas_has_fallback canvas_has_fallback,
// Set if this node is the host of an external AXTree, for
// example a web view that's a child of a native view, or a
// web iframe that's the child of another web frame.
is_ax_tree_host
}; };
[cpp_enum_prefix_override="ax_attr"] enum AXIntListAttribute { [cpp_enum_prefix_override="ax_attr"] enum AXIntListAttribute {
......
...@@ -343,6 +343,9 @@ std::string AXNodeData::ToString() const { ...@@ -343,6 +343,9 @@ std::string AXNodeData::ToString() const {
case AX_ATTR_CANVAS_HAS_FALLBACK: case AX_ATTR_CANVAS_HAS_FALLBACK:
result += " has_fallback=" + value; result += " has_fallback=" + value;
break; break;
case AX_ATTR_IS_AX_TREE_HOST:
result += " is_ax_tree_host=" + value;
break;
case AX_BOOL_ATTRIBUTE_NONE: case AX_BOOL_ATTRIBUTE_NONE:
break; break;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment