• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "content/browser/frame_host/frame_accessibility.h"
6 
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"
12 
13 namespace content {
14 
15 // static
GetInstance()16 FrameAccessibility* FrameAccessibility::GetInstance() {
17   return Singleton<FrameAccessibility>::get();
18 }
19 
ChildFrameMapping()20 FrameAccessibility::ChildFrameMapping::ChildFrameMapping()
21     : parent_frame_host(NULL),
22       accessibility_node_id(0),
23       child_frame_tree_node_id(0),
24       browser_plugin_instance_id(0) {}
25 
FrameAccessibility()26 FrameAccessibility::FrameAccessibility() {}
27 
~FrameAccessibility()28 FrameAccessibility::~FrameAccessibility() {}
29 
AddChildFrame(RenderFrameHostImpl * parent_frame_host,int accessibility_node_id,int64 child_frame_tree_node_id)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;
46     }
47   }
48 
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);
54 }
55 
AddGuestWebContents(RenderFrameHostImpl * parent_frame_host,int accessibility_node_id,int browser_plugin_instance_id)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;
72     }
73   }
74 
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);
80 }
81 
OnRenderFrameHostDestroyed(RenderFrameHostImpl * render_frame_host)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();
92     }
93   }
94 }
95 
GetChild(RenderFrameHostImpl * parent_frame_host,int accessibility_node_id)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;
105     }
106 
107     if (iter->child_frame_tree_node_id) {
108       FrameTreeNode* child_node =
109           FrameTree::GloballyFindByID(iter->child_frame_tree_node_id);
110       if (!child_node)
111         return NULL;
112 
113       // We should have gotten a node in the same frame tree.
114       if (child_node->frame_tree() !=
115               parent_frame_host->frame_tree_node()->frame_tree()) {
116         NOTREACHED();
117         return NULL;
118       }
119 
120       return child_node->current_frame_host();
121     }
122 
123     if (iter->browser_plugin_instance_id) {
124       RenderFrameHost* guest =
125           parent_frame_host->delegate()->GetGuestByInstanceID(
126               iter->browser_plugin_instance_id);
127       if (guest)
128         return static_cast<RenderFrameHostImpl*>(guest);
129     }
130   }
131 
132   return NULL;
133 }
134 
GetParent(RenderFrameHostImpl * child_frame_host,RenderFrameHostImpl ** out_parent_frame_host,int * out_accessibility_node_id)135 bool FrameAccessibility::GetParent(
136     RenderFrameHostImpl* child_frame_host,
137     RenderFrameHostImpl** out_parent_frame_host,
138     int* out_accessibility_node_id) {
139   for (std::vector<ChildFrameMapping>::iterator iter = mappings_.begin();
140        iter != mappings_.end();
141        ++iter) {
142     if (iter->child_frame_tree_node_id) {
143       FrameTreeNode* child_node =
144           FrameTree::GloballyFindByID(iter->child_frame_tree_node_id);
145       if (child_node &&
146           child_node->current_frame_host() == child_frame_host) {
147         // We should have gotten a node in the same frame tree.
148         if (child_node->frame_tree() !=
149                 iter->parent_frame_host->frame_tree_node()->frame_tree()) {
150           NOTREACHED();
151           return false;
152         }
153 
154         if (out_parent_frame_host)
155           *out_parent_frame_host = iter->parent_frame_host;
156         if (out_accessibility_node_id)
157           *out_accessibility_node_id = iter->accessibility_node_id;
158         return true;
159       }
160     }
161 
162     if (iter->browser_plugin_instance_id) {
163       RenderFrameHost* guest =
164           iter->parent_frame_host->delegate()->GetGuestByInstanceID(
165               iter->browser_plugin_instance_id);
166       if (guest == child_frame_host) {
167         if (out_parent_frame_host)
168           *out_parent_frame_host = iter->parent_frame_host;
169         if (out_accessibility_node_id)
170           *out_accessibility_node_id = iter->accessibility_node_id;
171         return true;
172       }
173     }
174   }
175 
176   return false;
177 }
178 
179 }  // namespace content
180