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