1/*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 * Portions are Copyright (C) 2002 Netscape Communications Corporation.
22 * Other contributors: David Baron <dbaron@fas.harvard.edu>
23 *
24 * This library is free software; you can redistribute it and/or
25 * modify it under the terms of the GNU Lesser General Public
26 * License as published by the Free Software Foundation; either
27 * version 2.1 of the License, or (at your option) any later version.
28 *
29 * This library is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
32 * Lesser General Public License for more details.
33 *
34 * You should have received a copy of the GNU Lesser General Public
35 * License along with this library; if not, write to the Free Software
36 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
37 *
38 * Alternatively, the document type parsing portions of this file may be used
39 * under the terms of either the Mozilla Public License Version 1.1, found at
40 * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
41 * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
42 * (the "GPL"), in which case the provisions of the MPL or the GPL are
43 * applicable instead of those above. If you wish to allow use of your
44 * version of this file only under the terms of one of those two
45 * licenses (the MPL or the GPL) and not to allow others to use your
46 * version of this file under the LGPL, indicate your decision by
47 * deleting the provisions above and replace them with the notice and
48 * other provisions required by the MPL or the GPL, as the case may be.
49 * If you do not delete the provisions above, a recipient may use your
50 * version of this file under any of the LGPL, the MPL or the GPL.
51 */
52
53#include "config.h"
54#include "HTMLDocument.h"
55
56#include "CSSPropertyNames.h"
57#include "CommonVM.h"
58#include "CookieJar.h"
59#include "DOMWindow.h"
60#include "DocumentLoader.h"
61#include "DocumentType.h"
62#include "ElementChildIterator.h"
63#include "FocusController.h"
64#include "Frame.h"
65#include "FrameLoader.h"
66#include "FrameTree.h"
67#include "FrameView.h"
68#include "HTMLBodyElement.h"
69#include "HTMLCollection.h"
70#include "HTMLDocumentParser.h"
71#include "HTMLElementFactory.h"
72#include "HTMLFrameOwnerElement.h"
73#include "HTMLFrameSetElement.h"
74#include "HTMLHtmlElement.h"
75#include "HTMLIFrameElement.h"
76#include "HTMLNames.h"
77#include "HashTools.h"
78#include "ScriptController.h"
79#include "StyleResolver.h"
80#include <wtf/IsoMallocInlines.h>
81#include <wtf/text/CString.h>
82
83namespace WebCore {
84
85WTF_MAKE_ISO_ALLOCATED_IMPL(HTMLDocument);
86
87using namespace HTMLNames;
88
89HTMLDocument::HTMLDocument(Frame* frame, const URL& url, DocumentClassFlags documentClasses, unsigned constructionFlags)
90 : Document(frame, url, documentClasses | HTMLDocumentClass, constructionFlags)
91{
92 clearXMLVersion();
93}
94
95HTMLDocument::~HTMLDocument() = default;
96
97int HTMLDocument::width()
98{
99 updateLayoutIgnorePendingStylesheets();
100 RefPtr<FrameView> frameView = view();
101 return frameView ? frameView->contentsWidth() : 0;
102}
103
104int HTMLDocument::height()
105{
106 updateLayoutIgnorePendingStylesheets();
107 RefPtr<FrameView> frameView = view();
108 return frameView ? frameView->contentsHeight() : 0;
109}
110
111Ref<DocumentParser> HTMLDocument::createParser()
112{
113 return HTMLDocumentParser::create(*this);
114}
115
116// https://html.spec.whatwg.org/multipage/dom.html#dom-document-nameditem
117Optional<Variant<RefPtr<WindowProxy>, RefPtr<Element>, RefPtr<HTMLCollection>>> HTMLDocument::namedItem(const AtomicString& name)
118{
119 if (name.isNull() || !hasDocumentNamedItem(*name.impl()))
120 return WTF::nullopt;
121
122 if (UNLIKELY(documentNamedItemContainsMultipleElements(*name.impl()))) {
123 auto collection = documentNamedItems(name);
124 ASSERT(collection->length() > 1);
125 return Variant<RefPtr<WindowProxy>, RefPtr<Element>, RefPtr<HTMLCollection>> { RefPtr<HTMLCollection> { WTFMove(collection) } };
126 }
127
128 auto& element = *documentNamedItem(*name.impl());
129 if (UNLIKELY(is<HTMLIFrameElement>(element))) {
130 if (auto domWindow = makeRefPtr(downcast<HTMLIFrameElement>(element).contentWindow()))
131 return Variant<RefPtr<WindowProxy>, RefPtr<Element>, RefPtr<HTMLCollection>> { WTFMove(domWindow) };
132 }
133
134 return Variant<RefPtr<WindowProxy>, RefPtr<Element>, RefPtr<HTMLCollection>> { RefPtr<Element> { &element } };
135}
136
137Vector<AtomicString> HTMLDocument::supportedPropertyNames() const
138{
139 // https://html.spec.whatwg.org/multipage/dom.html#dom-document-namedItem-which
140 //
141 // ... The supported property names of a Document object document at any moment consist of the following, in
142 // tree order according to the element that contributed them, ignoring later duplicates, and with values from
143 // id attributes coming before values from name attributes when the same element contributes both:
144 //
145 // - the value of the name content attribute for all applet, exposed embed, form, iframe, img, and exposed
146 // object elements that have a non-empty name content attribute and are in a document tree with document
147 // as their root;
148 // - the value of the id content attribute for all applet and exposed object elements that have a non-empty
149 // id content attribute and are in a document tree with document as their root; and
150 // - the value of the id content attribute for all img elements that have both a non-empty id content attribute
151 // and a non-empty name content attribute, and are in a document tree with document as their root.
152
153 // FIXME: Implement.
154 return { };
155}
156
157void HTMLDocument::addDocumentNamedItem(const AtomicStringImpl& name, Element& item)
158{
159 m_documentNamedItem.add(name, item, *this);
160 addImpureProperty(AtomicString(const_cast<AtomicStringImpl*>(&name)));
161}
162
163void HTMLDocument::removeDocumentNamedItem(const AtomicStringImpl& name, Element& item)
164{
165 m_documentNamedItem.remove(name, item);
166}
167
168void HTMLDocument::addWindowNamedItem(const AtomicStringImpl& name, Element& item)
169{
170 m_windowNamedItem.add(name, item, *this);
171}
172
173void HTMLDocument::removeWindowNamedItem(const AtomicStringImpl& name, Element& item)
174{
175 m_windowNamedItem.remove(name, item);
176}
177
178bool HTMLDocument::isCaseSensitiveAttribute(const QualifiedName& attributeName)
179{
180 static const auto caseInsensitiveAttributeSet = makeNeverDestroyed([] {
181 // This is the list of attributes in HTML 4.01 with values marked as "[CI]" or case-insensitive
182 // Mozilla treats all other values as case-sensitive, thus so do we.
183 static const QualifiedName* const names[] = {
184 &accept_charsetAttr.get(),
185 &acceptAttr.get(),
186 &alignAttr.get(),
187 &alinkAttr.get(),
188 &axisAttr.get(),
189 &bgcolorAttr.get(),
190 &charsetAttr.get(),
191 &checkedAttr.get(),
192 &clearAttr.get(),
193 &codetypeAttr.get(),
194 &colorAttr.get(),
195 &compactAttr.get(),
196 &declareAttr.get(),
197 &deferAttr.get(),
198 &dirAttr.get(),
199 &disabledAttr.get(),
200 &enctypeAttr.get(),
201 &faceAttr.get(),
202 &frameAttr.get(),
203 &hreflangAttr.get(),
204 &http_equivAttr.get(),
205 &langAttr.get(),
206 &languageAttr.get(),
207 &linkAttr.get(),
208 &mediaAttr.get(),
209 &methodAttr.get(),
210 &multipleAttr.get(),
211 &nohrefAttr.get(),
212 &noresizeAttr.get(),
213 &noshadeAttr.get(),
214 &nowrapAttr.get(),
215 &readonlyAttr.get(),
216 &relAttr.get(),
217 &revAttr.get(),
218 &rulesAttr.get(),
219 &scopeAttr.get(),
220 &scrollingAttr.get(),
221 &selectedAttr.get(),
222 &shapeAttr.get(),
223 &targetAttr.get(),
224 &textAttr.get(),
225 &typeAttr.get(),
226 &valignAttr.get(),
227 &valuetypeAttr.get(),
228 &vlinkAttr.get(),
229 };
230 HashSet<AtomicString> set;
231 for (auto* name : names)
232 set.add(name->localName());
233 return set;
234 }());
235
236 bool isPossibleHTMLAttr = !attributeName.hasPrefix() && attributeName.namespaceURI().isNull();
237 return !isPossibleHTMLAttr || !caseInsensitiveAttributeSet.get().contains(attributeName.localName());
238}
239
240bool HTMLDocument::isFrameSet() const
241{
242 if (!documentElement())
243 return false;
244 return !!childrenOfType<HTMLFrameSetElement>(*documentElement()).first();
245}
246
247Ref<Document> HTMLDocument::cloneDocumentWithoutChildren() const
248{
249 return create(nullptr, url());
250}
251
252}
253