tor-browser

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

SanitizerTypes.h (7377B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #ifndef mozilla_dom_SanitizerTypes_h
      6 #define mozilla_dom_SanitizerTypes_h
      7 
      8 #include "fmt/format.h"
      9 #include "mozilla/Maybe.h"
     10 #include "mozilla/dom/SanitizerBinding.h"
     11 #include "nsHashtablesFwd.h"
     12 #include "nsTHashSet.h"
     13 
     14 namespace mozilla::dom::sanitizer {
     15 
     16 struct CanonicalElementAttributes;
     17 
     18 class CanonicalAttribute : public PLDHashEntryHdr {
     19 public:
     20  using KeyType = const CanonicalAttribute&;
     21  using KeyTypePointer = const CanonicalAttribute*;
     22 
     23  explicit CanonicalAttribute(const CanonicalAttribute* aKey)
     24      : mLocalName(aKey->mLocalName), mNamespace(aKey->mNamespace) {}
     25  CanonicalAttribute(RefPtr<nsAtom> aLocalName, RefPtr<nsAtom> aNamespace)
     26      : mLocalName(std::move(aLocalName)), mNamespace(std::move(aNamespace)) {}
     27  CanonicalAttribute(nsStaticAtom* aLocalName, nsStaticAtom* aNamespace)
     28      : mLocalName(aLocalName), mNamespace(aNamespace) {}
     29  CanonicalAttribute(CanonicalAttribute&&) = default;
     30  ~CanonicalAttribute() = default;
     31 
     32  KeyType GetKey() const { return *this; }
     33  bool KeyEquals(const CanonicalAttribute* aKey) const {
     34    return mLocalName == aKey->mLocalName && mNamespace == aKey->mNamespace;
     35  }
     36 
     37  static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
     38  static PLDHashNumber HashKey(KeyTypePointer aKey) {
     39    return mozilla::HashGeneric(aKey->mLocalName.get(), aKey->mNamespace.get());
     40  }
     41 
     42  enum { ALLOW_MEMMOVE = true };
     43 
     44  // Returns true for names that start with data-* and have a null namespace.
     45  bool IsDataAttribute() const;
     46  SanitizerAttributeNamespace ToSanitizerAttributeNamespace() const;
     47 
     48  CanonicalAttribute Clone() const {
     49    return CanonicalAttribute(mLocalName, mNamespace);
     50  }
     51 
     52  nsAtom* LocalName() const { return mLocalName; }
     53  nsAtom* GetNamespace() const { return mNamespace; }
     54 
     55 protected:
     56  friend std::ostream& operator<<(std::ostream& aStream,
     57                                  const CanonicalAttribute& aName);
     58  RefPtr<nsAtom> mLocalName;
     59  // A "null" namespace is represented by the nullptr.
     60  RefPtr<nsAtom> mNamespace;
     61 };
     62 
     63 class CanonicalElement : public PLDHashEntryHdr {
     64 public:
     65  using KeyType = const CanonicalElement&;
     66  using KeyTypePointer = const CanonicalElement*;
     67 
     68  explicit CanonicalElement(const CanonicalElement* aKey)
     69      : mLocalName(aKey->mLocalName), mNamespace(aKey->mNamespace) {}
     70  CanonicalElement(RefPtr<nsAtom> aLocalName, RefPtr<nsAtom> aNamespace)
     71      : mLocalName(std::move(aLocalName)), mNamespace(std::move(aNamespace)) {}
     72  CanonicalElement(nsStaticAtom* aLocalName, nsStaticAtom* aNamespace)
     73      : mLocalName(aLocalName), mNamespace(aNamespace) {}
     74  CanonicalElement(CanonicalElement&&) = default;
     75  ~CanonicalElement() = default;
     76 
     77  KeyType GetKey() const { return *this; }
     78  bool KeyEquals(const CanonicalElement* aKey) const {
     79    return mLocalName == aKey->mLocalName && mNamespace == aKey->mNamespace;
     80  }
     81 
     82  static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
     83  static PLDHashNumber HashKey(KeyTypePointer aKey) {
     84    return mozilla::HashGeneric(aKey->mLocalName.get(), aKey->mNamespace.get());
     85  }
     86 
     87  enum { ALLOW_MEMMOVE = true };
     88 
     89  SanitizerElementNamespace ToSanitizerElementNamespace() const;
     90  SanitizerElementNamespaceWithAttributes
     91  ToSanitizerElementNamespaceWithAttributes(
     92      const CanonicalElementAttributes& aElementAttributes) const;
     93 
     94  nsAtom* LocalName() const { return mLocalName; }
     95  nsAtom* GetNamespace() const { return mNamespace; }
     96 
     97 protected:
     98  friend std::ostream& operator<<(std::ostream& aStream,
     99                                  const CanonicalElement& aName);
    100 
    101  RefPtr<nsAtom> mLocalName;
    102  // A "null" namespace is represented by the nullptr.
    103  RefPtr<nsAtom> mNamespace;
    104 };
    105 
    106 std::ostream& operator<<(std::ostream& aStream,
    107                         const CanonicalAttribute& aName);
    108 std::ostream& operator<<(std::ostream& aStream, const CanonicalElement& aName);
    109 
    110 using CanonicalAttributeSet = nsTHashSet<CanonicalAttribute>;
    111 using CanonicalElementSet = nsTHashSet<CanonicalElement>;
    112 
    113 struct CanonicalElementAttributes {
    114  Maybe<CanonicalAttributeSet> mAttributes;
    115  Maybe<CanonicalAttributeSet> mRemoveAttributes;
    116 
    117  bool Equals(const CanonicalElementAttributes& aOther) const;
    118 };
    119 
    120 using CanonicalElementMap =
    121    nsTHashMap<CanonicalElement, CanonicalElementAttributes>;
    122 
    123 nsTArray<OwningStringOrSanitizerAttributeNamespace> ToSanitizerAttributes(
    124    const CanonicalAttributeSet& aSet);
    125 
    126 inline const auto& GetAsDictionary(
    127    const OwningStringOrSanitizerAttributeNamespace& aOwning) {
    128  return aOwning.GetAsSanitizerAttributeNamespace();
    129 }
    130 
    131 inline const auto& GetAsDictionary(
    132    const OwningStringOrSanitizerElementNamespace& aOwning) {
    133  return aOwning.GetAsSanitizerElementNamespace();
    134 }
    135 
    136 inline const auto& GetAsDictionary(
    137    const OwningStringOrSanitizerElementNamespaceWithAttributes& aOwning) {
    138  return aOwning.GetAsSanitizerElementNamespaceWithAttributes();
    139 }
    140 
    141 inline const auto& GetAsDictionary(
    142    const StringOrSanitizerElementNamespace& aElement) {
    143  return aElement.GetAsSanitizerElementNamespace();
    144 }
    145 
    146 inline const auto& GetAsDictionary(
    147    const StringOrSanitizerElementNamespaceWithAttributes& aElement) {
    148  return aElement.GetAsSanitizerElementNamespaceWithAttributes();
    149 }
    150 
    151 template <typename SanitizerNameNamespace>
    152 class MOZ_STACK_CLASS SanitizerComparator final {
    153 public:
    154  bool Equals(const SanitizerNameNamespace& aItemA,
    155              const SanitizerNameNamespace& aItemB) const {
    156    const auto& itemA = GetAsDictionary(aItemA);
    157    const auto& itemB = GetAsDictionary(aItemB);
    158 
    159    return itemA.mNamespace.IsVoid() == itemB.mNamespace.IsVoid() &&
    160           itemA.mNamespace == itemB.mNamespace && itemA.mName == itemB.mName;
    161  }
    162 
    163  // https://wicg.github.io/sanitizer-api/#sanitizerconfig-less-than-item
    164  bool LessThan(const SanitizerNameNamespace& aItemA,
    165                const SanitizerNameNamespace& aItemB) const {
    166    const auto& itemA = GetAsDictionary(aItemA);
    167    const auto& itemB = GetAsDictionary(aItemB);
    168 
    169    // Step 1. If itemA["namespace"] is null:
    170    if (itemA.mNamespace.IsVoid()) {
    171      // Step 1.1. If itemB["namespace"] is not null, return true.
    172      if (!itemB.mNamespace.IsVoid()) {
    173        return true;
    174      }
    175    } else {
    176      // Step 2. Otherwise:
    177      // Step 2.1. If itemB["namespace"] is null, return false.
    178      if (itemB.mNamespace.IsVoid()) {
    179        return false;
    180      }
    181 
    182      int result = Compare(itemA.mNamespace, itemB.mNamespace);
    183      // Step 2.2. If itemA["namespace"] is code unit less than
    184      // itemB["namespace"], return true.
    185      if (result < 0) {
    186        return true;
    187      }
    188      // Step 2.3. If itemA["namespace"] is not equal itemB["namespace"], return
    189      // false.
    190      // XXX https://github.com/WICG/sanitizer-api/pull/341
    191      if (result != 0) {
    192        return false;
    193      }
    194    }
    195 
    196    // Step 3. Return itemA["name"] is code unit less thanitemB["name"].
    197    return itemA.mName < itemB.mName;
    198  }
    199 };
    200 
    201 }  // namespace mozilla::dom::sanitizer
    202 
    203 template <>
    204 struct fmt::formatter<mozilla::dom::sanitizer::CanonicalAttribute>
    205    : ostream_formatter {};
    206 
    207 template <>
    208 struct fmt::formatter<mozilla::dom::sanitizer::CanonicalElement>
    209    : ostream_formatter {};
    210 
    211 #endif