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