Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/a11y/DocAccessible.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
#ifndef mozilla_a11y_DocAccessible_h__
7
#define mozilla_a11y_DocAccessible_h__
8
9
#include "nsIAccessiblePivot.h"
10
11
#include "HyperTextAccessibleWrap.h"
12
#include "AccEvent.h"
13
14
#include "nsAutoPtr.h"
15
#include "nsClassHashtable.h"
16
#include "nsDataHashtable.h"
17
#include "nsIDocument.h"
18
#include "nsIDocumentObserver.h"
19
#include "nsIObserver.h"
20
#include "nsIScrollPositionListener.h"
21
#include "nsITimer.h"
22
#include "nsIWeakReference.h"
23
24
class nsAccessiblePivot;
25
26
const uint32_t kDefaultCacheLength = 128;
27
28
namespace mozilla {
29
30
class TextEditor;
31
32
namespace a11y {
33
34
class DocManager;
35
class NotificationController;
36
class DocAccessibleChild;
37
class RelatedAccIterator;
38
template<class Class, class ... Args>
39
class TNotification;
40
41
class DocAccessible : public HyperTextAccessibleWrap,
42
                      public nsIDocumentObserver,
43
                      public nsIObserver,
44
                      public nsIScrollPositionListener,
45
                      public nsSupportsWeakReference,
46
                      public nsIAccessiblePivotObserver
47
{
48
  NS_DECL_ISUPPORTS_INHERITED
49
  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DocAccessible, Accessible)
50
51
  NS_DECL_NSIOBSERVER
52
  NS_DECL_NSIACCESSIBLEPIVOTOBSERVER
53
54
public:
55
56
  DocAccessible(nsIDocument* aDocument, nsIPresShell* aPresShell);
57
58
  // nsIScrollPositionListener
59
  virtual void ScrollPositionWillChange(nscoord aX, nscoord aY) override {}
60
  virtual void ScrollPositionDidChange(nscoord aX, nscoord aY) override;
61
62
  // nsIDocumentObserver
63
  NS_DECL_NSIDOCUMENTOBSERVER
64
65
  // Accessible
66
  virtual void Init();
67
  virtual void Shutdown() override;
68
  virtual nsIFrame* GetFrame() const override;
69
  virtual nsINode* GetNode() const override { return mDocumentNode; }
70
0
  nsIDocument* DocumentNode() const { return mDocumentNode; }
71
72
  virtual mozilla::a11y::ENameValueFlag Name(nsString& aName) const override;
73
  virtual void Description(nsString& aDescription) override;
74
  virtual Accessible* FocusedChild() override;
75
  virtual mozilla::a11y::role NativeRole() const override;
76
  virtual uint64_t NativeState() const override;
77
  virtual uint64_t NativeInteractiveState() const override;
78
  virtual bool NativelyUnavailable() const override;
79
  virtual void ApplyARIAState(uint64_t* aState) const override;
80
  virtual already_AddRefed<nsIPersistentProperties> Attributes() override;
81
82
  virtual void TakeFocus() const override;
83
84
#ifdef A11Y_LOG
85
  virtual nsresult HandleAccEvent(AccEvent* aEvent) override;
86
#endif
87
88
  virtual nsRect RelativeBounds(nsIFrame** aRelativeFrame) const override;
89
90
  // HyperTextAccessible
91
  virtual already_AddRefed<TextEditor> GetEditor() const override;
92
93
  // DocAccessible
94
95
  /**
96
   * Return document URL.
97
   */
98
  void URL(nsAString& aURL) const;
99
100
  /**
101
   * Return DOM document title.
102
   */
103
0
  void Title(nsString& aTitle) const { mDocumentNode->GetTitle(aTitle); }
104
105
  /**
106
   * Return DOM document mime type.
107
   */
108
  void MimeType(nsAString& aType) const { mDocumentNode->GetContentType(aType); }
109
110
  /**
111
   * Return DOM document type.
112
   */
113
  void DocType(nsAString& aType) const;
114
115
  /**
116
   * Return virtual cursor associated with the document.
117
   */
118
  nsIAccessiblePivot* VirtualCursor();
119
120
  /**
121
   * Return presentation shell for this document accessible.
122
   */
123
  nsIPresShell* PresShell() const { return mPresShell; }
124
125
  /**
126
   * Return the presentation shell's context.
127
   */
128
0
  nsPresContext* PresContext() const { return mPresShell->GetPresContext(); }
129
130
  /**
131
   * Return true if associated DOM document was loaded and isn't unloading.
132
   */
133
  bool IsContentLoaded() const
134
0
  {
135
0
    // eDOMLoaded flag check is used for error pages as workaround to make this
136
0
    // method return correct result since error pages do not receive 'pageshow'
137
0
    // event and as consequence nsIDocument::IsShowing() returns false.
138
0
    return mDocumentNode && mDocumentNode->IsVisible() &&
139
0
      (mDocumentNode->IsShowing() || HasLoadState(eDOMLoaded));
140
0
  }
141
142
  bool IsHidden() const
143
0
  {
144
0
    return mDocumentNode->Hidden();
145
0
  }
146
147
  /**
148
   * Document load states.
149
   */
150
  enum LoadState {
151
    // initial tree construction is pending
152
    eTreeConstructionPending = 0,
153
    // initial tree construction done
154
    eTreeConstructed = 1,
155
    // DOM document is loaded.
156
    eDOMLoaded = 1 << 1,
157
    // document is ready
158
    eReady = eTreeConstructed | eDOMLoaded,
159
    // document and all its subdocuments are ready
160
    eCompletelyLoaded = eReady | 1 << 2
161
  };
162
163
  /**
164
   * Return true if the document has given document state.
165
   */
166
  bool HasLoadState(LoadState aState) const
167
0
    { return (mLoadState & static_cast<uint32_t>(aState)) ==
168
0
        static_cast<uint32_t>(aState); }
169
170
  /**
171
   * Return a native window handler or pointer depending on platform.
172
   */
173
  virtual void* GetNativeWindow() const;
174
175
  /**
176
   * Return the parent document.
177
   */
178
  DocAccessible* ParentDocument() const
179
0
    { return mParent ? mParent->Document() : nullptr; }
180
181
  /**
182
   * Return the child document count.
183
   */
184
  uint32_t ChildDocumentCount() const
185
0
    { return mChildDocuments.Length(); }
186
187
  /**
188
   * Return the child document at the given index.
189
   */
190
  DocAccessible* GetChildDocumentAt(uint32_t aIndex) const
191
0
    { return mChildDocuments.SafeElementAt(aIndex, nullptr); }
192
193
  /**
194
   * Fire accessible event asynchronously.
195
   */
196
  void FireDelayedEvent(AccEvent* aEvent);
197
  void FireDelayedEvent(uint32_t aEventType, Accessible* aTarget);
198
  void FireEventsOnInsertion(Accessible* aContainer);
199
200
  /**
201
   * Fire value change event on the given accessible if applicable.
202
   */
203
  void MaybeNotifyOfValueChange(Accessible* aAccessible);
204
205
  /**
206
   * Get/set the anchor jump.
207
   */
208
  Accessible* AnchorJump()
209
0
    { return GetAccessibleOrContainer(mAnchorJumpElm); }
210
211
  void SetAnchorJump(nsIContent* aTargetNode)
212
0
    { mAnchorJumpElm = aTargetNode; }
213
214
  /**
215
   * Bind the child document to the tree.
216
   */
217
  void BindChildDocument(DocAccessible* aDocument);
218
219
  /**
220
   * Process the generic notification.
221
   *
222
   * @note  The caller must guarantee that the given instance still exists when
223
   *          notification is processed.
224
   * @see   NotificationController::HandleNotification
225
   */
226
  template<class Class, class Arg>
227
  void HandleNotification(Class* aInstance,
228
                          typename TNotification<Class, Arg>::Callback aMethod,
229
                          Arg* aArg);
230
231
  /**
232
   * Return the cached accessible by the given DOM node if it's in subtree of
233
   * this document accessible or the document accessible itself, otherwise null.
234
   *
235
   * @return the accessible object
236
   */
237
  Accessible* GetAccessible(nsINode* aNode) const
238
  {
239
    return aNode == mDocumentNode ?
240
      const_cast<DocAccessible*>(this) : mNodeToAccessibleMap.Get(aNode);
241
  }
242
243
  /**
244
   * Return an accessible for the given node even if the node is not in
245
   * document's node map cache (like HTML area element).
246
   *
247
   * XXX: it should be really merged with GetAccessible().
248
   */
249
  Accessible* GetAccessibleEvenIfNotInMap(nsINode* aNode) const;
250
  Accessible* GetAccessibleEvenIfNotInMapOrContainer(nsINode* aNode) const;
251
252
  /**
253
   * Return whether the given DOM node has an accessible or not.
254
   */
255
  bool HasAccessible(nsINode* aNode) const
256
0
    { return GetAccessible(aNode); }
257
258
  /**
259
   * Return the cached accessible by the given unique ID within this document.
260
   *
261
   * @note   the unique ID matches with the uniqueID() of Accessible
262
   *
263
   * @param  aUniqueID  [in] the unique ID used to cache the node.
264
   */
265
  Accessible* GetAccessibleByUniqueID(void* aUniqueID)
266
0
  {
267
0
    return UniqueID() == aUniqueID ?
268
0
      this : mAccessibleCache.GetWeak(aUniqueID);
269
0
  }
270
271
  /**
272
   * Return the cached accessible by the given unique ID looking through
273
   * this and nested documents.
274
   */
275
  Accessible* GetAccessibleByUniqueIDInSubtree(void* aUniqueID);
276
277
  /**
278
   * Return an accessible for the given DOM node or container accessible if
279
   * the node is not accessible.
280
   */
281
  enum {
282
    eIgnoreARIAHidden = 0,
283
    eNoContainerIfARIAHidden = 1
284
  };
285
  Accessible* GetAccessibleOrContainer(nsINode* aNode,
286
                                       int aARIAHiddenFlag = eIgnoreARIAHidden) const;
287
288
  /**
289
   * Return a container accessible for the given DOM node.
290
   */
291
  Accessible* GetContainerAccessible(nsINode* aNode) const
292
0
  {
293
0
    return aNode ? GetAccessibleOrContainer(aNode->GetParentNode()) : nullptr;
294
0
  }
295
296
  /**
297
   * Return an accessible for the given node if any, or an immediate accessible
298
   * container for it.
299
   */
300
  Accessible* AccessibleOrTrueContainer(nsINode* aNode,
301
                                        int aARIAHiddenFlag = eIgnoreARIAHidden) const;
302
303
  /**
304
   * Return an accessible for the given node or its first accessible descendant.
305
   */
306
  Accessible* GetAccessibleOrDescendant(nsINode* aNode) const;
307
308
  /**
309
   * Returns aria-owns seized child at the given index.
310
   */
311
  Accessible* ARIAOwnedAt(Accessible* aParent, uint32_t aIndex) const
312
0
  {
313
0
    nsTArray<RefPtr<Accessible> >* children = mARIAOwnsHash.Get(aParent);
314
0
    if (children) {
315
0
      return children->SafeElementAt(aIndex);
316
0
    }
317
0
    return nullptr;
318
0
  }
319
  uint32_t ARIAOwnedCount(Accessible* aParent) const
320
0
  {
321
0
    nsTArray<RefPtr<Accessible> >* children = mARIAOwnsHash.Get(aParent);
322
0
    return children ? children->Length() : 0;
323
0
  }
324
325
  /**
326
   * Return true if the given ID is referred by relation attribute.
327
   *
328
   * @note Different elements may share the same ID if they are hosted inside
329
   *       XBL bindings. Be careful the result of this method may be  senseless
330
   *       while it's called for XUL elements (where XBL is used widely).
331
   */
332
  bool IsDependentID(const nsAString& aID) const
333
0
    { return mDependentIDsHash.Get(aID, nullptr); }
334
335
  /**
336
   * Initialize the newly created accessible and put it into document caches.
337
   *
338
   * @param  aAccessible    [in] created accessible
339
   * @param  aRoleMapEntry  [in] the role map entry role the ARIA role or nullptr
340
   *                          if none
341
   */
342
  void BindToDocument(Accessible* aAccessible,
343
                      const nsRoleMapEntry* aRoleMapEntry);
344
345
  /**
346
   * Remove from document and shutdown the given accessible.
347
   */
348
  void UnbindFromDocument(Accessible* aAccessible);
349
350
  /**
351
   * Notify the document accessible that content was inserted.
352
   */
353
  void ContentInserted(nsIContent* aContainerNode,
354
                       nsIContent* aStartChildNode,
355
                       nsIContent* aEndChildNode);
356
357
  /**
358
   * Update the tree on content removal.
359
   */
360
  void ContentRemoved(Accessible* aAccessible);
361
  void ContentRemoved(nsIContent* aContentNode);
362
363
  /**
364
   * Updates accessible tree when rendered text is changed.
365
   */
366
  void UpdateText(nsIContent* aTextNode);
367
368
  /**
369
   * Recreate an accessible, results in hide/show events pair.
370
   */
371
  void RecreateAccessible(nsIContent* aContent);
372
373
  /**
374
   * Schedule ARIA owned element relocation if needed. Return true if relocation
375
   * was scheduled.
376
   */
377
  bool RelocateARIAOwnedIfNeeded(nsIContent* aEl);
378
379
  /**
380
   * Return a notification controller associated with the document.
381
   */
382
0
  NotificationController* Controller() const { return mNotificationController; }
383
384
  /**
385
   * If this document is in a content process return the object responsible for
386
   * communicating with the main process for it.
387
   */
388
0
  DocAccessibleChild* IPCDoc() const { return mIPCDoc; }
389
390
protected:
391
  virtual ~DocAccessible();
392
393
  void LastRelease();
394
395
  // DocAccessible
396
  virtual nsresult AddEventListeners();
397
  virtual nsresult RemoveEventListeners();
398
399
  /**
400
   * Marks this document as loaded or loading.
401
   */
402
  void NotifyOfLoad(uint32_t aLoadEventType);
403
  void NotifyOfLoading(bool aIsReloading);
404
405
  friend class DocManager;
406
407
  /**
408
   * Perform initial update (create accessible tree).
409
   * Can be overridden by wrappers to prepare initialization work.
410
   */
411
  virtual void DoInitialUpdate();
412
413
  /**
414
   * Updates root element and picks up ARIA role on it if any.
415
   */
416
  void UpdateRootElIfNeeded();
417
418
  /**
419
   * Process document load notification, fire document load and state busy
420
   * events if applicable.
421
   */
422
  void ProcessLoad();
423
424
  /**
425
   * Add/remove scroll listeners, @see nsIScrollPositionListener interface.
426
   */
427
  void AddScrollListener();
428
  void RemoveScrollListener();
429
430
  /**
431
   * Append the given document accessible to this document's child document
432
   * accessibles.
433
   */
434
  bool AppendChildDocument(DocAccessible* aChildDocument)
435
0
  {
436
0
    return mChildDocuments.AppendElement(aChildDocument);
437
0
  }
438
439
  /**
440
   * Remove the given document accessible from this document's child document
441
   * accessibles.
442
   */
443
  void RemoveChildDocument(DocAccessible* aChildDocument)
444
0
  {
445
0
    mChildDocuments.RemoveElement(aChildDocument);
446
0
  }
447
448
  /**
449
   * Add dependent IDs pointed by accessible element by relation attribute to
450
   * cache. If the relation attribute is missed then all relation attributes
451
   * are checked.
452
   *
453
   * @param aRelProvider [in] accessible that element has relation attribute
454
   * @param aRelAttr     [in, optional] relation attribute
455
   */
456
  void AddDependentIDsFor(Accessible* aRelProvider,
457
                          nsAtom* aRelAttr = nullptr);
458
459
  /**
460
   * Remove dependent IDs pointed by accessible element by relation attribute
461
   * from cache. If the relation attribute is absent then all relation
462
   * attributes are checked.
463
   *
464
   * @param aRelProvider [in] accessible that element has relation attribute
465
   * @param aRelAttr     [in, optional] relation attribute
466
   */
467
  void RemoveDependentIDsFor(Accessible* aRelProvider,
468
                             nsAtom* aRelAttr = nullptr);
469
470
  /**
471
   * Update or recreate an accessible depending on a changed attribute.
472
   *
473
   * @param aElement   [in] the element the attribute was changed on
474
   * @param aAttribute [in] the changed attribute
475
   * @return            true if an action was taken on the attribute change
476
   */
477
  bool UpdateAccessibleOnAttrChange(mozilla::dom::Element* aElement,
478
                                    nsAtom* aAttribute);
479
480
  /**
481
   * Fire accessible events when attribute is changed.
482
   *
483
   * @param aAccessible   [in] accessible the DOM attribute is changed for
484
   * @param aNameSpaceID  [in] namespace of changed attribute
485
   * @param aAttribute    [in] changed attribute
486
   */
487
  void AttributeChangedImpl(Accessible* aAccessible,
488
                            int32_t aNameSpaceID, nsAtom* aAttribute);
489
490
  /**
491
   * Fire accessible events when ARIA attribute is changed.
492
   *
493
   * @param aAccessible  [in] accesislbe the DOM attribute is changed for
494
   * @param aAttribute   [in] changed attribute
495
   */
496
  void ARIAAttributeChanged(Accessible* aAccessible, nsAtom* aAttribute);
497
498
  /**
499
   * Process ARIA active-descendant attribute change.
500
   */
501
  void ARIAActiveDescendantChanged(Accessible* aAccessible);
502
503
  /**
504
   * Update the accessible tree for inserted content.
505
   */
506
  void ProcessContentInserted(Accessible* aContainer,
507
                              const nsTArray<nsCOMPtr<nsIContent> >* aInsertedContent);
508
  void ProcessContentInserted(Accessible* aContainer,
509
                              nsIContent* aInsertedContent);
510
511
  /**
512
   * Used to notify the document to make it process the invalidation list.
513
   *
514
   * While children are cached we may encounter the case there's no accessible
515
   * for referred content by related accessible. Store these related nodes to
516
   * invalidate their containers later.
517
   */
518
  void ProcessInvalidationList();
519
520
  /**
521
   * Steals or puts back accessible subtrees.
522
   */
523
  void DoARIAOwnsRelocation(Accessible* aOwner);
524
525
  /**
526
   * Moves children back under their original parents.
527
   */
528
  void PutChildrenBack(nsTArray<RefPtr<Accessible> >* aChildren,
529
                       uint32_t aStartIdx);
530
531
  bool MoveChild(Accessible* aChild, Accessible* aNewParent,
532
                 int32_t aIdxInParent);
533
534
  /**
535
   * Create accessible tree.
536
   *
537
   * @param aRoot       [in] a root of subtree to create
538
   * @param aFocusedAcc [in, optional] a focused accessible under created
539
   *                      subtree if any
540
   */
541
  void CacheChildrenInSubtree(Accessible* aRoot,
542
                              Accessible** aFocusedAcc = nullptr);
543
  void CreateSubtree(Accessible* aRoot);
544
545
  /**
546
   * Remove accessibles in subtree from node to accessible map.
547
   */
548
  void UncacheChildrenInSubtree(Accessible* aRoot);
549
550
  /**
551
   * Shutdown any cached accessible in the subtree.
552
   *
553
   * @param aAccessible  [in] the root of the subrtee to invalidate accessible
554
   *                      child/parent refs in
555
   */
556
  void ShutdownChildrenInSubtree(Accessible* aAccessible);
557
558
  /**
559
   * Return true if the document is a target of document loading events
560
   * (for example, state busy change or document reload events).
561
   *
562
   * Rules: The root chrome document accessible is never an event target
563
   * (for example, Firefox UI window). If the sub document is loaded within its
564
   * parent document then the parent document is a target only (aka events
565
   * coalescence).
566
   */
567
  bool IsLoadEventTarget() const;
568
569
  /*
570
   * Set the object responsible for communicating with the main process on
571
   * behalf of this document.
572
   */
573
0
  void SetIPCDoc(DocAccessibleChild* aIPCDoc) { mIPCDoc = aIPCDoc; }
574
575
  friend class DocAccessibleChildBase;
576
577
  /**
578
   * Used to fire scrolling end event after page scroll.
579
   *
580
   * @param aTimer    [in] the timer object
581
   * @param aClosure  [in] the document accessible where scrolling happens
582
   */
583
  static void ScrollTimerCallback(nsITimer* aTimer, void* aClosure);
584
585
  void DispatchScrollingEvent(uint32_t aEventType);
586
587
  /**
588
   * Check if an id attribute change affects aria-activedescendant and handle
589
   * the aria-activedescendant change if appropriate.
590
   * If the currently focused element has aria-activedescendant and an
591
   * element's id changes to match this, the id was probably moved from the
592
   * previous active descendant, thus making this element the new active
593
   * descendant. In that case, accessible focus must be changed accordingly.
594
   */
595
  void ARIAActiveDescendantIDMaybeMoved(dom::Element* aElm);
596
597
protected:
598
599
  /**
600
   * State and property flags, kept by mDocFlags.
601
   */
602
  enum {
603
    // Whether scroll listeners were added.
604
    eScrollInitialized = 1 << 0,
605
606
    // Whether the document is a tab document.
607
    eTabDocument = 1 << 1
608
  };
609
610
  /**
611
   * Cache of accessibles within this document accessible.
612
   */
613
  AccessibleHashtable mAccessibleCache;
614
  nsDataHashtable<nsPtrHashKey<const nsINode>, Accessible*>
615
    mNodeToAccessibleMap;
616
617
  nsIDocument* mDocumentNode;
618
  nsCOMPtr<nsITimer> mScrollWatchTimer;
619
  uint16_t mScrollPositionChangedTicks; // Used for tracking scroll events
620
  TimeStamp mLastScrollingDispatch;
621
622
  /**
623
   * Bit mask of document load states (@see LoadState).
624
   */
625
  uint32_t mLoadState : 3;
626
627
  /**
628
   * Bit mask of other states and props.
629
   */
630
  uint32_t mDocFlags : 28;
631
632
  /**
633
   * Type of document load event fired after the document is loaded completely.
634
   */
635
  uint32_t mLoadEventType;
636
637
  /**
638
   * Reference to anchor jump element.
639
   */
640
  nsCOMPtr<nsIContent> mAnchorJumpElm;
641
642
  /**
643
   * A generic state (see items below) before the attribute value was changed.
644
   * @see AttributeWillChange and AttributeChanged notifications.
645
   */
646
  union {
647
    // ARIA attribute value
648
    nsAtom* mARIAAttrOldValue;
649
650
    // True if the accessible state bit was on
651
    bool mStateBitWasOn;
652
  };
653
654
  nsTArray<RefPtr<DocAccessible> > mChildDocuments;
655
656
  /**
657
   * The virtual cursor of the document.
658
   */
659
  RefPtr<nsAccessiblePivot> mVirtualCursor;
660
661
  /**
662
   * A storage class for pairing content with one of its relation attributes.
663
   */
664
  class AttrRelProvider
665
  {
666
  public:
667
    AttrRelProvider(nsAtom* aRelAttr, nsIContent* aContent) :
668
0
      mRelAttr(aRelAttr), mContent(aContent) { }
669
670
    nsAtom* mRelAttr;
671
    nsCOMPtr<nsIContent> mContent;
672
673
  private:
674
    AttrRelProvider();
675
    AttrRelProvider(const AttrRelProvider&);
676
    AttrRelProvider& operator =(const AttrRelProvider&);
677
  };
678
679
  /**
680
   * The cache of IDs pointed by relation attributes.
681
   */
682
  typedef nsTArray<nsAutoPtr<AttrRelProvider> > AttrRelProviderArray;
683
  nsClassHashtable<nsStringHashKey, AttrRelProviderArray>
684
    mDependentIDsHash;
685
686
  friend class RelatedAccIterator;
687
688
  /**
689
   * Used for our caching algorithm. We store the list of nodes that should be
690
   * invalidated.
691
   *
692
   * @see ProcessInvalidationList
693
   */
694
  nsTArray<RefPtr<nsIContent>> mInvalidationList;
695
696
  /**
697
   * Holds a list of aria-owns relocations.
698
   */
699
  nsClassHashtable<nsPtrHashKey<Accessible>, nsTArray<RefPtr<Accessible> > >
700
    mARIAOwnsHash;
701
702
  /**
703
   * Used to process notification from core and accessible events.
704
   */
705
  RefPtr<NotificationController> mNotificationController;
706
  friend class EventTree;
707
  friend class NotificationController;
708
709
private:
710
711
  nsIPresShell* mPresShell;
712
713
  // Exclusively owned by IPDL so don't manually delete it!
714
  DocAccessibleChild* mIPCDoc;
715
};
716
717
inline DocAccessible*
718
Accessible::AsDoc()
719
{
720
  return IsDoc() ? static_cast<DocAccessible*>(this) : nullptr;
721
}
722
723
} // namespace a11y
724
} // namespace mozilla
725
726
#endif