Bug 1890277: part 2) Add `require-trusted-types-for` directive to CSP parser, guarded...
[gecko.git] / accessible / ipc / DocAccessibleParent.h
blobbb05fbafada4def7a7ef775e94a3a664b758f7ea
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/RemoteAccessible.h"
13 #include "mozilla/dom/BrowserBridgeParent.h"
14 #include "nsClassHashtable.h"
15 #include "nsHashKeys.h"
16 #include "nsISupportsImpl.h"
18 namespace mozilla {
19 namespace dom {
20 class CanonicalBrowsingContext;
23 namespace a11y {
25 class TextRange;
26 class xpcAccessibleGeneric;
29 * These objects live in the main process and comunicate with and represent
30 * an accessible document in a content process.
32 class DocAccessibleParent : public RemoteAccessible,
33 public PDocAccessibleParent,
34 public nsIMemoryReporter {
35 public:
36 NS_DECL_ISUPPORTS
37 NS_DECL_NSIMEMORYREPORTER
39 private:
40 DocAccessibleParent();
42 public:
43 static already_AddRefed<DocAccessibleParent> New();
45 /**
46 * Set this as a top level document; i.e. it is not embedded by another remote
47 * document. This also means it is a top level document in its content
48 * process.
49 * Tab documents are top level documents.
51 void SetTopLevel() {
52 mTopLevel = true;
53 mTopLevelInContentProcess = true;
55 bool IsTopLevel() const { return mTopLevel; }
57 /**
58 * Set this as a top level document in its content process.
59 * Note that this could be an out-of-process iframe embedded by a remote
60 * embedder document. In that case, IsToplevel() will return false, but
61 * IsTopLevelInContentProcess() will return true.
63 void SetTopLevelInContentProcess() { mTopLevelInContentProcess = true; }
64 bool IsTopLevelInContentProcess() const { return mTopLevelInContentProcess; }
66 /**
67 * Determine whether this is an out-of-process iframe document, embedded by a
68 * remote embedder document.
70 bool IsOOPIframeDoc() const {
71 return !mTopLevel && mTopLevelInContentProcess;
74 bool IsShutdown() const { return mShutdown; }
76 /**
77 * Mark this actor as shutdown without doing any cleanup. This should only
78 * be called on actors that have just been initialized, so probably only from
79 * RecvPDocAccessibleConstructor.
81 void MarkAsShutdown() {
82 MOZ_ASSERT(mChildDocs.IsEmpty());
83 MOZ_ASSERT(mAccessibles.Count() == 0);
84 MOZ_ASSERT(!mBrowsingContext);
85 mShutdown = true;
88 void SetBrowsingContext(dom::CanonicalBrowsingContext* aBrowsingContext);
90 dom::CanonicalBrowsingContext* GetBrowsingContext() const {
91 return mBrowsingContext;
95 * Called when a message from a document in a child process notifies the main
96 * process it is firing an event.
98 virtual mozilla::ipc::IPCResult RecvEvent(const uint64_t& aID,
99 const uint32_t& aType) override;
101 virtual mozilla::ipc::IPCResult RecvShowEvent(
102 nsTArray<AccessibleData>&& aNewTree, const bool& aEventSuppressed,
103 const bool& aComplete, const bool& aFromUser) override;
104 virtual mozilla::ipc::IPCResult RecvHideEvent(const uint64_t& aRootID,
105 const bool& aFromUser) override;
106 mozilla::ipc::IPCResult RecvStateChangeEvent(const uint64_t& aID,
107 const uint64_t& aState,
108 const bool& aEnabled) final;
110 mozilla::ipc::IPCResult RecvCaretMoveEvent(
111 const uint64_t& aID, const LayoutDeviceIntRect& aCaretRect,
112 const int32_t& aOffset, const bool& aIsSelectionCollapsed,
113 const bool& aIsAtEndOfLine, const int32_t& aGranularity,
114 const bool& aFromUser) final;
116 virtual mozilla::ipc::IPCResult RecvTextChangeEvent(
117 const uint64_t& aID, const nsAString& aStr, const int32_t& aStart,
118 const uint32_t& aLen, const bool& aIsInsert,
119 const bool& aFromUser) override;
121 virtual mozilla::ipc::IPCResult RecvFocusEvent(
122 const uint64_t& aID, const LayoutDeviceIntRect& aCaretRect) override;
124 virtual mozilla::ipc::IPCResult RecvSelectionEvent(
125 const uint64_t& aID, const uint64_t& aWidgetID,
126 const uint32_t& aType) override;
128 virtual mozilla::ipc::IPCResult RecvScrollingEvent(
129 const uint64_t& aID, const uint64_t& aType, const uint32_t& aScrollX,
130 const uint32_t& aScrollY, const uint32_t& aMaxScrollX,
131 const uint32_t& aMaxScrollY) override;
133 virtual mozilla::ipc::IPCResult RecvCache(
134 const mozilla::a11y::CacheUpdateType& aUpdateType,
135 nsTArray<CacheData>&& aData) override;
137 virtual mozilla::ipc::IPCResult RecvSelectedAccessiblesChanged(
138 nsTArray<uint64_t>&& aSelectedIDs,
139 nsTArray<uint64_t>&& aUnselectedIDs) override;
141 virtual mozilla::ipc::IPCResult RecvAccessiblesWillMove(
142 nsTArray<uint64_t>&& aIDs) override;
144 #if !defined(XP_WIN)
145 virtual mozilla::ipc::IPCResult RecvAnnouncementEvent(
146 const uint64_t& aID, const nsAString& aAnnouncement,
147 const uint16_t& aPriority) override;
148 #endif
150 virtual mozilla::ipc::IPCResult RecvTextSelectionChangeEvent(
151 const uint64_t& aID, nsTArray<TextRangeData>&& aSelection) override;
153 mozilla::ipc::IPCResult RecvRoleChangedEvent(
154 const a11y::role& aRole, const uint8_t& aRoleMapEntryIndex) final;
156 virtual mozilla::ipc::IPCResult RecvBindChildDoc(
157 NotNull<PDocAccessibleParent*> aChildDoc, const uint64_t& aID) override;
159 void Unbind() {
160 if (DocAccessibleParent* parent = ParentDoc()) {
161 parent->RemoveChildDoc(this);
164 SetParent(nullptr);
167 virtual mozilla::ipc::IPCResult RecvShutdown() override;
168 void Destroy();
169 virtual void ActorDestroy(ActorDestroyReason aWhy) override;
172 * Return the main processes representation of the parent document (if any)
173 * of the document this object represents.
175 DocAccessibleParent* ParentDoc() const;
176 static const uint64_t kNoParentDoc = UINT64_MAX;
179 * Called when a document in a content process notifies the main process of a
180 * new child document.
181 * Although this is called internally for OOP child documents, these should be
182 * added via the BrowserBridgeParent version of this method, as the parent id
183 * might not exist yet in that case.
185 ipc::IPCResult AddChildDoc(DocAccessibleParent* aChildDoc, uint64_t aParentID,
186 bool aCreating = true);
189 * Called when a document in a content process notifies the main process of a
190 * new OOP child document.
192 ipc::IPCResult AddChildDoc(dom::BrowserBridgeParent* aBridge);
194 void RemovePendingOOPChildDoc(dom::BrowserBridgeParent* aBridge) {
195 mPendingOOPChildDocs.Remove(aBridge);
199 * Called when the document in the content process this object represents
200 * notifies the main process a child document has been removed.
202 void RemoveChildDoc(DocAccessibleParent* aChildDoc) {
203 RemoteAccessible* parent = aChildDoc->RemoteParent();
204 MOZ_ASSERT(parent);
205 if (parent) {
206 aChildDoc->RemoteParent()->ClearChildDoc(aChildDoc);
208 DebugOnly<bool> result = mChildDocs.RemoveElement(aChildDoc->mActorID);
209 aChildDoc->mParentDoc = kNoParentDoc;
210 MOZ_ASSERT(result);
213 void RemoveAccessible(RemoteAccessible* aAccessible) {
214 MOZ_DIAGNOSTIC_ASSERT(mAccessibles.GetEntry(aAccessible->ID()));
215 mAccessibles.RemoveEntry(aAccessible->ID());
219 * Return the accessible for given id.
221 RemoteAccessible* GetAccessible(uintptr_t aID) {
222 if (!aID) return this;
224 ProxyEntry* e = mAccessibles.GetEntry(aID);
225 return e ? e->mProxy : nullptr;
228 const RemoteAccessible* GetAccessible(uintptr_t aID) const {
229 return const_cast<DocAccessibleParent*>(this)->GetAccessible(aID);
232 size_t ChildDocCount() const { return mChildDocs.Length(); }
233 const DocAccessibleParent* ChildDocAt(size_t aIdx) const {
234 return const_cast<DocAccessibleParent*>(this)->ChildDocAt(aIdx);
236 DocAccessibleParent* ChildDocAt(size_t aIdx) {
237 return LiveDocs().Get(mChildDocs[aIdx]);
240 #if defined(XP_WIN)
241 void MaybeInitWindowEmulation();
244 * Set emulated native window handle for a document.
245 * @param aWindowHandle emulated native window handle
247 void SetEmulatedWindowHandle(HWND aWindowHandle);
248 HWND GetEmulatedWindowHandle() const { return mEmulatedWindowHandle; }
249 #endif
251 // Accessible
252 virtual Accessible* Parent() const override {
253 if (IsTopLevel()) {
254 return OuterDocOfRemoteBrowser();
256 return RemoteParent();
259 virtual int32_t IndexInParent() const override {
260 if (IsTopLevel() && OuterDocOfRemoteBrowser()) {
261 // An OuterDoc can only have 1 child.
262 return 0;
264 return RemoteAccessible::IndexInParent();
268 * Get the focused Accessible in this document, if any.
270 RemoteAccessible* GetFocusedAcc() const {
271 return const_cast<DocAccessibleParent*>(this)->GetAccessible(mFocus);
275 * Get the HyperText Accessible containing the caret and the offset of the
276 * caret within. If there is no caret in this document, returns
277 * {nullptr, -1}.
279 std::pair<RemoteAccessible*, int32_t> GetCaret() const {
280 if (mCaretOffset == -1) {
281 return {nullptr, -1};
283 RemoteAccessible* acc =
284 const_cast<DocAccessibleParent*>(this)->GetAccessible(mCaretId);
285 if (!acc) {
286 return {nullptr, -1};
288 return {acc, mCaretOffset};
291 bool IsCaretAtEndOfLine() const { return mIsCaretAtEndOfLine; }
293 virtual void SelectionRanges(nsTArray<TextRange>* aRanges) const override;
295 virtual Accessible* FocusedChild() override;
297 void URL(nsAString& aURL) const;
298 void URL(nsACString& aURL) const;
300 void MimeType(nsAString& aURL) const;
302 virtual Relation RelationByType(RelationType aType) const override;
304 // Tracks cached reverse relations (ie. those not set explicitly by an
305 // attribute like aria-labelledby) for accessibles in this doc. This map is of
306 // the form: {accID, {relationType, [targetAccID, targetAccID, ...]}}
307 nsTHashMap<uint64_t, nsTHashMap<RelationType, nsTArray<uint64_t>>>
308 mReverseRelations;
310 // Computed from the viewport cache, the accs referenced by these ids
311 // are currently on screen (making any acc not in this list offscreen).
312 nsTHashSet<uint64_t> mOnScreenAccessibles;
314 static DocAccessibleParent* GetFrom(dom::BrowsingContext* aBrowsingContext);
316 size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) override;
318 private:
319 ~DocAccessibleParent();
321 class ProxyEntry : public PLDHashEntryHdr {
322 public:
323 explicit ProxyEntry(const void*) : mProxy(nullptr) {}
324 ProxyEntry(ProxyEntry&& aOther) : mProxy(aOther.mProxy) {
325 aOther.mProxy = nullptr;
327 ~ProxyEntry() { delete mProxy; }
329 typedef uint64_t KeyType;
330 typedef const void* KeyTypePointer;
332 bool KeyEquals(const void* aKey) const {
333 return mProxy->ID() == (uint64_t)aKey;
336 static const void* KeyToPointer(uint64_t aKey) { return (void*)aKey; }
338 static PLDHashNumber HashKey(const void* aKey) { return (uint64_t)aKey; }
340 enum { ALLOW_MEMMOVE = true };
342 RemoteAccessible* mProxy;
345 RemoteAccessible* CreateAcc(const AccessibleData& aAccData);
346 void AttachChild(RemoteAccessible* aParent, uint32_t aIndex,
347 RemoteAccessible* aChild);
348 [[nodiscard]] bool CheckDocTree() const;
349 xpcAccessibleGeneric* GetXPCAccessible(RemoteAccessible* aProxy);
351 void FireEvent(RemoteAccessible* aAcc, const uint32_t& aType);
354 * If this Accessible is being moved, prepare it for reuse. Otherwise, it is
355 * being removed, so shut it down.
357 void ShutdownOrPrepareForMove(RemoteAccessible* aAcc);
359 nsTArray<uint64_t> mChildDocs;
360 uint64_t mParentDoc;
362 #if defined(XP_WIN)
363 // The handle associated with the emulated window that contains this document
364 HWND mEmulatedWindowHandle;
365 #endif // defined(XP_WIN)
368 * Conceptually this is a map from IDs to proxies, but we store the ID in the
369 * proxy object so we can't use a real map.
371 nsTHashtable<ProxyEntry> mAccessibles;
372 uint64_t mPendingShowChild = 0;
373 uint64_t mPendingShowParent = 0;
374 uint32_t mPendingShowIndex = 0;
375 nsTHashSet<uint64_t> mMovingIDs;
376 uint64_t mActorID;
377 bool mTopLevel;
378 bool mTopLevelInContentProcess;
379 bool mShutdown;
380 RefPtr<dom::CanonicalBrowsingContext> mBrowsingContext;
382 nsTHashSet<RefPtr<dom::BrowserBridgeParent>> mPendingOOPChildDocs;
384 uint64_t mFocus;
385 uint64_t mCaretId;
386 int32_t mCaretOffset;
387 bool mIsCaretAtEndOfLine;
388 nsTArray<TextRangeData> mTextSelections;
390 static uint64_t sMaxDocID;
391 static nsTHashMap<nsUint64HashKey, DocAccessibleParent*>& LiveDocs() {
392 static nsTHashMap<nsUint64HashKey, DocAccessibleParent*> sLiveDocs;
393 return sLiveDocs;
397 } // namespace a11y
398 } // namespace mozilla
400 #endif