/work/obj-fuzz/dist/include/mozilla/a11y/DocAccessibleParent.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=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_DocAccessibleParent_h |
8 | | #define mozilla_a11y_DocAccessibleParent_h |
9 | | |
10 | | #include "nsAccessibilityService.h" |
11 | | #include "mozilla/a11y/PDocAccessibleParent.h" |
12 | | #include "mozilla/a11y/ProxyAccessible.h" |
13 | | #include "nsClassHashtable.h" |
14 | | #include "nsHashKeys.h" |
15 | | #include "nsISupportsImpl.h" |
16 | | |
17 | | namespace mozilla { |
18 | | namespace a11y { |
19 | | |
20 | | class xpcAccessibleGeneric; |
21 | | |
22 | | /* |
23 | | * These objects live in the main process and comunicate with and represent |
24 | | * an accessible document in a content process. |
25 | | */ |
26 | | class DocAccessibleParent : public ProxyAccessible, |
27 | | public PDocAccessibleParent |
28 | | { |
29 | | public: |
30 | | DocAccessibleParent() : |
31 | | ProxyAccessible(this), mParentDoc(kNoParentDoc), |
32 | | #if defined(XP_WIN) |
33 | | mEmulatedWindowHandle(nullptr), |
34 | | #endif // defined(XP_WIN) |
35 | | mTopLevel(false), mShutdown(false) |
36 | 0 | { |
37 | 0 | MOZ_COUNT_CTOR_INHERITED(DocAccessibleParent, ProxyAccessible); |
38 | 0 | sMaxDocID++; |
39 | 0 | mActorID = sMaxDocID; |
40 | 0 | MOZ_ASSERT(!LiveDocs().Get(mActorID)); |
41 | 0 | LiveDocs().Put(mActorID, this); |
42 | 0 | } |
43 | | |
44 | | ~DocAccessibleParent() |
45 | 0 | { |
46 | 0 | LiveDocs().Remove(mActorID); |
47 | 0 | MOZ_COUNT_DTOR_INHERITED(DocAccessibleParent, ProxyAccessible); |
48 | 0 | MOZ_ASSERT(mChildDocs.Length() == 0); |
49 | 0 | MOZ_ASSERT(!ParentDoc()); |
50 | 0 | } |
51 | | |
52 | 0 | void SetTopLevel() { mTopLevel = true; } |
53 | 0 | bool IsTopLevel() const { return mTopLevel; } |
54 | | |
55 | 0 | bool IsShutdown() const { return mShutdown; } |
56 | | |
57 | | /** |
58 | | * Mark this actor as shutdown without doing any cleanup. This should only |
59 | | * be called on actors that have just been initialized, so probably only from |
60 | | * RecvPDocAccessibleConstructor. |
61 | | */ |
62 | | void MarkAsShutdown() |
63 | 0 | { |
64 | 0 | MOZ_ASSERT(mChildDocs.IsEmpty()); |
65 | 0 | MOZ_ASSERT(mAccessibles.Count() == 0); |
66 | 0 | mShutdown = true; |
67 | 0 | } |
68 | | |
69 | | /* |
70 | | * Called when a message from a document in a child process notifies the main |
71 | | * process it is firing an event. |
72 | | */ |
73 | | virtual mozilla::ipc::IPCResult RecvEvent(const uint64_t& aID, const uint32_t& aType) |
74 | | override; |
75 | | |
76 | | virtual mozilla::ipc::IPCResult RecvShowEvent(const ShowEventData& aData, const bool& aFromUser) |
77 | | override; |
78 | | virtual mozilla::ipc::IPCResult RecvHideEvent(const uint64_t& aRootID, const bool& aFromUser) |
79 | | override; |
80 | | mozilla::ipc::IPCResult RecvStateChangeEvent(const uint64_t& aID, |
81 | | const uint64_t& aState, |
82 | | const bool& aEnabled) final; |
83 | | |
84 | | mozilla::ipc::IPCResult RecvCaretMoveEvent(const uint64_t& aID, |
85 | | #if defined(XP_WIN) |
86 | | const LayoutDeviceIntRect& aCaretRect, |
87 | | #endif |
88 | | const int32_t& aOffset) final; |
89 | | |
90 | | virtual mozilla::ipc::IPCResult RecvTextChangeEvent(const uint64_t& aID, const nsString& aStr, |
91 | | const int32_t& aStart, const uint32_t& aLen, |
92 | | const bool& aIsInsert, |
93 | | const bool& aFromUser) override; |
94 | | |
95 | | #if defined(XP_WIN) |
96 | | virtual mozilla::ipc::IPCResult RecvSyncTextChangeEvent(const uint64_t& aID, const nsString& aStr, |
97 | | const int32_t& aStart, const uint32_t& aLen, |
98 | | const bool& aIsInsert, |
99 | | const bool& aFromUser) override; |
100 | | |
101 | | virtual mozilla::ipc::IPCResult RecvFocusEvent(const uint64_t& aID, |
102 | | const LayoutDeviceIntRect& aCaretRect) override; |
103 | | #endif // defined(XP_WIN) |
104 | | |
105 | | virtual mozilla::ipc::IPCResult RecvSelectionEvent(const uint64_t& aID, |
106 | | const uint64_t& aWidgetID, |
107 | | const uint32_t& aType) override; |
108 | | |
109 | | virtual mozilla::ipc::IPCResult RecvVirtualCursorChangeEvent(const uint64_t& aID, |
110 | | const uint64_t& aOldPositionID, |
111 | | const int32_t& aOldStartOffset, |
112 | | const int32_t& aOldEndOffset, |
113 | | const uint64_t& aNewPositionID, |
114 | | const int32_t& aNewStartOffset, |
115 | | const int32_t& aNewEndOffset, |
116 | | const int16_t& aReason, |
117 | | const int16_t& aBoundaryType, |
118 | | const bool& aFromUser) override; |
119 | | |
120 | | virtual mozilla::ipc::IPCResult RecvScrollingEvent(const uint64_t& aID, |
121 | | const uint64_t& aType, |
122 | | const uint32_t& aScrollX, |
123 | | const uint32_t& aScrollY, |
124 | | const uint32_t& aMaxScrollX, |
125 | | const uint32_t& aMaxScrollY) override; |
126 | | |
127 | | mozilla::ipc::IPCResult RecvRoleChangedEvent(const a11y::role& aRole) final; |
128 | | |
129 | | virtual mozilla::ipc::IPCResult RecvBindChildDoc(PDocAccessibleParent* aChildDoc, const uint64_t& aID) override; |
130 | | |
131 | | void Unbind() |
132 | 0 | { |
133 | 0 | if (DocAccessibleParent* parent = ParentDoc()) { |
134 | 0 | parent->RemoveChildDoc(this); |
135 | 0 | } |
136 | 0 |
|
137 | 0 | SetParent(nullptr); |
138 | 0 | } |
139 | | |
140 | | virtual mozilla::ipc::IPCResult RecvShutdown() override; |
141 | | void Destroy(); |
142 | | virtual void ActorDestroy(ActorDestroyReason aWhy) override |
143 | 0 | { |
144 | 0 | MOZ_ASSERT(CheckDocTree()); |
145 | 0 | if (!mShutdown) |
146 | 0 | Destroy(); |
147 | 0 | } |
148 | | |
149 | | /* |
150 | | * Return the main processes representation of the parent document (if any) |
151 | | * of the document this object represents. |
152 | | */ |
153 | | DocAccessibleParent* ParentDoc() const; |
154 | | static const uint64_t kNoParentDoc = UINT64_MAX; |
155 | | |
156 | | /* |
157 | | * Called when a document in a content process notifies the main process of a |
158 | | * new child document. |
159 | | */ |
160 | | ipc::IPCResult AddChildDoc(DocAccessibleParent* aChildDoc, |
161 | | uint64_t aParentID, bool aCreating = true); |
162 | | |
163 | | /* |
164 | | * Called when the document in the content process this object represents |
165 | | * notifies the main process a child document has been removed. |
166 | | */ |
167 | | void RemoveChildDoc(DocAccessibleParent* aChildDoc) |
168 | 0 | { |
169 | 0 | ProxyAccessible* parent = aChildDoc->Parent(); |
170 | 0 | MOZ_ASSERT(parent); |
171 | 0 | if (parent) { |
172 | 0 | aChildDoc->Parent()->ClearChildDoc(aChildDoc); |
173 | 0 | } |
174 | 0 | DebugOnly<bool> result = mChildDocs.RemoveElement(aChildDoc->mActorID); |
175 | 0 | aChildDoc->mParentDoc = kNoParentDoc; |
176 | 0 | MOZ_ASSERT(result); |
177 | 0 | } |
178 | | |
179 | | void RemoveAccessible(ProxyAccessible* aAccessible) |
180 | 0 | { |
181 | 0 | MOZ_DIAGNOSTIC_ASSERT(mAccessibles.GetEntry(aAccessible->ID())); |
182 | 0 | mAccessibles.RemoveEntry(aAccessible->ID()); |
183 | 0 | } |
184 | | |
185 | | /** |
186 | | * Return the accessible for given id. |
187 | | */ |
188 | | ProxyAccessible* GetAccessible(uintptr_t aID) |
189 | 0 | { |
190 | 0 | if (!aID) |
191 | 0 | return this; |
192 | 0 | |
193 | 0 | ProxyEntry* e = mAccessibles.GetEntry(aID); |
194 | 0 | return e ? e->mProxy : nullptr; |
195 | 0 | } |
196 | | |
197 | | const ProxyAccessible* GetAccessible(uintptr_t aID) const |
198 | 0 | { return const_cast<DocAccessibleParent*>(this)->GetAccessible(aID); } |
199 | | |
200 | 0 | size_t ChildDocCount() const { return mChildDocs.Length(); } |
201 | | const DocAccessibleParent* ChildDocAt(size_t aIdx) const |
202 | 0 | { return const_cast<DocAccessibleParent*>(this)->ChildDocAt(aIdx); } |
203 | | DocAccessibleParent* ChildDocAt(size_t aIdx) |
204 | 0 | { return LiveDocs().Get(mChildDocs[aIdx]); } |
205 | | |
206 | | #if defined(XP_WIN) |
207 | | void MaybeInitWindowEmulation(); |
208 | | void SendParentCOMProxy(); |
209 | | |
210 | | virtual mozilla::ipc::IPCResult RecvGetWindowedPluginIAccessible( |
211 | | const WindowsHandle& aHwnd, IAccessibleHolder* aPluginCOMProxy) override; |
212 | | |
213 | | /** |
214 | | * Set emulated native window handle for a document. |
215 | | * @param aWindowHandle emulated native window handle |
216 | | */ |
217 | | void SetEmulatedWindowHandle(HWND aWindowHandle); |
218 | | HWND GetEmulatedWindowHandle() const { return mEmulatedWindowHandle; } |
219 | | #endif |
220 | | |
221 | | private: |
222 | | |
223 | | class ProxyEntry : public PLDHashEntryHdr |
224 | | { |
225 | | public: |
226 | 0 | explicit ProxyEntry(const void*) : mProxy(nullptr) {} |
227 | | ProxyEntry(ProxyEntry&& aOther) : |
228 | 0 | mProxy(aOther.mProxy) { aOther.mProxy = nullptr; } |
229 | 0 | ~ProxyEntry() { delete mProxy; } |
230 | | |
231 | | typedef uint64_t KeyType; |
232 | | typedef const void* KeyTypePointer; |
233 | | |
234 | | bool KeyEquals(const void* aKey) const |
235 | 0 | { return mProxy->ID() == (uint64_t)aKey; } |
236 | | |
237 | 0 | static const void* KeyToPointer(uint64_t aKey) { return (void*)aKey; } |
238 | | |
239 | 0 | static PLDHashNumber HashKey(const void* aKey) { return (uint64_t)aKey; } |
240 | | |
241 | | enum { ALLOW_MEMMOVE = true }; |
242 | | |
243 | | ProxyAccessible* mProxy; |
244 | | }; |
245 | | |
246 | | uint32_t AddSubtree(ProxyAccessible* aParent, |
247 | | const nsTArray<AccessibleData>& aNewTree, uint32_t aIdx, |
248 | | uint32_t aIdxInParent); |
249 | | MOZ_MUST_USE bool CheckDocTree() const; |
250 | | xpcAccessibleGeneric* GetXPCAccessible(ProxyAccessible* aProxy); |
251 | | |
252 | | nsTArray<uint64_t> mChildDocs; |
253 | | uint64_t mParentDoc; |
254 | | |
255 | | #if defined(XP_WIN) |
256 | | // The handle associated with the emulated window that contains this document |
257 | | HWND mEmulatedWindowHandle; |
258 | | |
259 | | #if defined(MOZ_CONTENT_SANDBOX) |
260 | | mscom::PreservedStreamPtr mParentProxyStream; |
261 | | #endif // defined(MOZ_CONTENT_SANDBOX) |
262 | | #endif // defined(XP_WIN) |
263 | | |
264 | | /* |
265 | | * Conceptually this is a map from IDs to proxies, but we store the ID in the |
266 | | * proxy object so we can't use a real map. |
267 | | */ |
268 | | nsTHashtable<ProxyEntry> mAccessibles; |
269 | | uint64_t mActorID; |
270 | | bool mTopLevel; |
271 | | bool mShutdown; |
272 | | |
273 | | static uint64_t sMaxDocID; |
274 | | static nsDataHashtable<nsUint64HashKey, DocAccessibleParent*>& |
275 | | LiveDocs() |
276 | 0 | { |
277 | 0 | static nsDataHashtable<nsUint64HashKey, DocAccessibleParent*> sLiveDocs; |
278 | 0 | return sLiveDocs; |
279 | 0 | } |
280 | | }; |
281 | | |
282 | | } |
283 | | } |
284 | | |
285 | | #endif |