Bug 1852740: add tests for the `fetchpriority` attribute in Link headers. r=necko...
[gecko.git] / dom / base / nsTreeSanitizer.h
blobed1c49c60ca523e73c10bd5b3fd7c26a1453a3d8
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/. */
5 #ifndef nsTreeSanitizer_h_
6 #define nsTreeSanitizer_h_
8 #include "nsAtom.h"
9 #include "nsHashKeys.h"
10 #include "nsHashtablesFwd.h"
11 #include "nsIPrincipal.h"
12 #include "nsTArray.h"
13 #include "nsTHashSet.h"
14 #include "mozilla/UniquePtr.h"
15 #include "mozilla/dom/NameSpaceConstants.h"
16 #include "mozilla/dom/SanitizerBinding.h"
18 class nsIContent;
19 class nsIGlobalObject;
20 class nsINode;
22 namespace mozilla {
23 class DeclarationBlock;
24 class ErrorResult;
25 enum class StyleSanitizationKind : uint8_t;
26 } // namespace mozilla
28 namespace mozilla::dom {
29 class DocumentFragment;
30 class Element;
31 class OwningStringOrSanitizerElementNameNamespace;
32 struct SanitizerAttribute;
33 } // namespace mozilla::dom
35 /**
36 * See the documentation of nsIParserUtils::sanitize for documentation
37 * about the default behavior and the configuration options of this sanitizer.
39 class nsTreeSanitizer {
40 public:
41 /**
42 * The constructor.
44 * @param aFlags Flags from nsIParserUtils
46 explicit nsTreeSanitizer(uint32_t aFlags = 0);
48 static void InitializeStatics();
49 static void ReleaseStatics();
51 /**
52 * Sanitizes a disconnected DOM fragment freshly obtained from a parser.
53 * The fragment must have just come from a parser so that it can't have
54 * mutation event listeners set on it.
56 void Sanitize(mozilla::dom::DocumentFragment* aFragment);
58 /**
59 * Sanitizes a disconnected (not in a docshell) document freshly obtained
60 * from a parser. The document must not be embedded in a docshell and must
61 * not have had a chance to get mutation event listeners attached to it.
62 * The root element must be <html>.
64 void Sanitize(mozilla::dom::Document* aDocument);
66 /**
67 * Provides additional options for usage from the Web Sanitizer API
68 * which allows modifying the allow-list from above
70 void WithWebSanitizerOptions(nsIGlobalObject* aGlobal,
71 const mozilla::dom::SanitizerConfig& aOptions,
72 mozilla::ErrorResult& aRv);
74 /**
75 * Removes conditional CSS from this subtree.
77 static void RemoveConditionalCSSFromSubtree(nsINode* aRoot);
79 private:
80 /**
81 * Whether <style> and style="" are allowed.
83 bool mAllowStyles;
85 /**
86 * Whether comment nodes are allowed.
88 bool mAllowComments;
90 /**
91 * Whether HTML <font>, <center>, bgcolor="", etc., are dropped.
93 bool mDropNonCSSPresentation;
95 /**
96 * Whether to remove forms and form controls (excluding fieldset/legend).
98 bool mDropForms;
101 * Whether only cid: embeds are allowed.
103 bool mCidEmbedsOnly;
106 * Whether to drop <img>, <video>, <audio> and <svg>.
108 bool mDropMedia;
111 * Whether we are sanitizing a full document (as opposed to a fragment).
113 bool mFullDocument;
116 * Whether we should notify to the console for anything that's stripped.
118 bool mLogRemovals;
120 // WindowID used for logging removals.
121 uint64_t mInnerWindowID = 0;
124 * We have various tables of static atoms for elements and attributes.
126 class AtomsTable : public nsTHashSet<const nsStaticAtom*> {
127 public:
128 explicit AtomsTable(uint32_t aLength)
129 : nsTHashSet<const nsStaticAtom*>(aLength) {}
131 bool Contains(nsAtom* aAtom) {
132 // Because this table only contains static atoms, if aAtom isn't
133 // static we can immediately fail.
134 return aAtom->IsStatic() && GetEntry(aAtom->AsStatic());
138 // The name of an element combined with its namespace.
139 class NamespaceAtom : public PLDHashEntryHdr {
140 public:
141 using KeyType = const NamespaceAtom&;
142 using KeyTypePointer = const NamespaceAtom*;
144 explicit NamespaceAtom(KeyTypePointer aKey)
145 : mNamespaceID(aKey->mNamespaceID), mLocalName(aKey->mLocalName) {}
146 NamespaceAtom(int32_t aNamespaceID, RefPtr<nsAtom> aLocalName)
147 : mNamespaceID(aNamespaceID), mLocalName(std::move(aLocalName)) {}
148 NamespaceAtom(NamespaceAtom&&) = default;
149 ~NamespaceAtom() = default;
151 bool KeyEquals(KeyTypePointer aKey) const {
152 return mNamespaceID == aKey->mNamespaceID &&
153 mLocalName == aKey->mLocalName;
156 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
157 static PLDHashNumber HashKey(KeyTypePointer aKey) {
158 if (!aKey) {
159 return 0;
162 return mozilla::HashGeneric(aKey->mNamespaceID, aKey->mLocalName.get());
165 enum { ALLOW_MEMMOVE = true };
167 private:
168 int32_t mNamespaceID = kNameSpaceID_None;
169 RefPtr<nsAtom> mLocalName;
172 using ElementName = NamespaceAtom;
173 using AttributeName = NamespaceAtom;
175 using ElementNameSet = nsTHashSet<ElementName>;
176 // nullptr value (ElementNameSet) means all elements (*).
177 using AttributesToElementsMap =
178 nsTHashMap<AttributeName, mozilla::UniquePtr<ElementNameSet>>;
180 void SanitizeChildren(nsINode* aRoot);
183 * Queries if an element must be replaced with its children.
184 * @param aNamespace the namespace of the element the question is about
185 * @param aLocal the local name of the element the question is about
186 * @return true if the element must be replaced with its children and
187 * false if the element is to be kept
189 bool MustFlatten(int32_t aNamespace, nsAtom* aLocal);
190 bool MustFlattenForSanitizerAPI(int32_t aNamespace, nsAtom* aLocal);
193 * Queries if an element including its children must be removed.
194 * @param aNamespace the namespace of the element the question is about
195 * @param aLocal the local name of the element the question is about
196 * @param aElement the element node itself for inspecting attributes
197 * @return true if the element and its children must be removed and
198 * false if the element is to be kept
200 bool MustPrune(int32_t aNamespace, nsAtom* aLocal,
201 mozilla::dom::Element* aElement);
202 bool MustPruneForSanitizerAPI(int32_t aNamespace, nsAtom* aLocal,
203 mozilla::dom::Element* aElement);
206 * Checks if a given local name (for an attribute) is on the given list
207 * of URL attribute names.
208 * @param aURLs the list of URL attribute names
209 * @param aLocalName the name to search on the list
210 * @return true if aLocalName is on the aURLs list and false otherwise
212 bool IsURL(const nsStaticAtom* const* aURLs, nsAtom* aLocalName);
215 * Struct for what attributes and their values are allowed.
217 struct AllowedAttributes {
218 // The whitelist of permitted local names to use.
219 AtomsTable* mNames = nullptr;
220 // The local names of URL-valued attributes for URL checking.
221 const nsStaticAtom* const* mURLs = nullptr;
222 // Whether XLink attributes are allowed.
223 bool mXLink = false;
224 // Whether the style attribute is allowed.
225 bool mStyle = false;
226 // Whether to leave the value of the src attribute unsanitized.
227 bool mDangerousSrc = false;
231 * Removes dangerous attributes from the element. If the style attribute
232 * is allowed, its value is sanitized. The values of URL attributes are
233 * sanitized, except src isn't sanitized when it is allowed to remain
234 * potentially dangerous.
236 * @param aElement the element whose attributes should be sanitized
237 * @param aAllowed options for sanitizing attributes
239 void SanitizeAttributes(mozilla::dom::Element* aElement,
240 AllowedAttributes aAllowed);
241 // Currently only used for the Sanitizer API.
242 bool MustDropAttribute(mozilla::dom::Element* aElement,
243 int32_t aAttrNamespace, nsAtom* aAttrLocalName);
244 bool MustDropFunkyAttribute(mozilla::dom::Element* aElement,
245 int32_t aAttrNamespace, nsAtom* aAttrLocalName);
248 * Remove the named URL attribute from the element if the URL fails a
249 * security check.
251 * @param aElement the element whose attribute to possibly modify
252 * @param aNamespace the namespace of the URL attribute
253 * @param aLocalName the local name of the URL attribute
254 * @param aFragmentsOnly allows same-document references only
255 * @return true if the attribute was removed and false otherwise
257 bool SanitizeURL(mozilla::dom::Element* aElement, int32_t aNamespace,
258 nsAtom* aLocalName, bool aFragmentsOnly = false);
261 * Checks a style rule for the presence of the 'binding' CSS property and
262 * removes that property from the rule.
264 * @param aDeclaration The style declaration to check
265 * @return true if the rule was modified and false otherwise
267 bool SanitizeStyleDeclaration(mozilla::DeclarationBlock* aDeclaration);
270 * Sanitizes an inline style element (an HTML or SVG <style>).
272 * Returns whether the style has changed.
274 static bool SanitizeInlineStyle(mozilla::dom::Element*,
275 mozilla::StyleSanitizationKind);
278 * Removes all attributes from an element node.
280 static void RemoveAllAttributes(mozilla::dom::Element* aElement);
283 * Removes all attributes from the descendants of an element but not from
284 * the element itself.
286 static void RemoveAllAttributesFromDescendants(mozilla::dom::Element*);
288 static bool MatchesElementName(ElementNameSet& aNames, int32_t aNamespace,
289 nsAtom* aLocalName);
290 static bool MatchesAttributeMatchList(AttributesToElementsMap& aMatchList,
291 mozilla::dom::Element& aElement,
292 int32_t aAttrNamespace,
293 nsAtom* aAttrLocalName);
295 static mozilla::UniquePtr<ElementNameSet> ConvertElements(
296 const nsTArray<mozilla::dom::OwningStringOrSanitizerElementNamespace>&
297 aElements,
298 mozilla::ErrorResult& aRv);
300 static mozilla::UniquePtr<ElementNameSet> ConvertElements(
301 const mozilla::dom::OwningStarOrStringOrSanitizerElementNamespaceSequence&
302 aElements,
303 mozilla::ErrorResult& aRv);
305 static mozilla::UniquePtr<AttributesToElementsMap> ConvertAttributes(
306 const nsTArray<mozilla::dom::SanitizerAttribute>& aAttributes,
307 mozilla::ErrorResult& aRv);
310 * Log a Console Service message to indicate we removed something.
311 * If you pass an element and/or attribute, their information will
312 * be appended to the message.
314 * @param aMessage the basic message to log.
315 * @param aDocument the base document we're modifying
316 * (used for the error message)
317 * @param aElement optional, the element being removed or modified.
318 * @param aAttribute optional, the attribute being removed or modified.
320 void LogMessage(const char* aMessage, mozilla::dom::Document* aDoc,
321 mozilla::dom::Element* aElement = nullptr,
322 nsAtom* aAttr = nullptr);
325 * The whitelist of HTML elements.
327 static AtomsTable* sElementsHTML;
330 * The whitelist of non-presentational HTML attributes.
332 static AtomsTable* sAttributesHTML;
335 * The whitelist of presentational HTML attributes.
337 static AtomsTable* sPresAttributesHTML;
340 * The whitelist of SVG elements.
342 static AtomsTable* sElementsSVG;
345 * The whitelist of SVG attributes.
347 static AtomsTable* sAttributesSVG;
350 * The whitelist of SVG elements.
352 static AtomsTable* sElementsMathML;
355 * The whitelist of MathML attributes.
357 static AtomsTable* sAttributesMathML;
360 * The built-in baseline attribute allow list used by the Sanitizer API.
362 static AtomsTable* sBaselineAttributeAllowlist;
365 * The built-in baseline element allow list used by the Sanitizer API.
367 static AtomsTable* sBaselineElementAllowlist;
370 * The default configuration's attribute allow list used by the Sanitizer API.
372 static AtomsTable* sDefaultConfigurationAttributeAllowlist;
375 * The default configuration's element allow list used by the Sanitizer API.
377 static AtomsTable* sDefaultConfigurationElementAllowlist;
380 * Reusable null principal for URL checks.
382 static nsIPrincipal* sNullPrincipal;
384 // === Variables used to implement HTML Sanitizer API. ==
386 // This nsTreeSanitizer instance should behave like the Sanitizer API.
387 bool mIsForSanitizerAPI = false;
389 bool mAllowCustomElements = false;
390 bool mAllowUnknownMarkup = false;
392 // An allow-list of elements to keep.
393 mozilla::UniquePtr<ElementNameSet> mAllowElements;
395 // A deny-list of elements to block. (aka flatten)
396 mozilla::UniquePtr<ElementNameSet> mBlockElements;
398 // A deny-list of elements to drop. (aka prune)
399 mozilla::UniquePtr<ElementNameSet> mDropElements;
401 // An allow-list of attributes to keep.
402 mozilla::UniquePtr<AttributesToElementsMap> mAllowAttributes;
404 // A deny-list of attributes to drop.
405 mozilla::UniquePtr<AttributesToElementsMap> mDropAttributes;
408 #endif // nsTreeSanitizer_h_