diff options
Diffstat (limited to 'chrome/browser/browser_accessibility_manager.cc')
-rw-r--r-- | chrome/browser/browser_accessibility_manager.cc | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/chrome/browser/browser_accessibility_manager.cc b/chrome/browser/browser_accessibility_manager.cc new file mode 100644 index 0000000..c670cf8 --- /dev/null +++ b/chrome/browser/browser_accessibility_manager.cc @@ -0,0 +1,167 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/browser_accessibility_manager.h" + +#include "chrome/browser/browser_accessibility.h" +#include "chrome/browser/render_process_host.h" +#include "chrome/browser/render_widget_host.h" + +// The time in ms after which we give up and return an error when processing an +// accessibility message and no response has been received from the renderer. +static const int kAccessibilityMessageTimeOut = 500; + +// static +BrowserAccessibilityManager* BrowserAccessibilityManager::Instance() { + return Singleton<BrowserAccessibilityManager>::get(); +} + +BrowserAccessibilityManager::BrowserAccessibilityManager() + : instance_id_(0) { + NotificationService::current()->AddObserver(this, + NOTIFY_RENDERER_PROCESS_TERMINATED, NotificationService::AllSources()); +} + +BrowserAccessibilityManager::~BrowserAccessibilityManager() { + // Clear hashmaps. + instance_map_.clear(); + render_process_host_map_.clear(); + + NotificationService::current()->RemoveObserver(this, + NOTIFY_RENDERER_PROCESS_TERMINATED, NotificationService::AllSources()); +} + +STDMETHODIMP BrowserAccessibilityManager::CreateAccessibilityInstance( + REFIID iid, int iaccessible_id, int instance_id, void** interface_ptr) { + if (IID_IUnknown == iid || IID_IDispatch == iid || IID_IAccessible == iid) { + CComObject<BrowserAccessibility>* instance = NULL; + + HRESULT hr = CComObject<BrowserAccessibility>::CreateInstance(&instance); + DCHECK(SUCCEEDED(hr)); + + if (!instance) + return E_FAIL; + + CComPtr<IAccessible> accessibility_instance(instance); + + // Set unique ids. + instance->set_iaccessible_id(iaccessible_id); + instance->set_instance_id(instance_id); + + // Retrieve the RenderWidgetHost connected to this request. + InstanceMap::iterator it = instance_map_.find(instance_id); + + if (it != instance_map_.end()) { + UniqueMembers* members = it->second; + + if (!members || !members->render_widget_host_) + return E_FAIL; + + render_process_host_map_[members->render_widget_host_->process()] = + instance; + } else { + // No RenderProcess active for this instance. + return E_FAIL; + } + + // All is well, assign the temp instance to the output pointer. + *interface_ptr = accessibility_instance.Detach(); + return S_OK; + } + // No supported interface found, return error. + *interface_ptr = NULL; + return E_NOINTERFACE; +} + +bool BrowserAccessibilityManager::RequestAccessibilityInfo( + int iaccessible_id, int instance_id, int iaccessible_func_id, + VARIANT var_id, LONG input1, LONG input2) { + // Create and populate input message structure. + ViewMsg_Accessibility_In_Params in_params; + + in_params.iaccessible_id = iaccessible_id; + in_params.iaccessible_function_id = iaccessible_func_id; + in_params.input_variant_lval = var_id.lVal; + in_params.input_long1 = input1; + in_params.input_long2 = input2; + + // Retrieve the RenderWidgetHost connected to this request. + InstanceMap::iterator it = instance_map_.find(instance_id); + + if (it == instance_map_.end()) { + // Id not found. + return false; + } + + UniqueMembers* members = it->second; + + if (!members || !members->render_widget_host_) + return false; + + IPC::SyncMessage* msg = + new ViewMsg_GetAccessibilityInfo( + members->render_widget_host_->routing_id(), in_params, &out_params_); + + // Necessary for the send to keep the UI responsive. + msg->EnableMessagePumping(); + bool success = members->render_widget_host_->process()->channel()-> + SendWithTimeout(msg, kAccessibilityMessageTimeOut); + + return success; +} + +ViewHostMsg_Accessibility_Out_Params BrowserAccessibilityManager::response() { + return out_params_; +} + +HWND BrowserAccessibilityManager::parent_hwnd(int id) { + // Retrieve the parent HWND connected to the requester's id. + InstanceMap::iterator it = instance_map_.find(id); + + if (it == instance_map_.end()) { + // Id not found. + return NULL; + } + + UniqueMembers* members = it->second; + + if (!members || !members->parent_hwnd_) + return NULL; + + return members->parent_hwnd_; +} + +int BrowserAccessibilityManager::SetMembers(BrowserAccessibility* browser_acc, + HWND parent_hwnd, RenderWidgetHost* render_widget_host) { + // Set HWND and RenderWidgetHost connected to |browser_acc|. + instance_map_[instance_id_] = + new UniqueMembers(parent_hwnd, render_widget_host); + + render_process_host_map_[render_widget_host->process()] = browser_acc; + return instance_id_++; +} + +void BrowserAccessibilityManager::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + DCHECK(type == NOTIFY_RENDERER_PROCESS_TERMINATED); + RenderProcessHost* rph = Source<RenderProcessHost>(source).ptr(); + DCHECK(rph); + RenderProcessHostMap::iterator it = render_process_host_map_.find(rph); + + if (it == render_process_host_map_.end() || !it->second) { + // RenderProcessHost not associated with any BrowserAccessibility instance. + return; + } + + // Set BrowserAccessibility instance to inactive state. + it->second->set_instance_active(false); + render_process_host_map_.erase(it); + + // Delete entry also from InstanceMap. + InstanceMap::iterator it2 = instance_map_.find(it->second->instance_id()); + + if (it2 != instance_map_.end()) + instance_map_.erase(it2); +} |