diff options
author | klink@chromium.org <klink@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-20 00:53:06 +0000 |
---|---|---|
committer | klink@chromium.org <klink@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-20 00:53:06 +0000 |
commit | e846d0dba2bf9506a929c9e16294997e37014039 (patch) | |
tree | 5ac70d2216fd450b3d4f164a26f752504c8cb220 | |
parent | fabd89f6aa700cb0e59b04e92ce54e729cbd0c66 (diff) | |
download | chromium_src-e846d0dba2bf9506a929c9e16294997e37014039.zip chromium_src-e846d0dba2bf9506a929c9e16294997e37014039.tar.gz chromium_src-e846d0dba2bf9506a929c9e16294997e37014039.tar.bz2 |
Adds propagation and handling of render-side focus events, for the benefit of assistive technologies (accessibility). Also cleans up the handling of WM_GETOBJECT in RenderWidgetHostViewWin and WidgetWin, as well as in BrowserAccessibilityManager.
Review URL: http://codereview.chromium.org/115374
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16449 0039d316-1c4b-4281-b951-d872f2087c98
22 files changed, 380 insertions, 266 deletions
diff --git a/chrome/browser/browser_accessibility.cc b/chrome/browser/browser_accessibility.cc index af56972..9fade8d 100644 --- a/chrome/browser/browser_accessibility.cc +++ b/chrome/browser/browser_accessibility.cc @@ -9,15 +9,29 @@ using webkit_glue::WebAccessibility; -BrowserAccessibility::BrowserAccessibility() - : iaccessible_id_(-1), - instance_active_(true) { +HRESULT BrowserAccessibility::Initialize(int iaccessible_id, int routing_id, + int process_id, HWND parent_hwnd) { + if (!parent_hwnd || iaccessible_id < 0) + return E_INVALIDARG; + + iaccessible_id_ = iaccessible_id; + routing_id_ = routing_id; + process_id_ = process_id; + parent_hwnd_ = parent_hwnd; + + // Mark instance as active. + instance_active_ = true; + + // Treat child ids intitially as referring to direct children of the object. + direct_descendant_ = true; + + return S_OK; } HRESULT BrowserAccessibility::accDoDefaultAction(VARIANT var_id) { if (!instance_active()) { // Instance no longer active, fail gracefully. - // TODO(klink): Once we have MSAA events, change these fails for having + // TODO(klink): Once we have MSAA events, change these fails to having // BrowserAccessibilityManager firing the right event. return E_FAIL; } @@ -46,7 +60,7 @@ STDMETHODIMP BrowserAccessibility::accHitTest(LONG x_left, LONG y_top, if (!child) return E_INVALIDARG; - if (!parent_hwnd()) { + if (!parent_hwnd_) { // Parent HWND needed for coordinate conversion. return E_FAIL; } @@ -54,7 +68,7 @@ STDMETHODIMP BrowserAccessibility::accHitTest(LONG x_left, LONG y_top, // Convert coordinates to test from screen into client window coordinates, to // maintain sandbox functionality on renderer side. POINT p = {x_left, y_top}; - ::ScreenToClient(parent_hwnd(), &p); + ::ScreenToClient(parent_hwnd_, &p); if (!RequestAccessibilityInfo(WebAccessibility::FUNCTION_HITTEST, EmptyVariant(), p.x, p.y)) { @@ -93,7 +107,7 @@ STDMETHODIMP BrowserAccessibility::accLocation(LONG* x_left, LONG* y_top, } if (var_id.vt != VT_I4 || !x_left || !y_top || !width || !height || - !parent_hwnd()) { + !parent_hwnd_) { return E_INVALIDARG; } @@ -106,7 +120,7 @@ STDMETHODIMP BrowserAccessibility::accLocation(LONG* x_left, LONG* y_top, // Find the top left corner of the containing window in screen coords, and // adjust the output position by this amount. - ::ClientToScreen(parent_hwnd(), &top_left); + ::ClientToScreen(parent_hwnd_, &top_left); *x_left = response().output_long1 + top_left.x; *y_top = response().output_long2 + top_left.y; @@ -393,15 +407,15 @@ STDMETHODIMP BrowserAccessibility::get_accParent(IDispatch** disp_parent) { return E_FAIL; } - if (!disp_parent || !parent_hwnd()) + if (!disp_parent || !parent_hwnd_) return E_INVALIDARG; // Root node's parent is the containing HWND's IAccessible. - if (iaccessible_id() == 0) { + if (iaccessible_id_ == 0) { // For an object that has no parent (e.g. root), point the accessible parent // to the default implementation. HRESULT hr = - ::CreateStdAccessibleObject(parent_hwnd(), OBJID_WINDOW, + ::CreateStdAccessibleObject(parent_hwnd_, OBJID_WINDOW, IID_IAccessible, reinterpret_cast<void**>(disp_parent)); @@ -498,20 +512,15 @@ STDMETHODIMP BrowserAccessibility::get_accValue(VARIANT var_id, BSTR* value) { return S_OK; } -STDMETHODIMP BrowserAccessibility::accSelect(LONG flags_select, - VARIANT var_id) { - return E_NOTIMPL; -} - STDMETHODIMP BrowserAccessibility::get_accHelpTopic(BSTR* help_file, VARIANT var_id, LONG* topic_id) { - if (help_file) { + if (help_file) *help_file = NULL; - } - if (topic_id) { + + if (topic_id) *topic_id = static_cast<LONG>(-1); - } + return E_NOTIMPL; } @@ -522,38 +531,38 @@ STDMETHODIMP BrowserAccessibility::get_accSelection(VARIANT* selected) { return E_NOTIMPL; } -STDMETHODIMP BrowserAccessibility::put_accName(VARIANT var_id, BSTR put_name) { - return E_NOTIMPL; -} - -STDMETHODIMP BrowserAccessibility::put_accValue(VARIANT var_id, BSTR put_val) { - return E_NOTIMPL; -} - STDMETHODIMP BrowserAccessibility::CreateInstance(REFIID iid, int iaccessible_id, void** interface_ptr) { return BrowserAccessibilityManager::GetInstance()-> - CreateAccessibilityInstance(iid, iaccessible_id, instance_id(), - interface_ptr); + CreateAccessibilityInstance(iid, iaccessible_id, routing_id_, + process_id_, parent_hwnd_, interface_ptr); } bool BrowserAccessibility::RequestAccessibilityInfo(int iaccessible_func_id, VARIANT var_id, LONG input1, LONG input2) { - return BrowserAccessibilityManager::GetInstance()->RequestAccessibilityInfo( - iaccessible_id(), instance_id(), iaccessible_func_id, var_id.lVal, input1, - input2); + // Create and populate IPC message structure, for retrieval of accessibility + // information from the renderer. + WebAccessibility::InParams in_params; + in_params.object_id = iaccessible_id_; + in_params.function_id = iaccessible_func_id; + in_params.child_id = var_id.lVal; + in_params.direct_descendant = direct_descendant(); + in_params.input_long1 = input1; + in_params.input_long2 = input2; + + if (!direct_descendant()) + set_direct_descendant(true); + + return BrowserAccessibilityManager::GetInstance()-> + RequestAccessibilityInfo(&in_params, routing_id_, process_id_); } const WebAccessibility::OutParams& BrowserAccessibility::response() { return BrowserAccessibilityManager::GetInstance()->response(); } -HWND BrowserAccessibility::parent_hwnd() { - return BrowserAccessibilityManager::GetInstance()->parent_hwnd(instance_id()); -} - long BrowserAccessibility::MSAARole(long browser_accessibility_role) { switch (browser_accessibility_role) { case WebAccessibility::ROLE_PUSHBUTTON : diff --git a/chrome/browser/browser_accessibility.h b/chrome/browser/browser_accessibility.h index 8b56662..c8d4187 100644 --- a/chrome/browser/browser_accessibility.h +++ b/chrome/browser/browser_accessibility.h @@ -10,7 +10,6 @@ #include <oleacc.h> -#include "base/basictypes.h" #include "webkit/glue/webaccessibility.h" using webkit_glue::WebAccessibility; @@ -33,9 +32,14 @@ class ATL_NO_VTABLE BrowserAccessibility COM_INTERFACE_ENTRY(IAccessible) END_COM_MAP() - BrowserAccessibility(); + BrowserAccessibility() {} ~BrowserAccessibility() {} + HRESULT Initialize(int iaccessible_id, + int routing_id, + int process_id, + HWND parent_hwnd); + // Supported IAccessible methods. // Performs the default action on a given object. @@ -91,7 +95,7 @@ class ATL_NO_VTABLE BrowserAccessibility STDMETHODIMP get_accValue(VARIANT var_id, BSTR* value); // Non-supported (by WebKit) IAccessible methods. - STDMETHODIMP accSelect(LONG flags_sel, VARIANT var_id); + STDMETHODIMP accSelect(LONG flags_sel, VARIANT var_id) { return E_NOTIMPL; } STDMETHODIMP get_accHelpTopic(BSTR* help_file, VARIANT var_id, @@ -100,20 +104,11 @@ class ATL_NO_VTABLE BrowserAccessibility STDMETHODIMP get_accSelection(VARIANT* selected); // Deprecated functions, not implemented here. - STDMETHODIMP put_accName(VARIANT var_id, BSTR put_name); - STDMETHODIMP put_accValue(VARIANT var_id, BSTR put_val); - - // Modify/retrieve the unique id of this IAccessible instance. - void set_iaccessible_id(int iaccessible_id) { - iaccessible_id_ = iaccessible_id; - } - int iaccessible_id() const { return iaccessible_id_; } + STDMETHODIMP put_accName(VARIANT var_id, BSTR put_name) { return E_NOTIMPL; } + STDMETHODIMP put_accValue(VARIANT var_id, BSTR put_val) { return E_NOTIMPL; } - // Modify/retrieve the unique id of this IAccessible's routing variables. - void set_instance_id(int instance_id) { - instance_id_ = instance_id; - } - int instance_id() const { return instance_id_; } + // Accessors/mutators. + HWND parent_hwnd() const { return parent_hwnd_;} // Modify/retrieve the state (active/inactive) of this instance. void set_instance_active(bool instance_active) { @@ -121,6 +116,13 @@ class ATL_NO_VTABLE BrowserAccessibility } int instance_active() const { return instance_active_; } + void set_direct_descendant(bool direct_descendant) { + direct_descendant_ = direct_descendant; + } + bool direct_descendant() const { return direct_descendant_; } + + int routing_id() const { return routing_id_; } + private: // Creates an empty VARIANT. Used as the equivalent of a NULL (unused) input // parameter. @@ -148,7 +150,6 @@ class ATL_NO_VTABLE BrowserAccessibility // Accessors. const WebAccessibility::OutParams& response(); - HWND parent_hwnd(); // Returns a conversion from the BrowserAccessibilityRole (as defined in // webkit/glue/webaccessibility.h) to an MSAA role. @@ -162,10 +163,21 @@ class ATL_NO_VTABLE BrowserAccessibility // mapping it to the correct IAccessible on that side. Initialized to -1. int iaccessible_id_; - // The unique id of this IAccessible instance. Used to help + // The unique ids of this IAccessible instance. Used to help // BrowserAccessibilityManager instance retrieve the correct member // variables for this process. - int instance_id_; + int routing_id_; + int process_id_; + + HWND parent_hwnd_; + + // Indicates if an incoming request for child information relates to a child + // id of a direct child of the BrowserAccessibility object, or if it refers + // to an object elsewhere in the MSAA tree. Set by BrowserAccessibilityManager + // and applicable only to the root BrowserAccessibility object (id 0). Needed + // to properly handled MSAA focus events, where the child id is the only + // parameter in our control. + bool direct_descendant_; // The instance should only be active if there is a non-terminated // RenderProcessHost associated with it. The BrowserAccessibilityManager keeps diff --git a/chrome/browser/browser_accessibility_manager.cc b/chrome/browser/browser_accessibility_manager.cc index e97e0e4..0930024 100644 --- a/chrome/browser/browser_accessibility_manager.cc +++ b/chrome/browser/browser_accessibility_manager.cc @@ -6,7 +6,7 @@ #include "chrome/browser/browser_accessibility.h" #include "chrome/browser/renderer_host/render_process_host.h" -#include "chrome/browser/renderer_host/render_widget_host.h" +#include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/common/notification_service.h" #include "chrome/common/render_messages.h" @@ -21,16 +21,14 @@ BrowserAccessibilityManager* BrowserAccessibilityManager::GetInstance() { return Singleton<BrowserAccessibilityManager>::get(); } -BrowserAccessibilityManager::BrowserAccessibilityManager() - : instance_id_(0) { +BrowserAccessibilityManager::BrowserAccessibilityManager() { NotificationService::current()->AddObserver(this, NotificationType::RENDERER_PROCESS_TERMINATED, NotificationService::AllSources()); } BrowserAccessibilityManager::~BrowserAccessibilityManager() { - // Clear hashmaps. - instance_map_.clear(); + // Clear hashmap. render_process_host_map_.clear(); // We don't remove ourselves as an observer because we are a Singleton object, @@ -38,7 +36,8 @@ BrowserAccessibilityManager::~BrowserAccessibilityManager() { } STDMETHODIMP BrowserAccessibilityManager::CreateAccessibilityInstance( - REFIID iid, int acc_obj_id, int instance_id, void** interface_ptr) { + REFIID iid, int acc_obj_id, int routing_id, int process_id, + HWND parent_hwnd, void** interface_ptr) { if (IID_IUnknown == iid || IID_IDispatch == iid || IID_IAccessible == iid) { CComObject<BrowserAccessibility>* instance = NULL; @@ -50,21 +49,16 @@ STDMETHODIMP BrowserAccessibilityManager::CreateAccessibilityInstance( CComPtr<IAccessible> accessibility_instance(instance); - // Set unique ids. - instance->set_iaccessible_id(acc_obj_id); - instance->set_instance_id(instance_id); + // Set class member variables. + instance->Initialize(acc_obj_id, routing_id, process_id, parent_hwnd); - // Retrieve the RenderWidgetHost connected to this request. - InstanceMap::iterator it = instance_map_.find(instance_id); + // Retrieve the RenderViewHost connected to this request. + RenderViewHost* rvh = RenderViewHost::FromID(process_id, routing_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; + // Update cache with RenderProcessHost/BrowserAccessibility pair. + if (rvh && rvh->process()) { + render_process_host_map_.insert( + MapEntry(rvh->process()->pid(), instance)); } else { // No RenderProcess active for this instance. return E_FAIL; @@ -80,73 +74,71 @@ STDMETHODIMP BrowserAccessibilityManager::CreateAccessibilityInstance( } bool BrowserAccessibilityManager::RequestAccessibilityInfo( - int acc_obj_id, int instance_id, int acc_func_id, int child_id, long input1, - long input2) { + WebAccessibility::InParams* in, int routing_id, int process_id) { // Create and populate IPC message structure, for retrieval of accessibility // information from the renderer. WebAccessibility::InParams in_params; - in_params.object_id = acc_obj_id; - in_params.function_id = acc_func_id; - in_params.child_id = child_id; - 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; - } + in_params.object_id = in->object_id; + in_params.function_id = in->function_id; + in_params.child_id = in->child_id; + in_params.direct_descendant = in->direct_descendant; + in_params.input_long1 = in->input_long1; + in_params.input_long2 = in->input_long2; - UniqueMembers* members = it->second; - - if (!members || !members->render_widget_host_) - return false; + // Retrieve the RenderViewHost connected to this request. + RenderViewHost* rvh = RenderViewHost::FromID(process_id, routing_id); + // Send accessibility information retrieval message to the renderer. bool success = false; - if (members->render_widget_host_->process() && - members->render_widget_host_->process()->channel()) { + if (rvh && rvh->process() && rvh->process()->channel()) { IPC::SyncMessage* msg = - new ViewMsg_GetAccessibilityInfo(members->render_widget_host_-> - routing_id(), in_params, &out_params_); + new ViewMsg_GetAccessibilityInfo(routing_id, in_params, &out_params_); // Necessary for the send to keep the UI responsive. msg->EnableMessagePumping(); - success = members->render_widget_host_->process()->channel()-> - SendWithTimeout(msg, kAccessibilityMessageTimeOut); + success = rvh->process()->channel()->SendWithTimeout(msg, + kAccessibilityMessageTimeOut); } return success; } +bool BrowserAccessibilityManager::ChangeAccessibilityFocus(int acc_obj_id, + int process_id, + int routing_id) { + BrowserAccessibility* browser_acc = + GetBrowserAccessibility(process_id, routing_id); + if (browser_acc) { + // Indicate that the request for child information is referring to a non- + // direct descendant of the root. + browser_acc->set_direct_descendant(false); + + // Notify Access Technology that there was a change in keyboard focus. + ::NotifyWinEvent(EVENT_OBJECT_FOCUS, browser_acc->parent_hwnd(), + OBJID_CLIENT, static_cast<LONG>(acc_obj_id)); + return true; + } + return false; +} + const WebAccessibility::OutParams& 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; +BrowserAccessibility* BrowserAccessibilityManager::GetBrowserAccessibility( + int process_id, int routing_id) { + // Retrieve the BrowserAccessibility connected to the requester's id. There + // could be multiple BrowserAccessibility connected to the given |process_id|, + // but they all have the same parent HWND, so using the first hit is fine. + RenderProcessHostMap::iterator it = + render_process_host_map_.lower_bound(process_id); - if (!members || !members->parent_hwnd_) - return NULL; + RenderProcessHostMap::iterator end_of_matching_objects = + render_process_host_map_.upper_bound(process_id); - 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_++; + for (; it != end_of_matching_objects; ++it) { + if (it->second && it->second->routing_id() == routing_id) + return it->second; + } + return NULL; } void BrowserAccessibilityManager::Observe(NotificationType type, @@ -155,22 +147,18 @@ void BrowserAccessibilityManager::Observe(NotificationType type, DCHECK(type == NotificationType::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; - } + RenderProcessHostMap::iterator it = + render_process_host_map_.lower_bound(rph->pid()); - // Set BrowserAccessibility instance to inactive state. - it->second->set_instance_active(false); + RenderProcessHostMap::iterator end_of_matching_objects = + render_process_host_map_.upper_bound(rph->pid()); - // Delete entry also from InstanceMap. - InstanceMap::iterator it2 = instance_map_.find(it->second->instance_id()); - - if (it2 != instance_map_.end()) - instance_map_.erase(it2); - - // Only delete the first entry once it is no longer in use. - render_process_host_map_.erase(it); + for (; it != end_of_matching_objects; ++it) { + if (it->second) { + // Set all matching BrowserAccessibility instances to inactive state. + // TODO(klink): Do more active memory cleanup as well. + it->second->set_instance_active(false); + } + } } diff --git a/chrome/browser/browser_accessibility_manager.h b/chrome/browser/browser_accessibility_manager.h index defcb9e..081f978 100644 --- a/chrome/browser/browser_accessibility_manager.h +++ b/chrome/browser/browser_accessibility_manager.h @@ -5,8 +5,7 @@ #ifndef CHROME_BROWSER_BROWSER_ACCESSIBILITY_MANAGER_H_ #define CHROME_BROWSER_BROWSER_ACCESSIBILITY_MANAGER_H_ -#include <oaidl.h> // Needed for VARIANT structure. -#include <hash_map> +#include <map> #include "base/singleton.h" #include "chrome/common/notification_observer.h" @@ -16,6 +15,8 @@ class BrowserAccessibility; class RenderProcessHost; class RenderWidgetHost; +using webkit_glue::WebAccessibility; + //////////////////////////////////////////////////////////////////////////////// // // BrowserAccessibilityManager @@ -35,35 +36,28 @@ class BrowserAccessibilityManager : public NotificationObserver { static BrowserAccessibilityManager* GetInstance(); // Creates an instance of BrowserAccessibility, initializes it and sets the - // [acc_obj_id], which is used for IPC communication, and [instance_id], + // |acc_obj_id|, which is used for IPC communication, and |instance_id|, // which is used to identify the mapping between accessibility instance and // RenderProcess. STDMETHODIMP CreateAccessibilityInstance(REFIID iid, int acc_obj_id, - int instance_id, + int routing_id, + int process_id, + HWND parent_hwnd, void** interface_ptr); // Composes and sends a message for requesting needed accessibility - // information. Unused LONG input parameters should be NULL, and the VARIANT - // [var_id] an empty, valid instance. - bool RequestAccessibilityInfo(int acc_obj_id, - int instance_id, - int acc_func_id, - int child_id, - long input1, - long input2); - - // Wrapper function, for cleaner code. - const webkit_glue::WebAccessibility::OutParams& response(); + // information. + bool RequestAccessibilityInfo(WebAccessibility::InParams* in, + int routing_id, + int process_id); - // Retrieves the parent HWND connected to the provided id. - HWND parent_hwnd(int id); + // Notifies assistive technology that renderer focus changed, through the + // platform-specific channels. + bool ChangeAccessibilityFocus(int acc_obj_id, int process_id, int routing_id); - // Mutator, needed since constructor does not take any arguments, and to keep - // instance accessor clean. - int SetMembers(BrowserAccessibility* browser_acc, - HWND parent_hwnd, - RenderWidgetHost* render_widget_host); + // Wrapper function, for cleaner code. + const WebAccessibility::OutParams& response(); // NotificationObserver implementation. virtual void Observe(NotificationType type, @@ -78,32 +72,24 @@ class BrowserAccessibilityManager : public NotificationObserver { ~BrowserAccessibilityManager(); private: - // Member variable structure, used in instance hashmap. - struct UniqueMembers { - RenderWidgetHost* render_widget_host_; - HWND parent_hwnd_; - - UniqueMembers(HWND parent_hwnd, RenderWidgetHost* render_widget_host) - : parent_hwnd_(parent_hwnd), - render_widget_host_(render_widget_host) { - } - }; - - typedef stdext::hash_map<int, UniqueMembers*> InstanceMap; - typedef stdext::hash_map<RenderProcessHost*, BrowserAccessibility*> - RenderProcessHostMap; - - // Caching of the unique member variables used to handle browser accessibility - // requests from multiple processes. - InstanceMap instance_map_; - int instance_id_; - - // Reverse mapping to track which RenderProcessHosts are active. If a - // RenderProcessHost is found to be terminated, it should be removed from this - // mapping, and the connected BrowserAccessibility ids/instances invalidated. + // Retrieves the BrowserAccessibility instance connected to the + // RenderProcessHost identified by the process/routing id pair. + BrowserAccessibility* GetBrowserAccessibility(int process_id, int routing_id); + + // Multi-map from process id (key) to active BrowserAccessibility instances + // for that RenderProcessHost. + typedef std::multimap<int, BrowserAccessibility*> RenderProcessHostMap; + typedef std::pair<int, BrowserAccessibility*> MapEntry; + + // Mapping to track which RenderProcessHosts ids are active. If a + // RenderProcessHost is found to be terminated, its id (key) should be removed + // from this mapping, and the connected BrowserAccessibility ids/instances + // invalidated. RenderProcessHostMap render_process_host_map_; - webkit_glue::WebAccessibility::OutParams out_params_; + // Structure passed by reference to hold response parameters from the + // renderer. + WebAccessibility::OutParams out_params_; DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityManager); }; diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index 792b6ee..44c0023 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -41,6 +41,11 @@ #include "webkit/api/public/WebFindOptions.h" #include "webkit/glue/autofill_form.h" +#if defined(OS_WIN) +// TODO(port): accessibility not yet implemented. See http://crbug.com/8288. +#include "chrome/browser/browser_accessibility_manager.h" +#endif + using base::TimeDelta; using WebKit::WebConsoleMessage; using WebKit::WebFindOptions; @@ -800,6 +805,8 @@ void RenderViewHost::OnMessageReceived(const IPC::Message& msg) { OnMsgPasteFromSelectionClipboard) IPC_MESSAGE_HANDLER(ViewHostMsg_ExtensionPostMessage, OnExtensionPostMessage) + IPC_MESSAGE_HANDLER(ViewHostMsg_AccessibilityFocusChange, + OnAccessibilityFocusChange) // Have the super handle all other messages. IPC_MESSAGE_UNHANDLED(RenderWidgetHost::OnMessageReceived(msg)) IPC_END_MESSAGE_MAP_EX() @@ -1432,3 +1439,12 @@ void RenderViewHost::OnExtensionPostMessage( ExtensionMessageService::GetInstance(context)-> PostMessageFromRenderer(port_id, message); } + +void RenderViewHost::OnAccessibilityFocusChange(int acc_obj_id) { +#if defined(OS_WIN) + BrowserAccessibilityManager::GetInstance()-> + ChangeAccessibilityFocus(acc_obj_id, process()->pid(), routing_id()); +#else + // TODO(port): accessibility not yet implemented. See http://crbug.com/8288. +#endif +} diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h index 5c20c12..9c08f11 100644 --- a/chrome/browser/renderer_host/render_view_host.h +++ b/chrome/browser/renderer_host/render_view_host.h @@ -555,6 +555,7 @@ class RenderViewHost : public RenderWidgetHost { void OnExtensionRequest(const std::string& name, const std::string& args, int request_id, bool has_callback); void OnExtensionPostMessage(int port_id, const std::string& message); + void OnAccessibilityFocusChange(int acc_obj_id); // Helper function to send a navigation message. If a cross-site request is // in progress, we may be suspended while waiting for the onbeforeunload diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.cc b/chrome/browser/renderer_host/render_widget_host_view_win.cc index 82d95f1c..22f50f7 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc @@ -13,7 +13,6 @@ #include "base/gfx/rect.h" #include "base/histogram.h" #include "base/win_util.h" -#include "chrome/browser/browser_accessibility.h" #include "chrome/browser/browser_accessibility_manager.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_trial.h" @@ -685,7 +684,7 @@ void RenderWidgetHostViewWin::OnDestroy() { TrackMouseLeave(false); #ifdef ENABLE_TRACK_HWND_DESTRUCTION TRACK_HWND_DESTRUCTION(m_hWnd); -#endif // ENABLE_TRACK_HWND_DESTRUCTION +#endif // ENABLE_TRACK_HWND_DESTRUCTION } void RenderWidgetHostViewWin::OnPaint(HDC dc) { @@ -1194,41 +1193,23 @@ LRESULT RenderWidgetHostViewWin::OnGetObject(UINT message, WPARAM wparam, // If our MSAA DOM root is already created, reuse that pointer. Otherwise, // create a new one. if (!browser_accessibility_root_) { - CComObject<BrowserAccessibility>* accessibility = NULL; - - if (!SUCCEEDED(CComObject<BrowserAccessibility>::CreateInstance( - &accessibility)) || !accessibility) { - // Return with failure. - return static_cast<LRESULT>(0L); - } - - CComPtr<IAccessible> accessibility_comptr(accessibility); - - // Root id is always 0, to distinguish this particular instance when - // mapping to the render-side IAccessible. - accessibility->set_iaccessible_id(0); - - // Set the unique member variables of this particular process. - accessibility->set_instance_id( - BrowserAccessibilityManager::GetInstance()-> - SetMembers(accessibility, m_hWnd, render_widget_host_)); - - // All is well, assign the temp instance to the class smart pointer. - browser_accessibility_root_.Attach(accessibility_comptr.Detach()); + // Create a new instance of IAccessible. Root id is always 0. + BrowserAccessibilityManager::GetInstance()-> + CreateAccessibilityInstance(IID_IAccessible, 0, + render_widget_host_->routing_id(), + render_widget_host_->process()->pid(), + m_hWnd, reinterpret_cast<void **> + (&browser_accessibility_root_)); if (!browser_accessibility_root_) { - // Paranoia check. Return with failure. + // No valid root found, return with failure. NOTREACHED(); return static_cast<LRESULT>(0L); } - - // Notify that an instance of IAccessible was allocated for m_hWnd. - ::NotifyWinEvent(EVENT_OBJECT_CREATE, m_hWnd, OBJID_CLIENT, - CHILDID_SELF); } - // Create a reference to ViewAccessibility that MSAA will marshall - // to the client. + // Create a reference to BrowserAccessibility which MSAA will marshall to + // the client. reference_result = LresultFromObject(IID_IAccessible, wparam, static_cast<IAccessible*>(browser_accessibility_root_)); } diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h index 2908480..e3028a2 100644 --- a/chrome/common/render_messages.h +++ b/chrome/common/render_messages.h @@ -509,6 +509,7 @@ struct ParamTraits<webkit_glue::WebAccessibility::InParams> { WriteParam(m, p.object_id); WriteParam(m, p.function_id); WriteParam(m, p.child_id); + WriteParam(m, p.direct_descendant); WriteParam(m, p.input_long1); WriteParam(m, p.input_long2); } @@ -517,6 +518,7 @@ struct ParamTraits<webkit_glue::WebAccessibility::InParams> { ReadParam(m, iter, &p->object_id) && ReadParam(m, iter, &p->function_id) && ReadParam(m, iter, &p->child_id) && + ReadParam(m, iter, &p->direct_descendant) && ReadParam(m, iter, &p->input_long1) && ReadParam(m, iter, &p->input_long2); } @@ -528,6 +530,8 @@ struct ParamTraits<webkit_glue::WebAccessibility::InParams> { l->append(L", "); LogParam(p.child_id, l); l->append(L", "); + LogParam(p.direct_descendant, l); + l->append(L", "); LogParam(p.input_long1, l); l->append(L", "); LogParam(p.input_long2, l); diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 4cf50d1..f359677 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -406,7 +406,7 @@ IPC_BEGIN_MESSAGES(View) // id to clear a specific hashmap entry, and a bool; true clears all, false // does not. IPC_MESSAGE_ROUTED2(ViewMsg_ClearAccessibilityInfo, - int /* iaccessible_id */, + int /* accessibility object id */, bool /* clear_all */) // Get all savable resource links from current webpage, include main @@ -1381,6 +1381,13 @@ IPC_BEGIN_MESSAGES(ViewHost) IPC_MESSAGE_ROUTED1(ViewHostMsg_ShowPopup, ViewHostMsg_ShowPopup_Params) + // Sent as a result of a focus change in the renderer (if accessibility is + // enabled), to notify the browser side that its accessibility focus needs to + // change as well. Takes the id of the accessibility object that now has + // focus. + IPC_MESSAGE_ROUTED1(ViewHostMsg_AccessibilityFocusChange, + int /* accessibility object id */) + //--------------------------------------------------------------------------- // Utility process host messages: // These are messages from the utility process to the browser. They're here diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index dc7e284..8a311af 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -91,7 +91,6 @@ using base::Time; using base::TimeDelta; -using webkit_glue::WebAccessibility; using WebKit::WebConsoleMessage; using WebKit::WebDragData; using WebKit::WebRect; @@ -2048,7 +2047,6 @@ void RenderView::DidDownloadImage(int id, void RenderView::OnDownloadImage(int id, const GURL& image_url, int image_size) { - bool data_image_failed = false; if (image_url.SchemeIs("data")) { SkBitmap data_image = ImageFromDataUrl(image_url); @@ -2765,8 +2763,10 @@ void RenderView::OnClearAccessibilityInfo(int acc_obj_id, bool clear_all) { // If accessibility is not activated, ignore clearing message. return; } + if (!web_accessibility_manager_->ClearAccObjMap(acc_obj_id, clear_all)) return; + #else // defined(OS_WIN) // TODO(port): accessibility not yet implemented NOTIMPLEMENTED(); @@ -3024,3 +3024,25 @@ void RenderView::DumpLoadHistograms() const { "Renderer.All.StartToFirstLayout", start_to_first_layout); } } + +void RenderView::FocusAccessibilityObject( + WebCore::AccessibilityObject* acc_obj) { +#if defined(OS_WIN) + if (!web_accessibility_manager_.get()) { + web_accessibility_manager_.reset( + webkit_glue::WebAccessibilityManager::Create()); + } + + // Retrieve the accessibility object id of the AccessibilityObject. + int acc_obj_id = web_accessibility_manager_->FocusAccObj(acc_obj); + + // If id is valid, alert the browser side that an accessibility focus change + // occurred. + if (acc_obj_id >= 0) + Send(new ViewHostMsg_AccessibilityFocusChange(routing_id_, acc_obj_id)); + +#else // defined(OS_WIN) + // TODO(port): accessibility not yet implemented + NOTIMPLEMENTED(); +#endif +} diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 936adae..f42b8ff 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -49,7 +49,6 @@ class FilePath; class GURL; class RenderThread; class ResourceDispatcher; -class WebAccessibilityManager; class WebError; class WebFrame; class WebPluginDelegate; @@ -307,6 +306,7 @@ class RenderView : public RenderWidget, int active_match_ordinal, const WebKit::WebRect& selection); virtual bool WasOpenedByUserGesture() const; + virtual void FocusAccessibilityObject(WebCore::AccessibilityObject* acc_obj); virtual void SpellCheck(const std::wstring& word, int& misspell_location, int& misspell_length); virtual void GetAutoCorrectWord(const std::wstring& misspelled_word, diff --git a/views/widget/widget_win.cc b/views/widget/widget_win.cc index 4fa77a8..4dfb0ca 100644 --- a/views/widget/widget_win.cc +++ b/views/widget/widget_win.cc @@ -558,10 +558,6 @@ LRESULT WidgetWin::OnGetObject(UINT uMsg, WPARAM w_param, LPARAM l_param) { // Return with failure. return static_cast<LRESULT>(0L); } - - // Notify that an instance of IAccessible was allocated for m_hWnd - ::NotifyWinEvent(EVENT_OBJECT_CREATE, GetNativeView(), OBJID_CLIENT, - CHILDID_SELF); } // Create a reference to ViewAccessibility that MSAA will marshall diff --git a/webkit/glue/chrome_client_impl.cc b/webkit/glue/chrome_client_impl.cc index b235d35..9553e93 100644 --- a/webkit/glue/chrome_client_impl.cc +++ b/webkit/glue/chrome_client_impl.cc @@ -7,8 +7,11 @@ #include "base/compiler_specific.h" MSVC_PUSH_WARNING_LEVEL(0); +#include "AccessibilityObject.h" +#include "AXObjectCache.h" #include "Console.h" #include "Cursor.h" +#include "Document.h" #include "DocumentLoader.h" #include "FloatRect.h" #include "FileChooser.h" @@ -16,6 +19,7 @@ MSVC_PUSH_WARNING_LEVEL(0); #include "FrameView.h" #include "HitTestResult.h" #include "IntRect.h" +#include "Node.h" #include "Page.h" #include "PopupMenuChromium.h" #include "ScriptController.h" @@ -29,7 +33,6 @@ MSVC_POP_WARNING(); #include "webkit/glue/chrome_client_impl.h" -#include "base/logging.h" #include "base/gfx/rect.h" #include "googleurl/src/gurl.h" #include "webkit/api/public/WebInputEvent.h" @@ -141,6 +144,28 @@ void ChromeClientImpl::focus() { WebViewDelegate* delegate = webview_->delegate(); if (delegate) delegate->Focus(webview_); + + // If accessibility is enabled, we should notify assistive technology that the + // active AccessibilityObject changed. + WebCore::Document* doc = webview_->GetFocusedWebCoreFrame()->document(); + + if (doc && doc->axObjectCache()->accessibilityEnabled()) { + WebCore::Node* focused_node = webview_->GetFocusedNode(); + + if (!focused_node) { + // Could not retrieve focused Node. + return; + } + + // Retrieve the focused AccessibilityObject. + WebCore::AccessibilityObject* focused_acc_obj = + doc->axObjectCache()->getOrCreate(focused_node->renderer()); + + // Alert assistive technology that focus changed. + if (focused_acc_obj) { + delegate->FocusAccessibilityObject(focused_acc_obj); + } + } } void ChromeClientImpl::unfocus() { @@ -201,7 +226,8 @@ static inline bool CurrentEventShouldCauseBackgroundTab( if (input_event->type != WebInputEvent::MouseUp) return false; - const WebMouseEvent* mouse_event = static_cast<const WebMouseEvent*>(input_event); + const WebMouseEvent* mouse_event = + static_cast<const WebMouseEvent*>(input_event); return (mouse_event->button == WebMouseEvent::ButtonMiddle); } @@ -294,7 +320,8 @@ void ChromeClientImpl::addMessageToConsole(WebCore::MessageSource source, } WebDevToolsAgentImpl* devtools_agent = webview_->GetWebDevToolsAgentImpl(); if (devtools_agent) { - devtools_agent->AddMessageToConsole(source, level, message, line_no, source_id); + devtools_agent->AddMessageToConsole(source, level, message, line_no, + source_id); } } diff --git a/webkit/glue/chrome_client_impl.h b/webkit/glue/chrome_client_impl.h index e372f7c..3a3fdc5 100644 --- a/webkit/glue/chrome_client_impl.h +++ b/webkit/glue/chrome_client_impl.h @@ -24,7 +24,7 @@ struct WindowFeatures; // Handles window-level notifications from WebCore on behalf of a WebView. class ChromeClientImpl : public WebCore::ChromeClientChromium { public: - ChromeClientImpl(WebViewImpl* webview); + explicit ChromeClientImpl(WebViewImpl* webview); virtual ~ChromeClientImpl(); WebViewImpl* webview() const { return webview_; } @@ -67,7 +67,8 @@ class ChromeClientImpl : public WebCore::ChromeClientChromium { virtual void setResizable(bool); virtual void addMessageToConsole(WebCore::MessageSource source, - WebCore::MessageLevel level, const WebCore::String& message, + WebCore::MessageLevel level, + const WebCore::String& message, unsigned int lineNumber, const WebCore::String& sourceID); diff --git a/webkit/glue/glue_accessibility_object.cc b/webkit/glue/glue_accessibility_object.cc index 17a693e..8c056eb 100644 --- a/webkit/glue/glue_accessibility_object.cc +++ b/webkit/glue/glue_accessibility_object.cc @@ -134,7 +134,7 @@ GlueAccessibilityObject* GlueAccessibilityObject::Navigate( GlueAccessibilityObject* GlueAccessibilityObject::GetChild(int child_id) { AccessibilityObject* child_obj; if (!GetAccessibilityObjectForChild(child_id, child_obj)) - return false; + return NULL; // TODO(klink): simple object child? ToWrapper(child_obj)->ref(); diff --git a/webkit/glue/glue_accessibility_object.h b/webkit/glue/glue_accessibility_object.h index 137a7e3..f94f9a1 100644 --- a/webkit/glue/glue_accessibility_object.h +++ b/webkit/glue/glue_accessibility_object.h @@ -27,6 +27,8 @@ class GlueAccessibilityObject : public WebCore::AccessibilityObjectWrapper { public: static GlueAccessibilityObject* CreateInstance(WebCore::AccessibilityObject*); + virtual ~GlueAccessibilityObject() {} + // Performs the default action on a given object. bool DoDefaultAction(int child_id); @@ -91,7 +93,6 @@ class GlueAccessibilityObject : public WebCore::AccessibilityObjectWrapper { protected: explicit GlueAccessibilityObject(WebCore::AccessibilityObject*); - virtual ~GlueAccessibilityObject() {} // Helper functions. WebCore::String name() const; diff --git a/webkit/glue/webaccessibility.h b/webkit/glue/webaccessibility.h index 538e612..250c665 100644 --- a/webkit/glue/webaccessibility.h +++ b/webkit/glue/webaccessibility.h @@ -117,6 +117,10 @@ class WebAccessibility { // Id of accessible child, whose information is being requested. int child_id; + // Indicates if the |child_id| refers to a direct child of the active + // accessibility object (true) or not (false). + bool direct_descendant; + // LONG input parameters, used differently depending on the function called. long input_long1; long input_long2; diff --git a/webkit/glue/webaccessibilitymanager.h b/webkit/glue/webaccessibilitymanager.h index cebe94c..c94fbb9 100644 --- a/webkit/glue/webaccessibilitymanager.h +++ b/webkit/glue/webaccessibilitymanager.h @@ -7,6 +7,10 @@ #include "webkit/glue/webaccessibility.h" +namespace WebCore { +class AccessibilityObject; +} + class WebView; //////////////////////////////////////////////////////////////////////////////// @@ -24,6 +28,7 @@ class WebAccessibilityManager { WebAccessibilityManager() {} virtual ~WebAccessibilityManager() {} + // Creates a new instance of WebAccessibilityManager. static WebAccessibilityManager* Create(); // Retrieves the accessibility information as requested in in_params, by @@ -39,13 +44,17 @@ class WebAccessibilityManager { // false otherwise. virtual bool ClearAccObjMap(int acc_obj_id, bool clear_all) = 0; + // Retrieves the id of the input AccessibilityObject, due to a focus event. + // Returns an id greater than or equal to 0 if successful, -1 otherwise. + virtual int FocusAccObj(WebCore::AccessibilityObject* acc_obj) = 0; + + private: // Retrieves the RenderObject associated with this WebView, and uses it to // initialize the root of the GlueAccessibilityObject tree with the // associated accessibility information. Returns true if successful, false // otherwise. virtual bool InitAccObjRoot(WebView* view) = 0; - private: DISALLOW_COPY_AND_ASSIGN(WebAccessibilityManager); }; diff --git a/webkit/glue/webaccessibilitymanager_impl.cc b/webkit/glue/webaccessibilitymanager_impl.cc index 57ac0c7..f765127 100644 --- a/webkit/glue/webaccessibilitymanager_impl.cc +++ b/webkit/glue/webaccessibilitymanager_impl.cc @@ -34,7 +34,13 @@ WebAccessibilityManager* WebAccessibilityManager::Create() { // class WebAccessibilityManagerImpl WebAccessibilityManagerImpl::WebAccessibilityManagerImpl() - : root_(new GlueAccessibilityObjectRoot) { + : root_(new GlueAccessibilityObjectRoot), + acc_obj_id_(0) { +} + +WebAccessibilityManagerImpl::~WebAccessibilityManagerImpl() { + int_to_glue_acc_obj_map_.clear(); + acc_obj_to_int_map_.clear(); } bool WebAccessibilityManagerImpl::GetAccObjInfo(WebView* view, @@ -45,18 +51,28 @@ bool WebAccessibilityManagerImpl::GetAccObjInfo(WebView* view, return false; } - // Find GlueAccessibilityObject requested by [in_params.object_id]. - IntToAccObjMap::iterator it = - int_to_acc_obj_map_.find(in_params.object_id); - if (it == int_to_acc_obj_map_.end() || !it->second) { + // Function input parameters. + int object_id = in_params.object_id; + int child_id = in_params.child_id; + + if (!in_params.direct_descendant) { + // Object is not a direct child, re-map the input parameters accordingly. + // The object to be retrieved is referred to by the |in_params.child_id|, as + // a result of e.g. a focus event. The local |child_id| is set to 0, to + // indicate that any function call should refer to the object itself. + object_id = in_params.child_id; + child_id = 0; + } + + // Find GlueAccessibilityObject requested by |object_id|. + IntToGlueAccObjMap::iterator it = + int_to_glue_acc_obj_map_.find(object_id); + if (it == int_to_glue_acc_obj_map_.end() || !it->second) { // Map did not contain a valid instance of the data requested. return false; } RefPtr<GlueAccessibilityObject> active_acc_obj = it->second; - // Function input parameters. - int child_id = in_params.child_id; - // Temp paramters for holding output information. RefPtr<GlueAccessibilityObject> out_acc_obj = NULL; WebCore::String out_string; @@ -156,7 +172,8 @@ bool WebAccessibilityManagerImpl::GetAccObjInfo(WebView* view, out_params->output_string = StringToString16(out_string); if (out_acc_obj) { - AccObjToIntMap::iterator it = acc_obj_to_int_map_.find(out_acc_obj.get()); + AccObjToIntMap::iterator it = + acc_obj_to_int_map_.find(out_acc_obj->accessibilityObject()); if (it != acc_obj_to_int_map_.end()) { // Data already present in map, return previously assigned id. @@ -164,8 +181,8 @@ bool WebAccessibilityManagerImpl::GetAccObjInfo(WebView* view, out_params->output_long1 = -1; } else { // Insert new GlueAccessibilityObject in hashmaps. - int_to_acc_obj_map_[acc_obj_id_] = out_acc_obj.get(); - acc_obj_to_int_map_[out_acc_obj.get()] = acc_obj_id_; + int_to_glue_acc_obj_map_[acc_obj_id_] = out_acc_obj.get(); + acc_obj_to_int_map_[out_acc_obj->accessibilityObject()] = acc_obj_id_; out_params->object_id = acc_obj_id_++; out_params->output_long1 = -1; } @@ -175,9 +192,6 @@ bool WebAccessibilityManagerImpl::GetAccObjInfo(WebView* view, } bool WebAccessibilityManagerImpl::InitAccObjRoot(WebView* view) { - // Root id is always 0. - acc_obj_id_ = 0; - // Enable accessibility and retrieve Document. WebCore::AXObjectCache::enableAccessibility(); WebFrameImpl* main_frame_impl = @@ -199,8 +213,9 @@ bool WebAccessibilityManagerImpl::InitAccObjRoot(WebView* view) { axObjectCache()->getOrCreate(doc->renderer())); } // Insert root in hashmaps. - int_to_acc_obj_map_[acc_obj_id_] = root_->acc_obj_root_.get(); - acc_obj_to_int_map_[root_->acc_obj_root_.get()] = acc_obj_id_++; + int_to_glue_acc_obj_map_[acc_obj_id_] = root_->acc_obj_root_.get(); + acc_obj_to_int_map_[root_->acc_obj_root_->accessibilityObject()] = + acc_obj_id_++; return true; } @@ -209,27 +224,28 @@ bool WebAccessibilityManagerImpl::ClearAccObjMap(int acc_obj_id, bool clear_all) { if (clear_all) { // Clear maps and invalidate root. - int_to_acc_obj_map_.clear(); + int_to_glue_acc_obj_map_.clear(); acc_obj_to_int_map_.clear(); root_->acc_obj_root_ = 0; return true; } - IntToAccObjMap::iterator it = int_to_acc_obj_map_.find(acc_obj_id); + IntToGlueAccObjMap::iterator it = int_to_glue_acc_obj_map_.find(acc_obj_id); - if (it == int_to_acc_obj_map_.end()) { + if (it == int_to_glue_acc_obj_map_.end()) { // Element not found. return false; } if (it->second) { // Erase element from reverse hashmap. - AccObjToIntMap::iterator it2 = acc_obj_to_int_map_.find(it->second); + AccObjToIntMap::iterator it2 = + acc_obj_to_int_map_.find(it->second->accessibilityObject()); if (it2 != acc_obj_to_int_map_.end()) acc_obj_to_int_map_.erase(it2); } - int_to_acc_obj_map_.erase(it); + int_to_glue_acc_obj_map_.erase(it); if (acc_obj_id == 0) { // Invalidate root. @@ -238,4 +254,25 @@ bool WebAccessibilityManagerImpl::ClearAccObjMap(int acc_obj_id, return true; } +int WebAccessibilityManagerImpl::FocusAccObj( + WebCore::AccessibilityObject* acc_obj) { + if (!acc_obj) { + // Return with failure. + return -1; + } + + AccObjToIntMap::iterator it = acc_obj_to_int_map_.find(acc_obj); + + if (it != acc_obj_to_int_map_.end()) + return it->second; + + // Insert new accessibility object in hashmaps and return its newly + // assigned accessibility object id. + int_to_glue_acc_obj_map_[acc_obj_id_] = + GlueAccessibilityObject::CreateInstance(acc_obj); + acc_obj_to_int_map_[acc_obj] = acc_obj_id_; + + return acc_obj_id_++; +} + } // namespace webkit_glue diff --git a/webkit/glue/webaccessibilitymanager_impl.h b/webkit/glue/webaccessibilitymanager_impl.h index fe28e4e..1bc0607 100644 --- a/webkit/glue/webaccessibilitymanager_impl.h +++ b/webkit/glue/webaccessibilitymanager_impl.h @@ -10,10 +10,6 @@ class GlueAccessibilityObject; -namespace webkit_glue { -typedef base::hash_map<int, GlueAccessibilityObject*> IntToAccObjMap; -typedef base::hash_map<GlueAccessibilityObject*, int> AccObjToIntMap; - //////////////////////////////////////////////////////////////////////////////// // // WebAccessibilityManagerImpl @@ -24,21 +20,23 @@ typedef base::hash_map<GlueAccessibilityObject*, int> AccObjToIntMap; // the requested information from the active AccessibilityObject, through the // GlueAccessibilityObject. //////////////////////////////////////////////////////////////////////////////// + +namespace webkit_glue { + class WebAccessibilityManagerImpl : public WebAccessibilityManager { public: // From WebAccessibilityManager. bool GetAccObjInfo(WebView* view, const WebAccessibility::InParams& in_params, WebAccessibility::OutParams* out_params); - - // From WebAccessibilityManager. bool ClearAccObjMap(int acc_obj_id, bool clear_all); + int FocusAccObj(WebCore::AccessibilityObject* acc_obj); protected: // Needed so WebAccessibilityManager::Create can call our constructor. friend class WebAccessibilityManager; WebAccessibilityManagerImpl(); - ~WebAccessibilityManagerImpl() {} + ~WebAccessibilityManagerImpl(); private: // From WebAccessibilityManager. @@ -49,17 +47,21 @@ class WebAccessibilityManagerImpl : public WebAccessibilityManager { struct GlueAccessibilityObjectRoot; GlueAccessibilityObjectRoot* root_; + typedef base::hash_map<int, GlueAccessibilityObject*> IntToGlueAccObjMap; + typedef base::hash_map<WebCore::AccessibilityObject*, int> AccObjToIntMap; + // Hashmap for cashing of elements in use by the AT, mapping id (int) to a // GlueAccessibilityObject pointer. - IntToAccObjMap int_to_acc_obj_map_; + IntToGlueAccObjMap int_to_glue_acc_obj_map_; // Hashmap for cashing of elements in use by the AT, mapping a - // GlueAccessibilityObject pointer to its id (int). Needed for reverse lookup, + // AccessibilityObject pointer to its id (int). Needed for reverse lookup, // to ensure unnecessary duplicate entries are not created in the - // IntToAccObjMap (above). + // IntToGlueAccObjMap (above) and for focus changes in WebKit. AccObjToIntMap acc_obj_to_int_map_; - // Unique identifier for retrieving a GlueAccessibilityObject from the page's - // hashmaps. + // Unique identifier for retrieving an accessibility object from the page's + // hashmaps. Id is always 0 for the root of the accessibility object + // hierarchy (on a per-renderer process basis). int acc_obj_id_; DISALLOW_COPY_AND_ASSIGN(WebAccessibilityManagerImpl); diff --git a/webkit/glue/webview_delegate.h b/webkit/glue/webview_delegate.h index 525f745..7d503ad 100644 --- a/webkit/glue/webview_delegate.h +++ b/webkit/glue/webview_delegate.h @@ -37,6 +37,10 @@ namespace webkit_glue { class WebMediaPlayerDelegate; } +namespace WebCore { +class AccessibilityObject; +} + namespace WebKit { class WebDragData; class WebWorker; @@ -169,6 +173,13 @@ class WebViewDelegate : virtual public WebWidgetDelegate { return true; } + // Called by ChromeClientImpl::focus() if accessibility on the renderer side + // is enabled, and a focus change has occurred. Will retrieve the id of the + // input AccessibilityObject and send it through IPC for handling on the + // browser side. + virtual void FocusAccessibilityObject(WebCore::AccessibilityObject* acc_obj) { + } + // FrameLoaderClient ------------------------------------------------------- // Notifies the delegate that a load has begun. diff --git a/webkit/glue/webview_impl.h b/webkit/glue/webview_impl.h index ae26890..caac1c8 100644 --- a/webkit/glue/webview_impl.h +++ b/webkit/glue/webview_impl.h @@ -138,6 +138,9 @@ class WebViewImpl : public WebView, public base::RefCounted<WebViewImpl> { WebCore::Frame* GetFocusedWebCoreFrame(); + // Returns the currently focused Node or NULL if no node has focus. + WebCore::Node* GetFocusedNode(); + static WebViewImpl* FromPage(WebCore::Page* page); WebViewDelegate* delegate() { @@ -285,9 +288,6 @@ class WebViewImpl : public WebView, public base::RefCounted<WebViewImpl> { WebCore::HitTestResult HitTestResultForWindowPos( const WebCore::IntPoint& pos); - // Returns the currently focused Node or NULL if no node has focus. - WebCore::Node* GetFocusedNode(); - // ImageResourceFetchers schedule via DownloadImage. std::set<ImageResourceFetcher*> image_fetchers_; |