1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef mozilla_a11y_AccessibleHandler_h
8 #define mozilla_a11y_AccessibleHandler_h
9 
10 #define NEWEST_IA2_BASENAME Accessible2_3
11 
12 #define __GENIFACE(base) I##base
13 #define INTERFACEFOR(base) __GENIFACE(base)
14 #define NEWEST_IA2_INTERFACE INTERFACEFOR(NEWEST_IA2_BASENAME)
15 
16 #define __GENIID(iface) IID_##iface
17 #define IIDFOR(iface) __GENIID(iface)
18 #define NEWEST_IA2_IID IIDFOR(NEWEST_IA2_INTERFACE)
19 
20 #if defined(__midl) || defined(__WIDL__)
21 
22 import "Accessible2_3.idl";
23 
24 #else
25 
26 #  include "HandlerData.h"
27 
28 #  include <windows.h>
29 
30 namespace mozilla {
31 namespace a11y {
32 
33 static const GUID kUnsupportedServices[] = {
34     // clang-format off
35   // Unknown, queried by Windows on devices with touch screens or similar devices
36   // connected.
37   {0x33f139ee, 0xe509, 0x47f7, {0xbf, 0x39, 0x83, 0x76, 0x44, 0xf7, 0x45, 0x76}},
38   // Unknown, queried by Windows
39   {0xFDA075CF, 0x7C8B, 0x498C, { 0xB5, 0x14, 0xA9, 0xCB, 0x52, 0x1B, 0xBF, 0xB4 }},
40   // Unknown, queried by Windows
41   {0x8EDAA462, 0x21F4, 0x4C87, { 0xA0, 0x12, 0xB3, 0xCD, 0xA3, 0xAB, 0x01, 0xFC }},
42   // Unknown, queried by Windows
43   {0xacd46652, 0x829d, 0x41cb, { 0xa5, 0xfc, 0x17, 0xac, 0xf4, 0x36, 0x61, 0xac }},
44   // SID_IsUIAutomationObject (undocumented), queried by Windows
45   {0xb96fdb85, 0x7204, 0x4724, { 0x84, 0x2b, 0xc7, 0x05, 0x9d, 0xed, 0xb9, 0xd0 }},
46   // IIS_IsOleaccProxy (undocumented), queried by Windows
47   {0x902697FA, 0x80E4, 0x4560, {0x80, 0x2A, 0xA1, 0x3F, 0x22, 0xA6, 0x47, 0x09}},
48   // IID_IHTMLElement, queried by JAWS
49   {0x3050F1FF, 0x98B5, 0x11CF, {0xBB, 0x82, 0x00, 0xAA, 0x00, 0xBD, 0xCE, 0x0B}}
50     // clang-format on
51 };
52 
53 }
54 }  // namespace mozilla
55 
56 #  if !defined(MOZILLA_INTERNAL_API)
57 
58 #    include "Accessible2_3.h"
59 #    include "AccessibleHyperlink.h"
60 #    include "AccessibleHypertext2.h"
61 #    include "AccessibleTableCell.h"
62 #    include "Handler.h"
63 #    include "mozilla/mscom/StructStream.h"
64 #    include "mozilla/UniquePtr.h"
65 
66 #    include <ocidl.h>
67 #    include <servprov.h>
68 
69 namespace mozilla {
70 namespace a11y {
71 
72 class AccessibleHandler final : public mscom::Handler,
73                                 public NEWEST_IA2_INTERFACE,
74                                 public IServiceProvider,
75                                 public IProvideClassInfo,
76                                 public IAccessibleHyperlink,
77                                 public IAccessibleTableCell,
78                                 public IAccessibleHypertext2 {
79  public:
80   static HRESULT Create(IUnknown* aOuter, REFIID aIid, void** aOutInterface);
81 
82   // mscom::Handler
83   HRESULT QueryHandlerInterface(IUnknown* aProxyUnknown, REFIID aIid,
84                                 void** aOutInterface) override;
85   HRESULT ReadHandlerPayload(IStream* aStream, REFIID aIid) override;
86 
87   REFIID MarshalAs(REFIID aRequestedIid) override;
88   HRESULT GetMarshalInterface(REFIID aMarshalAsIid, NotNull<IUnknown*> aProxy,
89                               NotNull<IID*> aOutIid,
90                               NotNull<IUnknown**> aOutUnk) override;
91   HRESULT GetHandlerPayloadSize(REFIID aIid, DWORD* aOutPayloadSize) override;
92   HRESULT WriteHandlerPayload(IStream* aStream, REFIID aIId) override;
93 
94   // IUnknown
95   STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override;
96   STDMETHODIMP_(ULONG) AddRef() override;
97   STDMETHODIMP_(ULONG) Release() override;
98 
99   // IDispatch
100   STDMETHODIMP GetTypeInfoCount(UINT* pctinfo) override;
101   STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid,
102                            ITypeInfo** ppTInfo) override;
103   STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
104                              LCID lcid, DISPID* rgDispId) override;
105   STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
106                       DISPPARAMS* pDispParams, VARIANT* pVarResult,
107                       EXCEPINFO* pExcepInfo, UINT* puArgErr) override;
108 
109   // IAccessible
110   STDMETHODIMP get_accParent(IDispatch** ppdispParent) override;
111   STDMETHODIMP get_accChildCount(long* pcountChildren) override;
112   STDMETHODIMP get_accChild(VARIANT varChild, IDispatch** ppdispChild) override;
113   STDMETHODIMP get_accName(VARIANT varChild, BSTR* pszName) override;
114   STDMETHODIMP get_accValue(VARIANT varChild, BSTR* pszValue) override;
115   STDMETHODIMP get_accDescription(VARIANT varChild,
116                                   BSTR* pszDescription) override;
117   STDMETHODIMP get_accRole(VARIANT varChild, VARIANT* pvarRole) override;
118   STDMETHODIMP get_accState(VARIANT varChild, VARIANT* pvarState) override;
119   STDMETHODIMP get_accHelp(VARIANT varChild, BSTR* pszHelp) override;
120   STDMETHODIMP get_accHelpTopic(BSTR* pszHelpFile, VARIANT varChild,
121                                 long* pidTopic) override;
122   STDMETHODIMP get_accKeyboardShortcut(VARIANT varChild,
123                                        BSTR* pszKeyboardShortcut) override;
124   STDMETHODIMP get_accFocus(VARIANT* pvarChild) override;
125   STDMETHODIMP get_accSelection(VARIANT* pvarChildren) override;
126   STDMETHODIMP get_accDefaultAction(VARIANT varChild,
127                                     BSTR* pszDefaultAction) override;
128   STDMETHODIMP accSelect(long flagsSelect, VARIANT varChild) override;
129   STDMETHODIMP accLocation(long* pxLeft, long* pyTop, long* pcxWidth,
130                            long* pcyHeight, VARIANT varChild) override;
131   STDMETHODIMP accNavigate(long navDir, VARIANT varStart,
132                            VARIANT* pvarEndUpAt) override;
133   STDMETHODIMP accHitTest(long xLeft, long yTop, VARIANT* pvarChild) override;
134   STDMETHODIMP accDoDefaultAction(VARIANT varChild) override;
135   STDMETHODIMP put_accName(VARIANT varChild, BSTR szName) override;
136   STDMETHODIMP put_accValue(VARIANT varChild, BSTR szValue) override;
137 
138   // IAccessible2
139   STDMETHODIMP get_nRelations(long* nRelations) override;
140   STDMETHODIMP get_relation(long relationIndex,
141                             IAccessibleRelation** relation) override;
142   STDMETHODIMP get_relations(long maxRelations, IAccessibleRelation** relations,
143                              long* nRelations) override;
144   STDMETHODIMP role(long* role) override;
145   STDMETHODIMP scrollTo(IA2ScrollType scrollType) override;
146   STDMETHODIMP scrollToPoint(IA2CoordinateType coordinateType, long x,
147                              long y) override;
148   STDMETHODIMP get_groupPosition(long* groupLevel, long* similarItemsInGroup,
149                                  long* positionInGroup) override;
150   STDMETHODIMP get_states(AccessibleStates* states) override;
151   STDMETHODIMP get_extendedRole(BSTR* extendedRole) override;
152   STDMETHODIMP get_localizedExtendedRole(BSTR* localizedExtendedRole) override;
153   STDMETHODIMP get_nExtendedStates(long* nExtendedStates) override;
154   STDMETHODIMP get_extendedStates(long maxExtendedStates, BSTR** extendedStates,
155                                   long* nExtendedStates) override;
156   STDMETHODIMP get_localizedExtendedStates(
157       long maxLocalizedExtendedStates, BSTR** localizedExtendedStates,
158       long* nLocalizedExtendedStates) override;
159   STDMETHODIMP get_uniqueID(long* uniqueID) override;
160   STDMETHODIMP get_windowHandle(HWND* windowHandle) override;
161   STDMETHODIMP get_indexInParent(long* indexInParent) override;
162   STDMETHODIMP get_locale(IA2Locale* locale) override;
163   STDMETHODIMP get_attributes(BSTR* attributes) override;
164 
165   // IAccessible2_2
166   STDMETHODIMP get_attribute(BSTR name, VARIANT* attribute) override;
167   STDMETHODIMP get_accessibleWithCaret(IUnknown** accessible,
168                                        long* caretOffset) override;
169   STDMETHODIMP get_relationTargetsOfType(BSTR type, long maxTargets,
170                                          IUnknown*** targets,
171                                          long* nTargets) override;
172 
173   // IAccessible2_3
174   STDMETHODIMP get_selectionRanges(IA2Range** ranges, long* nRanges) override;
175 
176   // IServiceProvider
177   STDMETHODIMP QueryService(REFGUID aServiceId, REFIID aIid,
178                             void** aOutInterface) override;
179 
180   // IProvideClassInfo
181   STDMETHODIMP GetClassInfo(ITypeInfo** aOutTypeInfo) override;
182 
183   // IAccessibleAction
184   STDMETHODIMP nActions(long* nActions) override;
185   STDMETHODIMP doAction(long actionIndex) override;
186   STDMETHODIMP get_description(long actionIndex, BSTR* description) override;
187   STDMETHODIMP get_keyBinding(long actionIndex, long nMaxBindings,
188                               BSTR** keyBindings, long* nBindings) override;
189   STDMETHODIMP get_name(long actionIndex, BSTR* name) override;
190   STDMETHODIMP get_localizedName(long actionIndex,
191                                  BSTR* localizedName) override;
192 
193   // IAccessibleHyperlink
194   STDMETHODIMP get_anchor(long index, VARIANT* anchor) override;
195   STDMETHODIMP get_anchorTarget(long index, VARIANT* anchorTarget) override;
196   STDMETHODIMP get_startIndex(long* index) override;
197   STDMETHODIMP get_endIndex(long* index) override;
198   STDMETHODIMP get_valid(boolean* valid) override;
199 
200   // IAccessibleTableCell
201   STDMETHODIMP get_columnExtent(long* nColumnsSpanned) override;
202   STDMETHODIMP get_columnHeaderCells(IUnknown*** cellAccessibles,
203                                      long* nColumnHeaderCells) override;
204   STDMETHODIMP get_columnIndex(long* columnIndex) override;
205   STDMETHODIMP get_rowExtent(long* nRowsSpanned) override;
206   STDMETHODIMP get_rowHeaderCells(IUnknown*** cellAccessibles,
207                                   long* nRowHeaderCells) override;
208   STDMETHODIMP get_rowIndex(long* rowIndex) override;
209   STDMETHODIMP get_isSelected(boolean* isSelected) override;
210   STDMETHODIMP get_rowColumnExtents(long* row, long* column, long* rowExtents,
211                                     long* columnExtents,
212                                     boolean* isSelected) override;
213   STDMETHODIMP get_table(IUnknown** table) override;
214 
215   // IAccessibleText
216   STDMETHODIMP addSelection(long startOffset, long endOffset) override;
217   STDMETHODIMP get_attributes(long offset, long* startOffset, long* endOffset,
218                               BSTR* textAttributes) override;
219   STDMETHODIMP get_caretOffset(long* offset) override;
220   STDMETHODIMP get_characterExtents(long offset,
221                                     enum IA2CoordinateType coordType, long* x,
222                                     long* y, long* width,
223                                     long* height) override;
224   STDMETHODIMP get_nSelections(long* nSelections) override;
225   STDMETHODIMP get_offsetAtPoint(long x, long y,
226                                  enum IA2CoordinateType coordType,
227                                  long* offset) override;
228   STDMETHODIMP get_selection(long selectionIndex, long* startOffset,
229                              long* endOffset) override;
230   STDMETHODIMP get_text(long startOffset, long endOffset, BSTR* text) override;
231   STDMETHODIMP get_textBeforeOffset(long offset,
232                                     enum IA2TextBoundaryType boundaryType,
233                                     long* startOffset, long* endOffset,
234                                     BSTR* text) override;
235   STDMETHODIMP get_textAfterOffset(long offset,
236                                    enum IA2TextBoundaryType boundaryType,
237                                    long* startOffset, long* endOffset,
238                                    BSTR* text) override;
239   STDMETHODIMP get_textAtOffset(long offset,
240                                 enum IA2TextBoundaryType boundaryType,
241                                 long* startOffset, long* endOffset,
242                                 BSTR* text) override;
243   STDMETHODIMP removeSelection(long selectionIndex) override;
244   STDMETHODIMP setCaretOffset(long offset) override;
245   STDMETHODIMP setSelection(long selectionIndex, long startOffset,
246                             long endOffset) override;
247   STDMETHODIMP get_nCharacters(long* nCharacters) override;
248   STDMETHODIMP scrollSubstringTo(long startIndex, long endIndex,
249                                  enum IA2ScrollType scrollType) override;
250   STDMETHODIMP scrollSubstringToPoint(long startIndex, long endIndex,
251                                       enum IA2CoordinateType coordinateType,
252                                       long x, long y) override;
253   STDMETHODIMP get_newText(IA2TextSegment* newText) override;
254   STDMETHODIMP get_oldText(IA2TextSegment* oldText) override;
255 
256   // IAccessibleHypertext
257   STDMETHODIMP get_nHyperlinks(long* hyperlinkCount) override;
258   STDMETHODIMP get_hyperlink(long index,
259                              IAccessibleHyperlink** hyperlink) override;
260   STDMETHODIMP get_hyperlinkIndex(long charIndex,
261                                   long* hyperlinkIndex) override;
262 
263   // IAccessibleHypertext2
264   STDMETHODIMP get_hyperlinks(IAccessibleHyperlink*** hyperlinks,
265                               long* nHyperlinks) override;
266 
267  private:
268   AccessibleHandler(IUnknown* aOuter, HRESULT* aResult);
269   virtual ~AccessibleHandler();
270 
271   HRESULT ResolveIA2();
272   HRESULT ResolveIDispatch();
273   HRESULT ResolveIAHyperlink();
274   HRESULT ResolveIAHypertext();
275   HRESULT ResolveIATableCell();
276   HRESULT MaybeUpdateCachedData();
277   HRESULT GetAllTextInfo(BSTR* aText);
278   void ClearTextCache();
279   HRESULT GetRelationsInfo();
280   void ClearRelationCache();
281 
282   RefPtr<IUnknown> mDispatchUnk;
283   /**
284    * Handlers aggregate their proxies. This means that their proxies delegate
285    * their IUnknown implementation to us.
286    *
287    * mDispatchUnk and the result of Handler::GetProxy() are both strong
288    * references to the aggregated objects. OTOH, any interfaces that are QI'd
289    * from those aggregated objects have delegated unknowns.
290    *
291    * AddRef'ing an interface with a delegated unknown ends up incrementing the
292    * refcount of the *aggregator*. Since we are the aggregator of mDispatchUnk
293    * and of the wrapped proxy, holding a strong reference to any interfaces
294    * QI'd off of those objects would create a reference cycle.
295    *
296    * We may hold onto pointers to those references, but when we query them we
297    * must immediately Release() them to prevent these cycles.
298    *
299    * It is safe for us to use these raw pointers because the aggregated
300    * objects's lifetimes are proper subsets of our own lifetime.
301    */
302   IDispatch* mDispatch;                         // weak
303   NEWEST_IA2_INTERFACE* mIA2PassThru;           // weak
304   IServiceProvider* mServProvPassThru;          // weak
305   IAccessibleHyperlink* mIAHyperlinkPassThru;   // weak
306   IAccessibleTableCell* mIATableCellPassThru;   // weak
307   IAccessibleHypertext2* mIAHypertextPassThru;  // weak
308   IA2Payload mCachedData;
309   bool mCachedDynamicDataMarshaledByCom;
310   UniquePtr<mscom::StructToStream> mSerializer;
311   uint32_t mCacheGen;
312   IAccessibleHyperlink** mCachedHyperlinks;
313   long mCachedNHyperlinks;
314   IA2TextSegment* mCachedTextAttribRuns;
315   long mCachedNTextAttribRuns;
316   IARelationData* mCachedRelations;
317   long mCachedNRelations;
318   bool mIsEmulatedWindow;
319 };
320 
CopyBSTR(BSTR aSrc)321 inline static BSTR CopyBSTR(BSTR aSrc) {
322   if (!aSrc) {
323     return nullptr;
324   }
325 
326   return ::SysAllocStringLen(aSrc, ::SysStringLen(aSrc));
327 }
328 
329 }  // namespace a11y
330 }  // namespace mozilla
331 
332 #  endif  // !defined(MOZILLA_INTERNAL_API)
333 
334 #endif  // defined(__midl)
335 
336 #endif  // mozilla_a11y_AccessibleHandler_h
337