Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/accessible/generic/Accessible.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 _Accessible_H_
7
#define _Accessible_H_
8
9
#include "mozilla/a11y/AccTypes.h"
10
#include "mozilla/a11y/RelationType.h"
11
#include "mozilla/a11y/Role.h"
12
#include "mozilla/a11y/States.h"
13
14
#include "mozilla/UniquePtr.h"
15
16
#include "nsIContent.h"
17
#include "nsIContentInlines.h"
18
#include "nsString.h"
19
#include "nsTArray.h"
20
#include "nsRefPtrHashtable.h"
21
#include "nsRect.h"
22
23
struct nsRoleMapEntry;
24
25
struct nsRect;
26
class nsIFrame;
27
class nsAtom;
28
class nsIPersistentProperties;
29
30
namespace mozilla {
31
namespace a11y {
32
33
class Accessible;
34
class AccEvent;
35
class AccGroupInfo;
36
class ApplicationAccessible;
37
class DocAccessible;
38
class EmbeddedObjCollector;
39
class EventTree;
40
class HTMLImageMapAccessible;
41
class HTMLLIAccessible;
42
class HyperTextAccessible;
43
class ImageAccessible;
44
class KeyBinding;
45
class OuterDocAccessible;
46
class ProxyAccessible;
47
class Relation;
48
class RootAccessible;
49
class TableAccessible;
50
class TableCellAccessible;
51
class TextLeafAccessible;
52
class XULLabelAccessible;
53
class XULTreeAccessible;
54
55
#ifdef A11Y_LOG
56
namespace logging {
57
  typedef const char* (*GetTreePrefix)(void* aData, Accessible*);
58
  void Tree(const char* aTitle, const char* aMsgText, Accessible* aRoot,
59
            GetTreePrefix aPrefixFunc, void* GetTreePrefixData);
60
};
61
#endif
62
63
/**
64
 * Name type flags.
65
 */
66
enum ENameValueFlag {
67
  /**
68
   * Name either
69
   *  a) present (not empty): !name.IsEmpty()
70
   *  b) no name (was missed): name.IsVoid()
71
   */
72
 eNameOK,
73
74
 /**
75
  * Name was left empty by the author on purpose:
76
  * name.IsEmpty() && !name.IsVoid().
77
  */
78
 eNoNameOnPurpose,
79
80
 /**
81
  * Name was computed from the subtree.
82
  */
83
 eNameFromSubtree,
84
85
 /**
86
  * Tooltip was used as a name.
87
  */
88
 eNameFromTooltip
89
};
90
91
/**
92
 * Group position (level, position in set and set size).
93
 */
94
struct GroupPos
95
{
96
  GroupPos() : level(0), posInSet(0), setSize(0) { }
97
  GroupPos(int32_t aLevel, int32_t aPosInSet, int32_t aSetSize) :
98
    level(aLevel), posInSet(aPosInSet), setSize(aSetSize) { }
99
100
  int32_t level;
101
  int32_t posInSet;
102
  int32_t setSize;
103
};
104
105
/**
106
 * An index type. Assert if out of range value was attempted to be used.
107
 */
108
class index_t
109
{
110
public:
111
  MOZ_IMPLICIT index_t(int32_t aVal) : mVal(aVal) {}
112
113
  operator uint32_t() const
114
  {
115
    MOZ_ASSERT(mVal >= 0, "Attempt to use wrong index!");
116
    return mVal;
117
  }
118
119
  bool IsValid() const { return mVal >= 0; }
120
121
private:
122
  int32_t mVal;
123
};
124
125
typedef nsRefPtrHashtable<nsPtrHashKey<const void>, Accessible>
126
  AccessibleHashtable;
127
128
129
#define NS_ACCESSIBLE_IMPL_IID                          \
130
{  /* 133c8bf4-4913-4355-bd50-426bd1d6e1ad */           \
131
  0x133c8bf4,                                           \
132
  0x4913,                                               \
133
  0x4355,                                               \
134
  { 0xbd, 0x50, 0x42, 0x6b, 0xd1, 0xd6, 0xe1, 0xad }    \
135
}
136
137
class Accessible : public nsISupports
138
{
139
public:
140
  Accessible(nsIContent* aContent, DocAccessible* aDoc);
141
142
  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
143
  NS_DECL_CYCLE_COLLECTION_CLASS(Accessible)
144
145
  NS_DECLARE_STATIC_IID_ACCESSOR(NS_ACCESSIBLE_IMPL_IID)
146
147
  //////////////////////////////////////////////////////////////////////////////
148
  // Public methods
149
150
  /**
151
   * Return the document accessible for this accessible.
152
   */
153
0
  DocAccessible* Document() const { return mDoc; }
154
155
  /**
156
   * Return the root document accessible for this accessible.
157
   */
158
  a11y::RootAccessible* RootAccessible() const;
159
160
  /**
161
   * Return frame for this accessible.
162
   */
163
  virtual nsIFrame* GetFrame() const;
164
165
  /**
166
   * Return DOM node associated with the accessible.
167
   */
168
  virtual nsINode* GetNode() const;
169
170
0
  nsIContent* GetContent() const { return mContent; }
171
  dom::Element* Elm() const
172
    { return dom::Element::FromNodeOrNull(mContent); }
173
174
  /**
175
   * Return node type information of DOM node associated with the accessible.
176
   */
177
  bool IsContent() const
178
    { return GetNode() && GetNode()->IsContent(); }
179
180
  /**
181
   * Return the unique identifier of the accessible.
182
   */
183
0
  void* UniqueID() {
184
0
    // When recording or replaying, use an ID which will be consistent when
185
0
    // recording/replaying (pointer values are not consistent), so that IPC
186
0
    // messages from the parent process can be handled when replaying.
187
0
    if (recordreplay::IsRecordingOrReplaying()) {
188
0
      return reinterpret_cast<void*>(recordreplay::ThingIndex(this));
189
0
    }
190
0
    return static_cast<void*>(this);
191
0
  }
192
193
  /**
194
   * Return language associated with the accessible.
195
   */
196
  void Language(nsAString& aLocale);
197
198
  /**
199
   * Get the description of this accessible.
200
   */
201
  virtual void Description(nsString& aDescription);
202
203
  /**
204
   * Get the value of this accessible.
205
   */
206
  virtual void Value(nsString& aValue) const;
207
208
  /**
209
   * Get help string for the accessible.
210
   */
211
0
  void Help(nsString& aHelp) const { aHelp.Truncate(); }
212
213
  /**
214
   * Get the name of this accessible.
215
   *
216
   * Note: aName.IsVoid() when name was left empty by the author on purpose.
217
   * aName.IsEmpty() when the author missed name, AT can try to repair a name.
218
   */
219
  virtual ENameValueFlag Name(nsString& aName) const;
220
221
  /**
222
   * Maps ARIA state attributes to state of accessible. Note the given state
223
   * argument should hold states for accessible before you pass it into this
224
   * method.
225
   *
226
   * @param  [in/out] where to fill the states into.
227
   */
228
  virtual void ApplyARIAState(uint64_t* aState) const;
229
230
  /**
231
   * Return enumerated accessible role (see constants in Role.h).
232
   */
233
  mozilla::a11y::role Role() const;
234
235
  /**
236
   * Return true if ARIA role is specified on the element.
237
   */
238
  bool HasARIARole() const;
239
  bool IsARIARole(nsAtom* aARIARole) const;
240
  bool HasStrongARIARole() const;
241
242
  /**
243
   * Retrun ARIA role map if any.
244
   */
245
  const nsRoleMapEntry* ARIARoleMap() const;
246
247
  /**
248
   * Return accessible role specified by ARIA (see constants in
249
   * roles).
250
   */
251
  mozilla::a11y::role ARIARole();
252
253
  /**
254
   * Return a landmark role if applied.
255
   */
256
  virtual nsAtom* LandmarkRole() const;
257
258
  /**
259
   * Returns enumerated accessible role from native markup (see constants in
260
   * Role.h). Doesn't take into account ARIA roles.
261
   */
262
  virtual mozilla::a11y::role NativeRole() const;
263
264
  /**
265
   * Return all states of accessible (including ARIA states).
266
   */
267
  virtual uint64_t State();
268
269
  /**
270
   * Return interactive states present on the accessible
271
   * (@see NativeInteractiveState).
272
   */
273
  uint64_t InteractiveState() const
274
  {
275
    uint64_t state = NativeInteractiveState();
276
    ApplyARIAState(&state);
277
    return state;
278
  }
279
280
  /**
281
   * Return link states present on the accessible.
282
   */
283
  uint64_t LinkState() const
284
  {
285
    uint64_t state = NativeLinkState();
286
    ApplyARIAState(&state);
287
    return state;
288
  }
289
290
  /**
291
   * Return if accessible is unavailable.
292
   */
293
  bool Unavailable() const
294
  {
295
    uint64_t state = NativelyUnavailable() ? states::UNAVAILABLE : 0;
296
    ApplyARIAState(&state);
297
    return state & states::UNAVAILABLE;
298
  }
299
300
  /**
301
   * Return the states of accessible, not taking into account ARIA states.
302
   * Use State() to get complete set of states.
303
   */
304
  virtual uint64_t NativeState() const;
305
306
  /**
307
   * Return native interactice state (unavailable, focusable or selectable).
308
   */
309
  virtual uint64_t NativeInteractiveState() const;
310
311
  /**
312
   * Return native link states present on the accessible.
313
   */
314
  virtual uint64_t NativeLinkState() const;
315
316
  /**
317
   * Return bit set of invisible and offscreen states.
318
   */
319
  uint64_t VisibilityState() const;
320
321
  /**
322
   * Return true if native unavailable state present.
323
   */
324
  virtual bool NativelyUnavailable() const;
325
326
  /**
327
   * Return object attributes for the accessible.
328
   */
329
  virtual already_AddRefed<nsIPersistentProperties> Attributes();
330
331
  /**
332
   * Return group position (level, position in set and set size).
333
   */
334
  virtual mozilla::a11y::GroupPos GroupPosition();
335
336
  /**
337
   * Used by ChildAtPoint() method to get direct or deepest child at point.
338
   */
339
  enum EWhichChildAtPoint {
340
    eDirectChild,
341
    eDeepestChild
342
  };
343
344
  /**
345
   * Return direct or deepest child at the given point.
346
   *
347
   * @param  aX           [in] x coordinate relative screen
348
   * @param  aY           [in] y coordinate relative screen
349
   * @param  aWhichChild  [in] flag points if deepest or direct child
350
   *                        should be returned
351
   */
352
  virtual Accessible* ChildAtPoint(int32_t aX, int32_t aY,
353
                                   EWhichChildAtPoint aWhichChild);
354
355
  /**
356
   * Return the focused child if any.
357
   */
358
  virtual Accessible* FocusedChild();
359
360
  /**
361
   * Return calculated group level based on accessible hierarchy.
362
   */
363
  virtual int32_t GetLevelInternal();
364
365
  /**
366
   * Calculate position in group and group size ('posinset' and 'setsize') based
367
   * on accessible hierarchy.
368
   *
369
   * @param  aPosInSet  [out] accessible position in the group
370
   * @param  aSetSize   [out] the group size
371
   */
372
  virtual void GetPositionAndSizeInternal(int32_t *aPosInSet,
373
                                          int32_t *aSetSize);
374
375
  /**
376
   * Get the relation of the given type.
377
   */
378
  virtual Relation RelationByType(RelationType aType) const;
379
380
  //////////////////////////////////////////////////////////////////////////////
381
  // Initializing methods
382
383
  /**
384
   * Shutdown this accessible object.
385
   */
386
  virtual void Shutdown();
387
388
  /**
389
   * Set the ARIA role map entry for a new accessible.
390
   */
391
  void SetRoleMapEntry(const nsRoleMapEntry* aRoleMapEntry);
392
393
  /**
394
   * Append/insert/remove a child. Return true if operation was successful.
395
   */
396
  bool AppendChild(Accessible* aChild)
397
0
    { return InsertChildAt(mChildren.Length(), aChild); }
398
  virtual bool InsertChildAt(uint32_t aIndex, Accessible* aChild);
399
400
  /**
401
   * Inserts a child after given sibling. If the child cannot be inserted,
402
   * then the child is unbound from the document, and false is returned. Make
403
   * sure to null out any references on the child object as it may be destroyed.
404
   */
405
  bool InsertAfter(Accessible* aNewChild, Accessible* aRefChild);
406
407
  virtual bool RemoveChild(Accessible* aChild);
408
409
  /**
410
   * Reallocates the child withing its parent.
411
   */
412
  void MoveChild(uint32_t aNewIndex, Accessible* aChild);
413
414
  //////////////////////////////////////////////////////////////////////////////
415
  // Accessible tree traverse methods
416
417
  /**
418
   * Return parent accessible.
419
   */
420
  Accessible* Parent() const { return mParent; }
421
422
  /**
423
   * Return child accessible at the given index.
424
   */
425
  virtual Accessible* GetChildAt(uint32_t aIndex) const;
426
427
  /**
428
   * Return child accessible count.
429
   */
430
  virtual uint32_t ChildCount() const;
431
432
  /**
433
   * Return index of the given child accessible.
434
   */
435
  int32_t GetIndexOf(const Accessible* aChild) const
436
0
    { return (aChild->mParent != this) ? -1 : aChild->IndexInParent(); }
437
438
  /**
439
   * Return index in parent accessible.
440
   */
441
  virtual int32_t IndexInParent() const;
442
443
  /**
444
   * Return true if accessible has children;
445
   */
446
  bool HasChildren() const { return !!GetChildAt(0); }
447
448
  /**
449
   * Return first/last/next/previous sibling of the accessible.
450
   */
451
  inline Accessible* NextSibling() const
452
0
    {  return GetSiblingAtOffset(1); }
453
  inline Accessible* PrevSibling() const
454
0
    { return GetSiblingAtOffset(-1); }
455
  inline Accessible* FirstChild() const
456
0
    { return GetChildAt(0); }
457
  inline Accessible* LastChild() const
458
0
  {
459
0
    uint32_t childCount = ChildCount();
460
0
    return childCount != 0 ? GetChildAt(childCount - 1) : nullptr;
461
0
  }
462
463
  /**
464
   * Return embedded accessible children count.
465
   */
466
  uint32_t EmbeddedChildCount();
467
468
  /**
469
   * Return embedded accessible child at the given index.
470
   */
471
  Accessible* GetEmbeddedChildAt(uint32_t aIndex);
472
473
  /**
474
   * Return index of the given embedded accessible child.
475
   */
476
  int32_t GetIndexOfEmbeddedChild(Accessible* aChild);
477
478
  /**
479
   * Return number of content children/content child at index. The content
480
   * child is created from markup in contrast to it's never constructed by its
481
   * parent accessible (like treeitem accessibles for XUL trees).
482
   */
483
  uint32_t ContentChildCount() const { return mChildren.Length(); }
484
  Accessible* ContentChildAt(uint32_t aIndex) const
485
    { return mChildren.ElementAt(aIndex); }
486
487
  /**
488
   * Return true if the accessible is attached to tree.
489
   */
490
0
  bool IsBoundToParent() const { return !!mParent; }
491
492
  //////////////////////////////////////////////////////////////////////////////
493
  // Miscellaneous methods
494
495
  /**
496
   * Handle accessible event, i.e. process it, notifies observers and fires
497
   * platform specific event.
498
   */
499
  virtual nsresult HandleAccEvent(AccEvent* aAccEvent);
500
501
  /**
502
   * Return true if the accessible is an acceptable child.
503
   */
504
  virtual bool IsAcceptableChild(nsIContent* aEl) const
505
    { return aEl && !aEl->IsAnyOfHTMLElements(nsGkAtoms::option, nsGkAtoms::optgroup); }
506
507
  /**
508
   * Returns text of accessible if accessible has text role otherwise empty
509
   * string.
510
   *
511
   * @param aText         [in] returned text of the accessible
512
   * @param aStartOffset  [in, optional] start offset inside of the accessible,
513
   *                        if missed entire text is appended
514
   * @param aLength       [in, optional] required length of text, if missed
515
   *                        then text form start offset till the end is appended
516
   */
517
  virtual void AppendTextTo(nsAString& aText, uint32_t aStartOffset = 0,
518
                            uint32_t aLength = UINT32_MAX);
519
520
  /**
521
   * Return boundaries in screen coordinates in app units.
522
   */
523
  virtual nsRect BoundsInAppUnits() const;
524
525
  /**
526
   * Return boundaries in screen coordinates.
527
   */
528
  virtual nsIntRect Bounds() const;
529
530
  /**
531
   * Return boundaries in screen coordinates in CSS pixels.
532
   */
533
  virtual nsIntRect BoundsInCSSPixels() const;
534
535
  /**
536
   * Return boundaries rect relative the bounding frame.
537
   */
538
  virtual nsRect RelativeBounds(nsIFrame** aRelativeFrame) const;
539
540
  /**
541
   * Selects the accessible within its container if applicable.
542
   */
543
  virtual void SetSelected(bool aSelect);
544
545
  /**
546
   * Select the accessible within its container.
547
   */
548
  void TakeSelection();
549
550
  /**
551
   * Focus the accessible.
552
   */
553
  virtual void TakeFocus() const;
554
555
  /**
556
   * Scroll the accessible into view.
557
   */
558
  void ScrollTo(uint32_t aHow) const;
559
560
  /**
561
   * Scroll the accessible to the given point.
562
   */
563
  void ScrollToPoint(uint32_t aCoordinateType, int32_t aX, int32_t aY);
564
565
  /**
566
   * Get a pointer to accessibility interface for this node, which is specific
567
   * to the OS/accessibility toolkit we're running on.
568
   */
569
  virtual void GetNativeInterface(void** aNativeAccessible);
570
571
  //////////////////////////////////////////////////////////////////////////////
572
  // Downcasting and types
573
574
  inline bool IsAbbreviation() const
575
  {
576
    return mContent->IsAnyOfHTMLElements(nsGkAtoms::abbr, nsGkAtoms::acronym);
577
  }
578
579
  bool IsAlert() const { return HasGenericType(eAlert); }
580
581
0
  bool IsApplication() const { return mType == eApplicationType; }
582
  ApplicationAccessible* AsApplication();
583
584
  bool IsAutoComplete() const { return HasGenericType(eAutoComplete); }
585
586
  bool IsAutoCompletePopup() const
587
    { return HasGenericType(eAutoCompletePopup); }
588
589
  bool IsButton() const { return HasGenericType(eButton); }
590
591
0
  bool IsCombobox() const { return HasGenericType(eCombobox); }
592
593
  bool IsDoc() const { return HasGenericType(eDocument); }
594
  DocAccessible* AsDoc();
595
596
  bool IsGenericHyperText() const { return mType == eHyperTextType; }
597
  bool IsHyperText() const { return HasGenericType(eHyperText); }
598
  HyperTextAccessible* AsHyperText();
599
600
  bool IsHTMLBr() const { return mType == eHTMLBRType; }
601
  bool IsHTMLCaption() const { return mType == eHTMLCaptionType; }
602
0
  bool IsHTMLCombobox() const { return mType == eHTMLComboboxType; }
603
  bool IsHTMLFileInput() const { return mType == eHTMLFileInputType; }
604
605
  bool IsHTMLListItem() const { return mType == eHTMLLiType; }
606
  HTMLLIAccessible* AsHTMLListItem();
607
608
  bool IsHTMLOptGroup() const { return mType == eHTMLOptGroupType; }
609
610
  bool IsHTMLTable() const { return mType == eHTMLTableType; }
611
  bool IsHTMLTableRow() const { return mType == eHTMLTableRowType; }
612
613
  bool IsImage() const { return mType == eImageType; }
614
  ImageAccessible* AsImage();
615
616
  bool IsImageMap() const { return mType == eImageMapType; }
617
  HTMLImageMapAccessible* AsImageMap();
618
619
  bool IsList() const { return HasGenericType(eList); }
620
621
  bool IsListControl() const { return HasGenericType(eListControl); }
622
623
  bool IsMenuButton() const { return HasGenericType(eMenuButton); }
624
625
  bool IsMenuPopup() const { return mType == eMenuPopupType; }
626
627
  bool IsProxy() const { return mType == eProxyType; }
628
  ProxyAccessible* Proxy() const
629
  {
630
    MOZ_ASSERT(IsProxy());
631
    return mBits.proxy;
632
  }
633
  uint32_t ProxyInterfaces() const
634
  {
635
    MOZ_ASSERT(IsProxy());
636
    return mInt.mProxyInterfaces;
637
  }
638
  void SetProxyInterfaces(uint32_t aInterfaces)
639
  {
640
    MOZ_ASSERT(IsProxy());
641
    mInt.mProxyInterfaces = aInterfaces;
642
  }
643
644
  bool IsOuterDoc() const { return mType == eOuterDocType; }
645
  OuterDocAccessible* AsOuterDoc();
646
647
  bool IsProgress() const { return mType == eProgressType; }
648
649
  bool IsRoot() const { return mType == eRootType; }
650
  a11y::RootAccessible* AsRoot();
651
652
  bool IsSearchbox() const;
653
654
  bool IsSelect() const { return HasGenericType(eSelect); }
655
656
  bool IsTable() const { return HasGenericType(eTable); }
657
  virtual TableAccessible* AsTable() { return nullptr; }
658
659
0
  bool IsTableCell() const { return HasGenericType(eTableCell); }
660
  virtual TableCellAccessible* AsTableCell() { return nullptr; }
661
  const TableCellAccessible* AsTableCell() const
662
    { return const_cast<Accessible*>(this)->AsTableCell(); }
663
664
0
  bool IsTableRow() const { return HasGenericType(eTableRow); }
665
666
  bool IsTextField() const { return mType == eHTMLTextFieldType ||
667
                                    mType == eHTMLTextPasswordFieldType; }
668
669
  bool IsPassword() const { return mType == eHTMLTextPasswordFieldType; }
670
671
  bool IsText() const { return mGenericTypes & eText; }
672
673
0
  bool IsTextLeaf() const { return mType == eTextLeafType; }
674
  TextLeafAccessible* AsTextLeaf();
675
676
  bool IsXULLabel() const { return mType == eXULLabelType; }
677
  XULLabelAccessible* AsXULLabel();
678
679
  bool IsXULListItem() const { return mType == eXULListItemType; }
680
681
  bool IsXULTabpanels() const { return mType == eXULTabpanelsType; }
682
683
  bool IsXULTree() const { return mType == eXULTreeType; }
684
  XULTreeAccessible* AsXULTree();
685
686
  /**
687
   * Return true if the accessible belongs to the given accessible type.
688
   */
689
  bool HasGenericType(AccGenericType aType) const;
690
691
  //////////////////////////////////////////////////////////////////////////////
692
  // ActionAccessible
693
694
  /**
695
   * Return the number of actions that can be performed on this accessible.
696
   */
697
  virtual uint8_t ActionCount() const;
698
699
  /**
700
   * Return action name at given index.
701
   */
702
  virtual void ActionNameAt(uint8_t aIndex, nsAString& aName);
703
704
  /**
705
   * Default to localized action name.
706
   */
707
  void ActionDescriptionAt(uint8_t aIndex, nsAString& aDescription)
708
  {
709
    nsAutoString name;
710
    ActionNameAt(aIndex, name);
711
    TranslateString(name, aDescription);
712
  }
713
714
  /**
715
   * Invoke the accessible action.
716
   */
717
  virtual bool DoAction(uint8_t aIndex) const;
718
719
  /**
720
   * Return access key, such as Alt+D.
721
   */
722
  virtual KeyBinding AccessKey() const;
723
724
  /**
725
   * Return global keyboard shortcut for default action, such as Ctrl+O for
726
   * Open file menuitem.
727
   */
728
  virtual KeyBinding KeyboardShortcut() const;
729
730
  //////////////////////////////////////////////////////////////////////////////
731
  // HyperLinkAccessible (any embedded object in text can implement HyperLink,
732
  // which helps determine where it is located within containing text).
733
734
  /**
735
   * Return true if the accessible is hyper link accessible.
736
   */
737
  virtual bool IsLink() const;
738
739
  /**
740
   * Return the start offset of the link within the parent accessible.
741
   */
742
  virtual uint32_t StartOffset();
743
744
  /**
745
   * Return the end offset of the link within the parent accessible.
746
   */
747
  virtual uint32_t EndOffset();
748
749
  /**
750
   * Return true if the link is valid (e. g. points to a valid URL).
751
   */
752
  inline bool IsLinkValid()
753
0
  {
754
0
    MOZ_ASSERT(IsLink(), "IsLinkValid is called on not hyper link!");
755
0
756
0
    // XXX In order to implement this we would need to follow every link
757
0
    // Perhaps we can get information about invalid links from the cache
758
0
    // In the mean time authors can use role="link" aria-invalid="true"
759
0
    // to force it for links they internally know to be invalid
760
0
    return (0 == (State() & mozilla::a11y::states::INVALID));
761
0
  }
762
763
  /**
764
   * Return the number of anchors within the link.
765
   */
766
  virtual uint32_t AnchorCount();
767
768
  /**
769
   * Returns an anchor accessible at the given index.
770
   */
771
  virtual Accessible* AnchorAt(uint32_t aAnchorIndex);
772
773
  /**
774
   * Returns an anchor URI at the given index.
775
   */
776
  virtual already_AddRefed<nsIURI> AnchorURIAt(uint32_t aAnchorIndex) const;
777
778
  /**
779
   * Returns a text point for the accessible element.
780
   */
781
  void ToTextPoint(HyperTextAccessible** aContainer, int32_t* aOffset,
782
                   bool aIsBefore = true) const;
783
784
  //////////////////////////////////////////////////////////////////////////////
785
  // SelectAccessible
786
787
  /**
788
   * Return an array of selected items.
789
   */
790
  virtual void SelectedItems(nsTArray<Accessible*>* aItems);
791
792
  /**
793
   * Return the number of selected items.
794
   */
795
  virtual uint32_t SelectedItemCount();
796
797
  /**
798
   * Return selected item at the given index.
799
   */
800
  virtual Accessible* GetSelectedItem(uint32_t aIndex);
801
802
  /**
803
   * Determine if item at the given index is selected.
804
   */
805
  virtual bool IsItemSelected(uint32_t aIndex);
806
807
  /**
808
   * Add item at the given index the selection. Return true if success.
809
   */
810
  virtual bool AddItemToSelection(uint32_t aIndex);
811
812
  /**
813
   * Remove item at the given index from the selection. Return if success.
814
   */
815
  virtual bool RemoveItemFromSelection(uint32_t aIndex);
816
817
  /**
818
   * Select all items. Return true if success.
819
   */
820
  virtual bool SelectAll();
821
822
  /**
823
   * Unselect all items. Return true if success.
824
   */
825
  virtual bool UnselectAll();
826
827
  //////////////////////////////////////////////////////////////////////////////
828
  // Value (numeric value interface)
829
830
  virtual double MaxValue() const;
831
  virtual double MinValue() const;
832
  virtual double CurValue() const;
833
  virtual double Step() const;
834
  virtual bool SetCurValue(double aValue);
835
836
  //////////////////////////////////////////////////////////////////////////////
837
  // Widgets
838
839
  /**
840
   * Return true if accessible is a widget, i.e. control or accessible that
841
   * manages its items. Note, being a widget the accessible may be a part of
842
   * composite widget.
843
   */
844
  virtual bool IsWidget() const;
845
846
  /**
847
   * Return true if the widget is active, i.e. has a focus within it.
848
   */
849
  virtual bool IsActiveWidget() const;
850
851
  /**
852
   * Return true if the widget has items and items are operable by user and
853
   * can be activated.
854
   */
855
  virtual bool AreItemsOperable() const;
856
857
  /**
858
   * Return the current item of the widget, i.e. an item that has or will have
859
   * keyboard focus when widget gets active.
860
   */
861
  virtual Accessible* CurrentItem() const;
862
863
  /**
864
   * Set the current item of the widget.
865
   */
866
  virtual void SetCurrentItem(const Accessible* aItem);
867
868
  /**
869
   * Return container widget this accessible belongs to.
870
   */
871
  virtual Accessible* ContainerWidget() const;
872
873
  /**
874
   * Return the localized string for the given key.
875
   */
876
  static void TranslateString(const nsString& aKey, nsAString& aStringOut);
877
878
  /**
879
   * Return true if the accessible is defunct.
880
   */
881
  bool IsDefunct() const;
882
883
  /**
884
   * Return false if the accessible is no longer in the document.
885
   */
886
0
  bool IsInDocument() const { return !(mStateFlags & eIsNotInDocument); }
887
888
  /**
889
   * Return true if the accessible should be contained by document node map.
890
   */
891
  bool IsNodeMapEntry() const
892
    { return HasOwnContent() && !(mStateFlags & eNotNodeMapEntry); }
893
894
  /**
895
   * Return true if the accessible's group info needs to be updated.
896
   */
897
  inline bool HasDirtyGroupInfo() const { return mStateFlags & eGroupInfoDirty; }
898
899
  /**
900
   * Return true if the accessible has associated DOM content.
901
   */
902
  bool HasOwnContent() const
903
0
    { return mContent && !(mStateFlags & eSharedNode); }
904
905
  /**
906
  * Return true if the accessible has a numeric value.
907
  */
908
  bool HasNumericValue() const;
909
910
  /**
911
   * Return true if the accessible state change is processed by handling proper
912
   * DOM UI event, if otherwise then false. For example, CheckboxAccessible
913
   * created for HTML:input@type="checkbox" will process
914
   * nsIDocumentObserver::ContentStateChanged instead of 'CheckboxStateChange'
915
   * event.
916
   */
917
  bool NeedsDOMUIEvent() const
918
    { return !(mStateFlags & eIgnoreDOMUIEvent); }
919
920
  /**
921
   * Get/set repositioned bit indicating that the accessible was moved in
922
   * the accessible tree, i.e. the accessible tree structure differs from DOM.
923
   */
924
  bool IsRelocated() const { return mStateFlags & eRelocated; }
925
  void SetRelocated(bool aRelocated)
926
  {
927
    if (aRelocated)
928
      mStateFlags |= eRelocated;
929
    else
930
      mStateFlags &= ~eRelocated;
931
  }
932
933
  /**
934
   * Return true if the accessible doesn't allow accessible children from XBL
935
   * anonymous subtree.
936
   */
937
  bool NoXBLKids() const { return mStateFlags & eNoXBLKids; }
938
939
  /**
940
   * Return true if the accessible allows accessible children from subtree of
941
   * a DOM element of this accessible.
942
   */
943
  bool KidsFromDOM() const { return !(mStateFlags & eNoKidsFromDOM); }
944
945
  /**
946
   * Return true if this accessible has a parent whose name depends on this
947
   * accessible.
948
   */
949
  bool HasNameDependentParent() const
950
0
    { return mContextFlags & eHasNameDependentParent; }
951
952
  /**
953
   * Return true if the element is inside an alert.
954
   */
955
  bool IsInsideAlert() const { return mContextFlags & eInsideAlert; }
956
957
  /**
958
   * Return true if there is a pending reorder event for this accessible.
959
   */
960
0
  bool ReorderEventTarget() const { return mReorderEventTarget; }
961
962
  /**
963
   * Return true if there is a pending show event for this accessible.
964
   */
965
0
  bool ShowEventTarget() const { return mShowEventTarget; }
966
967
  /**
968
   * Return true if there is a pending hide event for this accessible.
969
   */
970
0
  bool HideEventTarget() const { return mHideEventTarget; }
971
972
  /**
973
   * Set if there is a pending reorder event for this accessible.
974
   */
975
0
  void SetReorderEventTarget(bool aTarget) { mReorderEventTarget = aTarget; }
976
977
  /**
978
   * Set if this accessible is a show event target.
979
   */
980
0
  void SetShowEventTarget(bool aTarget) { mShowEventTarget = aTarget; }
981
982
  /**
983
   * Set if this accessible is a hide event target.
984
   */
985
0
  void SetHideEventTarget(bool aTarget) { mHideEventTarget = aTarget; }
986
987
protected:
988
  virtual ~Accessible();
989
990
  /**
991
   * Return the accessible name provided by native markup. It doesn't take
992
   * into account ARIA markup used to specify the name.
993
   */
994
  virtual mozilla::a11y::ENameValueFlag NativeName(nsString& aName) const;
995
996
  /**
997
   * Return the accessible description provided by native markup. It doesn't take
998
   * into account ARIA markup used to specify the description.
999
   */
1000
  virtual void NativeDescription(nsString& aDescription);
1001
1002
  /**
1003
   * Return object attributes provided by native markup. It doesn't take into
1004
   * account ARIA.
1005
   */
1006
  virtual already_AddRefed<nsIPersistentProperties> NativeAttributes();
1007
1008
  //////////////////////////////////////////////////////////////////////////////
1009
  // Initializing, cache and tree traverse methods
1010
1011
  /**
1012
   * Destroy the object.
1013
   */
1014
  void LastRelease();
1015
1016
  /**
1017
   * Set accessible parent and index in parent.
1018
   */
1019
  void BindToParent(Accessible* aParent, uint32_t aIndexInParent);
1020
  void UnbindFromParent();
1021
1022
  /**
1023
   * Return sibling accessible at the given offset.
1024
   */
1025
  virtual Accessible* GetSiblingAtOffset(int32_t aOffset,
1026
                                         nsresult *aError = nullptr) const;
1027
1028
  /**
1029
   * Flags used to describe the state of this accessible.
1030
   */
1031
  enum StateFlags {
1032
    eIsDefunct = 1 << 0, // accessible is defunct
1033
    eIsNotInDocument = 1 << 1, // accessible is not in document
1034
    eSharedNode = 1 << 2, // accessible shares DOM node from another accessible
1035
    eNotNodeMapEntry = 1 << 3, // accessible shouldn't be in document node map
1036
    eHasNumericValue = 1 << 4, // accessible has a numeric value
1037
    eGroupInfoDirty = 1 << 5, // accessible needs to update group info
1038
    eKidsMutating = 1 << 6, // subtree is being mutated
1039
    eIgnoreDOMUIEvent = 1 << 7, // don't process DOM UI events for a11y events
1040
    eRelocated = 1 << 8, // accessible was moved in tree
1041
    eNoXBLKids = 1 << 9, // accessible don't allows XBL children
1042
    eNoKidsFromDOM = 1 << 10, // accessible doesn't allow children from DOM
1043
    eHasTextKids = 1 << 11, // accessible have a text leaf in children
1044
1045
    eLastStateFlag = eNoKidsFromDOM
1046
  };
1047
1048
  /**
1049
   * Flags used for contextual information about the accessible.
1050
   */
1051
  enum ContextFlags {
1052
    eHasNameDependentParent = 1 << 0, // Parent's name depends on this accessible.
1053
    eInsideAlert = 1 << 1,
1054
1055
    eLastContextFlag = eInsideAlert
1056
  };
1057
1058
protected:
1059
1060
  //////////////////////////////////////////////////////////////////////////////
1061
  // Miscellaneous helpers
1062
1063
  /**
1064
   * Return ARIA role (helper method).
1065
   */
1066
  mozilla::a11y::role ARIATransformRole(mozilla::a11y::role aRole) const;
1067
1068
  //////////////////////////////////////////////////////////////////////////////
1069
  // Name helpers
1070
1071
  /**
1072
   * Returns the accessible name specified by ARIA.
1073
   */
1074
  void ARIAName(nsString& aName) const;
1075
1076
  /**
1077
   * Return the name for XUL element.
1078
   */
1079
  static void XULElmName(DocAccessible* aDocument,
1080
                         nsIContent* aElm, nsString& aName);
1081
1082
  // helper method to verify frames
1083
  static nsresult GetFullKeyName(const nsAString& aModifierName, const nsAString& aKeyName, nsAString& aStringOut);
1084
1085
  //////////////////////////////////////////////////////////////////////////////
1086
  // Action helpers
1087
1088
  /**
1089
   * Prepares click action that will be invoked in timeout.
1090
   *
1091
   * @note  DoCommand() prepares an action in timeout because when action
1092
   *  command opens a modal dialog/window, it won't return until the
1093
   *  dialog/window is closed. If executing action command directly in
1094
   *  nsIAccessible::DoAction() method, it will block AT tools (e.g. GOK) that
1095
   *  invoke action of mozilla accessibles direclty (see bug 277888 for details).
1096
   *
1097
   * @param  aContent      [in, optional] element to click
1098
   * @param  aActionIndex  [in, optional] index of accessible action
1099
   */
1100
  void DoCommand(nsIContent* aContent = nullptr,
1101
                 uint32_t aActionIndex = 0) const;
1102
1103
  /**
1104
   * Dispatch click event.
1105
   */
1106
  virtual void DispatchClickEvent(nsIContent *aContent,
1107
                                  uint32_t aActionIndex) const;
1108
1109
  //////////////////////////////////////////////////////////////////////////////
1110
  // Helpers
1111
1112
  /**
1113
   *  Get the container node for an atomic region, defined by aria-atomic="true"
1114
   *  @return the container node
1115
   */
1116
  nsIContent* GetAtomicRegion() const;
1117
1118
  /**
1119
   * Return numeric value of the given ARIA attribute, NaN if not applicable.
1120
   *
1121
   * @param aARIAProperty  [in] the ARIA property we're using
1122
   * @return  a numeric value
1123
   */
1124
  double AttrNumericValue(nsAtom* aARIAAttr) const;
1125
1126
  /**
1127
   * Return the action rule based on ARIA enum constants EActionRule
1128
   * (see ARIAMap.h). Used by ActionCount() and ActionNameAt().
1129
   */
1130
  uint32_t GetActionRule() const;
1131
1132
  /**
1133
   * Return group info.
1134
   */
1135
  AccGroupInfo* GetGroupInfo() const;
1136
1137
  // Data Members
1138
  nsCOMPtr<nsIContent> mContent;
1139
  RefPtr<DocAccessible> mDoc;
1140
1141
  Accessible* mParent;
1142
  nsTArray<Accessible*> mChildren;
1143
  int32_t mIndexInParent;
1144
1145
  static const uint8_t kStateFlagsBits = 12;
1146
  static const uint8_t kContextFlagsBits = 2;
1147
  static const uint8_t kTypeBits = 6;
1148
  static const uint8_t kGenericTypesBits = 16;
1149
1150
  /**
1151
   * Non-NO_ROLE_MAP_ENTRY_INDEX indicates author-supplied role;
1152
   * possibly state & value as well
1153
   */
1154
  uint8_t mRoleMapEntryIndex;
1155
1156
  /**
1157
   * Keep in sync with StateFlags, ContextFlags, and AccTypes.
1158
   */
1159
  mutable uint32_t mStateFlags : kStateFlagsBits;
1160
  uint32_t mContextFlags : kContextFlagsBits;
1161
  uint32_t mType : kTypeBits;
1162
  uint32_t mGenericTypes : kGenericTypesBits;
1163
  uint32_t mReorderEventTarget : 1;
1164
  uint32_t mShowEventTarget : 1;
1165
  uint32_t mHideEventTarget : 1;
1166
1167
  void StaticAsserts() const;
1168
1169
#ifdef A11Y_LOG
1170
  friend void logging::Tree(const char* aTitle, const char* aMsgText,
1171
                            Accessible* aRoot,
1172
                            logging::GetTreePrefix aPrefixFunc,
1173
                            void* aGetTreePrefixData);
1174
#endif
1175
  friend class DocAccessible;
1176
  friend class xpcAccessible;
1177
  friend class TreeMutation;
1178
1179
  UniquePtr<mozilla::a11y::EmbeddedObjCollector> mEmbeddedObjCollector;
1180
  union {
1181
    int32_t mIndexOfEmbeddedChild;
1182
    uint32_t mProxyInterfaces;
1183
  } mInt;
1184
1185
  friend class EmbeddedObjCollector;
1186
1187
  union
1188
  {
1189
    AccGroupInfo* groupInfo;
1190
    ProxyAccessible* proxy;
1191
  } mutable mBits;
1192
  friend class AccGroupInfo;
1193
1194
private:
1195
  Accessible() = delete;
1196
  Accessible(const Accessible&) = delete;
1197
  Accessible& operator =(const Accessible&) = delete;
1198
};
1199
1200
NS_DEFINE_STATIC_IID_ACCESSOR(Accessible,
1201
                              NS_ACCESSIBLE_IMPL_IID)
1202
1203
1204
/**
1205
 * Represent key binding associated with accessible (such as access key and
1206
 * global keyboard shortcuts).
1207
 */
1208
class KeyBinding
1209
{
1210
public:
1211
  /**
1212
   * Modifier mask values.
1213
   */
1214
  static const uint32_t kShift = 1;
1215
  static const uint32_t kControl = 2;
1216
  static const uint32_t kAlt = 4;
1217
  static const uint32_t kMeta = 8;
1218
  static const uint32_t kOS = 16;
1219
1220
  static uint32_t AccelModifier();
1221
1222
  KeyBinding() : mKey(0), mModifierMask(0) {}
1223
  KeyBinding(uint32_t aKey, uint32_t aModifierMask) :
1224
    mKey(aKey), mModifierMask(aModifierMask) {}
1225
1226
  inline bool IsEmpty() const { return !mKey; }
1227
0
  inline uint32_t Key() const { return mKey; }
1228
0
  inline uint32_t ModifierMask() const { return mModifierMask; }
1229
1230
  enum Format {
1231
    ePlatformFormat,
1232
    eAtkFormat
1233
  };
1234
1235
  /**
1236
   * Return formatted string for this key binding depending on the given format.
1237
   */
1238
  inline void ToString(nsAString& aValue,
1239
                       Format aFormat = ePlatformFormat) const
1240
  {
1241
    aValue.Truncate();
1242
    AppendToString(aValue, aFormat);
1243
  }
1244
  inline void AppendToString(nsAString& aValue,
1245
                             Format aFormat = ePlatformFormat) const
1246
  {
1247
    if (mKey) {
1248
      if (aFormat == ePlatformFormat)
1249
        ToPlatformFormat(aValue);
1250
      else
1251
        ToAtkFormat(aValue);
1252
    }
1253
  }
1254
1255
private:
1256
  void ToPlatformFormat(nsAString& aValue) const;
1257
  void ToAtkFormat(nsAString& aValue) const;
1258
1259
  uint32_t mKey;
1260
  uint32_t mModifierMask;
1261
};
1262
1263
} // namespace a11y
1264
} // namespace mozilla
1265
1266
#endif