/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 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. * * Portions are Copyright (C) 2002 Netscape Communications Corporation. * Other contributors: David Baron * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Alternatively, the document type parsing portions of this file may be used * under the terms of either the Mozilla Public License Version 1.1, found at * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html * (the "GPL"), in which case the provisions of the MPL or the GPL are * applicable instead of those above. If you wish to allow use of your * version of this file only under the terms of one of those two * licenses (the MPL or the GPL) and not to allow others to use your * version of this file under the LGPL, indicate your decision by * deleting the provisions above and replace them with the notice and * other provisions required by the MPL or the GPL, as the case may be. * If you do not delete the provisions above, a recipient may use your * version of this file under any of the LGPL, the MPL or the GPL. */ #include "config.h" #include "HTMLDocument.h" #include "CSSPropertyNames.h" #include "CommonVM.h" #include "CookieJar.h" #include "DOMWindow.h" #include "DocumentLoader.h" #include "DocumentType.h" #include "ElementChildIterator.h" #include "FocusController.h" #include "Frame.h" #include "FrameLoader.h" #include "FrameTree.h" #include "FrameView.h" #include "HTMLBodyElement.h" #include "HTMLCollection.h" #include "HTMLDocumentParser.h" #include "HTMLElementFactory.h" #include "HTMLFrameOwnerElement.h" #include "HTMLFrameSetElement.h" #include "HTMLHtmlElement.h" #include "HTMLIFrameElement.h" #include "HTMLNames.h" #include "Quirks.h" #include "ScriptController.h" #include "StyleResolver.h" #include #include #include namespace WebCore { WTF_MAKE_ISO_ALLOCATED_IMPL(HTMLDocument); using namespace HTMLNames; Ref HTMLDocument::createSynthesizedDocument(Frame& frame, const URL& url) { return adoptRef(*new HTMLDocument(&frame, frame.settings(), url, HTMLDocumentClass, Synthesized)); } HTMLDocument::HTMLDocument(Frame* frame, const Settings& settings, const URL& url, DocumentClassFlags documentClasses, unsigned constructionFlags) : Document(frame, settings, url, documentClasses | HTMLDocumentClass, constructionFlags) { clearXMLVersion(); } HTMLDocument::~HTMLDocument() = default; int HTMLDocument::width() { updateLayoutIgnorePendingStylesheets(); RefPtr frameView = view(); return frameView ? frameView->contentsWidth() : 0; } int HTMLDocument::height() { updateLayoutIgnorePendingStylesheets(); RefPtr frameView = view(); return frameView ? frameView->contentsHeight() : 0; } Ref HTMLDocument::createParser() { return HTMLDocumentParser::create(*this); } // https://html.spec.whatwg.org/multipage/dom.html#dom-document-nameditem std::optional, RefPtr, RefPtr>> HTMLDocument::namedItem(const AtomString& name) { if (name.isNull() || !hasDocumentNamedItem(*name.impl())) return std::nullopt; if (UNLIKELY(documentNamedItemContainsMultipleElements(*name.impl()))) { auto collection = documentNamedItems(name); ASSERT(collection->length() > 1); return Variant, RefPtr, RefPtr> { RefPtr { WTFMove(collection) } }; } auto& element = *documentNamedItem(*name.impl()); if (UNLIKELY(is(element))) { if (auto domWindow = makeRefPtr(downcast(element).contentWindow())) return Variant, RefPtr, RefPtr> { WTFMove(domWindow) }; } return Variant, RefPtr, RefPtr> { RefPtr { &element } }; } Vector HTMLDocument::supportedPropertyNames() const { if (Quirks::shouldOmitHTMLDocumentSupportedPropertyNames()) return { }; auto properties = m_documentNamedItem.keys(); // The specification says these should be sorted in document order but this would be expensive // and other browser engines do not comply with this part of the specification. For now, just // do an alphabetical sort to get consistent results. std::sort(properties.begin(), properties.end(), WTF::codePointCompareLessThan); return properties; } void HTMLDocument::addDocumentNamedItem(const AtomStringImpl& name, Element& item) { m_documentNamedItem.add(name, item, *this); addImpureProperty(AtomString(const_cast(&name))); } void HTMLDocument::removeDocumentNamedItem(const AtomStringImpl& name, Element& item) { m_documentNamedItem.remove(name, item); } void HTMLDocument::addWindowNamedItem(const AtomStringImpl& name, Element& item) { m_windowNamedItem.add(name, item, *this); } void HTMLDocument::removeWindowNamedItem(const AtomStringImpl& name, Element& item) { m_windowNamedItem.remove(name, item); } bool HTMLDocument::isCaseSensitiveAttribute(const QualifiedName& attributeName) { static const auto caseInsensitiveAttributeSet = makeNeverDestroyed([] { // This is the list of attributes in HTML 4.01 with values marked as "[CI]" or case-insensitive // Mozilla treats all other values as case-sensitive, thus so do we. static const QualifiedName* const names[] = { &accept_charsetAttr.get(), &acceptAttr.get(), &alignAttr.get(), &alinkAttr.get(), &axisAttr.get(), &bgcolorAttr.get(), &charsetAttr.get(), &checkedAttr.get(), &clearAttr.get(), &codetypeAttr.get(), &colorAttr.get(), &compactAttr.get(), &declareAttr.get(), &deferAttr.get(), &dirAttr.get(), &disabledAttr.get(), &enctypeAttr.get(), &faceAttr.get(), &frameAttr.get(), &hreflangAttr.get(), &http_equivAttr.get(), &langAttr.get(), &languageAttr.get(), &linkAttr.get(), &mediaAttr.get(), &methodAttr.get(), &multipleAttr.get(), &nohrefAttr.get(), &noresizeAttr.get(), &noshadeAttr.get(), &nowrapAttr.get(), &readonlyAttr.get(), &relAttr.get(), &revAttr.get(), &rulesAttr.get(), &scopeAttr.get(), &scrollingAttr.get(), &selectedAttr.get(), &shapeAttr.get(), &targetAttr.get(), &textAttr.get(), &typeAttr.get(), &valignAttr.get(), &valuetypeAttr.get(), &vlinkAttr.get(), }; MemoryCompactLookupOnlyRobinHoodHashSet set; for (auto* name : names) set.add(name->localName()); return set; }()); bool isPossibleHTMLAttr = !attributeName.hasPrefix() && attributeName.namespaceURI().isNull(); return !isPossibleHTMLAttr || !caseInsensitiveAttributeSet.get().contains(attributeName.localName()); } bool HTMLDocument::isFrameSet() const { if (!documentElement()) return false; return !!childrenOfType(*documentElement()).first(); } Ref HTMLDocument::cloneDocumentWithoutChildren() const { return create(nullptr, settings(), url()); } }