Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(340)

Side by Side Diff: chrome/browser/browser_accessibility_manager.cc

Issue 115374: Adds propagation and handling of render-side focus events, for the benefit of... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/browser_accessibility_manager.h" 5 #include "chrome/browser/browser_accessibility_manager.h"
6 6
7 #include "chrome/browser/browser_accessibility.h" 7 #include "chrome/browser/browser_accessibility.h"
8 #include "chrome/browser/renderer_host/render_process_host.h" 8 #include "chrome/browser/renderer_host/render_process_host.h"
9 #include "chrome/browser/renderer_host/render_widget_host.h" 9 #include "chrome/browser/renderer_host/render_view_host.h"
10 #include "chrome/common/notification_service.h" 10 #include "chrome/common/notification_service.h"
11 #include "chrome/common/render_messages.h" 11 #include "chrome/common/render_messages.h"
12 12
13 using webkit_glue::WebAccessibility; 13 using webkit_glue::WebAccessibility;
14 14
15 // The time in ms after which we give up and return an error when processing an 15 // The time in ms after which we give up and return an error when processing an
16 // accessibility message and no response has been received from the renderer. 16 // accessibility message and no response has been received from the renderer.
17 static const int kAccessibilityMessageTimeOut = 10000; 17 static const int kAccessibilityMessageTimeOut = 10000;
18 18
19 // static 19 // static
20 BrowserAccessibilityManager* BrowserAccessibilityManager::GetInstance() { 20 BrowserAccessibilityManager* BrowserAccessibilityManager::GetInstance() {
21 return Singleton<BrowserAccessibilityManager>::get(); 21 return Singleton<BrowserAccessibilityManager>::get();
22 } 22 }
23 23
24 BrowserAccessibilityManager::BrowserAccessibilityManager() 24 BrowserAccessibilityManager::BrowserAccessibilityManager() {
25 : instance_id_(0) {
26 NotificationService::current()->AddObserver(this, 25 NotificationService::current()->AddObserver(this,
27 NotificationType::RENDERER_PROCESS_TERMINATED, 26 NotificationType::RENDERER_PROCESS_TERMINATED,
28 NotificationService::AllSources()); 27 NotificationService::AllSources());
29 } 28 }
30 29
31 BrowserAccessibilityManager::~BrowserAccessibilityManager() { 30 BrowserAccessibilityManager::~BrowserAccessibilityManager() {
32 // Clear hashmaps. 31 // Clear hashmap.
33 instance_map_.clear();
34 render_process_host_map_.clear(); 32 render_process_host_map_.clear();
35 33
36 // We don't remove ourselves as an observer because we are a Singleton object, 34 // We don't remove ourselves as an observer because we are a Singleton object,
37 // and NotifcationService is likely gone by this point. 35 // and NotifcationService is likely gone by this point.
38 } 36 }
39 37
40 STDMETHODIMP BrowserAccessibilityManager::CreateAccessibilityInstance( 38 STDMETHODIMP BrowserAccessibilityManager::CreateAccessibilityInstance(
41 REFIID iid, int acc_obj_id, int instance_id, void** interface_ptr) { 39 REFIID iid, int acc_obj_id, int routing_id, int process_id,
40 HWND parent_hwnd, void** interface_ptr) {
42 if (IID_IUnknown == iid || IID_IDispatch == iid || IID_IAccessible == iid) { 41 if (IID_IUnknown == iid || IID_IDispatch == iid || IID_IAccessible == iid) {
43 CComObject<BrowserAccessibility>* instance = NULL; 42 CComObject<BrowserAccessibility>* instance = NULL;
44 43
45 HRESULT hr = CComObject<BrowserAccessibility>::CreateInstance(&instance); 44 HRESULT hr = CComObject<BrowserAccessibility>::CreateInstance(&instance);
46 DCHECK(SUCCEEDED(hr)); 45 DCHECK(SUCCEEDED(hr));
47 46
48 if (!instance) 47 if (!instance)
49 return E_FAIL; 48 return E_FAIL;
50 49
51 CComPtr<IAccessible> accessibility_instance(instance); 50 CComPtr<IAccessible> accessibility_instance(instance);
52 51
53 // Set unique ids. 52 // Set class member variables.
54 instance->set_iaccessible_id(acc_obj_id); 53 instance->Initialize(acc_obj_id, routing_id, process_id, parent_hwnd);
55 instance->set_instance_id(instance_id);
56 54
57 // Retrieve the RenderWidgetHost connected to this request. 55 // Retrieve the RenderViewHost connected to this request.
58 InstanceMap::iterator it = instance_map_.find(instance_id); 56 RenderViewHost* rvh = RenderViewHost::FromID(process_id, routing_id);
59 57
60 if (it != instance_map_.end()) { 58 // Update cache with RenderProcessHost/BrowserAccessibility pair.
61 UniqueMembers* members = it->second; 59 if (rvh && rvh->process()) {
62 60 render_process_host_map_.insert(
63 if (!members || !members->render_widget_host_) 61 MapEntry(rvh->process()->pid(), instance));
64 return E_FAIL;
65
66 render_process_host_map_[members->render_widget_host_->process()] =
67 instance;
68 } else { 62 } else {
69 // No RenderProcess active for this instance. 63 // No RenderProcess active for this instance.
70 return E_FAIL; 64 return E_FAIL;
71 } 65 }
72 66
73 // All is well, assign the temp instance to the output pointer. 67 // All is well, assign the temp instance to the output pointer.
74 *interface_ptr = accessibility_instance.Detach(); 68 *interface_ptr = accessibility_instance.Detach();
75 return S_OK; 69 return S_OK;
76 } 70 }
77 // No supported interface found, return error. 71 // No supported interface found, return error.
78 *interface_ptr = NULL; 72 *interface_ptr = NULL;
79 return E_NOINTERFACE; 73 return E_NOINTERFACE;
80 } 74 }
81 75
82 bool BrowserAccessibilityManager::RequestAccessibilityInfo( 76 bool BrowserAccessibilityManager::RequestAccessibilityInfo(
83 int acc_obj_id, int instance_id, int acc_func_id, int child_id, long input1, 77 WebAccessibility::InParams* in, int routing_id, int process_id) {
84 long input2) {
85 // Create and populate IPC message structure, for retrieval of accessibility 78 // Create and populate IPC message structure, for retrieval of accessibility
86 // information from the renderer. 79 // information from the renderer.
87 WebAccessibility::InParams in_params; 80 WebAccessibility::InParams in_params;
88 in_params.object_id = acc_obj_id; 81 in_params.object_id = in->object_id;
89 in_params.function_id = acc_func_id; 82 in_params.function_id = in->function_id;
90 in_params.child_id = child_id; 83 in_params.child_id = in->child_id;
91 in_params.input_long1 = input1; 84 in_params.direct_descendant = in->direct_descendant;
92 in_params.input_long2 = input2; 85 in_params.input_long1 = in->input_long1;
86 in_params.input_long2 = in->input_long2;
93 87
94 // Retrieve the RenderWidgetHost connected to this request. 88 // Retrieve the RenderViewHost connected to this request.
95 InstanceMap::iterator it = instance_map_.find(instance_id); 89 RenderViewHost* rvh = RenderViewHost::FromID(process_id, routing_id);
96 90
97 if (it == instance_map_.end()) { 91 // Send accessibility information retrieval message to the renderer.
98 // Id not found.
99 return false;
100 }
101
102 UniqueMembers* members = it->second;
103
104 if (!members || !members->render_widget_host_)
105 return false;
106
107 bool success = false; 92 bool success = false;
108 if (members->render_widget_host_->process() && 93 if (rvh && rvh->process() && rvh->process()->channel()) {
109 members->render_widget_host_->process()->channel()) {
110 IPC::SyncMessage* msg = 94 IPC::SyncMessage* msg =
111 new ViewMsg_GetAccessibilityInfo(members->render_widget_host_-> 95 new ViewMsg_GetAccessibilityInfo(routing_id, in_params, &out_params_);
112 routing_id(), in_params, &out_params_);
113 // Necessary for the send to keep the UI responsive. 96 // Necessary for the send to keep the UI responsive.
114 msg->EnableMessagePumping(); 97 msg->EnableMessagePumping();
115 success = members->render_widget_host_->process()->channel()-> 98 success = rvh->process()->channel()->SendWithTimeout(msg,
116 SendWithTimeout(msg, kAccessibilityMessageTimeOut); 99 kAccessibilityMessageTimeOut);
117 } 100 }
118 return success; 101 return success;
119 } 102 }
120 103
104 bool BrowserAccessibilityManager::ChangeAccessibilityFocus(int acc_obj_id,
105 int process_id,
106 int routing_id) {
107 BrowserAccessibility* browser_acc =
108 GetBrowserAccessibility(process_id, routing_id);
109 if (browser_acc) {
110 // Indicate that the request for child information is referring to a non-
111 // direct descendant of the root.
112 browser_acc->set_direct_descendant(false);
113
114 // Notify Access Technology that there was a change in keyboard focus.
115 ::NotifyWinEvent(EVENT_OBJECT_FOCUS, browser_acc->parent_hwnd(),
116 OBJID_CLIENT, static_cast<LONG>(acc_obj_id));
117 return true;
118 }
119 return false;
120 }
121
121 const WebAccessibility::OutParams& BrowserAccessibilityManager::response() { 122 const WebAccessibility::OutParams& BrowserAccessibilityManager::response() {
122 return out_params_; 123 return out_params_;
123 } 124 }
124 125
125 HWND BrowserAccessibilityManager::parent_hwnd(int id) { 126 BrowserAccessibility* BrowserAccessibilityManager::GetBrowserAccessibility(
126 // Retrieve the parent HWND connected to the requester's id. 127 int process_id, int routing_id) {
127 InstanceMap::iterator it = instance_map_.find(id); 128 // Retrieve the BrowserAccessibility connected to the requester's id. There
129 // could be multiple BrowserAccessibility connected to the given |process_id|,
130 // but they all have the same parent HWND, so using the first hit is fine.
131 RenderProcessHostMap::iterator it =
132 render_process_host_map_.lower_bound(process_id);
128 133
129 if (it == instance_map_.end()) { 134 RenderProcessHostMap::iterator end_of_matching_objects =
130 // Id not found. 135 render_process_host_map_.upper_bound(process_id);
131 return NULL; 136
137 for (; it != end_of_matching_objects; ++it) {
138 if (it->second && it->second->routing_id() == routing_id)
139 return it->second;
132 } 140 }
133 141 return NULL;
134 UniqueMembers* members = it->second;
135
136 if (!members || !members->parent_hwnd_)
137 return NULL;
138
139 return members->parent_hwnd_;
140 }
141
142 int BrowserAccessibilityManager::SetMembers(BrowserAccessibility* browser_acc,
143 HWND parent_hwnd, RenderWidgetHost* render_widget_host) {
144 // Set HWND and RenderWidgetHost connected to |browser_acc|.
145 instance_map_[instance_id_] =
146 new UniqueMembers(parent_hwnd, render_widget_host);
147
148 render_process_host_map_[render_widget_host->process()] = browser_acc;
149 return instance_id_++;
150 } 142 }
151 143
152 void BrowserAccessibilityManager::Observe(NotificationType type, 144 void BrowserAccessibilityManager::Observe(NotificationType type,
153 const NotificationSource& source, 145 const NotificationSource& source,
154 const NotificationDetails& details) { 146 const NotificationDetails& details) {
155 DCHECK(type == NotificationType::RENDERER_PROCESS_TERMINATED); 147 DCHECK(type == NotificationType::RENDERER_PROCESS_TERMINATED);
156 RenderProcessHost* rph = Source<RenderProcessHost>(source).ptr(); 148 RenderProcessHost* rph = Source<RenderProcessHost>(source).ptr();
157 DCHECK(rph); 149 DCHECK(rph);
158 RenderProcessHostMap::iterator it = render_process_host_map_.find(rph);
159 150
160 if (it == render_process_host_map_.end() || !it->second) { 151 RenderProcessHostMap::iterator it =
161 // RenderProcessHost not associated with any BrowserAccessibility instance. 152 render_process_host_map_.lower_bound(rph->pid());
162 return; 153
154 RenderProcessHostMap::iterator end_of_matching_objects =
155 render_process_host_map_.upper_bound(rph->pid());
156
157 for (; it != end_of_matching_objects; ++it) {
158 if (it->second) {
159 // Set all matching BrowserAccessibility instances to inactive state.
160 // TODO(klink): Do more active memory cleanup as well.
161 it->second->set_instance_active(false);
162 }
163 } 163 }
164
165 // Set BrowserAccessibility instance to inactive state.
166 it->second->set_instance_active(false);
167
168 // Delete entry also from InstanceMap.
169 InstanceMap::iterator it2 = instance_map_.find(it->second->instance_id());
170
171 if (it2 != instance_map_.end())
172 instance_map_.erase(it2);
173
174 // Only delete the first entry once it is no longer in use.
175 render_process_host_map_.erase(it);
176 } 164 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698