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