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
->parent_frame_host
,
116 iter
->browser_plugin_instance_id
);
118 return static_cast<RenderFrameHostImpl
*>(guest
);
125 void FrameAccessibility::GetAllChildFrames(
126 RenderFrameHostImpl
* parent_frame_host
,
127 std::vector
<RenderFrameHostImpl
*>* child_frame_hosts
) {
128 CHECK(child_frame_hosts
);
130 for (std::vector
<ChildFrameMapping
>::iterator iter
= mappings_
.begin();
131 iter
!= mappings_
.end();
133 if (iter
->parent_frame_host
!= parent_frame_host
)
136 if (iter
->child_frame_tree_node_id
) {
137 RenderFrameHostImpl
* child_frame_host
= GetRFHIFromFrameTreeNodeId(
138 parent_frame_host
, iter
->child_frame_tree_node_id
);
139 if (child_frame_host
)
140 child_frame_hosts
->push_back(child_frame_host
);
143 if (iter
->browser_plugin_instance_id
) {
144 RenderFrameHost
* guest
=
145 parent_frame_host
->delegate()->GetGuestByInstanceID(
146 iter
->parent_frame_host
,
147 iter
->browser_plugin_instance_id
);
149 child_frame_hosts
->push_back(static_cast<RenderFrameHostImpl
*>(guest
));
154 bool FrameAccessibility::GetParent(
155 RenderFrameHostImpl
* child_frame_host
,
156 RenderFrameHostImpl
** out_parent_frame_host
,
157 int* out_accessibility_node_id
) {
158 for (std::vector
<ChildFrameMapping
>::iterator iter
= mappings_
.begin();
159 iter
!= mappings_
.end();
161 if (iter
->child_frame_tree_node_id
) {
162 FrameTreeNode
* child_node
=
163 FrameTreeNode::GloballyFindByID(iter
->child_frame_tree_node_id
);
165 child_node
->current_frame_host() == child_frame_host
) {
166 // Assert that the child node is a descendant of the parent frame in
167 // the frame tree. It may not be a direct descendant because the
168 // parent frame's accessibility tree may span multiple frames from the
170 FrameTreeNode
* parent_node
= iter
->parent_frame_host
->frame_tree_node();
171 FrameTreeNode
* child_node_ancestor
= child_node
->parent();
172 while (child_node_ancestor
&& child_node_ancestor
!= parent_node
)
173 child_node_ancestor
= child_node_ancestor
->parent();
174 if (child_node_ancestor
!= parent_node
) {
179 if (out_parent_frame_host
)
180 *out_parent_frame_host
= iter
->parent_frame_host
;
181 if (out_accessibility_node_id
)
182 *out_accessibility_node_id
= iter
->accessibility_node_id
;
187 if (iter
->browser_plugin_instance_id
) {
188 RenderFrameHost
* guest
=
189 iter
->parent_frame_host
->delegate()->GetGuestByInstanceID(
190 iter
->parent_frame_host
,
191 iter
->browser_plugin_instance_id
);
192 if (guest
== child_frame_host
) {
193 if (out_parent_frame_host
)
194 *out_parent_frame_host
= iter
->parent_frame_host
;
195 if (out_accessibility_node_id
)
196 *out_accessibility_node_id
= iter
->accessibility_node_id
;
205 RenderFrameHostImpl
* FrameAccessibility::GetRFHIFromFrameTreeNodeId(
206 RenderFrameHostImpl
* parent_frame_host
,
207 int64 child_frame_tree_node_id
) {
208 FrameTreeNode
* child_node
=
209 FrameTreeNode::GloballyFindByID(child_frame_tree_node_id
);
213 // Assert that the child node is a descendant of the parent frame in
214 // the frame tree. It may not be a direct descendant because the
215 // parent frame's accessibility tree may span multiple frames from the
217 FrameTreeNode
* parent_node
= parent_frame_host
->frame_tree_node();
218 FrameTreeNode
* child_node_ancestor
= child_node
->parent();
219 while (child_node_ancestor
&& child_node_ancestor
!= parent_node
)
220 child_node_ancestor
= child_node_ancestor
->parent();
221 if (child_node_ancestor
!= parent_node
) {
226 return child_node
->current_frame_host();
229 } // namespace content