/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Simon Hausmann (hausmann@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) * Copyright (C) 2004-2021 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "config.h" #include "HTMLBodyElement.h" #include "CSSImageValue.h" #include "CSSParser.h" #include "CSSValueKeywords.h" #include "DOMWindow.h" #include "DOMWrapperWorld.h" #include "ElementInlines.h" #include "EventNames.h" #include "HTMLFrameElement.h" #include "HTMLIFrameElement.h" #include "HTMLNames.h" #include "HTMLParserIdioms.h" #include "JSHTMLBodyElement.h" #include "StyleProperties.h" #include #include namespace WebCore { WTF_MAKE_ISO_ALLOCATED_IMPL(HTMLBodyElement); using namespace HTMLNames; HTMLBodyElement::HTMLBodyElement(const QualifiedName& tagName, Document& document) : HTMLElement(tagName, document) { ASSERT(hasTagName(bodyTag)); } Ref HTMLBodyElement::create(Document& document) { return adoptRef(*new HTMLBodyElement(bodyTag, document)); } Ref HTMLBodyElement::create(const QualifiedName& tagName, Document& document) { return adoptRef(*new HTMLBodyElement(tagName, document)); } HTMLBodyElement::~HTMLBodyElement() = default; bool HTMLBodyElement::hasPresentationalHintsForAttribute(const QualifiedName& name) const { if (name == backgroundAttr || name == marginwidthAttr || name == leftmarginAttr || name == marginheightAttr || name == topmarginAttr || name == bgcolorAttr || name == textAttr || name == bgpropertiesAttr) return true; return HTMLElement::hasPresentationalHintsForAttribute(name); } void HTMLBodyElement::collectPresentationalHintsForAttribute(const QualifiedName& name, const AtomString& value, MutableStyleProperties& style) { if (name == backgroundAttr) { String url = stripLeadingAndTrailingHTMLSpaces(value); if (!url.isEmpty()) { auto imageValue = CSSImageValue::create(document().completeURL(url), LoadedFromOpaqueSource::No); imageValue.get().setInitiator(localName()); style.setProperty(CSSProperty(CSSPropertyBackgroundImage, WTFMove(imageValue))); } } else if (name == marginwidthAttr || name == leftmarginAttr) { addHTMLLengthToStyle(style, CSSPropertyMarginRight, value); addHTMLLengthToStyle(style, CSSPropertyMarginLeft, value); } else if (name == marginheightAttr || name == topmarginAttr) { addHTMLLengthToStyle(style, CSSPropertyMarginBottom, value); addHTMLLengthToStyle(style, CSSPropertyMarginTop, value); } else if (name == bgcolorAttr) { addHTMLColorToStyle(style, CSSPropertyBackgroundColor, value); } else if (name == textAttr) { addHTMLColorToStyle(style, CSSPropertyColor, value); } else if (name == bgpropertiesAttr) { if (equalLettersIgnoringASCIICase(value, "fixed")) addPropertyToPresentationalHintStyle(style, CSSPropertyBackgroundAttachment, CSSValueFixed); } else HTMLElement::collectPresentationalHintsForAttribute(name, value, style); } const AtomString& HTMLBodyElement::eventNameForWindowEventHandlerAttribute(const QualifiedName& attributeName) { static NeverDestroyed map = [] { EventHandlerNameMap map; JSHTMLBodyElement::forEachWindowEventHandlerContentAttribute([&] (const AtomString& attributeName, const AtomString& eventName) { // FIXME: Remove these special cases. These have has an [WindowEventHandler] line in the IDL but were not in this map before, so this preserves behavior. if (attributeName == onrejectionhandledAttr.get().localName() || attributeName == onunhandledrejectionAttr.get().localName()) return; map.add(attributeName.impl(), eventName); }); return map; }(); return eventNameForEventHandlerAttribute(attributeName, map); } void HTMLBodyElement::parseAttribute(const QualifiedName& name, const AtomString& value) { if (name == vlinkAttr || name == alinkAttr || name == linkAttr) { if (value.isNull()) { if (name == linkAttr) document().resetLinkColor(); else if (name == vlinkAttr) document().resetVisitedLinkColor(); else document().resetActiveLinkColor(); } else { Color color = CSSParser::parseColorWithoutContext(value, !document().inQuirksMode()); if (color.isValid()) { if (name == linkAttr) document().setLinkColor(color); else if (name == vlinkAttr) document().setVisitedLinkColor(color); else document().setActiveLinkColor(color); } } invalidateStyleForSubtree(); return; } // FIXME: Emit "selectionchange" event at /