Bug 1646700 [wpt PR 24235] - Update picture-in-picture idlharness test, a=testonly
[gecko.git] / accessible / ipc / DocAccessibleParent.h
blob9d7919c00832f5d23b5e2c4c176b989230eff1bd
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/. */
7 #ifndef mozilla_a11y_DocAccessibleParent_h
8 #define mozilla_a11y_DocAccessibleParent_h
10 #include "nsAccessibilityService.h"
11 #include "mozilla/a11y/PDocAccessibleParent.h"
12 #include "mozilla/a11y/ProxyAccessible.h"
13 #include "mozilla/Tuple.h"
14 #include "nsClassHashtable.h"
15 #include "nsHashKeys.h"
16 #include "nsISupportsImpl.h"
18 namespace mozilla {
19 namespace a11y {
21 class xpcAccessibleGeneric;
23 #if !defined(XP_WIN)
24 class DocAccessiblePlatformExtParent;
25 #endif
28 * These objects live in the main process and comunicate with and represent
29 * an accessible document in a content process.
31 class DocAccessibleParent : public ProxyAccessible,
32 public PDocAccessibleParent {
33 public:
34 NS_INLINE_DECL_REFCOUNTING(DocAccessibleParent);
36 DocAccessibleParent()
37 : ProxyAccessible(this),
38 mParentDoc(kNoParentDoc),
39 #if defined(XP_WIN)
40 mEmulatedWindowHandle(nullptr),
41 #endif // defined(XP_WIN)
42 mTopLevel(false),
43 mTopLevelInContentProcess(false),
44 mShutdown(false) {
45 sMaxDocID++;
46 mActorID = sMaxDocID;
47 MOZ_ASSERT(!LiveDocs().Get(mActorID));
48 LiveDocs().Put(mActorID, this);
51 /**
52 * Set this as a top level document; i.e. it is not embedded by another remote
53 * document. This also means it is a top level document in its content
54 * process.
55 * Tab documents are top level documents.
57 void SetTopLevel() {
58 mTopLevel = true;
59 mTopLevelInContentProcess = true;
61 bool IsTopLevel() const { return mTopLevel; }
63 /**
64 * Set this as a top level document in its content process.
65 * Note that this could be an out-of-process iframe embedded by a remote
66 * embedder document. In that case, IsToplevel() will return false, but
67 * IsTopLevelInContentProcess() will return true.
69 void SetTopLevelInContentProcess() { mTopLevelInContentProcess = true; }
70 bool IsTopLevelInContentProcess() const { return mTopLevelInContentProcess; }
72 bool IsShutdown() const { return mShutdown; }
74 /**
75 * Mark this actor as shutdown without doing any cleanup. This should only
76 * be called on actors that have just been initialized, so probably only from
77 * RecvPDocAccessibleConstructor.
79 void MarkAsShutdown() {
80 MOZ_ASSERT(mChildDocs.IsEmpty());
81 MOZ_ASSERT(mAccessibles.Count() == 0);
82 mShutdown = true;
86 * Called when a message from a document in a child process notifies the main
87 * process it is firing an event.
89 virtual mozilla::ipc::IPCResult RecvEvent(const uint64_t& aID,
90 const uint32_t& aType) override;
92 virtual mozilla::ipc::IPCResult RecvShowEvent(const ShowEventData& aData,
93 const bool& aFromUser) override;
94 virtual mozilla::ipc::IPCResult RecvHideEvent(const uint64_t& aRootID,
95 const bool& aFromUser) override;
96 mozilla::ipc::IPCResult RecvStateChangeEvent(const uint64_t& aID,
97 const uint64_t& aState,
98 const bool& aEnabled) final;
100 mozilla::ipc::IPCResult RecvCaretMoveEvent(
101 const uint64_t& aID,
102 #if defined(XP_WIN)
103 const LayoutDeviceIntRect& aCaretRect,
104 #endif
105 const int32_t& aOffset, const bool& aIsSelectionCollapsed) final;
107 virtual mozilla::ipc::IPCResult RecvTextChangeEvent(
108 const uint64_t& aID, const nsString& aStr, const int32_t& aStart,
109 const uint32_t& aLen, const bool& aIsInsert,
110 const bool& aFromUser) override;
112 #if defined(XP_WIN)
113 virtual mozilla::ipc::IPCResult RecvSyncTextChangeEvent(
114 const uint64_t& aID, const nsString& aStr, const int32_t& aStart,
115 const uint32_t& aLen, const bool& aIsInsert,
116 const bool& aFromUser) override;
118 virtual mozilla::ipc::IPCResult RecvFocusEvent(
119 const uint64_t& aID, const LayoutDeviceIntRect& aCaretRect) override;
120 #endif // defined(XP_WIN)
122 virtual mozilla::ipc::IPCResult RecvSelectionEvent(
123 const uint64_t& aID, const uint64_t& aWidgetID,
124 const uint32_t& aType) override;
126 MOZ_CAN_RUN_SCRIPT_BOUNDARY
127 virtual mozilla::ipc::IPCResult RecvVirtualCursorChangeEvent(
128 const uint64_t& aID, const uint64_t& aOldPositionID,
129 const int32_t& aOldStartOffset, const int32_t& aOldEndOffset,
130 const uint64_t& aNewPositionID, const int32_t& aNewStartOffset,
131 const int32_t& aNewEndOffset, const int16_t& aReason,
132 const int16_t& aBoundaryType, const bool& aFromUser) override;
134 virtual mozilla::ipc::IPCResult RecvScrollingEvent(
135 const uint64_t& aID, const uint64_t& aType, const uint32_t& aScrollX,
136 const uint32_t& aScrollY, const uint32_t& aMaxScrollX,
137 const uint32_t& aMaxScrollY) override;
139 #if !defined(XP_WIN)
140 virtual mozilla::ipc::IPCResult RecvAnnouncementEvent(
141 const uint64_t& aID, const nsString& aAnnouncement,
142 const uint16_t& aPriority) override;
144 virtual mozilla::ipc::IPCResult RecvTextSelectionChangeEvent(
145 const uint64_t& aID, nsTArray<TextRangeData>&& aSelection) override;
146 #endif
148 mozilla::ipc::IPCResult RecvRoleChangedEvent(const a11y::role& aRole) final;
150 virtual mozilla::ipc::IPCResult RecvBindChildDoc(
151 PDocAccessibleParent* aChildDoc, const uint64_t& aID) override;
153 void Unbind() {
154 if (DocAccessibleParent* parent = ParentDoc()) {
155 parent->RemoveChildDoc(this);
158 SetParent(nullptr);
161 virtual mozilla::ipc::IPCResult RecvShutdown() override;
162 void Destroy();
163 virtual void ActorDestroy(ActorDestroyReason aWhy) override {
164 MOZ_ASSERT(CheckDocTree());
165 if (!mShutdown) Destroy();
169 * Return the main processes representation of the parent document (if any)
170 * of the document this object represents.
172 DocAccessibleParent* ParentDoc() const;
173 static const uint64_t kNoParentDoc = UINT64_MAX;
176 * Called when a document in a content process notifies the main process of a
177 * new child document.
179 ipc::IPCResult AddChildDoc(DocAccessibleParent* aChildDoc, uint64_t aParentID,
180 bool aCreating = true);
183 * Called when the document in the content process this object represents
184 * notifies the main process a child document has been removed.
186 void RemoveChildDoc(DocAccessibleParent* aChildDoc) {
187 ProxyAccessible* parent = aChildDoc->Parent();
188 MOZ_ASSERT(parent);
189 if (parent) {
190 aChildDoc->Parent()->ClearChildDoc(aChildDoc);
192 DebugOnly<bool> result = mChildDocs.RemoveElement(aChildDoc->mActorID);
193 aChildDoc->mParentDoc = kNoParentDoc;
194 MOZ_ASSERT(result);
197 void RemoveAccessible(ProxyAccessible* aAccessible) {
198 MOZ_DIAGNOSTIC_ASSERT(mAccessibles.GetEntry(aAccessible->ID()));
199 mAccessibles.RemoveEntry(aAccessible->ID());
203 * Return the accessible for given id.
205 ProxyAccessible* GetAccessible(uintptr_t aID) {
206 if (!aID) return this;
208 ProxyEntry* e = mAccessibles.GetEntry(aID);
209 return e ? e->mProxy : nullptr;
212 const ProxyAccessible* GetAccessible(uintptr_t aID) const {
213 return const_cast<DocAccessibleParent*>(this)->GetAccessible(aID);
216 size_t ChildDocCount() const { return mChildDocs.Length(); }
217 const DocAccessibleParent* ChildDocAt(size_t aIdx) const {
218 return const_cast<DocAccessibleParent*>(this)->ChildDocAt(aIdx);
220 DocAccessibleParent* ChildDocAt(size_t aIdx) {
221 return LiveDocs().Get(mChildDocs[aIdx]);
224 #if defined(XP_WIN)
225 void MaybeInitWindowEmulation();
228 * Note that an OuterDocAccessible can be created before the
229 * DocAccessibleParent or vice versa. Therefore, this must be conditionally
230 * called when either of these is created.
231 * @param aOuterDoc The OuterDocAccessible to be returned as the parent of
232 * this document. Only GetNativeInterface() is called on this, so it
233 * may be a ProxyAccessibleWrap or similar.
235 void SendParentCOMProxy(Accessible* aOuterDoc);
237 virtual mozilla::ipc::IPCResult RecvGetWindowedPluginIAccessible(
238 const WindowsHandle& aHwnd, IAccessibleHolder* aPluginCOMProxy) override;
241 * Set emulated native window handle for a document.
242 * @param aWindowHandle emulated native window handle
244 void SetEmulatedWindowHandle(HWND aWindowHandle);
245 HWND GetEmulatedWindowHandle() const { return mEmulatedWindowHandle; }
246 #endif
248 #if !defined(XP_WIN)
249 virtual mozilla::ipc::IPCResult RecvBatch(
250 const uint64_t& aBatchType, nsTArray<BatchData>&& aData) override;
252 virtual bool DeallocPDocAccessiblePlatformExtParent(
253 PDocAccessiblePlatformExtParent* aActor) override;
255 virtual PDocAccessiblePlatformExtParent*
256 AllocPDocAccessiblePlatformExtParent() override;
258 DocAccessiblePlatformExtParent* GetPlatformExtension();
259 #endif
262 * If this is an iframe document rendered in a different process to its
263 * embedder, return the DocAccessibleParent and id for the embedder
264 * accessible. Otherwise, return null and 0.
266 Tuple<DocAccessibleParent*, uint64_t> GetRemoteEmbedder();
268 private:
269 ~DocAccessibleParent() {
270 LiveDocs().Remove(mActorID);
271 MOZ_ASSERT(mChildDocs.Length() == 0);
272 MOZ_ASSERT(!ParentDoc());
275 class ProxyEntry : public PLDHashEntryHdr {
276 public:
277 explicit ProxyEntry(const void*) : mProxy(nullptr) {}
278 ProxyEntry(ProxyEntry&& aOther) : mProxy(aOther.mProxy) {
279 aOther.mProxy = nullptr;
281 ~ProxyEntry() { delete mProxy; }
283 typedef uint64_t KeyType;
284 typedef const void* KeyTypePointer;
286 bool KeyEquals(const void* aKey) const {
287 return mProxy->ID() == (uint64_t)aKey;
290 static const void* KeyToPointer(uint64_t aKey) { return (void*)aKey; }
292 static PLDHashNumber HashKey(const void* aKey) { return (uint64_t)aKey; }
294 enum { ALLOW_MEMMOVE = true };
296 ProxyAccessible* mProxy;
299 uint32_t AddSubtree(ProxyAccessible* aParent,
300 const nsTArray<AccessibleData>& aNewTree, uint32_t aIdx,
301 uint32_t aIdxInParent);
302 [[nodiscard]] bool CheckDocTree() const;
303 xpcAccessibleGeneric* GetXPCAccessible(ProxyAccessible* aProxy);
305 nsTArray<uint64_t> mChildDocs;
306 uint64_t mParentDoc;
308 #if defined(XP_WIN)
309 // The handle associated with the emulated window that contains this document
310 HWND mEmulatedWindowHandle;
312 # if defined(MOZ_SANDBOX)
313 mscom::PreservedStreamPtr mParentProxyStream;
314 mscom::PreservedStreamPtr mDocProxyStream;
315 mscom::PreservedStreamPtr mTopLevelDocProxyStream;
316 # endif // defined(MOZ_SANDBOX)
317 #endif // defined(XP_WIN)
320 * Conceptually this is a map from IDs to proxies, but we store the ID in the
321 * proxy object so we can't use a real map.
323 nsTHashtable<ProxyEntry> mAccessibles;
324 uint64_t mActorID;
325 bool mTopLevel;
326 bool mTopLevelInContentProcess;
327 bool mShutdown;
329 struct PendingChildDoc {
330 PendingChildDoc(DocAccessibleParent* aChildDoc, uint64_t aParentID)
331 : mChildDoc(aChildDoc), mParentID(aParentID) {}
332 RefPtr<DocAccessibleParent> mChildDoc;
333 uint64_t mParentID;
335 // We use nsTArray because there will be very few entries.
336 nsTArray<PendingChildDoc> mPendingChildDocs;
338 static uint64_t sMaxDocID;
339 static nsDataHashtable<nsUint64HashKey, DocAccessibleParent*>& LiveDocs() {
340 static nsDataHashtable<nsUint64HashKey, DocAccessibleParent*> sLiveDocs;
341 return sLiveDocs;
345 } // namespace a11y
346 } // namespace mozilla
348 #endif