OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome/browser/browser_accessibility_manager.h" |
| 6 |
| 7 #include "chrome/browser/browser_accessibility.h" |
| 8 #include "chrome/browser/render_process_host.h" |
| 9 #include "chrome/browser/render_widget_host.h" |
| 10 |
| 11 // The time in ms after which we give up and return an error when processing an |
| 12 // accessibility message and no response has been received from the renderer. |
| 13 static const int kAccessibilityMessageTimeOut = 500; |
| 14 |
| 15 // static |
| 16 BrowserAccessibilityManager* BrowserAccessibilityManager::Instance() { |
| 17 return Singleton<BrowserAccessibilityManager>::get(); |
| 18 } |
| 19 |
| 20 BrowserAccessibilityManager::BrowserAccessibilityManager() |
| 21 : instance_id_(0) { |
| 22 NotificationService::current()->AddObserver(this, |
| 23 NOTIFY_RENDERER_PROCESS_TERMINATED, NotificationService::AllSources()); |
| 24 } |
| 25 |
| 26 BrowserAccessibilityManager::~BrowserAccessibilityManager() { |
| 27 // Clear hashmaps. |
| 28 instance_map_.clear(); |
| 29 render_process_host_map_.clear(); |
| 30 |
| 31 NotificationService::current()->RemoveObserver(this, |
| 32 NOTIFY_RENDERER_PROCESS_TERMINATED, NotificationService::AllSources()); |
| 33 } |
| 34 |
| 35 STDMETHODIMP BrowserAccessibilityManager::CreateAccessibilityInstance( |
| 36 REFIID iid, int iaccessible_id, int instance_id, void** interface_ptr) { |
| 37 if (IID_IUnknown == iid || IID_IDispatch == iid || IID_IAccessible == iid) { |
| 38 CComObject<BrowserAccessibility>* instance = NULL; |
| 39 |
| 40 HRESULT hr = CComObject<BrowserAccessibility>::CreateInstance(&instance); |
| 41 DCHECK(SUCCEEDED(hr)); |
| 42 |
| 43 if (!instance) |
| 44 return E_FAIL; |
| 45 |
| 46 CComPtr<IAccessible> accessibility_instance(instance); |
| 47 |
| 48 // Set unique ids. |
| 49 instance->set_iaccessible_id(iaccessible_id); |
| 50 instance->set_instance_id(instance_id); |
| 51 |
| 52 // Retrieve the RenderWidgetHost connected to this request. |
| 53 InstanceMap::iterator it = instance_map_.find(instance_id); |
| 54 |
| 55 if (it != instance_map_.end()) { |
| 56 UniqueMembers* members = it->second; |
| 57 |
| 58 if (!members || !members->render_widget_host_) |
| 59 return E_FAIL; |
| 60 |
| 61 render_process_host_map_[members->render_widget_host_->process()] = |
| 62 instance; |
| 63 } else { |
| 64 // No RenderProcess active for this instance. |
| 65 return E_FAIL; |
| 66 } |
| 67 |
| 68 // All is well, assign the temp instance to the output pointer. |
| 69 *interface_ptr = accessibility_instance.Detach(); |
| 70 return S_OK; |
| 71 } |
| 72 // No supported interface found, return error. |
| 73 *interface_ptr = NULL; |
| 74 return E_NOINTERFACE; |
| 75 } |
| 76 |
| 77 bool BrowserAccessibilityManager::RequestAccessibilityInfo( |
| 78 int iaccessible_id, int instance_id, int iaccessible_func_id, |
| 79 VARIANT var_id, LONG input1, LONG input2) { |
| 80 // Create and populate input message structure. |
| 81 ViewMsg_Accessibility_In_Params in_params; |
| 82 |
| 83 in_params.iaccessible_id = iaccessible_id; |
| 84 in_params.iaccessible_function_id = iaccessible_func_id; |
| 85 in_params.input_variant_lval = var_id.lVal; |
| 86 in_params.input_long1 = input1; |
| 87 in_params.input_long2 = input2; |
| 88 |
| 89 // Retrieve the RenderWidgetHost connected to this request. |
| 90 InstanceMap::iterator it = instance_map_.find(instance_id); |
| 91 |
| 92 if (it == instance_map_.end()) { |
| 93 // Id not found. |
| 94 return false; |
| 95 } |
| 96 |
| 97 UniqueMembers* members = it->second; |
| 98 |
| 99 if (!members || !members->render_widget_host_) |
| 100 return false; |
| 101 |
| 102 IPC::SyncMessage* msg = |
| 103 new ViewMsg_GetAccessibilityInfo( |
| 104 members->render_widget_host_->routing_id(), in_params, &out_params_); |
| 105 |
| 106 // Necessary for the send to keep the UI responsive. |
| 107 msg->EnableMessagePumping(); |
| 108 bool success = members->render_widget_host_->process()->channel()-> |
| 109 SendWithTimeout(msg, kAccessibilityMessageTimeOut); |
| 110 |
| 111 return success; |
| 112 } |
| 113 |
| 114 ViewHostMsg_Accessibility_Out_Params BrowserAccessibilityManager::response() { |
| 115 return out_params_; |
| 116 } |
| 117 |
| 118 HWND BrowserAccessibilityManager::parent_hwnd(int id) { |
| 119 // Retrieve the parent HWND connected to the requester's id. |
| 120 InstanceMap::iterator it = instance_map_.find(id); |
| 121 |
| 122 if (it == instance_map_.end()) { |
| 123 // Id not found. |
| 124 return NULL; |
| 125 } |
| 126 |
| 127 UniqueMembers* members = it->second; |
| 128 |
| 129 if (!members || !members->parent_hwnd_) |
| 130 return NULL; |
| 131 |
| 132 return members->parent_hwnd_; |
| 133 } |
| 134 |
| 135 int BrowserAccessibilityManager::SetMembers(BrowserAccessibility* browser_acc, |
| 136 HWND parent_hwnd, RenderWidgetHost* render_widget_host) { |
| 137 // Set HWND and RenderWidgetHost connected to |browser_acc|. |
| 138 instance_map_[instance_id_] = |
| 139 new UniqueMembers(parent_hwnd, render_widget_host); |
| 140 |
| 141 render_process_host_map_[render_widget_host->process()] = browser_acc; |
| 142 return instance_id_++; |
| 143 } |
| 144 |
| 145 void BrowserAccessibilityManager::Observe(NotificationType type, |
| 146 const NotificationSource& source, |
| 147 const NotificationDetails& details) { |
| 148 DCHECK(type == NOTIFY_RENDERER_PROCESS_TERMINATED); |
| 149 RenderProcessHost* rph = Source<RenderProcessHost>(source).ptr(); |
| 150 DCHECK(rph); |
| 151 RenderProcessHostMap::iterator it = render_process_host_map_.find(rph); |
| 152 |
| 153 if (it == render_process_host_map_.end() || !it->second) { |
| 154 // RenderProcessHost not associated with any BrowserAccessibility instance. |
| 155 return; |
| 156 } |
| 157 |
| 158 // Set BrowserAccessibility instance to inactive state. |
| 159 it->second->set_instance_active(false); |
| 160 render_process_host_map_.erase(it); |
| 161 |
| 162 // Delete entry also from InstanceMap. |
| 163 InstanceMap::iterator it2 = instance_map_.find(it->second->instance_id()); |
| 164 |
| 165 if (it2 != instance_map_.end()) |
| 166 instance_map_.erase(it2); |
| 167 } |
OLD | NEW |