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 13namespace content { 14 15// static 16FrameAccessibility* FrameAccessibility::GetInstance() { 17 return Singleton<FrameAccessibility>::get(); 18} 19 20FrameAccessibility::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 26FrameAccessibility::FrameAccessibility() {} 27 28FrameAccessibility::~FrameAccessibility() {} 29 30void 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 56void 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 82void 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 96RenderFrameHostImpl* 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 135bool 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