зеркало из https://github.com/mozilla/gecko-dev.git
2601 строка
92 KiB
C++
2601 строка
92 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||
|
||
#include "nsTreeSanitizer.h"
|
||
|
||
#include "mozilla/Algorithm.h"
|
||
#include "mozilla/ArrayUtils.h"
|
||
#include "mozilla/BindingStyleRule.h"
|
||
#include "mozilla/DeclarationBlock.h"
|
||
#include "mozilla/StaticPrefs_dom.h"
|
||
#include "mozilla/StyleSheetInlines.h"
|
||
#include "mozilla/UniquePtr.h"
|
||
#include "mozilla/css/Rule.h"
|
||
#include "mozilla/dom/CSSRuleList.h"
|
||
#include "mozilla/dom/DocumentFragment.h"
|
||
#include "mozilla/dom/HTMLFormElement.h"
|
||
#include "mozilla/dom/HTMLTemplateElement.h"
|
||
#include "mozilla/dom/HTMLUnknownElement.h"
|
||
#include "mozilla/dom/Link.h"
|
||
#include "mozilla/dom/SanitizerBinding.h"
|
||
#include "mozilla/dom/ShadowIncludingTreeIterator.h"
|
||
#include "mozilla/dom/SRIMetadata.h"
|
||
#include "mozilla/NullPrincipal.h"
|
||
#include "nsAtom.h"
|
||
#include "nsCSSPropertyID.h"
|
||
#include "nsHashtablesFwd.h"
|
||
#include "nsString.h"
|
||
#include "nsTHashtable.h"
|
||
#include "nsUnicharInputStream.h"
|
||
#include "nsAttrName.h"
|
||
#include "nsIScriptError.h"
|
||
#include "nsIScriptSecurityManager.h"
|
||
#include "nsNameSpaceManager.h"
|
||
#include "nsNetUtil.h"
|
||
#include "nsComponentManagerUtils.h"
|
||
#include "nsContentUtils.h"
|
||
#include "nsIParserUtils.h"
|
||
#include "mozilla/dom/Document.h"
|
||
#include "nsQueryObject.h"
|
||
|
||
#include <iterator>
|
||
|
||
using namespace mozilla;
|
||
using namespace mozilla::dom;
|
||
|
||
//
|
||
// Thanks to Mark Pilgrim and Sam Ruby for the initial whitelist
|
||
//
|
||
const nsStaticAtom* const kElementsHTML[] = {
|
||
// clang-format off
|
||
nsGkAtoms::a,
|
||
nsGkAtoms::abbr,
|
||
nsGkAtoms::acronym,
|
||
nsGkAtoms::address,
|
||
nsGkAtoms::area,
|
||
nsGkAtoms::article,
|
||
nsGkAtoms::aside,
|
||
nsGkAtoms::audio,
|
||
nsGkAtoms::b,
|
||
nsGkAtoms::bdi,
|
||
nsGkAtoms::bdo,
|
||
nsGkAtoms::big,
|
||
nsGkAtoms::blockquote,
|
||
// body checked specially
|
||
nsGkAtoms::br,
|
||
nsGkAtoms::button,
|
||
nsGkAtoms::canvas,
|
||
nsGkAtoms::caption,
|
||
nsGkAtoms::center,
|
||
nsGkAtoms::cite,
|
||
nsGkAtoms::code,
|
||
nsGkAtoms::col,
|
||
nsGkAtoms::colgroup,
|
||
nsGkAtoms::data,
|
||
nsGkAtoms::datalist,
|
||
nsGkAtoms::dd,
|
||
nsGkAtoms::del,
|
||
nsGkAtoms::details,
|
||
nsGkAtoms::dfn,
|
||
nsGkAtoms::dialog,
|
||
nsGkAtoms::dir,
|
||
nsGkAtoms::div,
|
||
nsGkAtoms::dl,
|
||
nsGkAtoms::dt,
|
||
nsGkAtoms::em,
|
||
nsGkAtoms::fieldset,
|
||
nsGkAtoms::figcaption,
|
||
nsGkAtoms::figure,
|
||
nsGkAtoms::font,
|
||
nsGkAtoms::footer,
|
||
nsGkAtoms::form,
|
||
nsGkAtoms::h1,
|
||
nsGkAtoms::h2,
|
||
nsGkAtoms::h3,
|
||
nsGkAtoms::h4,
|
||
nsGkAtoms::h5,
|
||
nsGkAtoms::h6,
|
||
// head checked specially
|
||
nsGkAtoms::header,
|
||
nsGkAtoms::hgroup,
|
||
nsGkAtoms::hr,
|
||
// html checked specially
|
||
nsGkAtoms::i,
|
||
nsGkAtoms::img,
|
||
nsGkAtoms::input,
|
||
nsGkAtoms::ins,
|
||
nsGkAtoms::kbd,
|
||
nsGkAtoms::keygen,
|
||
nsGkAtoms::label,
|
||
nsGkAtoms::legend,
|
||
nsGkAtoms::li,
|
||
nsGkAtoms::link,
|
||
nsGkAtoms::listing,
|
||
nsGkAtoms::main,
|
||
nsGkAtoms::map,
|
||
nsGkAtoms::mark,
|
||
nsGkAtoms::menu,
|
||
nsGkAtoms::meta,
|
||
nsGkAtoms::meter,
|
||
nsGkAtoms::nav,
|
||
nsGkAtoms::nobr,
|
||
nsGkAtoms::noscript,
|
||
nsGkAtoms::ol,
|
||
nsGkAtoms::optgroup,
|
||
nsGkAtoms::option,
|
||
nsGkAtoms::output,
|
||
nsGkAtoms::p,
|
||
nsGkAtoms::picture,
|
||
nsGkAtoms::pre,
|
||
nsGkAtoms::progress,
|
||
nsGkAtoms::q,
|
||
nsGkAtoms::rb,
|
||
nsGkAtoms::rp,
|
||
nsGkAtoms::rt,
|
||
nsGkAtoms::rtc,
|
||
nsGkAtoms::ruby,
|
||
nsGkAtoms::s,
|
||
nsGkAtoms::samp,
|
||
nsGkAtoms::section,
|
||
nsGkAtoms::select,
|
||
nsGkAtoms::small,
|
||
nsGkAtoms::source,
|
||
nsGkAtoms::span,
|
||
nsGkAtoms::strike,
|
||
nsGkAtoms::strong,
|
||
nsGkAtoms::sub,
|
||
nsGkAtoms::summary,
|
||
nsGkAtoms::sup,
|
||
// style checked specially
|
||
nsGkAtoms::table,
|
||
nsGkAtoms::tbody,
|
||
nsGkAtoms::td,
|
||
// template checked and traversed specially
|
||
nsGkAtoms::textarea,
|
||
nsGkAtoms::tfoot,
|
||
nsGkAtoms::th,
|
||
nsGkAtoms::thead,
|
||
nsGkAtoms::time,
|
||
// title checked specially
|
||
nsGkAtoms::tr,
|
||
nsGkAtoms::track,
|
||
nsGkAtoms::tt,
|
||
nsGkAtoms::u,
|
||
nsGkAtoms::ul,
|
||
nsGkAtoms::var,
|
||
nsGkAtoms::video,
|
||
nsGkAtoms::wbr,
|
||
nullptr
|
||
// clang-format on
|
||
};
|
||
|
||
const nsStaticAtom* const kAttributesHTML[] = {
|
||
// clang-format off
|
||
nsGkAtoms::abbr,
|
||
nsGkAtoms::accept,
|
||
nsGkAtoms::acceptcharset,
|
||
nsGkAtoms::accesskey,
|
||
nsGkAtoms::action,
|
||
nsGkAtoms::alt,
|
||
nsGkAtoms::as,
|
||
nsGkAtoms::autocomplete,
|
||
nsGkAtoms::autofocus,
|
||
nsGkAtoms::autoplay,
|
||
nsGkAtoms::axis,
|
||
nsGkAtoms::_char,
|
||
nsGkAtoms::charoff,
|
||
nsGkAtoms::charset,
|
||
nsGkAtoms::checked,
|
||
nsGkAtoms::cite,
|
||
nsGkAtoms::_class,
|
||
nsGkAtoms::cols,
|
||
nsGkAtoms::colspan,
|
||
nsGkAtoms::content,
|
||
nsGkAtoms::contenteditable,
|
||
nsGkAtoms::contextmenu,
|
||
nsGkAtoms::controls,
|
||
nsGkAtoms::coords,
|
||
nsGkAtoms::crossorigin,
|
||
nsGkAtoms::datetime,
|
||
nsGkAtoms::dir,
|
||
nsGkAtoms::disabled,
|
||
nsGkAtoms::draggable,
|
||
nsGkAtoms::enctype,
|
||
nsGkAtoms::face,
|
||
nsGkAtoms::_for,
|
||
nsGkAtoms::frame,
|
||
nsGkAtoms::headers,
|
||
nsGkAtoms::height,
|
||
nsGkAtoms::hidden,
|
||
nsGkAtoms::high,
|
||
nsGkAtoms::href,
|
||
nsGkAtoms::hreflang,
|
||
nsGkAtoms::icon,
|
||
nsGkAtoms::id,
|
||
nsGkAtoms::integrity,
|
||
nsGkAtoms::ismap,
|
||
nsGkAtoms::itemid,
|
||
nsGkAtoms::itemprop,
|
||
nsGkAtoms::itemref,
|
||
nsGkAtoms::itemscope,
|
||
nsGkAtoms::itemtype,
|
||
nsGkAtoms::kind,
|
||
nsGkAtoms::label,
|
||
nsGkAtoms::lang,
|
||
nsGkAtoms::list_,
|
||
nsGkAtoms::longdesc,
|
||
nsGkAtoms::loop,
|
||
nsGkAtoms::low,
|
||
nsGkAtoms::max,
|
||
nsGkAtoms::maxlength,
|
||
nsGkAtoms::media,
|
||
nsGkAtoms::method,
|
||
nsGkAtoms::min,
|
||
nsGkAtoms::minlength,
|
||
nsGkAtoms::multiple,
|
||
nsGkAtoms::muted,
|
||
nsGkAtoms::name,
|
||
nsGkAtoms::nohref,
|
||
nsGkAtoms::novalidate,
|
||
nsGkAtoms::nowrap,
|
||
nsGkAtoms::open,
|
||
nsGkAtoms::optimum,
|
||
nsGkAtoms::pattern,
|
||
nsGkAtoms::placeholder,
|
||
nsGkAtoms::playbackrate,
|
||
nsGkAtoms::poster,
|
||
nsGkAtoms::preload,
|
||
nsGkAtoms::prompt,
|
||
nsGkAtoms::pubdate,
|
||
nsGkAtoms::radiogroup,
|
||
nsGkAtoms::readonly,
|
||
nsGkAtoms::rel,
|
||
nsGkAtoms::required,
|
||
nsGkAtoms::rev,
|
||
nsGkAtoms::reversed,
|
||
nsGkAtoms::role,
|
||
nsGkAtoms::rows,
|
||
nsGkAtoms::rowspan,
|
||
nsGkAtoms::rules,
|
||
nsGkAtoms::scoped,
|
||
nsGkAtoms::scope,
|
||
nsGkAtoms::selected,
|
||
nsGkAtoms::shape,
|
||
nsGkAtoms::span,
|
||
nsGkAtoms::spellcheck,
|
||
nsGkAtoms::src,
|
||
nsGkAtoms::srclang,
|
||
nsGkAtoms::start,
|
||
nsGkAtoms::summary,
|
||
nsGkAtoms::tabindex,
|
||
nsGkAtoms::target,
|
||
nsGkAtoms::title,
|
||
nsGkAtoms::type,
|
||
nsGkAtoms::usemap,
|
||
nsGkAtoms::value,
|
||
nsGkAtoms::width,
|
||
nsGkAtoms::wrap,
|
||
nullptr
|
||
// clang-format on
|
||
};
|
||
|
||
const nsStaticAtom* const kPresAttributesHTML[] = {
|
||
// clang-format off
|
||
nsGkAtoms::align,
|
||
nsGkAtoms::background,
|
||
nsGkAtoms::bgcolor,
|
||
nsGkAtoms::border,
|
||
nsGkAtoms::cellpadding,
|
||
nsGkAtoms::cellspacing,
|
||
nsGkAtoms::color,
|
||
nsGkAtoms::compact,
|
||
nsGkAtoms::clear,
|
||
nsGkAtoms::hspace,
|
||
nsGkAtoms::noshade,
|
||
nsGkAtoms::pointSize,
|
||
nsGkAtoms::size,
|
||
nsGkAtoms::valign,
|
||
nsGkAtoms::vspace,
|
||
nullptr
|
||
// clang-format on
|
||
};
|
||
|
||
// List of HTML attributes with URLs that the
|
||
// browser will fetch. Should be kept in sync with
|
||
// https://html.spec.whatwg.org/multipage/indices.html#attributes-3
|
||
const nsStaticAtom* const kURLAttributesHTML[] = {
|
||
// clang-format off
|
||
nsGkAtoms::action,
|
||
nsGkAtoms::href,
|
||
nsGkAtoms::src,
|
||
nsGkAtoms::longdesc,
|
||
nsGkAtoms::cite,
|
||
nsGkAtoms::background,
|
||
nsGkAtoms::formaction,
|
||
nsGkAtoms::data,
|
||
nsGkAtoms::ping,
|
||
nsGkAtoms::poster,
|
||
nullptr
|
||
// clang-format on
|
||
};
|
||
|
||
const nsStaticAtom* const kElementsSVG[] = {
|
||
nsGkAtoms::a, // a
|
||
nsGkAtoms::circle, // circle
|
||
nsGkAtoms::clipPath, // clipPath
|
||
nsGkAtoms::colorProfile, // color-profile
|
||
nsGkAtoms::cursor, // cursor
|
||
nsGkAtoms::defs, // defs
|
||
nsGkAtoms::desc, // desc
|
||
nsGkAtoms::ellipse, // ellipse
|
||
nsGkAtoms::elevation, // elevation
|
||
nsGkAtoms::erode, // erode
|
||
nsGkAtoms::ex, // ex
|
||
nsGkAtoms::exact, // exact
|
||
nsGkAtoms::exponent, // exponent
|
||
nsGkAtoms::feBlend, // feBlend
|
||
nsGkAtoms::feColorMatrix, // feColorMatrix
|
||
nsGkAtoms::feComponentTransfer, // feComponentTransfer
|
||
nsGkAtoms::feComposite, // feComposite
|
||
nsGkAtoms::feConvolveMatrix, // feConvolveMatrix
|
||
nsGkAtoms::feDiffuseLighting, // feDiffuseLighting
|
||
nsGkAtoms::feDisplacementMap, // feDisplacementMap
|
||
nsGkAtoms::feDistantLight, // feDistantLight
|
||
nsGkAtoms::feDropShadow, // feDropShadow
|
||
nsGkAtoms::feFlood, // feFlood
|
||
nsGkAtoms::feFuncA, // feFuncA
|
||
nsGkAtoms::feFuncB, // feFuncB
|
||
nsGkAtoms::feFuncG, // feFuncG
|
||
nsGkAtoms::feFuncR, // feFuncR
|
||
nsGkAtoms::feGaussianBlur, // feGaussianBlur
|
||
nsGkAtoms::feImage, // feImage
|
||
nsGkAtoms::feMerge, // feMerge
|
||
nsGkAtoms::feMergeNode, // feMergeNode
|
||
nsGkAtoms::feMorphology, // feMorphology
|
||
nsGkAtoms::feOffset, // feOffset
|
||
nsGkAtoms::fePointLight, // fePointLight
|
||
nsGkAtoms::feSpecularLighting, // feSpecularLighting
|
||
nsGkAtoms::feSpotLight, // feSpotLight
|
||
nsGkAtoms::feTile, // feTile
|
||
nsGkAtoms::feTurbulence, // feTurbulence
|
||
nsGkAtoms::filter, // filter
|
||
nsGkAtoms::font, // font
|
||
nsGkAtoms::font_face, // font-face
|
||
nsGkAtoms::font_face_format, // font-face-format
|
||
nsGkAtoms::font_face_name, // font-face-name
|
||
nsGkAtoms::font_face_src, // font-face-src
|
||
nsGkAtoms::font_face_uri, // font-face-uri
|
||
nsGkAtoms::foreignObject, // foreignObject
|
||
nsGkAtoms::g, // g
|
||
// glyph
|
||
nsGkAtoms::glyphRef, // glyphRef
|
||
// hkern
|
||
nsGkAtoms::image, // image
|
||
nsGkAtoms::line, // line
|
||
nsGkAtoms::linearGradient, // linearGradient
|
||
nsGkAtoms::marker, // marker
|
||
nsGkAtoms::mask, // mask
|
||
nsGkAtoms::metadata, // metadata
|
||
nsGkAtoms::missingGlyph, // missingGlyph
|
||
nsGkAtoms::mpath, // mpath
|
||
nsGkAtoms::path, // path
|
||
nsGkAtoms::pattern, // pattern
|
||
nsGkAtoms::polygon, // polygon
|
||
nsGkAtoms::polyline, // polyline
|
||
nsGkAtoms::radialGradient, // radialGradient
|
||
nsGkAtoms::rect, // rect
|
||
nsGkAtoms::stop, // stop
|
||
nsGkAtoms::svg, // svg
|
||
nsGkAtoms::svgSwitch, // switch
|
||
nsGkAtoms::symbol, // symbol
|
||
nsGkAtoms::text, // text
|
||
nsGkAtoms::textPath, // textPath
|
||
nsGkAtoms::title, // title
|
||
nsGkAtoms::tref, // tref
|
||
nsGkAtoms::tspan, // tspan
|
||
nsGkAtoms::use, // use
|
||
nsGkAtoms::view, // view
|
||
// vkern
|
||
nullptr};
|
||
|
||
constexpr const nsStaticAtom* const kAttributesSVG[] = {
|
||
// accent-height
|
||
nsGkAtoms::accumulate, // accumulate
|
||
nsGkAtoms::additive, // additive
|
||
nsGkAtoms::alignment_baseline, // alignment-baseline
|
||
// alphabetic
|
||
nsGkAtoms::amplitude, // amplitude
|
||
// arabic-form
|
||
// ascent
|
||
nsGkAtoms::attributeName, // attributeName
|
||
nsGkAtoms::attributeType, // attributeType
|
||
nsGkAtoms::azimuth, // azimuth
|
||
nsGkAtoms::baseFrequency, // baseFrequency
|
||
nsGkAtoms::baseline_shift, // baseline-shift
|
||
// baseProfile
|
||
// bbox
|
||
nsGkAtoms::begin, // begin
|
||
nsGkAtoms::bias, // bias
|
||
nsGkAtoms::by, // by
|
||
nsGkAtoms::calcMode, // calcMode
|
||
// cap-height
|
||
nsGkAtoms::_class, // class
|
||
nsGkAtoms::clip_path, // clip-path
|
||
nsGkAtoms::clip_rule, // clip-rule
|
||
nsGkAtoms::clipPathUnits, // clipPathUnits
|
||
nsGkAtoms::color, // color
|
||
nsGkAtoms::colorInterpolation, // color-interpolation
|
||
nsGkAtoms::colorInterpolationFilters, // color-interpolation-filters
|
||
nsGkAtoms::cursor, // cursor
|
||
nsGkAtoms::cx, // cx
|
||
nsGkAtoms::cy, // cy
|
||
nsGkAtoms::d, // d
|
||
// descent
|
||
nsGkAtoms::diffuseConstant, // diffuseConstant
|
||
nsGkAtoms::direction, // direction
|
||
nsGkAtoms::display, // display
|
||
nsGkAtoms::divisor, // divisor
|
||
nsGkAtoms::dominant_baseline, // dominant-baseline
|
||
nsGkAtoms::dur, // dur
|
||
nsGkAtoms::dx, // dx
|
||
nsGkAtoms::dy, // dy
|
||
nsGkAtoms::edgeMode, // edgeMode
|
||
nsGkAtoms::elevation, // elevation
|
||
// enable-background
|
||
nsGkAtoms::end, // end
|
||
nsGkAtoms::fill, // fill
|
||
nsGkAtoms::fill_opacity, // fill-opacity
|
||
nsGkAtoms::fill_rule, // fill-rule
|
||
nsGkAtoms::filter, // filter
|
||
nsGkAtoms::filterUnits, // filterUnits
|
||
nsGkAtoms::flood_color, // flood-color
|
||
nsGkAtoms::flood_opacity, // flood-opacity
|
||
// XXX focusable
|
||
nsGkAtoms::font, // font
|
||
nsGkAtoms::font_family, // font-family
|
||
nsGkAtoms::font_size, // font-size
|
||
nsGkAtoms::font_size_adjust, // font-size-adjust
|
||
nsGkAtoms::font_stretch, // font-stretch
|
||
nsGkAtoms::font_style, // font-style
|
||
nsGkAtoms::font_variant, // font-variant
|
||
nsGkAtoms::fontWeight, // font-weight
|
||
nsGkAtoms::format, // format
|
||
nsGkAtoms::from, // from
|
||
nsGkAtoms::fx, // fx
|
||
nsGkAtoms::fy, // fy
|
||
// g1
|
||
// g2
|
||
// glyph-name
|
||
// glyphRef
|
||
// glyph-orientation-horizontal
|
||
// glyph-orientation-vertical
|
||
nsGkAtoms::gradientTransform, // gradientTransform
|
||
nsGkAtoms::gradientUnits, // gradientUnits
|
||
nsGkAtoms::height, // height
|
||
nsGkAtoms::href,
|
||
// horiz-adv-x
|
||
// horiz-origin-x
|
||
// horiz-origin-y
|
||
nsGkAtoms::id, // id
|
||
// ideographic
|
||
nsGkAtoms::image_rendering, // image-rendering
|
||
nsGkAtoms::in, // in
|
||
nsGkAtoms::in2, // in2
|
||
nsGkAtoms::intercept, // intercept
|
||
// k
|
||
nsGkAtoms::k1, // k1
|
||
nsGkAtoms::k2, // k2
|
||
nsGkAtoms::k3, // k3
|
||
nsGkAtoms::k4, // k4
|
||
// kerning
|
||
nsGkAtoms::kernelMatrix, // kernelMatrix
|
||
nsGkAtoms::kernelUnitLength, // kernelUnitLength
|
||
nsGkAtoms::keyPoints, // keyPoints
|
||
nsGkAtoms::keySplines, // keySplines
|
||
nsGkAtoms::keyTimes, // keyTimes
|
||
nsGkAtoms::lang, // lang
|
||
// lengthAdjust
|
||
nsGkAtoms::letter_spacing, // letter-spacing
|
||
nsGkAtoms::lighting_color, // lighting-color
|
||
nsGkAtoms::limitingConeAngle, // limitingConeAngle
|
||
// local
|
||
nsGkAtoms::marker, // marker
|
||
nsGkAtoms::marker_end, // marker-end
|
||
nsGkAtoms::marker_mid, // marker-mid
|
||
nsGkAtoms::marker_start, // marker-start
|
||
nsGkAtoms::markerHeight, // markerHeight
|
||
nsGkAtoms::markerUnits, // markerUnits
|
||
nsGkAtoms::markerWidth, // markerWidth
|
||
nsGkAtoms::mask, // mask
|
||
nsGkAtoms::maskContentUnits, // maskContentUnits
|
||
nsGkAtoms::maskUnits, // maskUnits
|
||
// mathematical
|
||
nsGkAtoms::max, // max
|
||
nsGkAtoms::media, // media
|
||
nsGkAtoms::method, // method
|
||
nsGkAtoms::min, // min
|
||
nsGkAtoms::mode, // mode
|
||
nsGkAtoms::name, // name
|
||
nsGkAtoms::numOctaves, // numOctaves
|
||
nsGkAtoms::offset, // offset
|
||
nsGkAtoms::opacity, // opacity
|
||
nsGkAtoms::_operator, // operator
|
||
nsGkAtoms::order, // order
|
||
nsGkAtoms::orient, // orient
|
||
nsGkAtoms::orientation, // orientation
|
||
// origin
|
||
// overline-position
|
||
// overline-thickness
|
||
nsGkAtoms::overflow, // overflow
|
||
// panose-1
|
||
nsGkAtoms::path, // path
|
||
nsGkAtoms::pathLength, // pathLength
|
||
nsGkAtoms::patternContentUnits, // patternContentUnits
|
||
nsGkAtoms::patternTransform, // patternTransform
|
||
nsGkAtoms::patternUnits, // patternUnits
|
||
nsGkAtoms::pointer_events, // pointer-events XXX is this safe?
|
||
nsGkAtoms::points, // points
|
||
nsGkAtoms::pointsAtX, // pointsAtX
|
||
nsGkAtoms::pointsAtY, // pointsAtY
|
||
nsGkAtoms::pointsAtZ, // pointsAtZ
|
||
nsGkAtoms::preserveAlpha, // preserveAlpha
|
||
nsGkAtoms::preserveAspectRatio, // preserveAspectRatio
|
||
nsGkAtoms::primitiveUnits, // primitiveUnits
|
||
nsGkAtoms::r, // r
|
||
nsGkAtoms::radius, // radius
|
||
nsGkAtoms::refX, // refX
|
||
nsGkAtoms::refY, // refY
|
||
nsGkAtoms::repeatCount, // repeatCount
|
||
nsGkAtoms::repeatDur, // repeatDur
|
||
nsGkAtoms::requiredExtensions, // requiredExtensions
|
||
nsGkAtoms::requiredFeatures, // requiredFeatures
|
||
nsGkAtoms::restart, // restart
|
||
nsGkAtoms::result, // result
|
||
nsGkAtoms::rotate, // rotate
|
||
nsGkAtoms::rx, // rx
|
||
nsGkAtoms::ry, // ry
|
||
nsGkAtoms::scale, // scale
|
||
nsGkAtoms::seed, // seed
|
||
nsGkAtoms::shape_rendering, // shape-rendering
|
||
nsGkAtoms::slope, // slope
|
||
nsGkAtoms::spacing, // spacing
|
||
nsGkAtoms::specularConstant, // specularConstant
|
||
nsGkAtoms::specularExponent, // specularExponent
|
||
nsGkAtoms::spreadMethod, // spreadMethod
|
||
nsGkAtoms::startOffset, // startOffset
|
||
nsGkAtoms::stdDeviation, // stdDeviation
|
||
// stemh
|
||
// stemv
|
||
nsGkAtoms::stitchTiles, // stitchTiles
|
||
nsGkAtoms::stop_color, // stop-color
|
||
nsGkAtoms::stop_opacity, // stop-opacity
|
||
// strikethrough-position
|
||
// strikethrough-thickness
|
||
nsGkAtoms::string, // string
|
||
nsGkAtoms::stroke, // stroke
|
||
nsGkAtoms::stroke_dasharray, // stroke-dasharray
|
||
nsGkAtoms::stroke_dashoffset, // stroke-dashoffset
|
||
nsGkAtoms::stroke_linecap, // stroke-linecap
|
||
nsGkAtoms::stroke_linejoin, // stroke-linejoin
|
||
nsGkAtoms::stroke_miterlimit, // stroke-miterlimit
|
||
nsGkAtoms::stroke_opacity, // stroke-opacity
|
||
nsGkAtoms::stroke_width, // stroke-width
|
||
nsGkAtoms::surfaceScale, // surfaceScale
|
||
nsGkAtoms::systemLanguage, // systemLanguage
|
||
nsGkAtoms::tableValues, // tableValues
|
||
nsGkAtoms::target, // target
|
||
nsGkAtoms::targetX, // targetX
|
||
nsGkAtoms::targetY, // targetY
|
||
nsGkAtoms::text_anchor, // text-anchor
|
||
nsGkAtoms::text_decoration, // text-decoration
|
||
// textLength
|
||
nsGkAtoms::text_rendering, // text-rendering
|
||
nsGkAtoms::title, // title
|
||
nsGkAtoms::to, // to
|
||
nsGkAtoms::transform, // transform
|
||
nsGkAtoms::transform_origin, // transform-origin
|
||
nsGkAtoms::type, // type
|
||
// u1
|
||
// u2
|
||
// underline-position
|
||
// underline-thickness
|
||
// unicode
|
||
nsGkAtoms::unicode_bidi, // unicode-bidi
|
||
// unicode-range
|
||
// units-per-em
|
||
// v-alphabetic
|
||
// v-hanging
|
||
// v-ideographic
|
||
// v-mathematical
|
||
nsGkAtoms::values, // values
|
||
nsGkAtoms::vector_effect, // vector-effect
|
||
// vert-adv-y
|
||
// vert-origin-x
|
||
// vert-origin-y
|
||
nsGkAtoms::viewBox, // viewBox
|
||
nsGkAtoms::viewTarget, // viewTarget
|
||
nsGkAtoms::visibility, // visibility
|
||
nsGkAtoms::width, // width
|
||
// widths
|
||
nsGkAtoms::word_spacing, // word-spacing
|
||
nsGkAtoms::writing_mode, // writing-mode
|
||
nsGkAtoms::x, // x
|
||
// x-height
|
||
nsGkAtoms::x1, // x1
|
||
nsGkAtoms::x2, // x2
|
||
nsGkAtoms::xChannelSelector, // xChannelSelector
|
||
nsGkAtoms::y, // y
|
||
nsGkAtoms::y1, // y1
|
||
nsGkAtoms::y2, // y2
|
||
nsGkAtoms::yChannelSelector, // yChannelSelector
|
||
nsGkAtoms::z, // z
|
||
nsGkAtoms::zoomAndPan, // zoomAndPan
|
||
nullptr};
|
||
|
||
constexpr const nsStaticAtom* const kURLAttributesSVG[] = {nsGkAtoms::href,
|
||
nullptr};
|
||
|
||
static_assert(AllOf(std::begin(kURLAttributesSVG), std::end(kURLAttributesSVG),
|
||
[](auto aURLAttributeSVG) {
|
||
return AnyOf(std::begin(kAttributesSVG),
|
||
std::end(kAttributesSVG),
|
||
[&](auto aAttributeSVG) {
|
||
return aAttributeSVG == aURLAttributeSVG;
|
||
});
|
||
}));
|
||
|
||
const nsStaticAtom* const kElementsMathML[] = {
|
||
nsGkAtoms::abs_, // abs
|
||
nsGkAtoms::_and, // and
|
||
nsGkAtoms::annotation_, // annotation
|
||
nsGkAtoms::annotation_xml_, // annotation-xml
|
||
nsGkAtoms::apply_, // apply
|
||
nsGkAtoms::approx_, // approx
|
||
nsGkAtoms::arccos_, // arccos
|
||
nsGkAtoms::arccosh_, // arccosh
|
||
nsGkAtoms::arccot_, // arccot
|
||
nsGkAtoms::arccoth_, // arccoth
|
||
nsGkAtoms::arccsc_, // arccsc
|
||
nsGkAtoms::arccsch_, // arccsch
|
||
nsGkAtoms::arcsec_, // arcsec
|
||
nsGkAtoms::arcsech_, // arcsech
|
||
nsGkAtoms::arcsin_, // arcsin
|
||
nsGkAtoms::arcsinh_, // arcsinh
|
||
nsGkAtoms::arctan_, // arctan
|
||
nsGkAtoms::arctanh_, // arctanh
|
||
nsGkAtoms::arg_, // arg
|
||
nsGkAtoms::bind_, // bind
|
||
nsGkAtoms::bvar_, // bvar
|
||
nsGkAtoms::card_, // card
|
||
nsGkAtoms::cartesianproduct_, // cartesianproduct
|
||
nsGkAtoms::cbytes_, // cbytes
|
||
nsGkAtoms::ceiling, // ceiling
|
||
nsGkAtoms::cerror_, // cerror
|
||
nsGkAtoms::ci_, // ci
|
||
nsGkAtoms::cn_, // cn
|
||
nsGkAtoms::codomain_, // codomain
|
||
nsGkAtoms::complexes_, // complexes
|
||
nsGkAtoms::compose_, // compose
|
||
nsGkAtoms::condition_, // condition
|
||
nsGkAtoms::conjugate_, // conjugate
|
||
nsGkAtoms::cos_, // cos
|
||
nsGkAtoms::cosh_, // cosh
|
||
nsGkAtoms::cot_, // cot
|
||
nsGkAtoms::coth_, // coth
|
||
nsGkAtoms::cs_, // cs
|
||
nsGkAtoms::csc_, // csc
|
||
nsGkAtoms::csch_, // csch
|
||
nsGkAtoms::csymbol_, // csymbol
|
||
nsGkAtoms::curl_, // curl
|
||
nsGkAtoms::declare, // declare
|
||
nsGkAtoms::degree_, // degree
|
||
nsGkAtoms::determinant_, // determinant
|
||
nsGkAtoms::diff_, // diff
|
||
nsGkAtoms::divergence_, // divergence
|
||
nsGkAtoms::divide_, // divide
|
||
nsGkAtoms::domain_, // domain
|
||
nsGkAtoms::domainofapplication_, // domainofapplication
|
||
nsGkAtoms::el, // el
|
||
nsGkAtoms::emptyset_, // emptyset
|
||
nsGkAtoms::eq_, // eq
|
||
nsGkAtoms::equivalent_, // equivalent
|
||
nsGkAtoms::eulergamma_, // eulergamma
|
||
nsGkAtoms::exists_, // exists
|
||
nsGkAtoms::exp_, // exp
|
||
nsGkAtoms::exponentiale_, // exponentiale
|
||
nsGkAtoms::factorial_, // factorial
|
||
nsGkAtoms::factorof_, // factorof
|
||
nsGkAtoms::_false, // false
|
||
nsGkAtoms::floor, // floor
|
||
nsGkAtoms::fn_, // fn
|
||
nsGkAtoms::forall_, // forall
|
||
nsGkAtoms::gcd_, // gcd
|
||
nsGkAtoms::geq_, // geq
|
||
nsGkAtoms::grad, // grad
|
||
nsGkAtoms::gt_, // gt
|
||
nsGkAtoms::ident_, // ident
|
||
nsGkAtoms::image, // image
|
||
nsGkAtoms::imaginary_, // imaginary
|
||
nsGkAtoms::imaginaryi_, // imaginaryi
|
||
nsGkAtoms::implies_, // implies
|
||
nsGkAtoms::in, // in
|
||
nsGkAtoms::infinity, // infinity
|
||
nsGkAtoms::int_, // int
|
||
nsGkAtoms::integers_, // integers
|
||
nsGkAtoms::intersect_, // intersect
|
||
nsGkAtoms::interval_, // interval
|
||
nsGkAtoms::inverse_, // inverse
|
||
nsGkAtoms::lambda_, // lambda
|
||
nsGkAtoms::laplacian_, // laplacian
|
||
nsGkAtoms::lcm_, // lcm
|
||
nsGkAtoms::leq_, // leq
|
||
nsGkAtoms::limit_, // limit
|
||
nsGkAtoms::list_, // list
|
||
nsGkAtoms::ln_, // ln
|
||
nsGkAtoms::log_, // log
|
||
nsGkAtoms::logbase_, // logbase
|
||
nsGkAtoms::lowlimit_, // lowlimit
|
||
nsGkAtoms::lt_, // lt
|
||
nsGkAtoms::maction_, // maction
|
||
nsGkAtoms::maligngroup_, // maligngroup
|
||
nsGkAtoms::malignmark_, // malignmark
|
||
nsGkAtoms::math, // math
|
||
nsGkAtoms::matrix, // matrix
|
||
nsGkAtoms::matrixrow_, // matrixrow
|
||
nsGkAtoms::max, // max
|
||
nsGkAtoms::mean_, // mean
|
||
nsGkAtoms::median_, // median
|
||
nsGkAtoms::menclose_, // menclose
|
||
nsGkAtoms::merror_, // merror
|
||
nsGkAtoms::mfrac_, // mfrac
|
||
nsGkAtoms::mglyph_, // mglyph
|
||
nsGkAtoms::mi_, // mi
|
||
nsGkAtoms::min, // min
|
||
nsGkAtoms::minus_, // minus
|
||
nsGkAtoms::mlabeledtr_, // mlabeledtr
|
||
nsGkAtoms::mlongdiv_, // mlongdiv
|
||
nsGkAtoms::mmultiscripts_, // mmultiscripts
|
||
nsGkAtoms::mn_, // mn
|
||
nsGkAtoms::mo_, // mo
|
||
nsGkAtoms::mode, // mode
|
||
nsGkAtoms::moment_, // moment
|
||
nsGkAtoms::momentabout_, // momentabout
|
||
nsGkAtoms::mover_, // mover
|
||
nsGkAtoms::mpadded_, // mpadded
|
||
nsGkAtoms::mphantom_, // mphantom
|
||
nsGkAtoms::mprescripts_, // mprescripts
|
||
nsGkAtoms::mroot_, // mroot
|
||
nsGkAtoms::mrow_, // mrow
|
||
nsGkAtoms::ms_, // ms
|
||
nsGkAtoms::mscarries_, // mscarries
|
||
nsGkAtoms::mscarry_, // mscarry
|
||
nsGkAtoms::msgroup_, // msgroup
|
||
nsGkAtoms::msline_, // msline
|
||
nsGkAtoms::mspace_, // mspace
|
||
nsGkAtoms::msqrt_, // msqrt
|
||
nsGkAtoms::msrow_, // msrow
|
||
nsGkAtoms::mstack_, // mstack
|
||
nsGkAtoms::mstyle_, // mstyle
|
||
nsGkAtoms::msub_, // msub
|
||
nsGkAtoms::msubsup_, // msubsup
|
||
nsGkAtoms::msup_, // msup
|
||
nsGkAtoms::mtable_, // mtable
|
||
nsGkAtoms::mtd_, // mtd
|
||
nsGkAtoms::mtext_, // mtext
|
||
nsGkAtoms::mtr_, // mtr
|
||
nsGkAtoms::munder_, // munder
|
||
nsGkAtoms::munderover_, // munderover
|
||
nsGkAtoms::naturalnumbers_, // naturalnumbers
|
||
nsGkAtoms::neq_, // neq
|
||
nsGkAtoms::none, // none
|
||
nsGkAtoms::_not, // not
|
||
nsGkAtoms::notanumber_, // notanumber
|
||
nsGkAtoms::note_, // note
|
||
nsGkAtoms::notin_, // notin
|
||
nsGkAtoms::notprsubset_, // notprsubset
|
||
nsGkAtoms::notsubset_, // notsubset
|
||
nsGkAtoms::_or, // or
|
||
nsGkAtoms::otherwise, // otherwise
|
||
nsGkAtoms::outerproduct_, // outerproduct
|
||
nsGkAtoms::partialdiff_, // partialdiff
|
||
nsGkAtoms::pi_, // pi
|
||
nsGkAtoms::piece_, // piece
|
||
nsGkAtoms::piecewise_, // piecewise
|
||
nsGkAtoms::plus_, // plus
|
||
nsGkAtoms::power_, // power
|
||
nsGkAtoms::primes_, // primes
|
||
nsGkAtoms::product_, // product
|
||
nsGkAtoms::prsubset_, // prsubset
|
||
nsGkAtoms::quotient_, // quotient
|
||
nsGkAtoms::rationals_, // rationals
|
||
nsGkAtoms::real_, // real
|
||
nsGkAtoms::reals_, // reals
|
||
nsGkAtoms::reln_, // reln
|
||
nsGkAtoms::rem, // rem
|
||
nsGkAtoms::root_, // root
|
||
nsGkAtoms::scalarproduct_, // scalarproduct
|
||
nsGkAtoms::sdev_, // sdev
|
||
nsGkAtoms::sec_, // sec
|
||
nsGkAtoms::sech_, // sech
|
||
nsGkAtoms::selector_, // selector
|
||
nsGkAtoms::semantics_, // semantics
|
||
nsGkAtoms::sep_, // sep
|
||
nsGkAtoms::set, // set
|
||
nsGkAtoms::setdiff_, // setdiff
|
||
nsGkAtoms::share_, // share
|
||
nsGkAtoms::sin_, // sin
|
||
nsGkAtoms::sinh_, // sinh
|
||
nsGkAtoms::subset_, // subset
|
||
nsGkAtoms::sum, // sum
|
||
nsGkAtoms::tan_, // tan
|
||
nsGkAtoms::tanh_, // tanh
|
||
nsGkAtoms::tendsto_, // tendsto
|
||
nsGkAtoms::times_, // times
|
||
nsGkAtoms::transpose_, // transpose
|
||
nsGkAtoms::_true, // true
|
||
nsGkAtoms::union_, // union
|
||
nsGkAtoms::uplimit_, // uplimit
|
||
nsGkAtoms::variance_, // variance
|
||
nsGkAtoms::vector_, // vector
|
||
nsGkAtoms::vectorproduct_, // vectorproduct
|
||
nsGkAtoms::xor_, // xor
|
||
nullptr};
|
||
|
||
const nsStaticAtom* const kAttributesMathML[] = {
|
||
nsGkAtoms::accent_, // accent
|
||
nsGkAtoms::accentunder_, // accentunder
|
||
nsGkAtoms::actiontype_, // actiontype
|
||
nsGkAtoms::align, // align
|
||
nsGkAtoms::alignmentscope_, // alignmentscope
|
||
nsGkAtoms::alt, // alt
|
||
nsGkAtoms::altimg_, // altimg
|
||
nsGkAtoms::altimg_height_, // altimg-height
|
||
nsGkAtoms::altimg_valign_, // altimg-valign
|
||
nsGkAtoms::altimg_width_, // altimg-width
|
||
nsGkAtoms::background, // background
|
||
nsGkAtoms::base, // base
|
||
nsGkAtoms::bevelled_, // bevelled
|
||
nsGkAtoms::cd_, // cd
|
||
nsGkAtoms::cdgroup_, // cdgroup
|
||
nsGkAtoms::charalign_, // charalign
|
||
nsGkAtoms::close, // close
|
||
nsGkAtoms::closure_, // closure
|
||
nsGkAtoms::color, // color
|
||
nsGkAtoms::columnalign_, // columnalign
|
||
nsGkAtoms::columnalignment_, // columnalignment
|
||
nsGkAtoms::columnlines_, // columnlines
|
||
nsGkAtoms::columnspacing_, // columnspacing
|
||
nsGkAtoms::columnspan_, // columnspan
|
||
nsGkAtoms::columnwidth_, // columnwidth
|
||
nsGkAtoms::crossout_, // crossout
|
||
nsGkAtoms::decimalpoint_, // decimalpoint
|
||
nsGkAtoms::definitionURL_, // definitionURL
|
||
nsGkAtoms::denomalign_, // denomalign
|
||
nsGkAtoms::depth_, // depth
|
||
nsGkAtoms::dir, // dir
|
||
nsGkAtoms::display, // display
|
||
nsGkAtoms::displaystyle_, // displaystyle
|
||
nsGkAtoms::edge_, // edge
|
||
nsGkAtoms::encoding, // encoding
|
||
nsGkAtoms::equalcolumns_, // equalcolumns
|
||
nsGkAtoms::equalrows_, // equalrows
|
||
nsGkAtoms::fence_, // fence
|
||
nsGkAtoms::fontfamily_, // fontfamily
|
||
nsGkAtoms::fontsize_, // fontsize
|
||
nsGkAtoms::fontstyle_, // fontstyle
|
||
nsGkAtoms::fontweight_, // fontweight
|
||
nsGkAtoms::form, // form
|
||
nsGkAtoms::frame, // frame
|
||
nsGkAtoms::framespacing_, // framespacing
|
||
nsGkAtoms::groupalign_, // groupalign
|
||
nsGkAtoms::height, // height
|
||
nsGkAtoms::href, // href
|
||
nsGkAtoms::id, // id
|
||
nsGkAtoms::indentalign_, // indentalign
|
||
nsGkAtoms::indentalignfirst_, // indentalignfirst
|
||
nsGkAtoms::indentalignlast_, // indentalignlast
|
||
nsGkAtoms::indentshift_, // indentshift
|
||
nsGkAtoms::indentshiftfirst_, // indentshiftfirst
|
||
nsGkAtoms::indenttarget_, // indenttarget
|
||
nsGkAtoms::index, // index
|
||
nsGkAtoms::integer, // integer
|
||
nsGkAtoms::largeop_, // largeop
|
||
nsGkAtoms::length, // length
|
||
nsGkAtoms::linebreak_, // linebreak
|
||
nsGkAtoms::linebreakmultchar_, // linebreakmultchar
|
||
nsGkAtoms::linebreakstyle_, // linebreakstyle
|
||
nsGkAtoms::linethickness_, // linethickness
|
||
nsGkAtoms::location_, // location
|
||
nsGkAtoms::longdivstyle_, // longdivstyle
|
||
nsGkAtoms::lquote_, // lquote
|
||
nsGkAtoms::lspace_, // lspace
|
||
nsGkAtoms::ltr, // ltr
|
||
nsGkAtoms::mathbackground_, // mathbackground
|
||
nsGkAtoms::mathcolor_, // mathcolor
|
||
nsGkAtoms::mathsize_, // mathsize
|
||
nsGkAtoms::mathvariant_, // mathvariant
|
||
nsGkAtoms::maxsize_, // maxsize
|
||
nsGkAtoms::minlabelspacing_, // minlabelspacing
|
||
nsGkAtoms::minsize_, // minsize
|
||
nsGkAtoms::movablelimits_, // movablelimits
|
||
nsGkAtoms::msgroup_, // msgroup
|
||
nsGkAtoms::name, // name
|
||
nsGkAtoms::newline, // newline
|
||
nsGkAtoms::notation_, // notation
|
||
nsGkAtoms::numalign_, // numalign
|
||
nsGkAtoms::number, // number
|
||
nsGkAtoms::open, // open
|
||
nsGkAtoms::order, // order
|
||
nsGkAtoms::other, // other
|
||
nsGkAtoms::overflow, // overflow
|
||
nsGkAtoms::position, // position
|
||
nsGkAtoms::role, // role
|
||
nsGkAtoms::rowalign_, // rowalign
|
||
nsGkAtoms::rowlines_, // rowlines
|
||
nsGkAtoms::rowspacing_, // rowspacing
|
||
nsGkAtoms::rowspan, // rowspan
|
||
nsGkAtoms::rquote_, // rquote
|
||
nsGkAtoms::rspace_, // rspace
|
||
nsGkAtoms::schemaLocation_, // schemaLocation
|
||
nsGkAtoms::scriptlevel_, // scriptlevel
|
||
nsGkAtoms::scriptminsize_, // scriptminsize
|
||
nsGkAtoms::scriptsize_, // scriptsize
|
||
nsGkAtoms::scriptsizemultiplier_, // scriptsizemultiplier
|
||
nsGkAtoms::selection_, // selection
|
||
nsGkAtoms::separator_, // separator
|
||
nsGkAtoms::separators_, // separators
|
||
nsGkAtoms::shift_, // shift
|
||
nsGkAtoms::side_, // side
|
||
nsGkAtoms::src, // src
|
||
nsGkAtoms::stackalign_, // stackalign
|
||
nsGkAtoms::stretchy_, // stretchy
|
||
nsGkAtoms::subscriptshift_, // subscriptshift
|
||
nsGkAtoms::superscriptshift_, // superscriptshift
|
||
nsGkAtoms::symmetric_, // symmetric
|
||
nsGkAtoms::type, // type
|
||
nsGkAtoms::voffset_, // voffset
|
||
nsGkAtoms::width, // width
|
||
nsGkAtoms::xref_, // xref
|
||
nullptr};
|
||
|
||
const nsStaticAtom* const kURLAttributesMathML[] = {
|
||
// clang-format off
|
||
nsGkAtoms::href,
|
||
nsGkAtoms::src,
|
||
nsGkAtoms::cdgroup_,
|
||
nsGkAtoms::altimg_,
|
||
nsGkAtoms::definitionURL_,
|
||
nullptr
|
||
// clang-format on
|
||
};
|
||
|
||
// https://wicg.github.io/sanitizer-api/#baseline-attribute-allow-list
|
||
constexpr const nsStaticAtom* const kBaselineAttributeAllowlist[] = {
|
||
// clang-format off
|
||
nsGkAtoms::abbr,
|
||
nsGkAtoms::accept,
|
||
nsGkAtoms::acceptcharset,
|
||
nsGkAtoms::charset,
|
||
nsGkAtoms::accesskey,
|
||
nsGkAtoms::action,
|
||
nsGkAtoms::align,
|
||
nsGkAtoms::alink,
|
||
nsGkAtoms::allow,
|
||
nsGkAtoms::allowfullscreen,
|
||
// nsGkAtoms::allowpaymentrequest,
|
||
nsGkAtoms::alt,
|
||
nsGkAtoms::anchor,
|
||
nsGkAtoms::archive,
|
||
nsGkAtoms::as,
|
||
nsGkAtoms::async,
|
||
nsGkAtoms::autocapitalize,
|
||
nsGkAtoms::autocomplete,
|
||
// nsGkAtoms::autocorrect,
|
||
nsGkAtoms::autofocus,
|
||
// nsGkAtoms::autopictureinpicture,
|
||
nsGkAtoms::autoplay,
|
||
nsGkAtoms::axis,
|
||
nsGkAtoms::background,
|
||
nsGkAtoms::behavior,
|
||
nsGkAtoms::bgcolor,
|
||
nsGkAtoms::border,
|
||
nsGkAtoms::bordercolor,
|
||
nsGkAtoms::capture,
|
||
nsGkAtoms::cellpadding,
|
||
nsGkAtoms::cellspacing,
|
||
// nsGkAtoms::challenge,
|
||
nsGkAtoms::_char,
|
||
nsGkAtoms::charoff,
|
||
nsGkAtoms::charset,
|
||
nsGkAtoms::checked,
|
||
nsGkAtoms::cite,
|
||
nsGkAtoms::_class,
|
||
nsGkAtoms::classid,
|
||
nsGkAtoms::clear,
|
||
nsGkAtoms::code,
|
||
nsGkAtoms::codebase,
|
||
nsGkAtoms::codetype,
|
||
nsGkAtoms::color,
|
||
nsGkAtoms::cols,
|
||
nsGkAtoms::colspan,
|
||
nsGkAtoms::compact,
|
||
nsGkAtoms::content,
|
||
nsGkAtoms::contenteditable,
|
||
nsGkAtoms::controls,
|
||
// nsGkAtoms::controlslist,
|
||
// nsGkAtoms::conversiondestination,
|
||
nsGkAtoms::coords,
|
||
nsGkAtoms::crossorigin,
|
||
nsGkAtoms::csp,
|
||
nsGkAtoms::data,
|
||
nsGkAtoms::datetime,
|
||
nsGkAtoms::declare,
|
||
nsGkAtoms::decoding,
|
||
nsGkAtoms::_default,
|
||
nsGkAtoms::defer,
|
||
nsGkAtoms::dir,
|
||
nsGkAtoms::direction,
|
||
// nsGkAtoms::dirname,
|
||
nsGkAtoms::disabled,
|
||
// nsGkAtoms::disablepictureinpicture,
|
||
// nsGkAtoms::disableremoteplayback,
|
||
// nsGkAtoms::disallowdocumentaccess,
|
||
nsGkAtoms::download,
|
||
nsGkAtoms::draggable,
|
||
// nsGkAtoms::elementtiming,
|
||
nsGkAtoms::enctype,
|
||
nsGkAtoms::end,
|
||
nsGkAtoms::enterkeyhint,
|
||
nsGkAtoms::event,
|
||
nsGkAtoms::exportparts,
|
||
nsGkAtoms::face,
|
||
nsGkAtoms::_for,
|
||
nsGkAtoms::form,
|
||
nsGkAtoms::formaction,
|
||
nsGkAtoms::formenctype,
|
||
nsGkAtoms::formmethod,
|
||
nsGkAtoms::formnovalidate,
|
||
nsGkAtoms::formtarget,
|
||
nsGkAtoms::frame,
|
||
nsGkAtoms::frameborder,
|
||
nsGkAtoms::headers,
|
||
nsGkAtoms::height,
|
||
nsGkAtoms::hidden,
|
||
nsGkAtoms::high,
|
||
nsGkAtoms::href,
|
||
nsGkAtoms::hreflang,
|
||
// nsGkAtoms::hreftranslate,
|
||
nsGkAtoms::hspace,
|
||
nsGkAtoms::http,
|
||
// nsGkAtoms::equiv,
|
||
nsGkAtoms::id,
|
||
nsGkAtoms::imagesizes,
|
||
nsGkAtoms::imagesrcset,
|
||
// nsGkAtoms::importance,
|
||
// nsGkAtoms::impressiondata,
|
||
// nsGkAtoms::impressionexpiry,
|
||
// nsGkAtoms::incremental,
|
||
nsGkAtoms::inert,
|
||
nsGkAtoms::inputmode,
|
||
nsGkAtoms::integrity,
|
||
// nsGkAtoms::invisible,
|
||
nsGkAtoms::is,
|
||
nsGkAtoms::ismap,
|
||
// nsGkAtoms::keytype,
|
||
nsGkAtoms::kind,
|
||
nsGkAtoms::label,
|
||
nsGkAtoms::lang,
|
||
nsGkAtoms::language,
|
||
// nsGkAtoms::latencyhint,
|
||
nsGkAtoms::leftmargin,
|
||
nsGkAtoms::link,
|
||
// nsGkAtoms::list,
|
||
nsGkAtoms::loading,
|
||
nsGkAtoms::longdesc,
|
||
nsGkAtoms::loop,
|
||
nsGkAtoms::low,
|
||
nsGkAtoms::lowsrc,
|
||
nsGkAtoms::manifest,
|
||
nsGkAtoms::marginheight,
|
||
nsGkAtoms::marginwidth,
|
||
nsGkAtoms::max,
|
||
nsGkAtoms::maxlength,
|
||
// nsGkAtoms::mayscript,
|
||
nsGkAtoms::media,
|
||
nsGkAtoms::method,
|
||
nsGkAtoms::min,
|
||
nsGkAtoms::minlength,
|
||
nsGkAtoms::multiple,
|
||
nsGkAtoms::muted,
|
||
nsGkAtoms::name,
|
||
nsGkAtoms::nohref,
|
||
nsGkAtoms::nomodule,
|
||
nsGkAtoms::nonce,
|
||
nsGkAtoms::noresize,
|
||
nsGkAtoms::noshade,
|
||
nsGkAtoms::novalidate,
|
||
nsGkAtoms::nowrap,
|
||
nsGkAtoms::object,
|
||
nsGkAtoms::open,
|
||
nsGkAtoms::optimum,
|
||
nsGkAtoms::part,
|
||
nsGkAtoms::pattern,
|
||
nsGkAtoms::ping,
|
||
nsGkAtoms::placeholder,
|
||
// nsGkAtoms::playsinline,
|
||
// nsGkAtoms::policy,
|
||
nsGkAtoms::poster,
|
||
nsGkAtoms::preload,
|
||
// nsGkAtoms::pseudo,
|
||
nsGkAtoms::readonly,
|
||
nsGkAtoms::referrerpolicy,
|
||
nsGkAtoms::rel,
|
||
// nsGkAtoms::reportingorigin,
|
||
nsGkAtoms::required,
|
||
nsGkAtoms::resources,
|
||
nsGkAtoms::rev,
|
||
nsGkAtoms::reversed,
|
||
nsGkAtoms::role,
|
||
nsGkAtoms::rows,
|
||
nsGkAtoms::rowspan,
|
||
nsGkAtoms::rules,
|
||
nsGkAtoms::sandbox,
|
||
nsGkAtoms::scheme,
|
||
nsGkAtoms::scope,
|
||
// nsGkAtoms::scopes,
|
||
nsGkAtoms::scrollamount,
|
||
nsGkAtoms::scrolldelay,
|
||
nsGkAtoms::scrolling,
|
||
nsGkAtoms::select,
|
||
nsGkAtoms::selected,
|
||
// nsGkAtoms::shadowroot,
|
||
// nsGkAtoms::shadowrootdelegatesfocus,
|
||
nsGkAtoms::shape,
|
||
nsGkAtoms::size,
|
||
nsGkAtoms::sizes,
|
||
nsGkAtoms::slot,
|
||
nsGkAtoms::span,
|
||
nsGkAtoms::spellcheck,
|
||
nsGkAtoms::src,
|
||
nsGkAtoms::srcdoc,
|
||
nsGkAtoms::srclang,
|
||
nsGkAtoms::srcset,
|
||
nsGkAtoms::standby,
|
||
nsGkAtoms::start,
|
||
nsGkAtoms::step,
|
||
nsGkAtoms::style,
|
||
nsGkAtoms::summary,
|
||
nsGkAtoms::tabindex,
|
||
nsGkAtoms::target,
|
||
nsGkAtoms::text,
|
||
nsGkAtoms::title,
|
||
nsGkAtoms::topmargin,
|
||
nsGkAtoms::translate,
|
||
nsGkAtoms::truespeed,
|
||
// nsGkAtoms::trusttoken,
|
||
nsGkAtoms::type,
|
||
nsGkAtoms::usemap,
|
||
nsGkAtoms::valign,
|
||
nsGkAtoms::value,
|
||
nsGkAtoms::valuetype,
|
||
nsGkAtoms::version,
|
||
// nsGkAtoms::virtualkeyboardpolicy,
|
||
nsGkAtoms::vlink,
|
||
nsGkAtoms::vspace,
|
||
nsGkAtoms::webkitdirectory,
|
||
nsGkAtoms::width,
|
||
nsGkAtoms::wrap,
|
||
// clang-format on
|
||
};
|
||
|
||
// https://wicg.github.io/sanitizer-api/#baseline-elements
|
||
constexpr const nsStaticAtom* const kBaselineElementAllowlist[] = {
|
||
nsGkAtoms::a, nsGkAtoms::abbr, nsGkAtoms::acronym,
|
||
nsGkAtoms::address, nsGkAtoms::area, nsGkAtoms::article,
|
||
nsGkAtoms::aside, nsGkAtoms::audio, nsGkAtoms::b,
|
||
nsGkAtoms::basefont, nsGkAtoms::bdi, nsGkAtoms::bdo,
|
||
nsGkAtoms::bgsound, nsGkAtoms::big, nsGkAtoms::blockquote,
|
||
nsGkAtoms::body, nsGkAtoms::br, nsGkAtoms::button,
|
||
nsGkAtoms::canvas, nsGkAtoms::caption, nsGkAtoms::center,
|
||
nsGkAtoms::cite, nsGkAtoms::code, nsGkAtoms::col,
|
||
nsGkAtoms::colgroup, nsGkAtoms::command, nsGkAtoms::data,
|
||
nsGkAtoms::datalist, nsGkAtoms::dd, nsGkAtoms::del,
|
||
nsGkAtoms::details, nsGkAtoms::dfn, nsGkAtoms::dialog,
|
||
nsGkAtoms::dir, nsGkAtoms::div, nsGkAtoms::dl,
|
||
nsGkAtoms::dt, nsGkAtoms::em, nsGkAtoms::fieldset,
|
||
nsGkAtoms::figcaption, nsGkAtoms::figure, nsGkAtoms::font,
|
||
nsGkAtoms::footer, nsGkAtoms::form, nsGkAtoms::h1,
|
||
nsGkAtoms::h2, nsGkAtoms::h3, nsGkAtoms::h4,
|
||
nsGkAtoms::h5, nsGkAtoms::h6, nsGkAtoms::head,
|
||
nsGkAtoms::header, nsGkAtoms::hgroup, nsGkAtoms::hr,
|
||
nsGkAtoms::html, nsGkAtoms::i, nsGkAtoms::image,
|
||
nsGkAtoms::img, nsGkAtoms::input, nsGkAtoms::ins,
|
||
nsGkAtoms::kbd, nsGkAtoms::keygen, nsGkAtoms::label,
|
||
nsGkAtoms::layer, nsGkAtoms::legend, nsGkAtoms::li,
|
||
nsGkAtoms::link, nsGkAtoms::listing, nsGkAtoms::main,
|
||
nsGkAtoms::map, nsGkAtoms::mark, nsGkAtoms::marquee,
|
||
nsGkAtoms::menu, nsGkAtoms::meta, nsGkAtoms::meter,
|
||
nsGkAtoms::nav, nsGkAtoms::nobr, nsGkAtoms::ol,
|
||
nsGkAtoms::optgroup, nsGkAtoms::option, nsGkAtoms::output,
|
||
nsGkAtoms::p, nsGkAtoms::picture, nsGkAtoms::plaintext,
|
||
nsGkAtoms::popup, nsGkAtoms::portal, nsGkAtoms::pre,
|
||
nsGkAtoms::progress, nsGkAtoms::q, nsGkAtoms::rb,
|
||
nsGkAtoms::rp, nsGkAtoms::rt, nsGkAtoms::rtc,
|
||
nsGkAtoms::ruby, nsGkAtoms::s, nsGkAtoms::samp,
|
||
nsGkAtoms::section, nsGkAtoms::select, nsGkAtoms::selectmenu,
|
||
nsGkAtoms::slot, nsGkAtoms::small, nsGkAtoms::source,
|
||
nsGkAtoms::span, nsGkAtoms::strike, nsGkAtoms::strong,
|
||
nsGkAtoms::style, nsGkAtoms::sub, nsGkAtoms::summary,
|
||
nsGkAtoms::sup, nsGkAtoms::table, nsGkAtoms::tbody,
|
||
nsGkAtoms::td, nsGkAtoms::_template, nsGkAtoms::textarea,
|
||
nsGkAtoms::tfoot, nsGkAtoms::th, nsGkAtoms::thead,
|
||
nsGkAtoms::time, nsGkAtoms::title, nsGkAtoms::tr,
|
||
nsGkAtoms::track, nsGkAtoms::tt, nsGkAtoms::u,
|
||
nsGkAtoms::ul, nsGkAtoms::var, nsGkAtoms::video,
|
||
nsGkAtoms::wbr, nsGkAtoms::xmp,
|
||
};
|
||
|
||
// https://wicg.github.io/sanitizer-api/#default-configuration
|
||
// default configuration's attribute allow list.
|
||
// Note: Currently all listed attributes are allowed for every element
|
||
// (e.g. they use "*").
|
||
// Compared to kBaselineAttributeAllowlist only deprecated allowpaymentrequest
|
||
// attribute is missing.
|
||
constexpr const nsStaticAtom* const kDefaultConfigurationAttributeAllowlist[] =
|
||
{
|
||
nsGkAtoms::abbr,
|
||
nsGkAtoms::accept,
|
||
nsGkAtoms::acceptcharset,
|
||
nsGkAtoms::charset,
|
||
nsGkAtoms::accesskey,
|
||
nsGkAtoms::action,
|
||
nsGkAtoms::align,
|
||
nsGkAtoms::alink,
|
||
nsGkAtoms::allow,
|
||
nsGkAtoms::allowfullscreen,
|
||
nsGkAtoms::alt,
|
||
nsGkAtoms::anchor,
|
||
nsGkAtoms::archive,
|
||
nsGkAtoms::as,
|
||
nsGkAtoms::async,
|
||
nsGkAtoms::autocapitalize,
|
||
nsGkAtoms::autocomplete,
|
||
// nsGkAtoms::autocorrect,
|
||
nsGkAtoms::autofocus,
|
||
// nsGkAtoms::autopictureinpicture,
|
||
nsGkAtoms::autoplay,
|
||
nsGkAtoms::axis,
|
||
nsGkAtoms::background,
|
||
nsGkAtoms::behavior,
|
||
nsGkAtoms::bgcolor,
|
||
nsGkAtoms::border,
|
||
nsGkAtoms::bordercolor,
|
||
nsGkAtoms::capture,
|
||
nsGkAtoms::cellpadding,
|
||
nsGkAtoms::cellspacing,
|
||
// nsGkAtoms::challenge,
|
||
nsGkAtoms::_char,
|
||
nsGkAtoms::charoff,
|
||
nsGkAtoms::charset,
|
||
nsGkAtoms::checked,
|
||
nsGkAtoms::cite,
|
||
nsGkAtoms::_class,
|
||
nsGkAtoms::classid,
|
||
nsGkAtoms::clear,
|
||
nsGkAtoms::code,
|
||
nsGkAtoms::codebase,
|
||
nsGkAtoms::codetype,
|
||
nsGkAtoms::color,
|
||
nsGkAtoms::cols,
|
||
nsGkAtoms::colspan,
|
||
nsGkAtoms::compact,
|
||
nsGkAtoms::content,
|
||
nsGkAtoms::contenteditable,
|
||
nsGkAtoms::controls,
|
||
// nsGkAtoms::controlslist,
|
||
// nsGkAtoms::conversiondestination,
|
||
nsGkAtoms::coords,
|
||
nsGkAtoms::crossorigin,
|
||
nsGkAtoms::csp,
|
||
nsGkAtoms::data,
|
||
nsGkAtoms::datetime,
|
||
nsGkAtoms::declare,
|
||
nsGkAtoms::decoding,
|
||
nsGkAtoms::_default,
|
||
nsGkAtoms::defer,
|
||
nsGkAtoms::dir,
|
||
nsGkAtoms::direction,
|
||
// nsGkAtoms::dirname,
|
||
nsGkAtoms::disabled,
|
||
// nsGkAtoms::disablepictureinpicture,
|
||
// nsGkAtoms::disableremoteplayback,
|
||
// nsGkAtoms::disallowdocumentaccess,
|
||
nsGkAtoms::download,
|
||
nsGkAtoms::draggable,
|
||
// nsGkAtoms::elementtiming,
|
||
nsGkAtoms::enctype,
|
||
nsGkAtoms::end,
|
||
nsGkAtoms::enterkeyhint,
|
||
nsGkAtoms::event,
|
||
nsGkAtoms::exportparts,
|
||
nsGkAtoms::face,
|
||
nsGkAtoms::_for,
|
||
nsGkAtoms::form,
|
||
nsGkAtoms::formaction,
|
||
nsGkAtoms::formenctype,
|
||
nsGkAtoms::formmethod,
|
||
nsGkAtoms::formnovalidate,
|
||
nsGkAtoms::formtarget,
|
||
nsGkAtoms::frame,
|
||
nsGkAtoms::frameborder,
|
||
nsGkAtoms::headers,
|
||
nsGkAtoms::height,
|
||
nsGkAtoms::hidden,
|
||
nsGkAtoms::high,
|
||
nsGkAtoms::href,
|
||
nsGkAtoms::hreflang,
|
||
// nsGkAtoms::hreftranslate,
|
||
nsGkAtoms::hspace,
|
||
nsGkAtoms::http,
|
||
// nsGkAtoms::equiv,
|
||
nsGkAtoms::id,
|
||
nsGkAtoms::imagesizes,
|
||
nsGkAtoms::imagesrcset,
|
||
// nsGkAtoms::importance,
|
||
// nsGkAtoms::impressiondata,
|
||
// nsGkAtoms::impressionexpiry,
|
||
// nsGkAtoms::incremental,
|
||
nsGkAtoms::inert,
|
||
nsGkAtoms::inputmode,
|
||
nsGkAtoms::integrity,
|
||
// nsGkAtoms::invisible,
|
||
nsGkAtoms::is,
|
||
nsGkAtoms::ismap,
|
||
// nsGkAtoms::keytype,
|
||
nsGkAtoms::kind,
|
||
nsGkAtoms::label,
|
||
nsGkAtoms::lang,
|
||
nsGkAtoms::language,
|
||
// nsGkAtoms::latencyhint,
|
||
nsGkAtoms::leftmargin,
|
||
nsGkAtoms::link,
|
||
// nsGkAtoms::list,
|
||
nsGkAtoms::loading,
|
||
nsGkAtoms::longdesc,
|
||
nsGkAtoms::loop,
|
||
nsGkAtoms::low,
|
||
nsGkAtoms::lowsrc,
|
||
nsGkAtoms::manifest,
|
||
nsGkAtoms::marginheight,
|
||
nsGkAtoms::marginwidth,
|
||
nsGkAtoms::max,
|
||
nsGkAtoms::maxlength,
|
||
// nsGkAtoms::mayscript,
|
||
nsGkAtoms::media,
|
||
nsGkAtoms::method,
|
||
nsGkAtoms::min,
|
||
nsGkAtoms::minlength,
|
||
nsGkAtoms::multiple,
|
||
nsGkAtoms::muted,
|
||
nsGkAtoms::name,
|
||
nsGkAtoms::nohref,
|
||
nsGkAtoms::nomodule,
|
||
nsGkAtoms::nonce,
|
||
nsGkAtoms::noresize,
|
||
nsGkAtoms::noshade,
|
||
nsGkAtoms::novalidate,
|
||
nsGkAtoms::nowrap,
|
||
nsGkAtoms::object,
|
||
nsGkAtoms::open,
|
||
nsGkAtoms::optimum,
|
||
nsGkAtoms::part,
|
||
nsGkAtoms::pattern,
|
||
nsGkAtoms::ping,
|
||
nsGkAtoms::placeholder,
|
||
// nsGkAtoms::playsinline,
|
||
// nsGkAtoms::policy,
|
||
nsGkAtoms::poster,
|
||
nsGkAtoms::preload,
|
||
// nsGkAtoms::pseudo,
|
||
nsGkAtoms::readonly,
|
||
nsGkAtoms::referrerpolicy,
|
||
nsGkAtoms::rel,
|
||
// nsGkAtoms::reportingorigin,
|
||
nsGkAtoms::required,
|
||
nsGkAtoms::resources,
|
||
nsGkAtoms::rev,
|
||
nsGkAtoms::reversed,
|
||
nsGkAtoms::role,
|
||
nsGkAtoms::rows,
|
||
nsGkAtoms::rowspan,
|
||
nsGkAtoms::rules,
|
||
nsGkAtoms::sandbox,
|
||
nsGkAtoms::scheme,
|
||
nsGkAtoms::scope,
|
||
// nsGkAtoms::scopes,
|
||
nsGkAtoms::scrollamount,
|
||
nsGkAtoms::scrolldelay,
|
||
nsGkAtoms::scrolling,
|
||
nsGkAtoms::select,
|
||
nsGkAtoms::selected,
|
||
// nsGkAtoms::shadowroot,
|
||
// nsGkAtoms::shadowrootdelegatesfocus,
|
||
nsGkAtoms::shape,
|
||
nsGkAtoms::size,
|
||
nsGkAtoms::sizes,
|
||
nsGkAtoms::slot,
|
||
nsGkAtoms::span,
|
||
nsGkAtoms::spellcheck,
|
||
nsGkAtoms::src,
|
||
nsGkAtoms::srcdoc,
|
||
nsGkAtoms::srclang,
|
||
nsGkAtoms::srcset,
|
||
nsGkAtoms::standby,
|
||
nsGkAtoms::start,
|
||
nsGkAtoms::step,
|
||
nsGkAtoms::style,
|
||
nsGkAtoms::summary,
|
||
nsGkAtoms::tabindex,
|
||
nsGkAtoms::target,
|
||
nsGkAtoms::text,
|
||
nsGkAtoms::title,
|
||
nsGkAtoms::topmargin,
|
||
nsGkAtoms::translate,
|
||
nsGkAtoms::truespeed,
|
||
// nsGkAtoms::trusttoken,
|
||
nsGkAtoms::type,
|
||
nsGkAtoms::usemap,
|
||
nsGkAtoms::valign,
|
||
nsGkAtoms::value,
|
||
nsGkAtoms::valuetype,
|
||
nsGkAtoms::version,
|
||
// nsGkAtoms::virtualkeyboardpolicy,
|
||
nsGkAtoms::vlink,
|
||
nsGkAtoms::vspace,
|
||
nsGkAtoms::webkitdirectory,
|
||
nsGkAtoms::width,
|
||
nsGkAtoms::wrap,
|
||
};
|
||
|
||
// https://wicg.github.io/sanitizer-api/#default-configuration
|
||
// default configuration's element allow list.
|
||
constexpr const nsStaticAtom* const kDefaultConfigurationElementAllowlist[] = {
|
||
nsGkAtoms::a, nsGkAtoms::abbr, nsGkAtoms::acronym,
|
||
nsGkAtoms::address, nsGkAtoms::area, nsGkAtoms::article,
|
||
nsGkAtoms::aside, nsGkAtoms::audio, nsGkAtoms::b,
|
||
nsGkAtoms::bdi, nsGkAtoms::bdo, nsGkAtoms::bgsound,
|
||
nsGkAtoms::big, nsGkAtoms::blockquote, nsGkAtoms::body,
|
||
nsGkAtoms::br, nsGkAtoms::button, nsGkAtoms::canvas,
|
||
nsGkAtoms::caption, nsGkAtoms::center, nsGkAtoms::cite,
|
||
nsGkAtoms::code, nsGkAtoms::col, nsGkAtoms::colgroup,
|
||
nsGkAtoms::datalist, nsGkAtoms::dd, nsGkAtoms::del,
|
||
nsGkAtoms::details, nsGkAtoms::dfn, nsGkAtoms::dialog,
|
||
nsGkAtoms::dir, nsGkAtoms::div, nsGkAtoms::dl,
|
||
nsGkAtoms::dt, nsGkAtoms::em, nsGkAtoms::fieldset,
|
||
nsGkAtoms::figcaption, nsGkAtoms::figure, nsGkAtoms::font,
|
||
nsGkAtoms::footer, nsGkAtoms::form, nsGkAtoms::h1,
|
||
nsGkAtoms::h2, nsGkAtoms::h3, nsGkAtoms::h4,
|
||
nsGkAtoms::h5, nsGkAtoms::h6, nsGkAtoms::head,
|
||
nsGkAtoms::header, nsGkAtoms::hgroup, nsGkAtoms::hr,
|
||
nsGkAtoms::html, nsGkAtoms::i, nsGkAtoms::img,
|
||
nsGkAtoms::input, nsGkAtoms::ins, nsGkAtoms::kbd,
|
||
nsGkAtoms::keygen, nsGkAtoms::label, nsGkAtoms::layer,
|
||
nsGkAtoms::legend, nsGkAtoms::li, nsGkAtoms::link,
|
||
nsGkAtoms::listing, nsGkAtoms::main, nsGkAtoms::map,
|
||
nsGkAtoms::mark, nsGkAtoms::marquee, nsGkAtoms::menu,
|
||
nsGkAtoms::meta, nsGkAtoms::meter, nsGkAtoms::nav,
|
||
nsGkAtoms::nobr, nsGkAtoms::ol, nsGkAtoms::optgroup,
|
||
nsGkAtoms::option, nsGkAtoms::output, nsGkAtoms::p,
|
||
nsGkAtoms::picture, nsGkAtoms::popup, nsGkAtoms::pre,
|
||
nsGkAtoms::progress, nsGkAtoms::q, nsGkAtoms::rb,
|
||
nsGkAtoms::rp, nsGkAtoms::rt, nsGkAtoms::rtc,
|
||
nsGkAtoms::ruby, nsGkAtoms::s, nsGkAtoms::samp,
|
||
nsGkAtoms::section, nsGkAtoms::select, nsGkAtoms::selectmenu,
|
||
nsGkAtoms::small, nsGkAtoms::source, nsGkAtoms::span,
|
||
nsGkAtoms::strike, nsGkAtoms::strong, nsGkAtoms::style,
|
||
nsGkAtoms::sub, nsGkAtoms::summary, nsGkAtoms::sup,
|
||
nsGkAtoms::table, nsGkAtoms::tbody, nsGkAtoms::td,
|
||
nsGkAtoms::tfoot, nsGkAtoms::th, nsGkAtoms::thead,
|
||
nsGkAtoms::time, nsGkAtoms::tr, nsGkAtoms::track,
|
||
nsGkAtoms::tt, nsGkAtoms::u, nsGkAtoms::ul,
|
||
nsGkAtoms::var, nsGkAtoms::video, nsGkAtoms::wbr,
|
||
};
|
||
|
||
nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sElementsHTML = nullptr;
|
||
nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sAttributesHTML = nullptr;
|
||
nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sPresAttributesHTML = nullptr;
|
||
nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sElementsSVG = nullptr;
|
||
nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sAttributesSVG = nullptr;
|
||
nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sElementsMathML = nullptr;
|
||
nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sAttributesMathML = nullptr;
|
||
nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sBaselineAttributeAllowlist =
|
||
nullptr;
|
||
nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sBaselineElementAllowlist =
|
||
nullptr;
|
||
nsTreeSanitizer::AtomsTable*
|
||
nsTreeSanitizer::sDefaultConfigurationAttributeAllowlist = nullptr;
|
||
nsTreeSanitizer::AtomsTable*
|
||
nsTreeSanitizer::sDefaultConfigurationElementAllowlist = nullptr;
|
||
nsIPrincipal* nsTreeSanitizer::sNullPrincipal = nullptr;
|
||
|
||
nsTreeSanitizer::nsTreeSanitizer(uint32_t aFlags)
|
||
: mAllowStyles(aFlags & nsIParserUtils::SanitizerAllowStyle),
|
||
mAllowComments(aFlags & nsIParserUtils::SanitizerAllowComments),
|
||
mDropNonCSSPresentation(aFlags &
|
||
nsIParserUtils::SanitizerDropNonCSSPresentation),
|
||
mDropForms(aFlags & nsIParserUtils::SanitizerDropForms),
|
||
mCidEmbedsOnly(aFlags & nsIParserUtils::SanitizerCidEmbedsOnly),
|
||
mDropMedia(aFlags & nsIParserUtils::SanitizerDropMedia),
|
||
mFullDocument(false),
|
||
mLogRemovals(aFlags & nsIParserUtils::SanitizerLogRemovals) {
|
||
if (mCidEmbedsOnly) {
|
||
// Sanitizing styles for external references is not supported.
|
||
mAllowStyles = false;
|
||
}
|
||
|
||
if (!sElementsHTML) {
|
||
// Initialize lazily to avoid having to initialize at all if the user
|
||
// doesn't paste HTML or load feeds.
|
||
InitializeStatics();
|
||
}
|
||
}
|
||
|
||
bool nsTreeSanitizer::MustFlatten(int32_t aNamespace, nsAtom* aLocal) {
|
||
if (mIsForSanitizerAPI) {
|
||
return MustFlattenForSanitizerAPI(aNamespace, aLocal);
|
||
}
|
||
|
||
if (aNamespace == kNameSpaceID_XHTML) {
|
||
if (mDropNonCSSPresentation &&
|
||
(nsGkAtoms::font == aLocal || nsGkAtoms::center == aLocal)) {
|
||
return true;
|
||
}
|
||
if (mDropForms &&
|
||
(nsGkAtoms::form == aLocal || nsGkAtoms::input == aLocal ||
|
||
nsGkAtoms::option == aLocal || nsGkAtoms::optgroup == aLocal)) {
|
||
return true;
|
||
}
|
||
if (mFullDocument &&
|
||
(nsGkAtoms::title == aLocal || nsGkAtoms::html == aLocal ||
|
||
nsGkAtoms::head == aLocal || nsGkAtoms::body == aLocal)) {
|
||
return false;
|
||
}
|
||
if (nsGkAtoms::_template == aLocal) {
|
||
return false;
|
||
}
|
||
return !sElementsHTML->Contains(aLocal);
|
||
}
|
||
if (aNamespace == kNameSpaceID_SVG) {
|
||
if (mCidEmbedsOnly || mDropMedia) {
|
||
// Sanitizing CSS-based URL references inside SVG presentational
|
||
// attributes is not supported, so flattening for cid: embed case.
|
||
return true;
|
||
}
|
||
return !sElementsSVG->Contains(aLocal);
|
||
}
|
||
if (aNamespace == kNameSpaceID_MathML) {
|
||
return !sElementsMathML->Contains(aLocal);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
bool nsTreeSanitizer::MustFlattenForSanitizerAPI(int32_t aNamespace,
|
||
nsAtom* aLocal) {
|
||
// This implements everything in
|
||
// https://wicg.github.io/sanitizer-api/#sanitize-action-for-an-element that
|
||
// is supposed to be blocked.
|
||
|
||
// Step 6. If element matches any name in config["blockElements"]: Return
|
||
// block.
|
||
if (mBlockElements &&
|
||
MatchesElementName(*mBlockElements, aNamespace, aLocal)) {
|
||
return true;
|
||
}
|
||
|
||
// Step 7. Let allow list be null.
|
||
// Step 8. If "allowElements" exists in config:
|
||
// Step 8.1. Then : Set allow list to config["allowElements"].
|
||
if (mAllowElements) {
|
||
// Step 9. If element does not match any name in allow list:
|
||
// Return block.
|
||
if (!MatchesElementName(*mAllowElements, aNamespace, aLocal)) {
|
||
return true;
|
||
}
|
||
} else {
|
||
// Step 8.2. Otherwise: Set allow list to the default configuration's
|
||
// element allow list.
|
||
|
||
// Step 9. If element does not match any name in allow list:
|
||
// Return block.
|
||
|
||
// The default configuration only contains HTML elements, so we can
|
||
// reject everything else.
|
||
if (aNamespace != kNameSpaceID_XHTML ||
|
||
!sDefaultConfigurationElementAllowlist->Contains(aLocal)) {
|
||
return true;
|
||
}
|
||
}
|
||
|
||
// Step 10. Return keep.
|
||
return false;
|
||
}
|
||
|
||
bool nsTreeSanitizer::IsURL(const nsStaticAtom* const* aURLs,
|
||
nsAtom* aLocalName) {
|
||
const nsStaticAtom* atom;
|
||
while ((atom = *aURLs)) {
|
||
if (atom == aLocalName) {
|
||
return true;
|
||
}
|
||
++aURLs;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
bool nsTreeSanitizer::MustPrune(int32_t aNamespace, nsAtom* aLocal,
|
||
mozilla::dom::Element* aElement) {
|
||
if (mIsForSanitizerAPI) {
|
||
return MustPruneForSanitizerAPI(aNamespace, aLocal, aElement);
|
||
}
|
||
|
||
// To avoid attacks where a MathML script becomes something that gets
|
||
// serialized in a way that it parses back as an HTML script, let's just
|
||
// drop elements with the local name 'script' regardless of namespace.
|
||
if (nsGkAtoms::script == aLocal) {
|
||
return true;
|
||
}
|
||
if (aNamespace == kNameSpaceID_XHTML) {
|
||
if (nsGkAtoms::title == aLocal && !mFullDocument) {
|
||
// emulate the quirks of the old parser
|
||
return true;
|
||
}
|
||
if (mDropForms &&
|
||
(nsGkAtoms::select == aLocal || nsGkAtoms::button == aLocal ||
|
||
nsGkAtoms::datalist == aLocal)) {
|
||
return true;
|
||
}
|
||
if (mDropMedia &&
|
||
(nsGkAtoms::img == aLocal || nsGkAtoms::video == aLocal ||
|
||
nsGkAtoms::audio == aLocal || nsGkAtoms::source == aLocal)) {
|
||
return true;
|
||
}
|
||
if (nsGkAtoms::meta == aLocal &&
|
||
(aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::charset) ||
|
||
aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv))) {
|
||
// Throw away charset declarations even if they also have microdata
|
||
// which they can't validly have.
|
||
return true;
|
||
}
|
||
if (((!mFullDocument && nsGkAtoms::meta == aLocal) ||
|
||
nsGkAtoms::link == aLocal) &&
|
||
!(aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::itemprop) ||
|
||
aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::itemscope))) {
|
||
// emulate old behavior for non-Microdata <meta> and <link> presumably
|
||
// in <head>. <meta> and <link> are whitelisted in order to avoid
|
||
// corrupting Microdata when they appear in <body>. Note that
|
||
// SanitizeAttributes() will remove the rel attribute from <link> and
|
||
// the name attribute from <meta>.
|
||
return true;
|
||
}
|
||
}
|
||
if (mAllowStyles) {
|
||
return nsGkAtoms::style == aLocal && !(aNamespace == kNameSpaceID_XHTML ||
|
||
aNamespace == kNameSpaceID_SVG);
|
||
}
|
||
if (nsGkAtoms::style == aLocal) {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
enum class ElementKind {
|
||
Regular,
|
||
Custom,
|
||
Unknown,
|
||
};
|
||
|
||
// https://wicg.github.io/sanitizer-api/#element-kind
|
||
static ElementKind GetElementKind(int32_t aNamespace, nsAtom* aLocal,
|
||
Element* aElement) {
|
||
// XXX(bug 1782926) The spec for this is known to be wrong.
|
||
// https://github.com/WICG/sanitizer-api/issues/147
|
||
|
||
// custom, if element’s local name is a valid custom element name,
|
||
// XXX shouldn't this happen after unknown.
|
||
if (nsContentUtils::IsCustomElementName(aLocal, kNameSpaceID_XHTML)) {
|
||
return ElementKind::Custom;
|
||
}
|
||
|
||
// unknown, if element is not in the [HTML] namespace
|
||
// XXX this doesn't really make sense to me
|
||
// https://github.com/WICG/sanitizer-api/issues/167
|
||
if (aNamespace != kNameSpaceID_XHTML) {
|
||
return ElementKind::Unknown;
|
||
}
|
||
|
||
// or if element’s local name denotes an unknown element
|
||
// — that is, if the element interface the [HTML] specification assigns to it
|
||
// would be HTMLUnknownElement,
|
||
if (nsCOMPtr<HTMLUnknownElement> el = do_QueryInterface(aElement)) {
|
||
return ElementKind::Unknown;
|
||
}
|
||
|
||
// regular, otherwise.
|
||
return ElementKind::Regular;
|
||
}
|
||
|
||
bool nsTreeSanitizer::MustPruneForSanitizerAPI(int32_t aNamespace,
|
||
nsAtom* aLocal,
|
||
Element* aElement) {
|
||
// This implements everything in
|
||
// https://wicg.github.io/sanitizer-api/#sanitize-action-for-an-element that
|
||
// is supposed to be dropped.
|
||
|
||
// Step 1. Let kind be element’s element kind.
|
||
ElementKind kind = GetElementKind(aNamespace, aLocal, aElement);
|
||
|
||
switch (kind) {
|
||
case ElementKind::Regular:
|
||
// Step 2. If kind is regular and element does not match any name in the
|
||
// baseline element allow list: Return drop.
|
||
if (!sBaselineElementAllowlist->Contains(aLocal)) {
|
||
return true;
|
||
}
|
||
break;
|
||
|
||
case ElementKind::Custom:
|
||
// Step 3. If kind is custom and if config["allowCustomElements"] does not
|
||
// exist or if config["allowCustomElements"] is false: Return drop.
|
||
if (!mAllowCustomElements) {
|
||
return true;
|
||
}
|
||
break;
|
||
|
||
case ElementKind::Unknown:
|
||
// Step 4. If kind is unknown and if config["allowUnknownMarkup"] does not
|
||
// exist or it config["allowUnknownMarkup"] is false: Return drop.
|
||
if (!mAllowUnknownMarkup) {
|
||
return true;
|
||
}
|
||
break;
|
||
}
|
||
|
||
// Step 5. If element matches any name in config["dropElements"]: Return drop.
|
||
if (mDropElements && MatchesElementName(*mDropElements, aNamespace, aLocal)) {
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Parses a style sheet and reserializes it with unsafe styles removed.
|
||
*
|
||
* @param aOriginal the original style sheet source
|
||
* @param aSanitized the reserialization without dangerous CSS.
|
||
* @param aDocument the document the style sheet belongs to
|
||
* @param aBaseURI the base URI to use
|
||
* @param aSanitizationKind the kind of style sanitization to use.
|
||
*/
|
||
static void SanitizeStyleSheet(const nsAString& aOriginal,
|
||
nsAString& aSanitized, Document* aDocument,
|
||
nsIURI* aBaseURI,
|
||
StyleSanitizationKind aSanitizationKind) {
|
||
aSanitized.Truncate();
|
||
|
||
NS_ConvertUTF16toUTF8 style(aOriginal);
|
||
nsIReferrerInfo* referrer =
|
||
aDocument->ReferrerInfoForInternalCSSAndSVGResources();
|
||
auto extraData =
|
||
MakeRefPtr<URLExtraData>(aBaseURI, referrer, aDocument->NodePrincipal());
|
||
RefPtr<RawServoStyleSheetContents> contents =
|
||
Servo_StyleSheet_FromUTF8Bytes(
|
||
/* loader = */ nullptr,
|
||
/* stylesheet = */ nullptr,
|
||
/* load_data = */ nullptr, &style,
|
||
css::SheetParsingMode::eAuthorSheetFeatures, extraData.get(),
|
||
/* line_number_offset = */ 0, aDocument->GetCompatibilityMode(),
|
||
/* reusable_sheets = */ nullptr,
|
||
/* use_counters = */ nullptr, StyleAllowImportRules::Yes,
|
||
aSanitizationKind, &aSanitized)
|
||
.Consume();
|
||
}
|
||
|
||
bool nsTreeSanitizer::SanitizeInlineStyle(
|
||
Element* aElement, StyleSanitizationKind aSanitizationKind) {
|
||
MOZ_ASSERT(aElement);
|
||
MOZ_ASSERT(aElement->IsHTMLElement(nsGkAtoms::style) ||
|
||
aElement->IsSVGElement(nsGkAtoms::style));
|
||
|
||
nsAutoString styleText;
|
||
nsContentUtils::GetNodeTextContent(aElement, false, styleText);
|
||
|
||
nsAutoString sanitizedStyle;
|
||
SanitizeStyleSheet(styleText, sanitizedStyle, aElement->OwnerDoc(),
|
||
aElement->GetBaseURI(), StyleSanitizationKind::Standard);
|
||
RemoveAllAttributesFromDescendants(aElement);
|
||
nsContentUtils::SetNodeTextContent(aElement, sanitizedStyle, true);
|
||
|
||
return sanitizedStyle.Length() != styleText.Length();
|
||
}
|
||
|
||
void nsTreeSanitizer::RemoveConditionalCSSFromSubtree(nsINode* aRoot) {
|
||
for (nsINode* node : ShadowIncludingTreeIterator(*aRoot)) {
|
||
if (!node->IsHTMLElement(nsGkAtoms::style) &&
|
||
!node->IsSVGElement(nsGkAtoms::style)) {
|
||
continue;
|
||
}
|
||
SanitizeInlineStyle(node->AsElement(),
|
||
StyleSanitizationKind::NoConditionalRules);
|
||
}
|
||
}
|
||
|
||
template <size_t Len>
|
||
static bool UTF16StringStartsWith(const char16_t* aStr, uint32_t aLength,
|
||
const char16_t (&aNeedle)[Len]) {
|
||
MOZ_ASSERT(aNeedle[Len - 1] == '\0',
|
||
"needle should be a UTF-16 encoded string literal");
|
||
|
||
if (aLength < Len - 1) {
|
||
return false;
|
||
}
|
||
for (size_t i = 0; i < Len - 1; i++) {
|
||
if (aStr[i] != aNeedle[i]) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
void nsTreeSanitizer::SanitizeAttributes(mozilla::dom::Element* aElement,
|
||
AllowedAttributes aAllowed) {
|
||
int32_t ac = (int)aElement->GetAttrCount();
|
||
|
||
for (int32_t i = ac - 1; i >= 0; --i) {
|
||
const nsAttrName* attrName = aElement->GetAttrNameAt(i);
|
||
int32_t attrNs = attrName->NamespaceID();
|
||
RefPtr<nsAtom> attrLocal = attrName->LocalName();
|
||
|
||
if (mIsForSanitizerAPI) {
|
||
if (MustDropAttribute(aElement, attrNs, attrLocal) ||
|
||
MustDropFunkyAttribute(aElement, attrNs, attrLocal)) {
|
||
aElement->UnsetAttr(kNameSpaceID_None, attrLocal, false);
|
||
if (mLogRemovals) {
|
||
LogMessage("Removed unsafe attribute.", aElement->OwnerDoc(),
|
||
aElement, attrLocal);
|
||
}
|
||
|
||
// in case the attribute removal shuffled the attribute order, start
|
||
// the loop again.
|
||
--ac;
|
||
i = ac; // i will be decremented immediately thanks to the for loop
|
||
}
|
||
continue;
|
||
}
|
||
|
||
if (kNameSpaceID_None == attrNs) {
|
||
if (aAllowed.mStyle && nsGkAtoms::style == attrLocal) {
|
||
continue;
|
||
}
|
||
if (aAllowed.mDangerousSrc && nsGkAtoms::src == attrLocal) {
|
||
continue;
|
||
}
|
||
if (IsURL(aAllowed.mURLs, attrLocal)) {
|
||
bool fragmentOnly = aElement->IsSVGElement(nsGkAtoms::use);
|
||
if (SanitizeURL(aElement, attrNs, attrLocal, fragmentOnly)) {
|
||
// in case the attribute removal shuffled the attribute order, start
|
||
// the loop again.
|
||
--ac;
|
||
i = ac; // i will be decremented immediately thanks to the for loop
|
||
continue;
|
||
}
|
||
// else fall through to see if there's another reason to drop this
|
||
// attribute (in particular if the attribute is background="" on an
|
||
// HTML element)
|
||
}
|
||
if (!mDropNonCSSPresentation &&
|
||
(aAllowed.mNames == sAttributesHTML) && // element is HTML
|
||
sPresAttributesHTML->Contains(attrLocal)) {
|
||
continue;
|
||
}
|
||
if (aAllowed.mNames->Contains(attrLocal) &&
|
||
!((attrLocal == nsGkAtoms::rel &&
|
||
aElement->IsHTMLElement(nsGkAtoms::link)) ||
|
||
(!mFullDocument && attrLocal == nsGkAtoms::name &&
|
||
aElement->IsHTMLElement(nsGkAtoms::meta)))) {
|
||
// name="" and rel="" are whitelisted, but treat them as blacklisted
|
||
// for <meta name> (fragment case) and <link rel> (all cases) to avoid
|
||
// document-wide metadata or styling overrides with non-conforming
|
||
// <meta name itemprop> or
|
||
// <link rel itemprop>
|
||
continue;
|
||
}
|
||
const char16_t* localStr = attrLocal->GetUTF16String();
|
||
uint32_t localLen = attrLocal->GetLength();
|
||
// Allow underscore to cater to the MCE editor library.
|
||
// Allow data-* on SVG and MathML, too, as a forward-compat measure.
|
||
// Allow aria-* on all for simplicity.
|
||
if (UTF16StringStartsWith(localStr, localLen, u"_") ||
|
||
UTF16StringStartsWith(localStr, localLen, u"data-") ||
|
||
UTF16StringStartsWith(localStr, localLen, u"aria-")) {
|
||
continue;
|
||
}
|
||
// else not allowed
|
||
} else if (kNameSpaceID_XML == attrNs) {
|
||
if (nsGkAtoms::lang == attrLocal || nsGkAtoms::space == attrLocal) {
|
||
continue;
|
||
}
|
||
// else not allowed
|
||
} else if (aAllowed.mXLink && kNameSpaceID_XLink == attrNs) {
|
||
if (nsGkAtoms::href == attrLocal) {
|
||
bool fragmentOnly = aElement->IsSVGElement(nsGkAtoms::use);
|
||
if (SanitizeURL(aElement, attrNs, attrLocal, fragmentOnly)) {
|
||
// in case the attribute removal shuffled the attribute order, start
|
||
// the loop again.
|
||
--ac;
|
||
i = ac; // i will be decremented immediately thanks to the for loop
|
||
}
|
||
continue;
|
||
}
|
||
if (nsGkAtoms::type == attrLocal || nsGkAtoms::title == attrLocal ||
|
||
nsGkAtoms::show == attrLocal || nsGkAtoms::actuate == attrLocal) {
|
||
continue;
|
||
}
|
||
// else not allowed
|
||
}
|
||
aElement->UnsetAttr(kNameSpaceID_None, attrLocal, false);
|
||
if (mLogRemovals) {
|
||
LogMessage("Removed unsafe attribute.", aElement->OwnerDoc(), aElement,
|
||
attrLocal);
|
||
}
|
||
// in case the attribute removal shuffled the attribute order, start the
|
||
// loop again.
|
||
--ac;
|
||
i = ac; // i will be decremented immediately thanks to the for loop
|
||
}
|
||
|
||
// If we've got HTML audio or video, add the controls attribute, because
|
||
// otherwise the content is unplayable with scripts removed.
|
||
if (aElement->IsAnyOfHTMLElements(nsGkAtoms::video, nsGkAtoms::audio)) {
|
||
aElement->SetAttr(kNameSpaceID_None, nsGkAtoms::controls, u""_ns, false);
|
||
}
|
||
}
|
||
|
||
// https://wicg.github.io/sanitizer-api/#element-matches-an-element-name
|
||
bool nsTreeSanitizer::MatchesElementName(ElementNameSet& aNames,
|
||
int32_t aNamespace,
|
||
nsAtom* aLocalName) {
|
||
return aNames.Contains(ElementName(aNamespace, aLocalName));
|
||
}
|
||
|
||
// https://wicg.github.io/sanitizer-api/#attribute-match-list
|
||
bool nsTreeSanitizer::MatchesAttributeMatchList(
|
||
AttributesToElementsMap& aMatchList, Element& aElement,
|
||
int32_t aAttrNamespace, nsAtom* aAttrLocalName) {
|
||
// Step 1. If attribute’s local name does not match the attribute match list
|
||
// list’s key and if the key is not "*": Return false.
|
||
ElementNameSet* names;
|
||
if (auto lookup =
|
||
aMatchList.Lookup(AttributeName(aAttrNamespace, aAttrLocalName))) {
|
||
names = lookup->get();
|
||
} else {
|
||
return false;
|
||
}
|
||
|
||
// Step 2. Let element be the attribute’s Element.
|
||
// Step 3. Let element name be element’s local name.
|
||
// Step 4. If element is a in either the SVG or MathML namespaces (i.e., it’s
|
||
// a foreign element), then prefix element name with the appropriate namespace
|
||
// designator plus a whitespace character.
|
||
|
||
// TODO: This is spec text is going to change.
|
||
int32_t namespaceID = aElement.NodeInfo()->NamespaceID();
|
||
RefPtr<nsAtom> nameAtom = aElement.NodeInfo()->NameAtom();
|
||
|
||
// Step 5. If list’s value does not contain element name and value is not
|
||
// ["*"]: Return false.
|
||
// Step 6. Return true.
|
||
|
||
// nullptr means star (*), i.e. any element.
|
||
if (!names) {
|
||
return true;
|
||
}
|
||
return MatchesElementName(*names, namespaceID, nameAtom);
|
||
}
|
||
|
||
// https://wicg.github.io/sanitizer-api/#sanitize-action-for-an-attribute
|
||
bool nsTreeSanitizer::MustDropAttribute(Element* aElement,
|
||
int32_t aAttrNamespace,
|
||
nsAtom* aAttrLocalName) {
|
||
// Step 1. Let kind be attribute’s attribute kind.
|
||
// Step 2. If kind is unknown and if config["allowUnknownMarkup"] does not
|
||
// exist or it config["allowUnknownMarkup"] is false: Return drop.
|
||
//
|
||
// TODO: Not clear how to determine if something is an "unknown" attribute.
|
||
// https://github.com/WICG/sanitizer-api/issues/147 should probably define
|
||
// an explicit list.
|
||
|
||
// Step 3. If kind is regular and attribute’s local name does not match any
|
||
// name in the baseline attribute allow list: Return drop.
|
||
if (!sBaselineAttributeAllowlist->Contains(aAttrLocalName)) {
|
||
return true;
|
||
}
|
||
|
||
// Step 4. If attribute matches any attribute match list in config’s attribute
|
||
// drop list: Return drop.
|
||
if (mDropAttributes &&
|
||
MatchesAttributeMatchList(*mDropAttributes, *aElement, aAttrNamespace,
|
||
aAttrLocalName)) {
|
||
return true;
|
||
}
|
||
|
||
// Step 5. If attribute allow list exists in config:
|
||
if (mAllowAttributes) {
|
||
// Step 5.1. Then let allow list be |config|["allowAttributes"].
|
||
// Step 6. If attribute does not match any attribute match list in allow
|
||
// list: Return drop.
|
||
if (!MatchesAttributeMatchList(*mAllowAttributes, *aElement, aAttrNamespace,
|
||
aAttrLocalName)) {
|
||
return true;
|
||
}
|
||
} else {
|
||
// Step 5.2. Otherwise: Let allow list be the default configuration's
|
||
// attribute allow list.
|
||
// Step 6. If attribute does not match any attribute
|
||
// match list in allow list: Return drop.
|
||
if (!sDefaultConfigurationAttributeAllowlist->Contains(aAttrLocalName)) {
|
||
return true;
|
||
}
|
||
}
|
||
|
||
// Step 7. Return keep.
|
||
return false;
|
||
}
|
||
|
||
// https://wicg.github.io/sanitizer-api/#handle-funky-elements
|
||
bool nsTreeSanitizer::MustDropFunkyAttribute(Element* aElement,
|
||
int32_t aAttrNamespace,
|
||
nsAtom* aAttrLocalName) {
|
||
// Step 1. If element’s element interface is HTMLTemplateElement:
|
||
// Note: This step is implemented in the main loop of SanitizeChildren.
|
||
|
||
// Step 2. If element’s element interface has a HTMLHyperlinkElementUtils
|
||
// mixin, and if element’s protocol property is "javascript:":
|
||
// TODO(https://github.com/WICG/sanitizer-api/issues/168)
|
||
if (aAttrLocalName == nsGkAtoms::href) {
|
||
if (nsCOMPtr<Link> link = do_QueryInterface(aElement)) {
|
||
nsCOMPtr<nsIURI> uri = link->GetURI();
|
||
if (uri && uri->SchemeIs("javascript")) {
|
||
// Step 2.1. Remove the `href` attribute from element.
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Step 3. if element’s element interface is HTMLFormElement, and if element’s
|
||
// action attribute is a URL with "javascript:" protocol:
|
||
if (auto* form = HTMLFormElement::FromNode(aElement)) {
|
||
if (aAttrNamespace == kNameSpaceID_None &&
|
||
aAttrLocalName == nsGkAtoms::action) {
|
||
nsCOMPtr<nsIURI> uri;
|
||
form->GetURIAttr(aAttrLocalName, nullptr, getter_AddRefs(uri));
|
||
if (uri && uri->SchemeIs("javascript")) {
|
||
// Step 3.1 Remove the `action` attribute from element.
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Step 4. if element’s element interface is HTMLInputElement or
|
||
// HTMLButtonElement, and if element’s formaction attribute is a [URL] with
|
||
// javascript: protocol
|
||
if (aElement->IsAnyOfHTMLElements(nsGkAtoms::input, nsGkAtoms::button) &&
|
||
aAttrNamespace == kNameSpaceID_None &&
|
||
aAttrLocalName == nsGkAtoms::formaction) {
|
||
// XXX nsGenericHTMLFormControlElementWithState::GetFormAction falls back to
|
||
// the document URI.
|
||
nsGenericHTMLElement* el = nsGenericHTMLElement::FromNode(aElement);
|
||
nsCOMPtr<nsIURI> uri;
|
||
el->GetURIAttr(aAttrLocalName, nullptr, getter_AddRefs(uri));
|
||
if (uri && uri->SchemeIs("javascript")) {
|
||
// Step 4.1 Remove the `formaction` attribute from element.
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
bool nsTreeSanitizer::SanitizeURL(mozilla::dom::Element* aElement,
|
||
int32_t aNamespace, nsAtom* aLocalName,
|
||
bool aFragmentsOnly) {
|
||
nsAutoString value;
|
||
aElement->GetAttr(aNamespace, aLocalName, value);
|
||
|
||
// Get value and remove mandatory quotes
|
||
static const char* kWhitespace = "\n\r\t\b";
|
||
const nsAString& v = nsContentUtils::TrimCharsInSet(kWhitespace, value);
|
||
// Fragment-only url cannot be harmful.
|
||
if (!v.IsEmpty() && v.First() == u'#') {
|
||
return false;
|
||
}
|
||
// if we allow only same-document fragment URLs, stop and remove here
|
||
if (aFragmentsOnly) {
|
||
aElement->UnsetAttr(aNamespace, aLocalName, false);
|
||
if (mLogRemovals) {
|
||
LogMessage("Removed unsafe URI from element attribute.",
|
||
aElement->OwnerDoc(), aElement, aLocalName);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
|
||
uint32_t flags = nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL;
|
||
|
||
nsCOMPtr<nsIURI> attrURI;
|
||
nsresult rv =
|
||
NS_NewURI(getter_AddRefs(attrURI), v, nullptr, aElement->GetBaseURI());
|
||
if (NS_SUCCEEDED(rv)) {
|
||
if (mCidEmbedsOnly && kNameSpaceID_None == aNamespace) {
|
||
if (nsGkAtoms::src == aLocalName || nsGkAtoms::background == aLocalName) {
|
||
// comm-central uses a hack that makes nsIURIs created with cid: specs
|
||
// actually have an about:blank spec. Therefore, nsIURI facilities are
|
||
// useless for cid: when comm-central code is participating.
|
||
if (!(v.Length() > 4 && (v[0] == 'c' || v[0] == 'C') &&
|
||
(v[1] == 'i' || v[1] == 'I') && (v[2] == 'd' || v[2] == 'D') &&
|
||
v[3] == ':')) {
|
||
rv = NS_ERROR_FAILURE;
|
||
}
|
||
} else if (nsGkAtoms::cdgroup_ == aLocalName ||
|
||
nsGkAtoms::altimg_ == aLocalName ||
|
||
nsGkAtoms::definitionURL_ == aLocalName) {
|
||
// Gecko doesn't fetch these now and shouldn't in the future, but
|
||
// in case someone goofs with these in the future, let's drop them.
|
||
rv = NS_ERROR_FAILURE;
|
||
} else {
|
||
rv = secMan->CheckLoadURIWithPrincipal(sNullPrincipal, attrURI, flags,
|
||
0);
|
||
}
|
||
} else {
|
||
rv = secMan->CheckLoadURIWithPrincipal(sNullPrincipal, attrURI, flags, 0);
|
||
}
|
||
}
|
||
if (NS_FAILED(rv)) {
|
||
aElement->UnsetAttr(aNamespace, aLocalName, false);
|
||
if (mLogRemovals) {
|
||
LogMessage("Removed unsafe URI from element attribute.",
|
||
aElement->OwnerDoc(), aElement, aLocalName);
|
||
}
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
void nsTreeSanitizer::Sanitize(DocumentFragment* aFragment) {
|
||
// If you want to relax these preconditions, be sure to check the code in
|
||
// here that notifies / does not notify or that fires mutation events if
|
||
// in tree.
|
||
MOZ_ASSERT(!aFragment->IsInUncomposedDoc(), "The fragment is in doc?");
|
||
|
||
mFullDocument = false;
|
||
SanitizeChildren(aFragment);
|
||
}
|
||
|
||
void nsTreeSanitizer::Sanitize(Document* aDocument) {
|
||
// If you want to relax these preconditions, be sure to check the code in
|
||
// here that notifies / does not notify or that fires mutation events if
|
||
// in tree.
|
||
#ifdef DEBUG
|
||
MOZ_ASSERT(!aDocument->GetContainer(), "The document is in a shell.");
|
||
RefPtr<mozilla::dom::Element> root = aDocument->GetRootElement();
|
||
MOZ_ASSERT(root->IsHTMLElement(nsGkAtoms::html), "Not HTML root.");
|
||
#endif
|
||
|
||
mFullDocument = true;
|
||
SanitizeChildren(aDocument);
|
||
}
|
||
|
||
void nsTreeSanitizer::SanitizeChildren(nsINode* aRoot) {
|
||
nsIContent* node = aRoot->GetFirstChild();
|
||
while (node) {
|
||
if (node->IsElement()) {
|
||
mozilla::dom::Element* elt = node->AsElement();
|
||
mozilla::dom::NodeInfo* nodeInfo = node->NodeInfo();
|
||
nsAtom* localName = nodeInfo->NameAtom();
|
||
int32_t ns = nodeInfo->NamespaceID();
|
||
|
||
if (MustPrune(ns, localName, elt)) {
|
||
if (mLogRemovals) {
|
||
LogMessage("Removing unsafe node.", elt->OwnerDoc(), elt);
|
||
}
|
||
RemoveAllAttributes(elt);
|
||
nsIContent* descendant = node;
|
||
while ((descendant = descendant->GetNextNode(node))) {
|
||
if (descendant->IsElement()) {
|
||
RemoveAllAttributes(descendant->AsElement());
|
||
}
|
||
}
|
||
nsIContent* next = node->GetNextNonChildNode(aRoot);
|
||
node->RemoveFromParent();
|
||
node = next;
|
||
continue;
|
||
}
|
||
if (auto* templateEl = HTMLTemplateElement::FromNode(elt)) {
|
||
// traverse into the DocFragment content attribute of template elements
|
||
bool wasFullDocument = mFullDocument;
|
||
mFullDocument = false;
|
||
RefPtr<DocumentFragment> frag = templateEl->Content();
|
||
SanitizeChildren(frag);
|
||
mFullDocument = wasFullDocument;
|
||
}
|
||
if (!mIsForSanitizerAPI && nsGkAtoms::style == localName) {
|
||
// If styles aren't allowed, style elements got pruned above. Even
|
||
// if styles are allowed, non-HTML, non-SVG style elements got pruned
|
||
// above.
|
||
NS_ASSERTION(ns == kNameSpaceID_XHTML || ns == kNameSpaceID_SVG,
|
||
"Should have only HTML or SVG here!");
|
||
if (SanitizeInlineStyle(elt, StyleSanitizationKind::Standard) &&
|
||
mLogRemovals) {
|
||
LogMessage("Removed some rules and/or properties from stylesheet.",
|
||
aRoot->OwnerDoc());
|
||
}
|
||
|
||
AllowedAttributes allowed;
|
||
allowed.mStyle = mAllowStyles;
|
||
if (ns == kNameSpaceID_XHTML) {
|
||
allowed.mNames = sAttributesHTML;
|
||
allowed.mURLs = kURLAttributesHTML;
|
||
} else {
|
||
allowed.mNames = sAttributesSVG;
|
||
allowed.mURLs = kURLAttributesSVG;
|
||
allowed.mXLink = true;
|
||
}
|
||
SanitizeAttributes(elt, allowed);
|
||
node = node->GetNextNonChildNode(aRoot);
|
||
continue;
|
||
}
|
||
if (MustFlatten(ns, localName)) {
|
||
if (mLogRemovals) {
|
||
LogMessage("Flattening unsafe node (descendants are preserved).",
|
||
elt->OwnerDoc(), elt);
|
||
}
|
||
RemoveAllAttributes(elt);
|
||
nsCOMPtr<nsIContent> next = node->GetNextNode(aRoot);
|
||
nsCOMPtr<nsIContent> parent = node->GetParent();
|
||
nsCOMPtr<nsIContent> child; // Must keep the child alive during move
|
||
ErrorResult rv;
|
||
while ((child = node->GetFirstChild())) {
|
||
nsCOMPtr<nsINode> refNode = node;
|
||
parent->InsertBefore(*child, refNode, rv);
|
||
if (rv.Failed()) {
|
||
break;
|
||
}
|
||
}
|
||
node->RemoveFromParent();
|
||
node = next;
|
||
continue;
|
||
}
|
||
NS_ASSERTION(ns == kNameSpaceID_XHTML || ns == kNameSpaceID_SVG ||
|
||
ns == kNameSpaceID_MathML,
|
||
"Should have only HTML, MathML or SVG here!");
|
||
AllowedAttributes allowed;
|
||
if (ns == kNameSpaceID_XHTML) {
|
||
allowed.mNames = sAttributesHTML;
|
||
allowed.mURLs = kURLAttributesHTML;
|
||
allowed.mStyle = mAllowStyles;
|
||
allowed.mDangerousSrc = nsGkAtoms::img == localName && !mCidEmbedsOnly;
|
||
SanitizeAttributes(elt, allowed);
|
||
} else if (ns == kNameSpaceID_SVG) {
|
||
allowed.mNames = sAttributesSVG;
|
||
allowed.mURLs = kURLAttributesSVG;
|
||
allowed.mXLink = true;
|
||
allowed.mStyle = mAllowStyles;
|
||
SanitizeAttributes(elt, allowed);
|
||
} else {
|
||
allowed.mNames = sAttributesMathML;
|
||
allowed.mURLs = kURLAttributesMathML;
|
||
allowed.mXLink = true;
|
||
SanitizeAttributes(elt, allowed);
|
||
}
|
||
node = node->GetNextNode(aRoot);
|
||
continue;
|
||
}
|
||
NS_ASSERTION(!node->GetFirstChild(), "How come non-element node had kids?");
|
||
nsIContent* next = node->GetNextNonChildNode(aRoot);
|
||
if (!mAllowComments && node->IsComment()) {
|
||
node->RemoveFromParent();
|
||
}
|
||
node = next;
|
||
}
|
||
}
|
||
|
||
void nsTreeSanitizer::RemoveAllAttributes(Element* aElement) {
|
||
const nsAttrName* attrName;
|
||
while ((attrName = aElement->GetAttrNameAt(0))) {
|
||
int32_t attrNs = attrName->NamespaceID();
|
||
RefPtr<nsAtom> attrLocal = attrName->LocalName();
|
||
aElement->UnsetAttr(attrNs, attrLocal, false);
|
||
}
|
||
}
|
||
|
||
void nsTreeSanitizer::RemoveAllAttributesFromDescendants(
|
||
mozilla::dom::Element* aElement) {
|
||
nsIContent* node = aElement->GetFirstChild();
|
||
while (node) {
|
||
if (node->IsElement()) {
|
||
mozilla::dom::Element* elt = node->AsElement();
|
||
RemoveAllAttributes(elt);
|
||
}
|
||
node = node->GetNextNode(aElement);
|
||
}
|
||
}
|
||
|
||
void nsTreeSanitizer::LogMessage(const char* aMessage, Document* aDoc,
|
||
Element* aElement, nsAtom* aAttr) {
|
||
if (mLogRemovals) {
|
||
nsAutoString msg;
|
||
msg.Assign(NS_ConvertASCIItoUTF16(aMessage));
|
||
if (aElement) {
|
||
msg.Append(u" Element: "_ns + aElement->LocalName() + u"."_ns);
|
||
}
|
||
if (aAttr) {
|
||
msg.Append(u" Attribute: "_ns + nsDependentAtomString(aAttr) + u"."_ns);
|
||
}
|
||
|
||
if (mInnerWindowID) {
|
||
nsContentUtils::ReportToConsoleByWindowID(
|
||
msg, nsIScriptError::warningFlag, "DOM"_ns, mInnerWindowID);
|
||
} else {
|
||
nsContentUtils::ReportToConsoleNonLocalized(
|
||
msg, nsIScriptError::warningFlag, "DOM"_ns, aDoc);
|
||
}
|
||
}
|
||
}
|
||
|
||
void nsTreeSanitizer::InitializeStatics() {
|
||
MOZ_ASSERT(!sElementsHTML, "Initializing a second time.");
|
||
|
||
sElementsHTML = new AtomsTable(ArrayLength(kElementsHTML));
|
||
for (uint32_t i = 0; kElementsHTML[i]; i++) {
|
||
sElementsHTML->Insert(kElementsHTML[i]);
|
||
}
|
||
|
||
sAttributesHTML = new AtomsTable(ArrayLength(kAttributesHTML));
|
||
for (uint32_t i = 0; kAttributesHTML[i]; i++) {
|
||
sAttributesHTML->Insert(kAttributesHTML[i]);
|
||
}
|
||
|
||
sPresAttributesHTML = new AtomsTable(ArrayLength(kPresAttributesHTML));
|
||
for (uint32_t i = 0; kPresAttributesHTML[i]; i++) {
|
||
sPresAttributesHTML->Insert(kPresAttributesHTML[i]);
|
||
}
|
||
|
||
sElementsSVG = new AtomsTable(ArrayLength(kElementsSVG));
|
||
for (uint32_t i = 0; kElementsSVG[i]; i++) {
|
||
sElementsSVG->Insert(kElementsSVG[i]);
|
||
}
|
||
|
||
sAttributesSVG = new AtomsTable(ArrayLength(kAttributesSVG));
|
||
for (uint32_t i = 0; kAttributesSVG[i]; i++) {
|
||
sAttributesSVG->Insert(kAttributesSVG[i]);
|
||
}
|
||
|
||
sElementsMathML = new AtomsTable(ArrayLength(kElementsMathML));
|
||
for (uint32_t i = 0; kElementsMathML[i]; i++) {
|
||
sElementsMathML->Insert(kElementsMathML[i]);
|
||
}
|
||
|
||
sAttributesMathML = new AtomsTable(ArrayLength(kAttributesMathML));
|
||
for (uint32_t i = 0; kAttributesMathML[i]; i++) {
|
||
sAttributesMathML->Insert(kAttributesMathML[i]);
|
||
}
|
||
|
||
sBaselineAttributeAllowlist =
|
||
new AtomsTable(ArrayLength(kBaselineAttributeAllowlist));
|
||
for (const auto* atom : kBaselineAttributeAllowlist) {
|
||
sBaselineAttributeAllowlist->Insert(atom);
|
||
}
|
||
|
||
sBaselineElementAllowlist =
|
||
new AtomsTable(ArrayLength(kBaselineElementAllowlist));
|
||
for (const auto* atom : kBaselineElementAllowlist) {
|
||
sBaselineElementAllowlist->Insert(atom);
|
||
}
|
||
|
||
sDefaultConfigurationAttributeAllowlist =
|
||
new AtomsTable(ArrayLength(kDefaultConfigurationAttributeAllowlist));
|
||
for (const auto* atom : kDefaultConfigurationAttributeAllowlist) {
|
||
sDefaultConfigurationAttributeAllowlist->Insert(atom);
|
||
}
|
||
|
||
sDefaultConfigurationElementAllowlist =
|
||
new AtomsTable(ArrayLength(kDefaultConfigurationElementAllowlist));
|
||
for (const auto* atom : kDefaultConfigurationElementAllowlist) {
|
||
sDefaultConfigurationElementAllowlist->Insert(atom);
|
||
}
|
||
|
||
nsCOMPtr<nsIPrincipal> principal =
|
||
NullPrincipal::CreateWithoutOriginAttributes();
|
||
principal.forget(&sNullPrincipal);
|
||
}
|
||
|
||
void nsTreeSanitizer::ReleaseStatics() {
|
||
delete sElementsHTML;
|
||
sElementsHTML = nullptr;
|
||
|
||
delete sAttributesHTML;
|
||
sAttributesHTML = nullptr;
|
||
|
||
delete sPresAttributesHTML;
|
||
sPresAttributesHTML = nullptr;
|
||
|
||
delete sElementsSVG;
|
||
sElementsSVG = nullptr;
|
||
|
||
delete sAttributesSVG;
|
||
sAttributesSVG = nullptr;
|
||
|
||
delete sElementsMathML;
|
||
sElementsMathML = nullptr;
|
||
|
||
delete sAttributesMathML;
|
||
sAttributesMathML = nullptr;
|
||
|
||
delete sBaselineAttributeAllowlist;
|
||
sBaselineAttributeAllowlist = nullptr;
|
||
|
||
delete sBaselineElementAllowlist;
|
||
sBaselineElementAllowlist = nullptr;
|
||
|
||
delete sDefaultConfigurationAttributeAllowlist;
|
||
sDefaultConfigurationAttributeAllowlist = nullptr;
|
||
|
||
delete sDefaultConfigurationElementAllowlist;
|
||
sDefaultConfigurationElementAllowlist = nullptr;
|
||
|
||
NS_IF_RELEASE(sNullPrincipal);
|
||
}
|
||
|
||
static int32_t ConvertNamespaceString(const nsAString& aNamespace,
|
||
bool aForAttribute,
|
||
mozilla::ErrorResult& aRv) {
|
||
int32_t namespaceID = nsNameSpaceManager::GetInstance()->GetNameSpaceID(
|
||
aNamespace, /* aInChromeDoc */ false);
|
||
if (namespaceID == kNameSpaceID_XHTML || namespaceID == kNameSpaceID_MathML ||
|
||
namespaceID == kNameSpaceID_SVG) {
|
||
return namespaceID;
|
||
}
|
||
if (aForAttribute && (namespaceID == kNameSpaceID_XMLNS ||
|
||
namespaceID == kNameSpaceID_XLink)) {
|
||
return namespaceID;
|
||
}
|
||
|
||
aRv.ThrowTypeError("Invalid namespace: \""_ns +
|
||
NS_ConvertUTF16toUTF8(aNamespace) + "\"."_ns);
|
||
return kNameSpaceID_Unknown;
|
||
}
|
||
|
||
UniquePtr<nsTreeSanitizer::ElementNameSet> nsTreeSanitizer::ConvertElements(
|
||
const nsTArray<OwningStringOrSanitizerElementNamespace>& aElements,
|
||
mozilla::ErrorResult& aRv) {
|
||
auto set = MakeUnique<ElementNameSet>(aElements.Length());
|
||
for (const auto& entry : aElements) {
|
||
if (entry.IsString()) {
|
||
RefPtr<nsAtom> nameAtom = NS_AtomizeMainThread(entry.GetAsString());
|
||
// The default namespace for elements is HTML.
|
||
ElementName elemName(kNameSpaceID_XHTML, std::move(nameAtom));
|
||
set->Insert(elemName);
|
||
} else {
|
||
const auto& elemNamespace = entry.GetAsSanitizerElementNamespace();
|
||
|
||
int32_t namespaceID =
|
||
ConvertNamespaceString(elemNamespace.mNamespace, false, aRv);
|
||
if (aRv.Failed()) {
|
||
return {};
|
||
}
|
||
|
||
RefPtr<nsAtom> nameAtom = NS_AtomizeMainThread(elemNamespace.mName);
|
||
ElementName elemName(namespaceID, std::move(nameAtom));
|
||
set->Insert(elemName);
|
||
}
|
||
}
|
||
|
||
return set;
|
||
}
|
||
|
||
UniquePtr<nsTreeSanitizer::ElementNameSet> nsTreeSanitizer::ConvertElements(
|
||
const OwningStarOrStringOrSanitizerElementNamespaceSequence& aElements,
|
||
mozilla::ErrorResult& aRv) {
|
||
if (aElements.IsStar()) {
|
||
return nullptr;
|
||
}
|
||
return ConvertElements(
|
||
aElements.GetAsStringOrSanitizerElementNamespaceSequence(), aRv);
|
||
}
|
||
|
||
UniquePtr<nsTreeSanitizer::AttributesToElementsMap>
|
||
nsTreeSanitizer::ConvertAttributes(
|
||
const nsTArray<SanitizerAttribute>& aAttributes, ErrorResult& aRv) {
|
||
auto map = MakeUnique<AttributesToElementsMap>();
|
||
|
||
for (const auto& entry : aAttributes) {
|
||
// The default namespace for attributes is the "null" namespace.
|
||
int32_t namespaceID = kNameSpaceID_None;
|
||
if (!entry.mNamespace.IsVoid()) {
|
||
namespaceID = ConvertNamespaceString(entry.mNamespace, true, aRv);
|
||
if (aRv.Failed()) {
|
||
return {};
|
||
}
|
||
}
|
||
RefPtr<nsAtom> attrAtom = NS_AtomizeMainThread(entry.mName);
|
||
AttributeName attrName(namespaceID, std::move(attrAtom));
|
||
|
||
UniquePtr<ElementNameSet> elements = ConvertElements(entry.mElements, aRv);
|
||
if (aRv.Failed()) {
|
||
return {};
|
||
}
|
||
map->InsertOrUpdate(attrName, std::move(elements));
|
||
}
|
||
|
||
return map;
|
||
}
|
||
|
||
void nsTreeSanitizer::WithWebSanitizerOptions(
|
||
nsIGlobalObject* aGlobal, const mozilla::dom::SanitizerConfig& aOptions,
|
||
ErrorResult& aRv) {
|
||
if (StaticPrefs::dom_security_sanitizer_logging()) {
|
||
mLogRemovals = true;
|
||
if (nsPIDOMWindowInner* win = aGlobal->AsInnerWindow()) {
|
||
mInnerWindowID = win->WindowID();
|
||
}
|
||
}
|
||
|
||
mIsForSanitizerAPI = true;
|
||
|
||
if (aOptions.mAllowComments.WasPassed()) {
|
||
mAllowComments = aOptions.mAllowComments.Value();
|
||
}
|
||
if (aOptions.mAllowCustomElements.WasPassed()) {
|
||
mAllowCustomElements = aOptions.mAllowCustomElements.Value();
|
||
}
|
||
if (aOptions.mAllowUnknownMarkup.WasPassed()) {
|
||
mAllowUnknownMarkup = aOptions.mAllowUnknownMarkup.Value();
|
||
}
|
||
|
||
if (aOptions.mAllowElements.WasPassed()) {
|
||
mAllowElements = ConvertElements(aOptions.mAllowElements.Value(), aRv);
|
||
if (aRv.Failed()) {
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (aOptions.mBlockElements.WasPassed()) {
|
||
mBlockElements = ConvertElements(aOptions.mBlockElements.Value(), aRv);
|
||
if (aRv.Failed()) {
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (aOptions.mDropElements.WasPassed()) {
|
||
mDropElements = ConvertElements(aOptions.mDropElements.Value(), aRv);
|
||
if (aRv.Failed()) {
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (aOptions.mAllowAttributes.WasPassed()) {
|
||
mAllowAttributes =
|
||
ConvertAttributes(aOptions.mAllowAttributes.Value(), aRv);
|
||
if (aRv.Failed()) {
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (aOptions.mDropAttributes.WasPassed()) {
|
||
mDropAttributes = ConvertAttributes(aOptions.mDropAttributes.Value(), aRv);
|
||
}
|
||
}
|