Backed out 9 changesets (bug 1846848) for causing multiple build bustages. CLOSED...
[gecko.git] / dom / base / nsTreeSanitizer.h
blobc360f03e126501bf9f8e14a351ad9063763560f6
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/Maybe.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;
32 class OwningStringOrSanitizerAttributeNamespace;
33 class OwningStringOrSanitizerElementNamespace;
34 class OwningStringOrSanitizerElementNamespaceWithAttributes;
35 } // namespace mozilla::dom
37 /**
38 * See the documentation of nsIParserUtils::sanitize for documentation
39 * about the default behavior and the configuration options of this sanitizer.
41 class nsTreeSanitizer {
42 public:
43 /**
44 * The constructor.
46 * @param aFlags Flags from nsIParserUtils
48 explicit nsTreeSanitizer(uint32_t aFlags = 0);
50 static void InitializeStatics();
51 static void ReleaseStatics();
53 /**
54 * Sanitizes a disconnected DOM fragment freshly obtained from a parser.
55 * The fragment must have just come from a parser so that it can't have
56 * mutation event listeners set on it.
58 void Sanitize(mozilla::dom::DocumentFragment* aFragment);
60 /**
61 * Sanitizes a disconnected (not in a docshell) document freshly obtained
62 * from a parser. The document must not be embedded in a docshell and must
63 * not have had a chance to get mutation event listeners attached to it.
64 * The root element must be <html>.
66 void Sanitize(mozilla::dom::Document* aDocument);
68 /**
69 * Provides additional options for usage from the Web Sanitizer API
70 * which allows modifying the allow-list from above
72 void WithWebSanitizerOptions(nsIGlobalObject* aGlobal,
73 const mozilla::dom::SanitizerConfig& aOptions,
74 mozilla::ErrorResult& aRv);
76 /**
77 * Removes conditional CSS from this subtree.
79 static void RemoveConditionalCSSFromSubtree(nsINode* aRoot);
81 private:
82 /**
83 * Whether <style> and style="" are allowed.
85 bool mAllowStyles;
87 /**
88 * Whether comment nodes are allowed.
90 bool mAllowComments;
92 /**
93 * Whether HTML <font>, <center>, bgcolor="", etc., are dropped.
95 bool mDropNonCSSPresentation;
97 /**
98 * Whether to remove forms and form controls (excluding fieldset/legend).
100 bool mDropForms;
103 * Whether only cid: embeds are allowed.
105 bool mCidEmbedsOnly;
108 * Whether to drop <img>, <video>, <audio> and <svg>.
110 bool mDropMedia;
113 * Whether we are sanitizing a full document (as opposed to a fragment).
115 bool mFullDocument;
118 * Whether we should notify to the console for anything that's stripped.
120 bool mLogRemovals;
122 // WindowID used for logging removals.
123 uint64_t mInnerWindowID = 0;
126 * We have various tables of static atoms for elements and attributes.
128 class AtomsTable : public nsTHashSet<const nsStaticAtom*> {
129 public:
130 explicit AtomsTable(uint32_t aLength)
131 : nsTHashSet<const nsStaticAtom*>(aLength) {}
133 bool Contains(nsAtom* aAtom) {
134 // Because this table only contains static atoms, if aAtom isn't
135 // static we can immediately fail.
136 return aAtom->IsStatic() && GetEntry(aAtom->AsStatic());
140 // The name of an element combined with its namespace.
141 class NamespaceAtom : public PLDHashEntryHdr {
142 public:
143 using KeyType = const NamespaceAtom&;
144 using KeyTypePointer = const NamespaceAtom*;
146 explicit NamespaceAtom(KeyTypePointer aKey)
147 : mNamespaceID(aKey->mNamespaceID), mLocalName(aKey->mLocalName) {}
148 NamespaceAtom(int32_t aNamespaceID, RefPtr<nsAtom> aLocalName)
149 : mNamespaceID(aNamespaceID), mLocalName(std::move(aLocalName)) {}
150 NamespaceAtom(NamespaceAtom&&) = default;
151 ~NamespaceAtom() = default;
153 bool KeyEquals(KeyTypePointer aKey) const {
154 return mNamespaceID == aKey->mNamespaceID &&
155 mLocalName == aKey->mLocalName;
158 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
159 static PLDHashNumber HashKey(KeyTypePointer aKey) {
160 if (!aKey) {
161 return 0;
164 return mozilla::HashGeneric(aKey->mNamespaceID, aKey->mLocalName.get());
167 enum { ALLOW_MEMMOVE = true };
169 private:
170 int32_t mNamespaceID = kNameSpaceID_None;
171 RefPtr<nsAtom> mLocalName;
174 using ElementName = NamespaceAtom;
175 using AttributeName = NamespaceAtom;
177 using ElementNameSet = nsTHashSet<ElementName>;
178 using AttributeNameSet = nsTHashSet<AttributeName>;
180 class ElementWithAttributes {
181 public:
182 mozilla::Maybe<AttributeNameSet> mAttributes;
183 mozilla::Maybe<AttributeNameSet> mRemoveAttributes;
186 using ElementsToAttributesMap =
187 nsTHashMap<ElementName, ElementWithAttributes>;
189 void SanitizeChildren(nsINode* aRoot);
192 * Queries if an element must be replaced with its children.
193 * @param aNamespace the namespace of the element the question is about
194 * @param aLocal the local name of the element the question is about
195 * @return true if the element must be replaced with its children and
196 * false if the element is to be kept
198 bool MustFlatten(int32_t aNamespace, nsAtom* aLocal);
199 bool MustFlattenForSanitizerAPI(int32_t aNamespace, nsAtom* aLocal);
202 * Queries if an element including its children must be removed.
203 * @param aNamespace the namespace of the element the question is about
204 * @param aLocal the local name of the element the question is about
205 * @param aElement the element node itself for inspecting attributes
206 * @return true if the element and its children must be removed and
207 * false if the element is to be kept
209 bool MustPrune(int32_t aNamespace, nsAtom* aLocal,
210 mozilla::dom::Element* aElement);
211 bool MustPruneForSanitizerAPI(int32_t aNamespace, nsAtom* aLocal,
212 mozilla::dom::Element* aElement);
215 * Checks if a given local name (for an attribute) is on the given list
216 * of URL attribute names.
217 * @param aURLs the list of URL attribute names
218 * @param aLocalName the name to search on the list
219 * @return true if aLocalName is on the aURLs list and false otherwise
221 bool IsURL(const nsStaticAtom* const* aURLs, nsAtom* aLocalName);
224 * Struct for what attributes and their values are allowed.
226 struct AllowedAttributes {
227 // The whitelist of permitted local names to use.
228 AtomsTable* mNames = nullptr;
229 // The local names of URL-valued attributes for URL checking.
230 const nsStaticAtom* const* mURLs = nullptr;
231 // Whether XLink attributes are allowed.
232 bool mXLink = false;
233 // Whether the style attribute is allowed.
234 bool mStyle = false;
235 // Whether to leave the value of the src attribute unsanitized.
236 bool mDangerousSrc = false;
240 * Removes dangerous attributes from the element. If the style attribute
241 * is allowed, its value is sanitized. The values of URL attributes are
242 * sanitized, except src isn't sanitized when it is allowed to remain
243 * potentially dangerous.
245 * @param aElement the element whose attributes should be sanitized
246 * @param aAllowed options for sanitizing attributes
248 void SanitizeAttributes(mozilla::dom::Element* aElement,
249 AllowedAttributes aAllowed);
250 // Currently only used for the Sanitizer API.
251 bool MustDropAttribute(mozilla::dom::Element* aElement,
252 int32_t aAttrNamespace, nsAtom* aAttrLocalName);
253 bool MustDropFunkyAttribute(mozilla::dom::Element* aElement,
254 int32_t aAttrNamespace, nsAtom* aAttrLocalName);
257 * Remove the named URL attribute from the element if the URL fails a
258 * security check.
260 * @param aElement the element whose attribute to possibly modify
261 * @param aNamespace the namespace of the URL attribute
262 * @param aLocalName the local name of the URL attribute
263 * @param aFragmentsOnly allows same-document references only
264 * @return true if the attribute was removed and false otherwise
266 bool SanitizeURL(mozilla::dom::Element* aElement, int32_t aNamespace,
267 nsAtom* aLocalName, bool aFragmentsOnly = false);
270 * Checks a style rule for the presence of the 'binding' CSS property and
271 * removes that property from the rule.
273 * @param aDeclaration The style declaration to check
274 * @return true if the rule was modified and false otherwise
276 bool SanitizeStyleDeclaration(mozilla::DeclarationBlock* aDeclaration);
279 * Sanitizes an inline style element (an HTML or SVG <style>).
281 * Returns whether the style has changed.
283 static bool SanitizeInlineStyle(mozilla::dom::Element*,
284 mozilla::StyleSanitizationKind);
287 * Removes all attributes from an element node.
289 static void RemoveAllAttributes(mozilla::dom::Element* aElement);
292 * Removes all attributes from the descendants of an element but not from
293 * the element itself.
295 static void RemoveAllAttributesFromDescendants(mozilla::dom::Element*);
297 static bool MatchesElementName(ElementNameSet& aNames, int32_t aNamespace,
298 nsAtom* aLocalName);
299 static bool MatchesAttributeName(AttributeNameSet& aNames, int32_t aNamespace,
300 nsAtom* aLocalName);
302 static ElementNameSet ConvertElements(
303 const nsTArray<mozilla::dom::OwningStringOrSanitizerElementNamespace>&
304 aElements,
305 mozilla::ErrorResult& aRv);
307 static ElementsToAttributesMap ConvertElementsWithAttributes(
308 const nsTArray<
309 mozilla::dom::OwningStringOrSanitizerElementNamespaceWithAttributes>&
310 aElements,
311 mozilla::ErrorResult& aRv);
313 static AttributeNameSet ConvertAttributes(
314 const nsTArray<mozilla::dom::OwningStringOrSanitizerAttributeNamespace>&
315 aAttributes,
316 mozilla::ErrorResult& aRv);
319 * Log a Console Service message to indicate we removed something.
320 * If you pass an element and/or attribute, their information will
321 * be appended to the message.
323 * @param aMessage the basic message to log.
324 * @param aDocument the base document we're modifying
325 * (used for the error message)
326 * @param aElement optional, the element being removed or modified.
327 * @param aAttribute optional, the attribute being removed or modified.
329 void LogMessage(const char* aMessage, mozilla::dom::Document* aDoc,
330 mozilla::dom::Element* aElement = nullptr,
331 nsAtom* aAttr = nullptr);
334 * The whitelist of HTML elements.
336 static AtomsTable* sElementsHTML;
339 * The whitelist of non-presentational HTML attributes.
341 static AtomsTable* sAttributesHTML;
344 * The whitelist of presentational HTML attributes.
346 static AtomsTable* sPresAttributesHTML;
349 * The whitelist of SVG elements.
351 static AtomsTable* sElementsSVG;
354 * The whitelist of SVG attributes.
356 static AtomsTable* sAttributesSVG;
359 * The whitelist of SVG elements.
361 static AtomsTable* sElementsMathML;
364 * The whitelist of MathML attributes.
366 static AtomsTable* sAttributesMathML;
369 * The built-in baseline attribute allow list used by the Sanitizer API.
371 static AtomsTable* sBaselineAttributeAllowlist;
374 * The built-in baseline element allow list used by the Sanitizer API.
376 static AtomsTable* sBaselineElementAllowlist;
379 * The default configuration's attribute allow list used by the Sanitizer API.
381 static AtomsTable* sDefaultConfigurationAttributeAllowlist;
384 * The default configuration's element allow list used by the Sanitizer API.
386 static AtomsTable* sDefaultConfigurationElementAllowlist;
389 * Reusable null principal for URL checks.
391 static nsIPrincipal* sNullPrincipal;
393 // === Variables used to implement HTML Sanitizer API. ==
395 // This nsTreeSanitizer instance should behave like the Sanitizer API.
396 bool mIsForSanitizerAPI = false;
398 bool mAllowCustomElements = false;
399 bool mAllowUnknownMarkup = false;
401 // An allow-list of elements to keep, with potentially associated lists of
402 // attributes to keep/remove.
403 mozilla::Maybe<ElementsToAttributesMap> mElements;
405 // A deny-list of elements to remove. (aka prune)
406 mozilla::Maybe<ElementNameSet> mRemoveElements;
408 // A deny-list of elements to replace with children. (aka flatten)
409 mozilla::Maybe<ElementNameSet> mReplaceWithChildrenElements;
411 // An allow-list of attributes to keep.
412 mozilla::Maybe<AttributeNameSet> mAttributes;
414 // A deny-list of attributes to remove.
415 mozilla::Maybe<AttributeNameSet> mRemoveAttributes;
418 #endif // nsTreeSanitizer_h_