• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "CSSStyleSelector.h"
58 #include "CString.h"
59 #include "CookieJar.h"
60 #include "DocumentLoader.h"
61 #include "DocumentType.h"
62 #include "ExceptionCode.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 "HTMLElementFactory.h"
70 #include "HTMLNames.h"
71 #include "HTMLTokenizer.h"
72 #include "InspectorController.h"
73 #include "KURL.h"
74 #include "Page.h"
75 
76 #include "DocTypeStrings.cpp"
77 
78 namespace WebCore {
79 
80 using namespace HTMLNames;
81 
HTMLDocument(Frame * frame)82 HTMLDocument::HTMLDocument(Frame* frame)
83     : Document(frame, false, true)
84 {
85     clearXMLVersion();
86     setParseMode(Compat);
87 }
88 
~HTMLDocument()89 HTMLDocument::~HTMLDocument()
90 {
91 }
92 
width()93 int HTMLDocument::width()
94 {
95     updateLayoutIgnorePendingStylesheets();
96     FrameView* frameView = view();
97     return frameView ? frameView->contentsWidth() : 0;
98 }
99 
height()100 int HTMLDocument::height()
101 {
102     updateLayoutIgnorePendingStylesheets();
103     FrameView* frameView = view();
104     return frameView ? frameView->contentsHeight() : 0;
105 }
106 
dir()107 String HTMLDocument::dir()
108 {
109     HTMLElement* b = body();
110     if (!b)
111         return String();
112     return b->getAttribute(dirAttr);
113 }
114 
setDir(const String & value)115 void HTMLDocument::setDir(const String& value)
116 {
117     HTMLElement* b = body();
118     if (b)
119         b->setAttribute(dirAttr, value);
120 }
121 
designMode() const122 String HTMLDocument::designMode() const
123 {
124     return inDesignMode() ? "on" : "off";
125 }
126 
setDesignMode(const String & value)127 void HTMLDocument::setDesignMode(const String& value)
128 {
129     InheritedBool mode;
130     if (equalIgnoringCase(value, "on"))
131         mode = on;
132     else if (equalIgnoringCase(value, "off"))
133         mode = off;
134     else
135         mode = inherit;
136     Document::setDesignMode(mode);
137 }
138 
compatMode() const139 String HTMLDocument::compatMode() const
140 {
141     return inCompatMode() ? "BackCompat" : "CSS1Compat";
142 }
143 
activeElement()144 Element* HTMLDocument::activeElement()
145 {
146     if (Node* node = focusedNode())
147         if (node->isElementNode())
148             return static_cast<Element*>(node);
149     return body();
150 }
151 
hasFocus()152 bool HTMLDocument::hasFocus()
153 {
154     Page* page = this->page();
155     if (!page)
156         return false;
157     if (!page->focusController()->isActive())
158         return false;
159     if (Frame* focusedFrame = page->focusController()->focusedFrame()) {
160         if (focusedFrame->tree()->isDescendantOf(frame()))
161             return true;
162     }
163     return false;
164 }
165 
bgColor()166 String HTMLDocument::bgColor()
167 {
168     HTMLElement* b = body();
169     HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
170 
171     if (!bodyElement)
172         return String();
173     return bodyElement->bgColor();
174 }
175 
setBgColor(const String & value)176 void HTMLDocument::setBgColor(const String& value)
177 {
178     HTMLElement* b = body();
179     HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
180 
181     if (bodyElement)
182         bodyElement->setBgColor(value);
183 }
184 
fgColor()185 String HTMLDocument::fgColor()
186 {
187     HTMLElement* b = body();
188     HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
189 
190     if (!bodyElement)
191         return String();
192     return bodyElement->text();
193 }
194 
setFgColor(const String & value)195 void HTMLDocument::setFgColor(const String& value)
196 {
197     HTMLElement* b = body();
198     HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
199 
200     if (bodyElement)
201         bodyElement->setText(value);
202 }
203 
alinkColor()204 String HTMLDocument::alinkColor()
205 {
206     HTMLElement* b = body();
207     HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
208 
209     if (!bodyElement)
210         return String();
211     return bodyElement->aLink();
212 }
213 
setAlinkColor(const String & value)214 void HTMLDocument::setAlinkColor(const String& value)
215 {
216     HTMLElement* b = body();
217     HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
218 
219     if (bodyElement) {
220         // This check is a bit silly, but some benchmarks like to set the
221         // document's link colors over and over to the same value and we
222         // don't want to incur a style update each time.
223         if (bodyElement->aLink() != value)
224             bodyElement->setALink(value);
225     }
226 }
227 
linkColor()228 String HTMLDocument::linkColor()
229 {
230     HTMLElement* b = body();
231     HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
232 
233     if (!bodyElement)
234         return String();
235     return bodyElement->link();
236 }
237 
setLinkColor(const String & value)238 void HTMLDocument::setLinkColor(const String& value)
239 {
240     HTMLElement* b = body();
241     HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
242 
243     if (bodyElement) {
244         // This check is a bit silly, but some benchmarks like to set the
245         // document's link colors over and over to the same value and we
246         // don't want to incur a style update each time.
247         if (bodyElement->link() != value)
248             bodyElement->setLink(value);
249     }
250 }
251 
vlinkColor()252 String HTMLDocument::vlinkColor()
253 {
254     HTMLElement* b = body();
255     HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
256 
257     if (!bodyElement)
258         return String();
259     return bodyElement->vLink();
260 }
261 
setVlinkColor(const String & value)262 void HTMLDocument::setVlinkColor(const String& value)
263 {
264     HTMLElement* b = body();
265     HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
266 
267     if (bodyElement) {
268         // This check is a bit silly, but some benchmarks like to set the
269         // document's link colors over and over to the same value and we
270         // don't want to incur a style update each time.
271         if (bodyElement->vLink() != value)
272             bodyElement->setVLink(value);
273     }
274 }
275 
captureEvents()276 void HTMLDocument::captureEvents()
277 {
278 }
279 
releaseEvents()280 void HTMLDocument::releaseEvents()
281 {
282 }
283 
createTokenizer()284 Tokenizer *HTMLDocument::createTokenizer()
285 {
286     bool reportErrors = false;
287 #if ENABLE(INSPECTOR)
288     if (Page* page = this->page())
289         reportErrors = page->inspectorController()->windowVisible();
290 #endif
291 
292     return new HTMLTokenizer(this, reportErrors);
293 }
294 
295 // --------------------------------------------------------------------------
296 // not part of the DOM
297 // --------------------------------------------------------------------------
298 
childAllowed(Node * newChild)299 bool HTMLDocument::childAllowed(Node *newChild)
300 {
301     return newChild->hasTagName(htmlTag) || newChild->isCommentNode() || (newChild->nodeType() == DOCUMENT_TYPE_NODE && !doctype());
302 }
303 
createElement(const AtomicString & name,ExceptionCode & ec)304 PassRefPtr<Element> HTMLDocument::createElement(const AtomicString& name, ExceptionCode& ec)
305 {
306     if (!isValidName(name)) {
307         ec = INVALID_CHARACTER_ERR;
308         return 0;
309     }
310     return HTMLElementFactory::createHTMLElement(QualifiedName(nullAtom, name.lower(), xhtmlNamespaceURI), this, 0, false);
311 }
312 
addItemToMap(HashCountedSet<AtomicStringImpl * > & map,const AtomicString & name)313 static void addItemToMap(HashCountedSet<AtomicStringImpl*>& map, const AtomicString& name)
314 {
315     if (name.isEmpty())
316         return;
317     map.add(name.impl());
318 }
319 
removeItemFromMap(HashCountedSet<AtomicStringImpl * > & map,const AtomicString & name)320 static void removeItemFromMap(HashCountedSet<AtomicStringImpl*>& map, const AtomicString& name)
321 {
322     if (name.isEmpty())
323         return;
324     map.remove(name.impl());
325 }
326 
addNamedItem(const AtomicString & name)327 void HTMLDocument::addNamedItem(const AtomicString& name)
328 {
329     addItemToMap(m_namedItemCounts, name);
330 }
331 
removeNamedItem(const AtomicString & name)332 void HTMLDocument::removeNamedItem(const AtomicString& name)
333 {
334     removeItemFromMap(m_namedItemCounts, name);
335 }
336 
addExtraNamedItem(const AtomicString & name)337 void HTMLDocument::addExtraNamedItem(const AtomicString& name)
338 {
339     addItemToMap(m_extraNamedItemCounts, name);
340 }
341 
removeExtraNamedItem(const AtomicString & name)342 void HTMLDocument::removeExtraNamedItem(const AtomicString& name)
343 {
344     removeItemFromMap(m_extraNamedItemCounts, name);
345 }
346 
determineParseMode()347 void HTMLDocument::determineParseMode()
348 {
349     // FIXME: It's terrible that this code runs separately and isn't just built in to the
350     // HTML tokenizer/parser.
351 
352     // This code more or less mimics Mozilla's implementation (specifically the
353     // doctype parsing implemented by David Baron in Mozilla's nsParser.cpp).
354     //
355     // There are three possible parse modes:
356     // COMPAT - quirks mode emulates WinIE and NS4.  CSS parsing is also relaxed in this mode, e.g., unit types can
357     // be omitted from numbers.
358     // ALMOST STRICT - This mode is identical to strict mode except for its treatment of line-height in the inline box model.  For
359     // now (until the inline box model is re-written), this mode is identical to STANDARDS mode.
360     // STRICT - no quirks apply.  Web pages will obey the specifications to the letter.
361     bool wasInCompatMode = inCompatMode();
362     DocumentType* docType = doctype();
363     if (!docType || !equalIgnoringCase(docType->name(), "html"))
364         // No doctype found at all or the doctype is not HTML.  Default to quirks mode and Html4.
365         setParseMode(Compat);
366     else if (!doctype()->systemId().isEmpty() && equalIgnoringCase(docType->systemId(), "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd"))
367         // Assume quirks mode for this particular system ID.  In the HTML5 spec, this is the only
368         // system identifier that is examined.
369         setParseMode(Compat);
370     else if (docType->publicId().isEmpty())
371         // A doctype without a public ID means use strict mode.
372         setParseMode(Strict);
373     else {
374         // We have to check a list of public IDs to see what we
375         // should do.
376         String lowerPubID = docType->publicId().lower();
377         CString pubIDStr = lowerPubID.latin1();
378 
379         // Look up the entry in our gperf-generated table.
380         const PubIDInfo* doctypeEntry = findDoctypeEntry(pubIDStr.data(), pubIDStr.length());
381         if (!doctypeEntry)
382             // The DOCTYPE is not in the list.  Assume strict mode.
383             setParseMode(Strict);
384         else {
385             switch (docType->systemId().isEmpty() ?
386                     doctypeEntry->mode_if_no_sysid :
387                     doctypeEntry->mode_if_sysid) {
388                 case PubIDInfo::eQuirks3:
389                 case PubIDInfo::eQuirks:
390                     setParseMode(Compat);
391                     break;
392                 case PubIDInfo::eAlmostStandards:
393                     setParseMode(AlmostStrict);
394                     break;
395                  default:
396                     ASSERT(false);
397             }
398         }
399     }
400 
401     if (inCompatMode() != wasInCompatMode) {
402         clearPageUserSheet();
403         clearPageGroupUserSheets();
404         updateStyleSelector();
405     }
406 }
407 
clear()408 void HTMLDocument::clear()
409 {
410     // FIXME: This does nothing, and that seems unlikely to be correct.
411     // We've long had a comment saying that IE doesn't support this.
412     // But I do see it in the documentation for Mozilla.
413 }
414 
isFrameSet() const415 bool HTMLDocument::isFrameSet() const
416 {
417     HTMLElement* bodyElement = body();
418     return bodyElement && bodyElement->renderer() && bodyElement->hasTagName(framesetTag);
419 }
420 
421 #ifdef ANDROID_INSTRUMENT
operator new(size_t size)422 void* HTMLDocument::operator new(size_t size)
423 {
424     return Node::operator new(size);
425 }
426 
operator new[](size_t size)427 void* HTMLDocument::operator new[](size_t size)
428 {
429     return Node::operator new[](size);
430 }
431 
operator delete(void * p,size_t size)432 void HTMLDocument::operator delete(void* p, size_t size)
433 {
434     Node::operator delete(p, size);
435 }
436 
operator delete[](void * p,size_t size)437 void HTMLDocument::operator delete[](void* p, size_t size)
438 {
439     Node::operator delete[](p, size);
440 }
441 #endif
442 
443 }
444