tor-browser

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

AccAttributes.h (12120B)


      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 AccAttributes_h_
      7 #define AccAttributes_h_
      8 
      9 #include "mozilla/ServoStyleConsts.h"
     10 #include "mozilla/a11y/AccGroupInfo.h"
     11 #include "mozilla/Variant.h"
     12 #include "nsTHashMap.h"
     13 #include "nsStringFwd.h"
     14 #include "mozilla/gfx/Matrix.h"
     15 #include "mozilla/WritingModes.h"
     16 
     17 class nsVariant;
     18 
     19 namespace IPC {
     20 template <typename T>
     21 struct ParamTraits;
     22 }  // namespace IPC
     23 
     24 namespace mozilla {
     25 
     26 namespace dom {
     27 class Element;
     28 }
     29 
     30 namespace a11y {
     31 
     32 struct FontSize {
     33  int32_t mValue;
     34 
     35  bool operator==(const FontSize& aOther) const {
     36    return mValue == aOther.mValue;
     37  }
     38 
     39  bool operator!=(const FontSize& aOther) const {
     40    return mValue != aOther.mValue;
     41  }
     42 };
     43 
     44 struct Color {
     45  nscolor mValue;
     46 
     47  bool operator==(const Color& aOther) const { return mValue == aOther.mValue; }
     48 
     49  bool operator!=(const Color& aOther) const { return mValue != aOther.mValue; }
     50 };
     51 
     52 // A special type. If an entry has a value of this type, it instructs the
     53 // target instance of an Update to remove the entry with the same key value.
     54 struct DeleteEntry {
     55  DeleteEntry() : mValue(true) {}
     56  bool mValue;
     57 
     58  bool operator==(const DeleteEntry& aOther) const { return true; }
     59 
     60  bool operator!=(const DeleteEntry& aOther) const { return false; }
     61 };
     62 
     63 /**
     64 * An attribute that applies to an offset range in a text leaf. This allows it
     65 * to span only part of a text leaf. This is used for spelling errors,
     66 * highlights, etc. which are mapped to DOM selections. This is in contrast to
     67 * most other attributes which can only apply to an entire text leaf and so just
     68 * reside on the leaf itself, rather than requiring offsets.
     69 */
     70 struct TextOffsetAttribute {
     71  // An offset used to indicate that this attribute extends outside of this
     72  // leaf.
     73  static const int32_t kOutsideLeaf = -1;
     74  // The offset in the text leaf where the attribute starts. If this is
     75  // kOutsideLeaf, the attribute begins before this leaf, crossing Accessibles.
     76  int32_t mStartOffset;
     77  // The offset in the text leaf where the attribute ends (exclusive). If this
     78  // is kOutsideLeaf, the attribute ends after this leaf, crossing Accessibles.
     79  int32_t mEndOffset;
     80  // The attribute:
     81  // nsGkAtoms::grammar: Grammar error.
     82  // nsGkAtoms::mark: Semantic highlight such as a text fragment.
     83  // nsGkAtoms::spelling: Spelling error.
     84  RefPtr<nsAtom> mAttribute;
     85 
     86  bool operator==(const TextOffsetAttribute& aOther) const {
     87    return mStartOffset == aOther.mStartOffset &&
     88           mEndOffset == aOther.mEndOffset && mAttribute == aOther.mAttribute;
     89  }
     90 
     91  bool operator!=(const TextOffsetAttribute& aOther) const {
     92    return !(*this == aOther);
     93  }
     94 
     95  bool operator<(const TextOffsetAttribute& aOther) const {
     96    return mStartOffset < aOther.mStartOffset;
     97  }
     98 };
     99 
    100 class AccAttributes {
    101  // Warning! An AccAttributes can contain another AccAttributes. This is
    102  // intended for object and text attributes. However, the nested
    103  // AccAttributes should never itself contain another AccAttributes, nor
    104  // should it create a cycle. We don't do cycle collection here for
    105  // performance reasons, so violating this rule will cause leaks!
    106  using AttrValueType =
    107      Variant<bool, float, double, int32_t, RefPtr<nsAtom>, nsTArray<int32_t>,
    108              CSSCoord, FontSize, Color, DeleteEntry, UniquePtr<nsString>,
    109              RefPtr<AccAttributes>, uint64_t, UniquePtr<AccGroupInfo>,
    110              UniquePtr<gfx::Matrix4x4>, UniquePtr<nsRect>, nsTArray<uint64_t>,
    111              nsTArray<TextOffsetAttribute>, WritingMode,
    112              nsTArray<RefPtr<nsAtom>>>;
    113  static_assert(sizeof(AttrValueType) <= 16);
    114  using AtomVariantMap = nsTHashMap<RefPtr<nsAtom>, AttrValueType>;
    115 
    116 protected:
    117  ~AccAttributes() = default;
    118 
    119 public:
    120  AccAttributes() = default;
    121  AccAttributes(const AccAttributes&) = delete;
    122  AccAttributes& operator=(const AccAttributes&) = delete;
    123 
    124  NS_INLINE_DECL_REFCOUNTING(mozilla::a11y::AccAttributes)
    125 
    126  template <typename T>
    127  void SetAttribute(nsAtom* aAttrName, T&& aAttrValue) {
    128    using ValType =
    129        std::remove_const_t<std::remove_reference_t<decltype(aAttrValue)>>;
    130    if constexpr (std::is_convertible_v<ValType, nsString>) {
    131      static_assert(std::is_rvalue_reference_v<decltype(aAttrValue)>,
    132                    "Please only move strings into this function. To make a "
    133                    "copy, use SetAttributeStringCopy.");
    134      UniquePtr<nsString> value = MakeUnique<nsString>(std::move(aAttrValue));
    135      mData.InsertOrUpdate(aAttrName, AsVariant(std::move(value)));
    136    } else if constexpr (std::is_same_v<ValType, gfx::Matrix4x4>) {
    137      UniquePtr<gfx::Matrix4x4> value = MakeUnique<gfx::Matrix4x4>(aAttrValue);
    138      mData.InsertOrUpdate(aAttrName, AsVariant(std::move(value)));
    139    } else if constexpr (std::is_same_v<ValType, nsRect>) {
    140      UniquePtr<nsRect> value = MakeUnique<nsRect>(aAttrValue);
    141      mData.InsertOrUpdate(aAttrName, AsVariant(std::move(value)));
    142    } else if constexpr (std::is_same_v<ValType, AccGroupInfo*>) {
    143      UniquePtr<AccGroupInfo> value(aAttrValue);
    144      mData.InsertOrUpdate(aAttrName, AsVariant(std::move(value)));
    145    } else if constexpr (std::is_convertible_v<ValType, nsAtom*>) {
    146      mData.InsertOrUpdate(aAttrName, AsVariant(RefPtr<nsAtom>(aAttrValue)));
    147    } else {
    148      mData.InsertOrUpdate(aAttrName, AsVariant(std::forward<T>(aAttrValue)));
    149    }
    150  }
    151 
    152  void SetAttributeStringCopy(nsAtom* aAttrName, nsString aAttrValue) {
    153    SetAttribute(aAttrName, std::move(aAttrValue));
    154  }
    155 
    156  template <typename T>
    157  Maybe<const T&> GetAttribute(nsAtom* aAttrName) const {
    158    if (auto value = mData.Lookup(aAttrName)) {
    159      if constexpr (std::is_same_v<nsString, T>) {
    160        if (value->is<UniquePtr<nsString>>()) {
    161          const T& val = *(value->as<UniquePtr<nsString>>().get());
    162          return SomeRef(val);
    163        }
    164      } else if constexpr (std::is_same_v<gfx::Matrix4x4, T>) {
    165        if (value->is<UniquePtr<gfx::Matrix4x4>>()) {
    166          const T& val = *(value->as<UniquePtr<gfx::Matrix4x4>>());
    167          return SomeRef(val);
    168        }
    169      } else if constexpr (std::is_same_v<nsRect, T>) {
    170        if (value->is<UniquePtr<nsRect>>()) {
    171          const T& val = *(value->as<UniquePtr<nsRect>>());
    172          return SomeRef(val);
    173        }
    174      } else {
    175        if (value->is<T>()) {
    176          const T& val = value->as<T>();
    177          return SomeRef(val);
    178        }
    179      }
    180    }
    181    return Nothing();
    182  }
    183 
    184  template <typename T>
    185  RefPtr<const T> GetAttributeRefPtr(nsAtom* aAttrName) const {
    186    if (auto value = mData.Lookup(aAttrName)) {
    187      if (value->is<RefPtr<T>>()) {
    188        RefPtr<const T> ref = value->as<RefPtr<T>>();
    189        return ref;
    190      }
    191    }
    192    return nullptr;
    193  }
    194 
    195  template <typename T>
    196  const T* GetAttributeWeakPtr(nsAtom* aAttrName) const {
    197    if (auto value = mData.Lookup(aAttrName)) {
    198      if (value->is<RefPtr<T>>()) {
    199        const T* ref = value->as<RefPtr<T>>();
    200        return ref;
    201      }
    202    }
    203    return nullptr;
    204  }
    205 
    206  template <typename T>
    207  Maybe<T&> GetMutableAttribute(nsAtom* aAttrName) const {
    208    static_assert(std::is_same_v<nsTArray<int32_t>, T> ||
    209                      std::is_same_v<nsTArray<uint64_t>, T> ||
    210                      std::is_same_v<nsTArray<RefPtr<nsAtom>>, T>,
    211                  "Only arrays should be mutable attributes");
    212    if (auto value = mData.Lookup(aAttrName)) {
    213      if (value->is<T>()) {
    214        T& val = value->as<T>();
    215        return SomeRef(val);
    216      }
    217    }
    218    return Nothing();
    219  }
    220 
    221  // Get stringified value
    222  bool GetAttribute(nsAtom* aAttrName, nsAString& aAttrValue) const;
    223 
    224  bool HasAttribute(nsAtom* aAttrName) const {
    225    return mData.Contains(aAttrName);
    226  }
    227 
    228  bool Remove(nsAtom* aAttrName) { return mData.Remove(aAttrName); }
    229 
    230  uint32_t Count() const { return mData.Count(); }
    231 
    232  // Update one instance with the entries in another. The supplied AccAttributes
    233  // will be emptied.
    234  void Update(AccAttributes* aOther);
    235 
    236  // Remove all entries that are identical to the supplied AccAttributes.
    237  void RemoveIdentical(const AccAttributes* aOther);
    238 
    239  /**
    240   * Return true if all the attributes in this instance are equal to all the
    241   * attributes in another instance.
    242   */
    243  bool Equal(const AccAttributes* aOther) const;
    244 
    245  /**
    246   * Copy attributes from this instance to another instance.
    247   * This should only be used in very specific cases; e.g. merging two sets of
    248   * cached attributes without modifying the cache. It can only copy simple
    249   * value types; e.g. it can't copy array values. Attempting to copy an
    250   * AccAttributes with uncopyable values will cause an assertion.
    251   * If aOnlyMissing is true, don't copy entries if destination already has
    252   * a given key.
    253   */
    254  void CopyTo(AccAttributes* aDest, bool aOnlyMissing = false) const;
    255 
    256  // An entry class for our iterator.
    257  class Entry {
    258   public:
    259    Entry(nsAtom* aAttrName, const AttrValueType* aAttrValue)
    260        : mName(aAttrName), mValue(aAttrValue) {}
    261 
    262    nsAtom* Name() const { return mName; }
    263 
    264    template <typename T>
    265    Maybe<const T&> Value() const {
    266      if constexpr (std::is_same_v<nsString, T>) {
    267        if (mValue->is<UniquePtr<nsString>>()) {
    268          const T& val = *(mValue->as<UniquePtr<nsString>>().get());
    269          return SomeRef(val);
    270        }
    271      } else if constexpr (std::is_same_v<gfx::Matrix4x4, T>) {
    272        if (mValue->is<UniquePtr<gfx::Matrix4x4>>()) {
    273          const T& val = *(mValue->as<UniquePtr<gfx::Matrix4x4>>());
    274          return SomeRef(val);
    275        }
    276      } else if constexpr (std::is_same_v<nsRect, T>) {
    277        if (mValue->is<UniquePtr<nsRect>>()) {
    278          const T& val = *(mValue->as<UniquePtr<nsRect>>());
    279          return SomeRef(val);
    280        }
    281      } else {
    282        if (mValue->is<T>()) {
    283          const T& val = mValue->as<T>();
    284          return SomeRef(val);
    285        }
    286      }
    287      return Nothing();
    288    }
    289 
    290    void NameAsString(nsString& aName) const {
    291      mName->ToString(aName);
    292      if (StringBeginsWith(aName, u"aria-"_ns)) {
    293        // Found 'aria-'
    294        aName.ReplaceLiteral(0, 5, u"");
    295      }
    296    }
    297 
    298    void ValueAsString(nsAString& aValueString) const {
    299      StringFromValueAndName(mName, *mValue, aValueString);
    300    }
    301 
    302    // Size of the pair in the hash table.
    303    size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf);
    304 
    305   private:
    306    nsAtom* mName;
    307    const AttrValueType* mValue;
    308 
    309    friend class AccAttributes;
    310  };
    311 
    312  class Iterator {
    313   public:
    314    explicit Iterator(AtomVariantMap::const_iterator aIter)
    315        : mHashIterator(aIter) {}
    316 
    317    Iterator() = delete;
    318    Iterator(const Iterator&) = delete;
    319    Iterator& operator=(const Iterator&) = delete;
    320 
    321    bool operator!=(const Iterator& aOther) const {
    322      return mHashIterator != aOther.mHashIterator;
    323    }
    324 
    325    Iterator& operator++() {
    326      mHashIterator++;
    327      return *this;
    328    }
    329 
    330    Entry operator*() const {
    331      auto& entry = *mHashIterator;
    332      return Entry(entry.GetKey(), &entry.GetData());
    333    }
    334 
    335   private:
    336    AtomVariantMap::const_iterator mHashIterator;
    337  };
    338 
    339  friend class Iterator;
    340 
    341  Iterator begin() const { return Iterator(mData.begin()); }
    342  Iterator end() const { return Iterator(mData.end()); }
    343 
    344 #ifdef A11Y_LOG
    345  static void DebugPrint(const char* aPrefix, const AccAttributes& aAttributes);
    346 #endif
    347 
    348  size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf);
    349 
    350 private:
    351  static void StringFromValueAndName(nsAtom* aAttrName,
    352                                     const AttrValueType& aValue,
    353                                     nsAString& aValueString);
    354 
    355  // Opts AccAttributes into the common ToString function.
    356  friend std::ostream& operator<<(std::ostream& aStream,
    357                                  const AccAttributes& aAttributes);
    358 
    359  AtomVariantMap mData;
    360 
    361  friend struct IPC::ParamTraits<AccAttributes*>;
    362 };
    363 
    364 }  // namespace a11y
    365 }  // namespace mozilla
    366 
    367 #endif