Coverage Report

Created: 2018-09-25 14:53

/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