1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/frame_host/frame_accessibility.h"
7 #include "content/browser/frame_host/frame_tree.h"
8 #include "content/browser/frame_host/frame_tree_node.h"
9 #include "content/browser/frame_host/render_frame_host_delegate.h"
10 #include "content/browser/frame_host/render_frame_host_impl.h"
11 #include "content/public/browser/browser_context.h"
16 FrameAccessibility
* FrameAccessibility::GetInstance() {
17 return Singleton
<FrameAccessibility
>::get();
20 FrameAccessibility::ChildFrameMapping::ChildFrameMapping()
21 : parent_frame_host(nullptr),
22 accessibility_node_id(0),
23 child_frame_tree_node_id(0),
24 browser_plugin_instance_id(0) {}
26 FrameAccessibility::FrameAccessibility() {}
28 FrameAccessibility::~FrameAccessibility() {}
30 void FrameAccessibility::AddChildFrame(
31 RenderFrameHostImpl
* parent_frame_host
,
32 int accessibility_node_id
,
33 int64 child_frame_tree_node_id
) {
34 for (std::vector
<ChildFrameMapping
>::iterator iter
= mappings_
.begin();
35 iter
!= mappings_
.end();
37 // TODO(dmazzoni): the renderer should keep track of these mappings
38 // and clear an existing mapping before setting a new one, that would
39 // be safer than just updating existing mappings. http://crbug.com/413464
40 if (iter
->parent_frame_host
== parent_frame_host
&&
41 (iter
->accessibility_node_id
== accessibility_node_id
||
42 iter
->child_frame_tree_node_id
== child_frame_tree_node_id
)) {
43 iter
->accessibility_node_id
= accessibility_node_id
;
44 iter
->child_frame_tree_node_id
= child_frame_tree_node_id
;
49 ChildFrameMapping new_mapping
;
50 new_mapping
.parent_frame_host
= parent_frame_host
;
51 new_mapping
.accessibility_node_id
= accessibility_node_id
;
52 new_mapping
.child_frame_tree_node_id
= child_frame_tree_node_id
;
53 mappings_
.push_back(new_mapping
);
56 void FrameAccessibility::AddGuestWebContents(
57 RenderFrameHostImpl
* parent_frame_host
,
58 int accessibility_node_id
,
59 int browser_plugin_instance_id
) {
60 for (std::vector
<ChildFrameMapping
>::iterator iter
= mappings_
.begin();
61 iter
!= mappings_
.end();
63 // TODO(dmazzoni): the renderer should keep track of these mappings
64 // and clear an existing mapping before setting a new one, that would
65 // be safer than just updating existing mappings. http://crbug.com/413464
66 if (iter
->parent_frame_host
== parent_frame_host
&&
67 (iter
->accessibility_node_id
== accessibility_node_id
||
68 iter
->browser_plugin_instance_id
== browser_plugin_instance_id
)) {
69 iter
->accessibility_node_id
= accessibility_node_id
;
70 iter
->browser_plugin_instance_id
= browser_plugin_instance_id
;
75 ChildFrameMapping new_mapping
;
76 new_mapping
.parent_frame_host
= parent_frame_host
;
77 new_mapping
.accessibility_node_id
= accessibility_node_id
;
78 new_mapping
.browser_plugin_instance_id
= browser_plugin_instance_id
;
79 mappings_
.push_back(new_mapping
);
82 void FrameAccessibility::OnRenderFrameHostDestroyed(
83 RenderFrameHostImpl
* render_frame_host
) {
84 // Since the order doesn't matter, the fastest way to remove all items
85 // with this render_frame_host is to iterate over the vector backwards,
86 // swapping each one with the back element if we need to delete it.
87 int initial_len
= static_cast<int>(mappings_
.size());
88 for (int i
= initial_len
- 1; i
>= 0; i
--) {
89 if (mappings_
[i
].parent_frame_host
== render_frame_host
) {
90 mappings_
[i
] = mappings_
.back();
96 RenderFrameHostImpl
* FrameAccessibility::GetChild(
97 RenderFrameHostImpl
* parent_frame_host
,
98 int accessibility_node_id
) {
99 for (std::vector
<ChildFrameMapping
>::iterator iter
= mappings_
.begin();
100 iter
!= mappings_
.end();
102 if (iter
->parent_frame_host
!= parent_frame_host
||
103 iter
->accessibility_node_id
!= accessibility_node_id
) {
107 if (iter
->child_frame_tree_node_id
) {
108 return GetRFHIFromFrameTreeNodeId(
109 parent_frame_host
, iter
->child_frame_tree_node_id
);
112 if (iter
->browser_plugin_instance_id
) {
113 RenderFrameHost
* guest
=
114 parent_frame_host
->delegate()->GetGuestByInstanceID(
115 iter
->browser_plugin_instance_id
);
117 return static_cast<RenderFrameHostImpl
*>(guest
);
124 void FrameAccessibility::GetAllChildFrames(
125 RenderFrameHostImpl
* parent_frame_host
,
126 std::vector
<RenderFrameHostImpl
*>* child_frame_hosts
) {
127 CHECK(child_frame_hosts
);
129 for (std::vector
<ChildFrameMapping
>::iterator iter
= mappings_
.begin();
130 iter
!= mappings_
.end();
132 if (iter
->parent_frame_host
!= parent_frame_host
)
135 if (iter
->child_frame_tree_node_id
) {
136 RenderFrameHostImpl
* child_frame_host
= GetRFHIFromFrameTreeNodeId(
137 parent_frame_host
, iter
->child_frame_tree_node_id
);
138 if (child_frame_host
)
139 child_frame_hosts
->push_back(child_frame_host
);
142 if (iter
->browser_plugin_instance_id
) {
143 RenderFrameHost
* guest
=
144 parent_frame_host
->delegate()->GetGuestByInstanceID(
145 iter
->browser_plugin_instance_id
);
147 child_frame_hosts
->push_back(static_cast<RenderFrameHostImpl
*>(guest
));
152 bool FrameAccessibility::GetParent(
153 RenderFrameHostImpl
* child_frame_host
,
154 RenderFrameHostImpl
** out_parent_frame_host
,
155 int* out_accessibility_node_id
) {
156 for (std::vector
<ChildFrameMapping
>::iterator iter
= mappings_
.begin();
157 iter
!= mappings_
.end();
159 if (iter
->child_frame_tree_node_id
) {
160 FrameTreeNode
* child_node
=
161 FrameTree::GloballyFindByID(iter
->child_frame_tree_node_id
);
163 child_node
->current_frame_host() == child_frame_host
) {
164 // Assert that the child node is a descendant of the parent frame in
165 // the frame tree. It may not be a direct descendant because the
166 // parent frame's accessibility tree may span multiple frames from the
168 FrameTreeNode
* parent_node
= iter
->parent_frame_host
->frame_tree_node();
169 FrameTreeNode
* child_node_ancestor
= child_node
->parent();
170 while (child_node_ancestor
&& child_node_ancestor
!= parent_node
)
171 child_node_ancestor
= child_node_ancestor
->parent();
172 if (child_node_ancestor
!= parent_node
) {
177 if (out_parent_frame_host
)
178 *out_parent_frame_host
= iter
->parent_frame_host
;
179 if (out_accessibility_node_id
)
180 *out_accessibility_node_id
= iter
->accessibility_node_id
;
185 if (iter
->browser_plugin_instance_id
) {
186 RenderFrameHost
* guest
=
187 iter
->parent_frame_host
->delegate()->GetGuestByInstanceID(
188 iter
->browser_plugin_instance_id
);
189 if (guest
== child_frame_host
) {
190 if (out_parent_frame_host
)
191 *out_parent_frame_host
= iter
->parent_frame_host
;
192 if (out_accessibility_node_id
)
193 *out_accessibility_node_id
= iter
->accessibility_node_id
;
202 RenderFrameHostImpl
* FrameAccessibility::GetRFHIFromFrameTreeNodeId(
203 RenderFrameHostImpl
* parent_frame_host
,
204 int64 child_frame_tree_node_id
) {
205 FrameTreeNode
* child_node
=
206 FrameTree::GloballyFindByID(child_frame_tree_node_id
);
210 // Assert that the child node is a descendant of the parent frame in
211 // the frame tree. It may not be a direct descendant because the
212 // parent frame's accessibility tree may span multiple frames from the
214 FrameTreeNode
* parent_node
= parent_frame_host
->frame_tree_node();
215 FrameTreeNode
* child_node_ancestor
= child_node
->parent();
216 while (child_node_ancestor
&& child_node_ancestor
!= parent_node
)
217 child_node_ancestor
= child_node_ancestor
->parent();
218 if (child_node_ancestor
!= parent_node
) {
223 return child_node
->current_frame_host();
226 } // namespace content