tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

RemoteAccessible.h (18185B)


      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_RemoteAccessible_h
      8 #define mozilla_a11y_RemoteAccessible_h
      9 
     10 #include "mozilla/a11y/Accessible.h"
     11 #include "mozilla/a11y/CacheConstants.h"
     12 #include "mozilla/a11y/HyperTextAccessibleBase.h"
     13 #include "mozilla/a11y/Role.h"
     14 #include "AccAttributes.h"
     15 #include "nsIAccessibleText.h"
     16 #include "nsIAccessibleTypes.h"
     17 #include "nsTArray.h"
     18 #include "nsRect.h"
     19 #include "LocalAccessible.h"
     20 
     21 namespace mozilla {
     22 namespace a11y {
     23 
     24 class Attribute;
     25 class DocAccessibleParent;
     26 class RemoteAccessible;
     27 enum class RelationType;
     28 
     29 /**
     30 * The class for an accessibility tree node that originated in the parent
     31 * process.
     32 */
     33 class RemoteAccessible : public Accessible, public HyperTextAccessibleBase {
     34 public:
     35  virtual ~RemoteAccessible() {
     36    MOZ_ASSERT(!mWrapper);
     37    MOZ_COUNT_DTOR(RemoteAccessible);
     38  }
     39 
     40  virtual bool IsRemote() const override { return true; }
     41 
     42  void AddChildAt(uint32_t aIdx, RemoteAccessible* aChild) {
     43    mChildren.InsertElementAt(aIdx, aChild);
     44    UpdateChildIndexCache(static_cast<int32_t>(aIdx));
     45    if (IsHyperText()) {
     46      InvalidateCachedHyperTextOffsets();
     47    }
     48  }
     49 
     50  virtual uint32_t ChildCount() const override { return mChildren.Length(); }
     51  RemoteAccessible* RemoteChildAt(uint32_t aIdx) const {
     52    RemoteAccessible* child = mChildren.SafeElementAt(aIdx);
     53    MOZ_ASSERT(!child || child->mParent == this,
     54               "Child's parent should be this");
     55    return child;
     56  }
     57  RemoteAccessible* RemoteFirstChild() const {
     58    return mChildren.Length() ? mChildren[0] : nullptr;
     59  }
     60  RemoteAccessible* RemoteLastChild() const {
     61    return mChildren.Length() ? mChildren[mChildren.Length() - 1] : nullptr;
     62  }
     63  RemoteAccessible* RemotePrevSibling() const {
     64    if (IsDoc()) {
     65      // The normal code path doesn't work for documents because the parent
     66      // might be a local OuterDoc, but IndexInParent() will return 0.
     67      // A document is always a single child of an OuterDoc anyway.
     68      return nullptr;
     69    }
     70    int32_t idx = IndexInParent();
     71    if (idx == -1) {
     72      return nullptr;  // No parent.
     73    }
     74    MOZ_ASSERT(RemoteParent());
     75    return idx > 0 ? RemoteParent()->mChildren[idx - 1] : nullptr;
     76  }
     77  RemoteAccessible* RemoteNextSibling() const {
     78    if (IsDoc()) {
     79      // The normal code path doesn't work for documents because the parent
     80      // might be a local OuterDoc, but IndexInParent() will return 0.
     81      // A document is always a single child of an OuterDoc anyway.
     82      return nullptr;
     83    }
     84    int32_t idx = IndexInParent();
     85    if (idx == -1) {
     86      return nullptr;  // No parent.
     87    }
     88    MOZ_ASSERT(idx >= 0);
     89    size_t newIdx = idx + 1;
     90    MOZ_ASSERT(RemoteParent());
     91    return newIdx < RemoteParent()->mChildren.Length()
     92               ? RemoteParent()->mChildren[newIdx]
     93               : nullptr;
     94  }
     95 
     96  // Accessible hierarchy method overrides
     97 
     98  virtual Accessible* Parent() const override { return RemoteParent(); }
     99 
    100  virtual Accessible* ChildAt(uint32_t aIndex) const override {
    101    return RemoteChildAt(aIndex);
    102  }
    103 
    104  virtual Accessible* NextSibling() const override {
    105    return RemoteNextSibling();
    106  }
    107 
    108  virtual Accessible* PrevSibling() const override {
    109    return RemotePrevSibling();
    110  }
    111 
    112  virtual int32_t IndexInParent() const override {
    113    MOZ_ASSERT(mParent || mIndexInParent == -1,
    114               "IndexInParent should be -1 if no parent");
    115    return mIndexInParent;
    116  }
    117 
    118  virtual uint32_t EmbeddedChildCount() override;
    119  virtual int32_t IndexOfEmbeddedChild(Accessible* aChild) override;
    120  virtual Accessible* EmbeddedChildAt(uint32_t aChildIdx) override;
    121 
    122  void Shutdown();
    123 
    124  void SetChildDoc(DocAccessibleParent* aChildDoc);
    125  void ClearChildDoc(DocAccessibleParent* aChildDoc);
    126 
    127  /**
    128   * Remove The given child.
    129   */
    130  void RemoveChild(RemoteAccessible* aChild) {
    131    mChildren.RemoveElement(aChild);
    132    MOZ_ASSERT(aChild->mIndexInParent != -1);
    133    UpdateChildIndexCache(aChild->mIndexInParent);
    134    aChild->mIndexInParent = -1;
    135    if (IsHyperText()) {
    136      InvalidateCachedHyperTextOffsets();
    137    }
    138  }
    139 
    140  /**
    141   * Return the proxy for the parent of the wrapped accessible.
    142   */
    143  RemoteAccessible* RemoteParent() const;
    144 
    145  LocalAccessible* OuterDocOfRemoteBrowser() const;
    146 
    147  /**
    148   * Get the native role of the accessible we're proxying.
    149   */
    150  virtual mozilla::a11y::role NativeRole() const override {
    151    return mNativeRole;
    152  }
    153 
    154  /**
    155   * Return true if this is an embedded object.
    156   */
    157  bool IsEmbeddedObject() const { return !IsText(); }
    158 
    159  virtual bool IsLink() const override {
    160    if (IsHTMLLink()) {
    161      // XXX: HTML links always return true for IsLink.
    162      return true;
    163    }
    164 
    165    if (IsText()) {
    166      return false;
    167    }
    168 
    169    if (Accessible* parent = Parent()) {
    170      return parent->IsHyperText();
    171    }
    172 
    173    return false;
    174  }
    175 
    176  virtual bool HasNumericValue() const override {
    177    // XXX: We combine the aria and native "has numeric value" field
    178    // when we serialize the local accessible into eNumericValue.
    179    return HasGenericType(eNumericValue);
    180  }
    181 
    182  // Methods that potentially access a cache.
    183 
    184  virtual ENameValueFlag Name(nsString& aName) const override final;
    185  virtual EDescriptionValueFlag Description(
    186      nsString& aDescription) const override;
    187  virtual void Value(nsString& aValue) const override;
    188 
    189  virtual double CurValue() const override;
    190  virtual double MinValue() const override;
    191  virtual double MaxValue() const override;
    192  virtual double Step() const override;
    193  virtual bool SetCurValue(double aValue) override;
    194 
    195  virtual Accessible* ChildAtPoint(
    196      int32_t aX, int32_t aY,
    197      LocalAccessible::EWhichChildAtPoint aWhichChild) override;
    198 
    199  virtual LayoutDeviceIntRect Bounds() const override;
    200 
    201  virtual nsRect BoundsInAppUnits() const override;
    202 
    203  virtual Relation RelationByType(RelationType aType) const override;
    204 
    205  virtual uint64_t State() override;
    206 
    207  virtual already_AddRefed<AccAttributes> Attributes() override;
    208 
    209  virtual nsAtom* TagName() const override;
    210 
    211  virtual already_AddRefed<nsAtom> DisplayStyle() const override;
    212 
    213  virtual float Opacity() const override;
    214 
    215  virtual WritingMode GetWritingMode() const override;
    216 
    217  virtual void LiveRegionAttributes(nsAString* aLive, nsAString* aRelevant,
    218                                    Maybe<bool>* aAtomic,
    219                                    nsAString* aBusy) const override;
    220 
    221  virtual Maybe<bool> ARIASelected() const override;
    222 
    223  virtual uint8_t ActionCount() const override;
    224 
    225  virtual void ActionNameAt(uint8_t aIndex, nsAString& aName) override;
    226 
    227  virtual bool DoAction(uint8_t aIndex) const override;
    228 
    229  virtual KeyBinding AccessKey() const override;
    230 
    231  virtual void SelectionRanges(nsTArray<TextRange>* aRanges) const override;
    232 
    233  MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual bool RemoveFromSelection(
    234      int32_t aSelectionNum) override;
    235 
    236  virtual Maybe<int32_t> GetIntARIAAttr(nsAtom* aAttrName) const override;
    237 
    238  virtual bool GetStringARIAAttr(nsAtom* aAttrName,
    239                                 nsAString& aAttrValue) const override;
    240 
    241  virtual bool ARIAAttrValueIs(nsAtom* aAttrName,
    242                               nsAtom* aAttrValue) const override;
    243 
    244  virtual bool HasARIAAttr(nsAtom* aAttrName) const override;
    245 
    246  virtual void Language(nsAString& aLocale) override;
    247 
    248  //////////////////////////////////////////////////////////////////////////////
    249  // EditableTextAccessible
    250 
    251  MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void ReplaceText(
    252      const nsAString& aText) override;
    253  MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void InsertText(
    254      const nsAString& aText, int32_t aPosition) override;
    255  MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void CopyText(int32_t aStartPos,
    256                                                    int32_t aEndPos) override;
    257  MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void CutText(int32_t aStartPos,
    258                                                   int32_t aEndPos) override;
    259  MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void DeleteText(int32_t aStartPos,
    260                                                      int32_t aEndPos) override;
    261  MOZ_CAN_RUN_SCRIPT virtual void PasteText(int32_t aPosition) override;
    262 
    263  //////////////////////////////////////////////////////////////////////////////
    264  // SelectAccessible
    265 
    266  virtual void SelectedItems(nsTArray<Accessible*>* aItems) override;
    267 
    268  virtual uint32_t SelectedItemCount() override;
    269 
    270  virtual Accessible* GetSelectedItem(uint32_t aIndex) override;
    271 
    272  virtual bool IsItemSelected(uint32_t aIndex) override;
    273 
    274  virtual bool AddItemToSelection(uint32_t aIndex) override;
    275 
    276  virtual bool RemoveItemFromSelection(uint32_t aIndex) override;
    277 
    278  virtual bool SelectAll() override;
    279 
    280  virtual bool UnselectAll() override;
    281 
    282  virtual void TakeSelection() override;
    283 
    284  virtual void SetSelected(bool aSelect) override;
    285 
    286  // Methods that interact with content.
    287 
    288  virtual void TakeFocus() const override;
    289  virtual void ScrollTo(uint32_t aHow) const override;
    290 
    291  /**
    292   * Allow the platform to store a pointers worth of data on us.
    293   */
    294  uintptr_t GetWrapper() const { return mWrapper; }
    295  void SetWrapper(uintptr_t aWrapper) { mWrapper = aWrapper; }
    296 
    297  virtual uint64_t ID() const override { return mID; }
    298 
    299  /**
    300   * Return the document containing this proxy, or the proxy itself if it is a
    301   * document.
    302   */
    303  DocAccessibleParent* Document() const { return mDoc; }
    304 
    305  DocAccessibleParent* AsDoc() const { return IsDoc() ? mDoc : nullptr; }
    306 
    307  void ApplyCache(CacheUpdateType aUpdateType, AccAttributes* aFields);
    308 
    309  void UpdateStateCache(uint64_t aState, bool aEnabled) {
    310    if (aState & kRemoteCalculatedStates) {
    311      return;
    312    }
    313    uint64_t state = 0;
    314    if (mCachedFields) {
    315      if (auto oldState =
    316              mCachedFields->GetAttribute<uint64_t>(CacheKey::State)) {
    317        state = *oldState;
    318      }
    319    } else {
    320      mCachedFields = new AccAttributes();
    321    }
    322    if (aEnabled) {
    323      state |= aState;
    324    } else {
    325      state &= ~aState;
    326    }
    327    mCachedFields->SetAttribute(CacheKey::State, state);
    328  }
    329 
    330  void InvalidateGroupInfo();
    331 
    332  virtual void AppendTextTo(nsAString& aText, uint32_t aStartOffset = 0,
    333                            uint32_t aLength = UINT32_MAX) override;
    334 
    335  virtual bool TableIsProbablyForLayout();
    336 
    337  /**
    338   * Iterates through each atom in kRelationTypeAtoms, checking to see
    339   * if it is present in aFields. If it is present (or if aFields contains
    340   * a DeleteEntry() for this atom) and mCachedFields is initialized,
    341   * fetches the old rel targets and removes their existing reverse relations
    342   * stored in mReverseRelations.
    343   * Returns an array of bools where the ith array entry corresponds
    344   * to whether or not the rel at the ith entry of kRelationTypeAtoms
    345   * requires a post-processing update.
    346   */
    347  nsTArray<bool> PreProcessRelations(AccAttributes* aFields);
    348 
    349  /**
    350   * Takes in the array returned from PreProcessRelations.
    351   * For each entry requiring an update, fetches the new relation
    352   * targets stored in mCachedFields and appropriately
    353   * updates their reverse relations in mReverseRelations.
    354   */
    355  void PostProcessRelations(const nsTArray<bool>& aToUpdate);
    356 
    357  /**
    358   * This method is called during shutdown, before we clear our
    359   * reverse rel map from the document's mReverseRelations cache.
    360   * Here, we traverse our reverse relations, removing our ID from
    361   * the corresponding forward relation's target list. This ensures
    362   * the stored forward relations do not reference defunct accessibles.
    363   */
    364  void PruneRelationsOnShutdown();
    365 
    366  uint32_t GetCachedTextLength();
    367  Maybe<const nsTArray<int32_t>&> GetCachedTextLines();
    368  nsRect GetCachedCharRect(int32_t aOffset);
    369  RefPtr<const AccAttributes> GetCachedTextAttributes();
    370  const AccAttributes* GetCachedARIAAttributes() const;
    371 
    372  nsString GetCachedHTMLNameAttribute() const;
    373 
    374  virtual HyperTextAccessibleBase* AsHyperTextBase() override {
    375    return IsHyperText() ? static_cast<HyperTextAccessibleBase*>(this)
    376                         : nullptr;
    377  }
    378 
    379  virtual TableAccessible* AsTable() override;
    380  virtual TableCellAccessible* AsTableCell() override;
    381 
    382  virtual void DOMNodeID(nsString& aID) const override;
    383 
    384  virtual void DOMNodeClass(nsString& aClass) const override;
    385 
    386  virtual void ScrollToPoint(uint32_t aScrollType, int32_t aX,
    387                             int32_t aY) override;
    388 
    389  virtual bool IsScrollable() const override;
    390 
    391  virtual bool IsPopover() const override;
    392 
    393  virtual bool HasPrimaryAction() const override;
    394 
    395  virtual bool HasCustomActions() const override;
    396  virtual bool IsEditable() const override;
    397 
    398 #if !defined(XP_WIN)
    399  void Announce(const nsString& aAnnouncement, uint16_t aPriority);
    400 #endif  // !defined(XP_WIN)
    401 
    402  // HTMLMeterAccessible
    403  int32_t ValueRegion() const;
    404 
    405  // HyperTextAccessibleBase
    406  virtual already_AddRefed<AccAttributes> DefaultTextAttributes() override;
    407 
    408  virtual void ScrollSubstringToPoint(int32_t aStartOffset, int32_t aEndOffset,
    409                                      uint32_t aCoordinateType, int32_t aX,
    410                                      int32_t aY) override;
    411 
    412  virtual std::pair<mozilla::LayoutDeviceIntRect, nsIWidget*> GetCaretRect()
    413      override;
    414 
    415  /**
    416   * Invalidate cached HyperText offsets. This should be called whenever a
    417   * child is added or removed or the text of a text leaf child is changed.
    418   * Although GetChildOffset can either fully or partially invalidate the
    419   * offsets cache, calculating which offset to invalidate is not worthwhile
    420   * because a client might not even query offsets. This is in contrast to
    421   * LocalAccessible, where the offsets are always needed to fire text change
    422   * events. For RemoteAccessible, it's cheaper overall to just rebuild the
    423   * offsets cache when a client next needs it.
    424   */
    425  void InvalidateCachedHyperTextOffsets() {
    426    if (mCachedFields) {
    427      mCachedFields->Remove(CacheKey::HyperTextOffsets);
    428    }
    429  }
    430 
    431  size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf);
    432  virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf);
    433 
    434 protected:
    435  RemoteAccessible(uint64_t aID, DocAccessibleParent* aDoc, role aRole,
    436                   AccType aType, AccGenericType aGenericTypes,
    437                   uint8_t aRoleMapEntryIndex)
    438      : Accessible(aType, aGenericTypes, aRoleMapEntryIndex),
    439        mParent(nullptr),
    440        mDoc(aDoc),
    441        mWrapper(0),
    442        mID(aID),
    443        mCachedFields(nullptr),
    444        mNativeRole(aRole) {
    445    MOZ_COUNT_CTOR(RemoteAccessible);
    446  }
    447 
    448  explicit RemoteAccessible(DocAccessibleParent* aThisAsDoc)
    449      : mParent(nullptr),
    450        mDoc(aThisAsDoc),
    451        mWrapper(0),
    452        mID(0),
    453        mCachedFields(nullptr),
    454        mNativeRole(roles::DOCUMENT) {
    455    mGenericTypes = eDocument | eHyperText;
    456    MOZ_COUNT_CTOR(RemoteAccessible);
    457  }
    458 
    459 protected:
    460  void SetParent(RemoteAccessible* aParent);
    461  Maybe<nsRect> RetrieveCachedBounds() const;
    462  bool ApplyTransform(nsRect& aCumulativeBounds) const;
    463  bool ApplyScrollOffset(nsRect& aBounds, float aResolution) const;
    464  void ApplyCrossDocOffset(nsRect& aBounds) const;
    465  void ApplyVisualViewportOffset(nsRect& aBounds) const;
    466  LayoutDeviceIntRect BoundsWithOffset(
    467      Maybe<nsRect> aOffset, bool aBoundsAreForHittesting = false) const;
    468  bool IsFixedPos() const;
    469  bool IsOverflowHidden() const;
    470 
    471  /**
    472   * Returns true if an accessible's frame has no scrollable overflow, and
    473   * false otherwise.
    474   * Does not return true for partially clipped accessibles.
    475   */
    476  bool IsClipped() const;
    477 
    478  /**
    479   * Checks if our hittesting match has any clipped children and, if so
    480   * descends it and subsequent TEXT_CONTAINERs in search of a text leaf.
    481   * We do this because some sites use clipping to hide text that is only
    482   * visible to a11y, while displaying a visual version of the same text on
    483   * the web page. We want a hittest of the visible text to resolve to the
    484   * hidden, a11y-only text node.
    485   */
    486  RemoteAccessible* DoFuzzyHittesting();
    487 
    488  // This function is used exclusively for hit testing.
    489  bool ContainsPoint(int32_t aX, int32_t aY);
    490 
    491  virtual void ARIAGroupPosition(int32_t* aLevel, int32_t* aSetSize,
    492                                 int32_t* aPosInSet) const override;
    493 
    494  virtual AccGroupInfo* GetGroupInfo() const override;
    495 
    496  virtual AccGroupInfo* GetOrCreateGroupInfo() override;
    497 
    498  virtual void GetPositionAndSetSize(int32_t* aPosInSet,
    499                                     int32_t* aSetSize) override;
    500  nsAtom* GetPrimaryAction() const;
    501 
    502  virtual nsTArray<int32_t>& GetCachedHyperTextOffsets() override;
    503 
    504  nsTArray<Accessible*> LegendsOrCaptions() const;
    505 
    506  RemoteAccessible* LegendOrCaptionFor() const;
    507 
    508 private:
    509  /**
    510   * Update mIndexInParent on each child starting at aStartIdx up to the last
    511   * child. This should be called when a child is added or removed.
    512   */
    513  void UpdateChildIndexCache(int32_t aStartIdx) {
    514    int32_t count = static_cast<int32_t>(mChildren.Length());
    515    for (int32_t idx = aStartIdx; idx < count; ++idx) {
    516      mChildren[idx]->mIndexInParent = idx;
    517    }
    518  }
    519 
    520  RemoteAccessible* mParent;
    521 
    522  friend DocAccessibleParent;
    523  friend TextLeafPoint;
    524  friend HyperTextAccessibleBase;
    525  friend class xpcAccessible;
    526  friend class CachedTableCellAccessible;
    527 #ifdef XP_WIN
    528  friend class sdnAccessible;
    529 #endif
    530 
    531  nsTArray<RemoteAccessible*> mChildren;
    532  DocAccessibleParent* mDoc;
    533  uintptr_t mWrapper;
    534  uint64_t mID;
    535  int32_t mIndexInParent = -1;
    536 
    537 protected:
    538  virtual const Accessible* Acc() const override { return this; }
    539 
    540  RefPtr<AccAttributes> mCachedFields;
    541 
    542  // XXX DocAccessibleParent gets to change this to change the role of
    543  // documents.
    544  role mNativeRole : 27;
    545 };
    546 
    547 ////////////////////////////////////////////////////////////////////////////////
    548 // RemoteAccessible downcasting method
    549 
    550 inline RemoteAccessible* Accessible::AsRemote() {
    551  return IsRemote() ? static_cast<RemoteAccessible*>(this) : nullptr;
    552 }
    553 
    554 }  // namespace a11y
    555 }  // namespace mozilla
    556 
    557 #endif