Home | History | Annotate | Download | only in accessibility
      1 // Copyright (c) 2012 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 #ifndef UI_VIEWS_ACCESSIBILITY_NATIVE_VIEW_ACCESSIBILITY_WIN_H_
      6 #define UI_VIEWS_ACCESSIBILITY_NATIVE_VIEW_ACCESSIBILITY_WIN_H_
      7 
      8 #include <atlbase.h>
      9 #include <atlcom.h>
     10 #include <oleacc.h>
     11 
     12 #include <UIAutomationCore.h>
     13 
     14 #include <set>
     15 #include <vector>
     16 
     17 #include "third_party/iaccessible2/ia2_api_all.h"
     18 #include "ui/accessibility/ax_view_state.h"
     19 #include "ui/views/accessibility/native_view_accessibility.h"
     20 #include "ui/views/controls/native/native_view_host.h"
     21 #include "ui/views/view.h"
     22 
     23 namespace ui {
     24 enum TextBoundaryDirection;
     25 enum TextBoundaryType;
     26 }
     27 
     28 namespace views {
     29 
     30 ////////////////////////////////////////////////////////////////////////////////
     31 //
     32 // NativeViewAccessibilityWin
     33 //
     34 // Class implementing the MSAA IAccessible COM interface for a generic View,
     35 // providing accessibility to be used by screen readers and other assistive
     36 // technology (AT).
     37 //
     38 ////////////////////////////////////////////////////////////////////////////////
     39 class __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
     40 NativeViewAccessibilityWin
     41   : public CComObjectRootEx<CComMultiThreadModel>,
     42     public IDispatchImpl<IAccessible2_2, &IID_IAccessible2_2,
     43                            &LIBID_IAccessible2Lib>,
     44     public IAccessibleText,
     45     public IServiceProvider,
     46     public IAccessibleEx,
     47     public IRawElementProviderSimple,
     48     public NativeViewAccessibility {
     49  public:
     50   BEGIN_COM_MAP(NativeViewAccessibilityWin)
     51     COM_INTERFACE_ENTRY2(IDispatch, IAccessible2_2)
     52     COM_INTERFACE_ENTRY(IAccessible)
     53     COM_INTERFACE_ENTRY(IAccessible2)
     54     COM_INTERFACE_ENTRY(IAccessible2_2)
     55     COM_INTERFACE_ENTRY(IAccessibleEx)
     56     COM_INTERFACE_ENTRY(IAccessibleText)
     57     COM_INTERFACE_ENTRY(IRawElementProviderSimple)
     58     COM_INTERFACE_ENTRY(IServiceProvider)
     59   END_COM_MAP()
     60 
     61   virtual ~NativeViewAccessibilityWin();
     62 
     63   // NativeViewAccessibility.
     64   virtual void NotifyAccessibilityEvent(
     65       ui::AXEvent event_type) OVERRIDE;
     66   virtual gfx::NativeViewAccessible GetNativeObject() OVERRIDE;
     67   virtual void Destroy() OVERRIDE;
     68 
     69   void set_view(views::View* view) { view_ = view; }
     70 
     71   // Supported IAccessible methods.
     72 
     73   // Retrieves the child element or child object at a given point on the screen.
     74   virtual STDMETHODIMP accHitTest(LONG x_left, LONG y_top, VARIANT* child);
     75 
     76   // Performs the object's default action.
     77   STDMETHODIMP accDoDefaultAction(VARIANT var_id);
     78 
     79   // Retrieves the specified object's current screen location.
     80   STDMETHODIMP accLocation(LONG* x_left,
     81                            LONG* y_top,
     82                            LONG* width,
     83                            LONG* height,
     84                            VARIANT var_id);
     85 
     86   // Traverses to another UI element and retrieves the object.
     87   STDMETHODIMP accNavigate(LONG nav_dir, VARIANT start, VARIANT* end);
     88 
     89   // Retrieves an IDispatch interface pointer for the specified child.
     90   virtual STDMETHODIMP get_accChild(VARIANT var_child, IDispatch** disp_child);
     91 
     92   // Retrieves the number of accessible children.
     93   virtual STDMETHODIMP get_accChildCount(LONG* child_count);
     94 
     95   // Retrieves a string that describes the object's default action.
     96   STDMETHODIMP get_accDefaultAction(VARIANT var_id, BSTR* default_action);
     97 
     98   // Retrieves the tooltip description.
     99   STDMETHODIMP get_accDescription(VARIANT var_id, BSTR* desc);
    100 
    101   // Retrieves the object that has the keyboard focus.
    102   STDMETHODIMP get_accFocus(VARIANT* focus_child);
    103 
    104   // Retrieves the specified object's shortcut.
    105   STDMETHODIMP get_accKeyboardShortcut(VARIANT var_id, BSTR* access_key);
    106 
    107   // Retrieves the name of the specified object.
    108   STDMETHODIMP get_accName(VARIANT var_id, BSTR* name);
    109 
    110   // Retrieves the IDispatch interface of the object's parent.
    111   STDMETHODIMP get_accParent(IDispatch** disp_parent);
    112 
    113   // Retrieves information describing the role of the specified object.
    114   STDMETHODIMP get_accRole(VARIANT var_id, VARIANT* role);
    115 
    116   // Retrieves the current state of the specified object.
    117   STDMETHODIMP get_accState(VARIANT var_id, VARIANT* state);
    118 
    119   // Retrieve or set the string value associated with the specified object.
    120   // Setting the value is not typically used by screen readers, but it's
    121   // used frequently by automation software.
    122   STDMETHODIMP get_accValue(VARIANT var_id, BSTR* value);
    123   STDMETHODIMP put_accValue(VARIANT var_id, BSTR new_value);
    124 
    125   // Selections not applicable to views.
    126   STDMETHODIMP get_accSelection(VARIANT* selected);
    127   STDMETHODIMP accSelect(LONG flags_sel, VARIANT var_id);
    128 
    129   // Help functions not supported.
    130   STDMETHODIMP get_accHelp(VARIANT var_id, BSTR* help);
    131   STDMETHODIMP get_accHelpTopic(BSTR* help_file,
    132                                 VARIANT var_id,
    133                                 LONG* topic_id);
    134 
    135   // Deprecated functions, not implemented here.
    136   STDMETHODIMP put_accName(VARIANT var_id, BSTR put_name);
    137 
    138   //
    139   // IAccessible2
    140   //
    141 
    142   STDMETHODIMP role(LONG* role);
    143 
    144   STDMETHODIMP get_states(AccessibleStates* states);
    145 
    146   STDMETHODIMP get_uniqueID(LONG* unique_id);
    147 
    148   STDMETHODIMP get_windowHandle(HWND* window_handle);
    149 
    150   STDMETHODIMP get_relationTargetsOfType(BSTR type,
    151                                          long max_targets,
    152                                          IUnknown ***targets,
    153                                          long *n_targets);
    154 
    155   //
    156   // IAccessible2 methods not implemented.
    157   //
    158 
    159   STDMETHODIMP get_attributes(BSTR* attributes) {
    160     return E_NOTIMPL;
    161   }
    162   STDMETHODIMP get_attribute(BSTR name, VARIANT* attribute) {
    163     return E_NOTIMPL;
    164   }
    165   STDMETHODIMP get_indexInParent(LONG* index_in_parent) {
    166     return E_NOTIMPL;
    167   }
    168   STDMETHODIMP get_extendedRole(BSTR* extended_role) {
    169     return E_NOTIMPL;
    170   }
    171   STDMETHODIMP get_nRelations(LONG* n_relations) {
    172     return E_NOTIMPL;
    173   }
    174   STDMETHODIMP get_relation(LONG relation_index,
    175                             IAccessibleRelation** relation) {
    176     return E_NOTIMPL;
    177   }
    178   STDMETHODIMP get_relations(LONG max_relations,
    179       IAccessibleRelation** relations,
    180       LONG* n_relations) {
    181     return E_NOTIMPL;
    182   }
    183   STDMETHODIMP scrollTo(enum IA2ScrollType scroll_type) {
    184     return E_NOTIMPL;
    185   }
    186   STDMETHODIMP scrollToPoint(
    187       enum IA2CoordinateType coordinate_type,
    188       LONG x,
    189       LONG y) {
    190     return E_NOTIMPL;
    191   }
    192   STDMETHODIMP get_groupPosition(LONG* group_level,
    193                                  LONG* similar_items_in_group,
    194                                  LONG* position_in_group) {
    195     return E_NOTIMPL;
    196   }
    197   STDMETHODIMP get_localizedExtendedRole(
    198       BSTR* localized_extended_role) {
    199     return E_NOTIMPL;
    200   }
    201   STDMETHODIMP get_nExtendedStates(LONG* n_extended_states) {
    202     return E_NOTIMPL;
    203   }
    204   STDMETHODIMP get_extendedStates(LONG max_extended_states,
    205                                   BSTR** extended_states,
    206                                   LONG* n_extended_states) {
    207     return E_NOTIMPL;
    208   }
    209   STDMETHODIMP get_localizedExtendedStates(
    210       LONG max_localized_extended_states,
    211       BSTR** localized_extended_states,
    212       LONG* n_localized_extended_states) {
    213     return E_NOTIMPL;
    214   }
    215   STDMETHODIMP get_locale(IA2Locale* locale) {
    216     return E_NOTIMPL;
    217   }
    218   STDMETHODIMP get_accessibleWithCaret(IUnknown** accessible,
    219                                        long* caret_offset) {
    220     return E_NOTIMPL;
    221   }
    222 
    223   //
    224   // IAccessibleText methods.
    225   //
    226 
    227   STDMETHODIMP get_nCharacters(LONG* n_characters);
    228 
    229   STDMETHODIMP get_caretOffset(LONG* offset);
    230 
    231   STDMETHODIMP get_nSelections(LONG* n_selections);
    232 
    233   STDMETHODIMP get_selection(LONG selection_index,
    234                              LONG* start_offset,
    235                              LONG* end_offset);
    236 
    237   STDMETHODIMP get_text(LONG start_offset, LONG end_offset, BSTR* text);
    238 
    239   STDMETHODIMP get_textAtOffset(LONG offset,
    240                                 enum IA2TextBoundaryType boundary_type,
    241                                 LONG* start_offset, LONG* end_offset,
    242                                 BSTR* text);
    243 
    244   STDMETHODIMP get_textBeforeOffset(LONG offset,
    245                                     enum IA2TextBoundaryType boundary_type,
    246                                     LONG* start_offset, LONG* end_offset,
    247                                     BSTR* text);
    248 
    249   STDMETHODIMP get_textAfterOffset(LONG offset,
    250                                    enum IA2TextBoundaryType boundary_type,
    251                                    LONG* start_offset, LONG* end_offset,
    252                                    BSTR* text);
    253 
    254   STDMETHODIMP get_offsetAtPoint(LONG x, LONG y,
    255       enum IA2CoordinateType coord_type,
    256       LONG* offset);
    257 
    258   //
    259   // IAccessibleText methods not implemented.
    260   //
    261 
    262   STDMETHODIMP get_newText(IA2TextSegment* new_text) {
    263     return E_NOTIMPL;
    264   }
    265   STDMETHODIMP get_oldText(IA2TextSegment* old_text) {
    266     return E_NOTIMPL;
    267   }
    268   STDMETHODIMP addSelection(LONG start_offset, LONG end_offset) {
    269     return E_NOTIMPL;
    270   }
    271   STDMETHODIMP get_attributes(LONG offset,
    272                               LONG* start_offset,
    273                               LONG* end_offset,
    274                               BSTR* text_attributes) {
    275     return E_NOTIMPL;
    276   }
    277   STDMETHODIMP get_characterExtents(LONG offset,
    278       enum IA2CoordinateType coord_type,
    279       LONG* x, LONG* y,
    280       LONG* width, LONG* height) {
    281     return E_NOTIMPL;
    282   }
    283   STDMETHODIMP removeSelection(LONG selection_index) {
    284     return E_NOTIMPL;
    285   }
    286   STDMETHODIMP setCaretOffset(LONG offset) {
    287     return E_NOTIMPL;
    288   }
    289   STDMETHODIMP setSelection(LONG selection_index,
    290                             LONG start_offset,
    291                             LONG end_offset) {
    292     return E_NOTIMPL;
    293   }
    294   STDMETHODIMP scrollSubstringTo(LONG start_index,
    295                                  LONG end_index,
    296                                  enum IA2ScrollType scroll_type) {
    297     return E_NOTIMPL;
    298   }
    299   STDMETHODIMP scrollSubstringToPoint(LONG start_index,
    300       LONG end_index,
    301       enum IA2CoordinateType coordinate_type,
    302       LONG x, LONG y) {
    303     return E_NOTIMPL;
    304   }
    305 
    306   //
    307   // IServiceProvider methods.
    308   //
    309 
    310   STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void** object);
    311 
    312   //
    313   // IAccessibleEx methods not implemented.
    314   //
    315   STDMETHODIMP GetObjectForChild(long child_id, IAccessibleEx** ret) {
    316     return E_NOTIMPL;
    317   }
    318 
    319   STDMETHODIMP GetIAccessiblePair(IAccessible** acc, long* child_id) {
    320     return E_NOTIMPL;
    321   }
    322 
    323   STDMETHODIMP GetRuntimeId(SAFEARRAY** runtime_id) {
    324     return E_NOTIMPL;
    325   }
    326 
    327   STDMETHODIMP ConvertReturnedElement(IRawElementProviderSimple* element,
    328                                       IAccessibleEx** acc) {
    329     return E_NOTIMPL;
    330   }
    331 
    332   //
    333   // IRawElementProviderSimple methods.
    334   //
    335   // The GetPatternProvider/GetPropertyValue methods need to be implemented for
    336   // the on-screen keyboard to show up in Windows 8 metro.
    337   STDMETHODIMP GetPatternProvider(PATTERNID id, IUnknown** provider);
    338   STDMETHODIMP GetPropertyValue(PROPERTYID id, VARIANT* ret);
    339 
    340   //
    341   // IRawElementProviderSimple methods not implemented.
    342   //
    343   STDMETHODIMP get_ProviderOptions(enum ProviderOptions* ret) {
    344     return E_NOTIMPL;
    345   }
    346 
    347   STDMETHODIMP get_HostRawElementProvider(
    348       IRawElementProviderSimple** provider) {
    349     return E_NOTIMPL;
    350   }
    351 
    352   // Static methods
    353 
    354   // Returns a conversion from the event (as defined in ax_enums.idl)
    355   // to an MSAA event.
    356   static int32 MSAAEvent(ui::AXEvent event);
    357 
    358   // Returns a conversion from the Role (as defined in ax_enums.idl)
    359   // to an MSAA role.
    360   static int32 MSAARole(ui::AXRole role);
    361 
    362   // Returns a conversion from the State (as defined in ax_enums.idl)
    363   // to MSAA states set.
    364   static int32 MSAAState(const ui::AXViewState& state);
    365 
    366  protected:
    367   NativeViewAccessibilityWin();
    368 
    369   const View* view() const { return view_; }
    370 
    371  private:
    372   // Determines navigation direction for accNavigate, based on left, up and
    373   // previous being mapped all to previous and right, down, next being mapped
    374   // to next. Returns true if navigation direction is next, false otherwise.
    375   bool IsNavDirNext(int nav_dir) const;
    376 
    377   // Determines if the navigation target is within the allowed bounds. Returns
    378   // true if it is, false otherwise.
    379   bool IsValidNav(int nav_dir,
    380                   int start_id,
    381                   int lower_bound,
    382                   int upper_bound) const;
    383 
    384   // Determines if the child id variant is valid.
    385   bool IsValidId(const VARIANT& child) const;
    386 
    387   // Helper function which sets applicable states of view.
    388   void SetState(VARIANT* msaa_state, View* view);
    389 
    390   // Return the text to use for IAccessibleText.
    391   base::string16 TextForIAccessibleText();
    392 
    393   // If offset is a member of IA2TextSpecialOffsets this function updates the
    394   // value of offset and returns, otherwise offset remains unchanged.
    395   void HandleSpecialTextOffset(const base::string16& text, LONG* offset);
    396 
    397   // Convert from a IA2TextBoundaryType to a ui::TextBoundaryType.
    398   ui::TextBoundaryType IA2TextBoundaryToTextBoundary(IA2TextBoundaryType type);
    399 
    400   // Search forwards (direction == 1) or backwards (direction == -1)
    401   // from the given offset until the given boundary is found, and
    402   // return the offset of that boundary.
    403   LONG FindBoundary(const base::string16& text,
    404                     IA2TextBoundaryType ia2_boundary,
    405                     LONG start_offset,
    406                     ui::TextBoundaryDirection direction);
    407 
    408   // Populates the given vector with all widgets that are either a child
    409   // or are owned by this view's widget, and who are not contained in a
    410   // NativeViewHost.
    411   void PopulateChildWidgetVector(std::vector<Widget*>* child_widgets);
    412 
    413   // Adds this view to alert_target_view_storage_ids_.
    414   void AddAlertTarget();
    415 
    416   // Removes this view from alert_target_view_storage_ids_.
    417   void RemoveAlertTarget();
    418 
    419   // Give CComObject access to the class constructor.
    420   template <class Base> friend class CComObject;
    421 
    422   // Member View needed for view-specific calls.
    423   View* view_;
    424 
    425   // A unique id for each object, needed for IAccessible2.
    426   long unique_id_;
    427 
    428   // Next unique id to assign.
    429   static long next_unique_id_;
    430 
    431   // Circular queue size.
    432   static const int kMaxViewStorageIds = 20;
    433 
    434   // Circular queue of view storage ids corresponding to child ids
    435   // used to post notifications using NotifyWinEvent.
    436   static int view_storage_ids_[kMaxViewStorageIds];
    437 
    438   // Next index into |view_storage_ids_| to use.
    439   static int next_view_storage_id_index_;
    440 
    441   // A vector of view storage ids of views that have been the target of
    442   // an alert event, in order to provide an api to quickly identify all
    443   // open alerts.
    444   static std::vector<int> alert_target_view_storage_ids_;
    445 
    446   DISALLOW_COPY_AND_ASSIGN(NativeViewAccessibilityWin);
    447 };
    448 
    449 }  // namespace views
    450 
    451 #endif  // UI_VIEWS_ACCESSIBILITY_NATIVE_VIEW_ACCESSIBILITY_WIN_H_
    452