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