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 "CookieJar.h"
58#include "DocumentLoader.h"
59#include "DocumentType.h"
60#include "ExceptionCode.h"
61#include "FocusController.h"
62#include "Frame.h"
63#include "FrameLoader.h"
64#include "FrameTree.h"
65#include "FrameView.h"
66#include "HashTools.h"
67#include "HTMLDocumentParser.h"
68#include "HTMLBodyElement.h"
69#include "HTMLElementFactory.h"
70#include "HTMLFrameOwnerElement.h"
71#include "HTMLFrameSetElement.h"
72#include "HTMLNames.h"
73#include "JSDOMBinding.h"
74#include "Page.h"
75#include "ScriptController.h"
76#include "Settings.h"
77#include "StyleResolver.h"
78#include <wtf/text/CString.h>
79
80namespace WebCore {
81
82using namespace HTMLNames;
83
84HTMLDocument::HTMLDocument(Frame* frame, const URL& url, DocumentClassFlags documentClasses, unsigned constructionFlags)
85    : Document(frame, url, documentClasses | HTMLDocumentClass, constructionFlags)
86{
87    clearXMLVersion();
88}
89
90HTMLDocument::~HTMLDocument()
91{
92}
93
94int HTMLDocument::width()
95{
96    updateLayoutIgnorePendingStylesheets();
97    FrameView* frameView = view();
98    return frameView ? frameView->contentsWidth() : 0;
99}
100
101int HTMLDocument::height()
102{
103    updateLayoutIgnorePendingStylesheets();
104    FrameView* frameView = view();
105    return frameView ? frameView->contentsHeight() : 0;
106}
107
108String HTMLDocument::dir()
109{
110    HTMLElement* b = body();
111    if (!b)
112        return String();
113    return b->getAttribute(dirAttr);
114}
115
116void HTMLDocument::setDir(const String& value)
117{
118    HTMLElement* b = body();
119    if (b)
120        b->setAttribute(dirAttr, value);
121}
122
123String HTMLDocument::designMode() const
124{
125    return inDesignMode() ? "on" : "off";
126}
127
128void HTMLDocument::setDesignMode(const String& value)
129{
130    InheritedBool mode;
131    if (equalIgnoringCase(value, "on"))
132        mode = on;
133    else if (equalIgnoringCase(value, "off"))
134        mode = off;
135    else
136        mode = inherit;
137    Document::setDesignMode(mode);
138}
139
140const AtomicString& HTMLDocument::bgColor() const
141{
142    HTMLElement* bodyElement = body();
143    if (!bodyElement || !isHTMLBodyElement(bodyElement))
144        return emptyAtom;
145    return bodyElement->fastGetAttribute(bgcolorAttr);
146}
147
148void HTMLDocument::setBgColor(const String& value)
149{
150    HTMLElement* bodyElement = body();
151    if (!bodyElement || !isHTMLBodyElement(bodyElement))
152        return;
153    bodyElement->setAttribute(bgcolorAttr, value);
154}
155
156const AtomicString& HTMLDocument::fgColor() const
157{
158    HTMLElement* bodyElement = body();
159    if (!bodyElement || !isHTMLBodyElement(bodyElement))
160        return emptyAtom;
161    return bodyElement->fastGetAttribute(textAttr);
162}
163
164void HTMLDocument::setFgColor(const String& value)
165{
166    HTMLElement* bodyElement = body();
167    if (!bodyElement || !isHTMLBodyElement(bodyElement))
168        return;
169    bodyElement->setAttribute(textAttr, value);
170}
171
172const AtomicString& HTMLDocument::alinkColor() const
173{
174    HTMLElement* bodyElement = body();
175    if (!bodyElement || !isHTMLBodyElement(bodyElement))
176        return emptyAtom;
177    return bodyElement->fastGetAttribute(alinkAttr);
178}
179
180void HTMLDocument::setAlinkColor(const String& value)
181{
182    HTMLElement* bodyElement = body();
183    if (!bodyElement || !isHTMLBodyElement(bodyElement))
184        return;
185    bodyElement->setAttribute(alinkAttr, value);
186}
187
188const AtomicString& HTMLDocument::linkColor() const
189{
190    HTMLElement* bodyElement = body();
191    if (!bodyElement || !isHTMLBodyElement(bodyElement))
192        return emptyAtom;
193    return bodyElement->fastGetAttribute(linkAttr);
194}
195
196void HTMLDocument::setLinkColor(const String& value)
197{
198    HTMLElement* bodyElement = body();
199    if (!bodyElement || !isHTMLBodyElement(bodyElement))
200        return;
201    return bodyElement->setAttribute(linkAttr, value);
202}
203
204const AtomicString& HTMLDocument::vlinkColor() const
205{
206    HTMLElement* bodyElement = body();
207    if (!bodyElement || !isHTMLBodyElement(bodyElement))
208        return emptyAtom;
209    return bodyElement->fastGetAttribute(vlinkAttr);
210}
211
212void HTMLDocument::setVlinkColor(const String& value)
213{
214    HTMLElement* bodyElement = body();
215    if (!bodyElement || !isHTMLBodyElement(bodyElement))
216        return;
217    return bodyElement->setAttribute(vlinkAttr, value);
218}
219
220void HTMLDocument::captureEvents()
221{
222}
223
224void HTMLDocument::releaseEvents()
225{
226}
227
228PassRefPtr<DocumentParser> HTMLDocument::createParser()
229{
230    return HTMLDocumentParser::create(*this);
231}
232
233// --------------------------------------------------------------------------
234// not part of the DOM
235// --------------------------------------------------------------------------
236
237PassRefPtr<Element> HTMLDocument::createElement(const AtomicString& name, ExceptionCode& ec)
238{
239    if (!isValidName(name)) {
240        ec = INVALID_CHARACTER_ERR;
241        return 0;
242    }
243    return HTMLElementFactory::createElement(QualifiedName(nullAtom, name.lower(), xhtmlNamespaceURI), *this);
244}
245
246static void addLocalNameToSet(HashSet<AtomicStringImpl*>* set, const QualifiedName& qName)
247{
248    set->add(qName.localName().impl());
249}
250
251static HashSet<AtomicStringImpl*>* createHtmlCaseInsensitiveAttributesSet()
252{
253    // This is the list of attributes in HTML 4.01 with values marked as "[CI]" or case-insensitive
254    // Mozilla treats all other values as case-sensitive, thus so do we.
255    HashSet<AtomicStringImpl*>* attrSet = new HashSet<AtomicStringImpl*>;
256
257    addLocalNameToSet(attrSet, accept_charsetAttr);
258    addLocalNameToSet(attrSet, acceptAttr);
259    addLocalNameToSet(attrSet, alignAttr);
260    addLocalNameToSet(attrSet, alinkAttr);
261    addLocalNameToSet(attrSet, axisAttr);
262    addLocalNameToSet(attrSet, bgcolorAttr);
263    addLocalNameToSet(attrSet, charsetAttr);
264    addLocalNameToSet(attrSet, checkedAttr);
265    addLocalNameToSet(attrSet, clearAttr);
266    addLocalNameToSet(attrSet, codetypeAttr);
267    addLocalNameToSet(attrSet, colorAttr);
268    addLocalNameToSet(attrSet, compactAttr);
269    addLocalNameToSet(attrSet, declareAttr);
270    addLocalNameToSet(attrSet, deferAttr);
271    addLocalNameToSet(attrSet, dirAttr);
272    addLocalNameToSet(attrSet, disabledAttr);
273    addLocalNameToSet(attrSet, enctypeAttr);
274    addLocalNameToSet(attrSet, faceAttr);
275    addLocalNameToSet(attrSet, frameAttr);
276    addLocalNameToSet(attrSet, hreflangAttr);
277    addLocalNameToSet(attrSet, http_equivAttr);
278    addLocalNameToSet(attrSet, langAttr);
279    addLocalNameToSet(attrSet, languageAttr);
280    addLocalNameToSet(attrSet, linkAttr);
281    addLocalNameToSet(attrSet, mediaAttr);
282    addLocalNameToSet(attrSet, methodAttr);
283    addLocalNameToSet(attrSet, multipleAttr);
284    addLocalNameToSet(attrSet, nohrefAttr);
285    addLocalNameToSet(attrSet, noresizeAttr);
286    addLocalNameToSet(attrSet, noshadeAttr);
287    addLocalNameToSet(attrSet, nowrapAttr);
288    addLocalNameToSet(attrSet, readonlyAttr);
289    addLocalNameToSet(attrSet, relAttr);
290    addLocalNameToSet(attrSet, revAttr);
291    addLocalNameToSet(attrSet, rulesAttr);
292    addLocalNameToSet(attrSet, scopeAttr);
293    addLocalNameToSet(attrSet, scrollingAttr);
294    addLocalNameToSet(attrSet, selectedAttr);
295    addLocalNameToSet(attrSet, shapeAttr);
296    addLocalNameToSet(attrSet, targetAttr);
297    addLocalNameToSet(attrSet, textAttr);
298    addLocalNameToSet(attrSet, typeAttr);
299    addLocalNameToSet(attrSet, valignAttr);
300    addLocalNameToSet(attrSet, valuetypeAttr);
301    addLocalNameToSet(attrSet, vlinkAttr);
302
303    return attrSet;
304}
305
306void HTMLDocument::addDocumentNamedItem(const AtomicStringImpl& name, Element& item)
307{
308    m_documentNamedItem.add(name, item, *this);
309    addImpureProperty(AtomicString(const_cast<AtomicStringImpl*>(&name)));
310}
311
312void HTMLDocument::removeDocumentNamedItem(const AtomicStringImpl& name, Element& item)
313{
314    m_documentNamedItem.remove(name, item);
315}
316
317void HTMLDocument::addWindowNamedItem(const AtomicStringImpl& name, Element& item)
318{
319    m_windowNamedItem.add(name, item, *this);
320}
321
322void HTMLDocument::removeWindowNamedItem(const AtomicStringImpl& name, Element& item)
323{
324    m_windowNamedItem.remove(name, item);
325}
326
327bool HTMLDocument::isCaseSensitiveAttribute(const QualifiedName& attributeName)
328{
329    static HashSet<AtomicStringImpl*>* htmlCaseInsensitiveAttributesSet = createHtmlCaseInsensitiveAttributesSet();
330    bool isPossibleHTMLAttr = !attributeName.hasPrefix() && (attributeName.namespaceURI() == nullAtom);
331    return !isPossibleHTMLAttr || !htmlCaseInsensitiveAttributesSet->contains(attributeName.localName().impl());
332}
333
334void HTMLDocument::clear()
335{
336    // FIXME: This does nothing, and that seems unlikely to be correct.
337    // We've long had a comment saying that IE doesn't support this.
338    // But I do see it in the documentation for Mozilla.
339}
340
341bool HTMLDocument::isFrameSet() const
342{
343    HTMLElement* bodyElement = body();
344    return bodyElement && isHTMLFrameSetElement(bodyElement);
345}
346
347PassRefPtr<Document> HTMLDocument::cloneDocumentWithoutChildren() const
348{
349    return create(nullptr, url());
350}
351
352}
353