Add remoting and PPAPI tests to GN build
[chromium-blink-merge.git] / content / browser / frame_host / frame_accessibility.cc
blob89347175965028170dd3ea8f3c222110fe124f63
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"
13 namespace content {
15 // static
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();
36 ++iter) {
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;
45 return;
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();
62 ++iter) {
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;
71 return;
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();
91 mappings_.pop_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();
101 ++iter) {
102 if (iter->parent_frame_host != parent_frame_host ||
103 iter->accessibility_node_id != accessibility_node_id) {
104 continue;
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);
117 if (guest)
118 return static_cast<RenderFrameHostImpl*>(guest);
122 return nullptr;
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();
132 ++iter) {
133 if (iter->parent_frame_host != parent_frame_host)
134 continue;
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);
148 if (guest)
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();
160 ++iter) {
161 if (iter->child_frame_tree_node_id) {
162 FrameTreeNode* child_node =
163 FrameTree::GloballyFindByID(iter->child_frame_tree_node_id);
164 if (child_node &&
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
169 // same origin.
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) {
175 NOTREACHED();
176 return false;
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;
183 return true;
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;
197 return true;
202 return false;
205 RenderFrameHostImpl* FrameAccessibility::GetRFHIFromFrameTreeNodeId(
206 RenderFrameHostImpl* parent_frame_host,
207 int64 child_frame_tree_node_id) {
208 FrameTreeNode* child_node =
209 FrameTree::GloballyFindByID(child_frame_tree_node_id);
210 if (!child_node)
211 return nullptr;
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
216 // same origin.
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) {
222 NOTREACHED();
223 return nullptr;
226 return child_node->current_frame_host();
229 } // namespace content