Home | History | Annotate | Download | only in html
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 1999 Antti Koivisto (koivisto (at) 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 (at) 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 "CookieJar.h"
     59 #include "DocumentLoader.h"
     60 #include "DocumentType.h"
     61 #include "ExceptionCode.h"
     62 #include "FocusController.h"
     63 #include "Frame.h"
     64 #include "FrameLoader.h"
     65 #include "FrameTree.h"
     66 #include "FrameView.h"
     67 #include "HashTools.h"
     68 #include "HTMLDocumentParser.h"
     69 #include "HTMLBodyElement.h"
     70 #include "HTMLElementFactory.h"
     71 #include "HTMLNames.h"
     72 #include "InspectorInstrumentation.h"
     73 #include "KURL.h"
     74 #include "Page.h"
     75 #include "Settings.h"
     76 #include <wtf/text/CString.h>
     77 
     78 namespace WebCore {
     79 
     80 using namespace HTMLNames;
     81 
     82 HTMLDocument::HTMLDocument(Frame* frame, const KURL& url)
     83     : Document(frame, url, false, true)
     84 {
     85     clearXMLVersion();
     86 }
     87 
     88 HTMLDocument::~HTMLDocument()
     89 {
     90 }
     91 
     92 int HTMLDocument::width()
     93 {
     94     updateLayoutIgnorePendingStylesheets();
     95     FrameView* frameView = view();
     96     return frameView ? frameView->contentsWidth() : 0;
     97 }
     98 
     99 int HTMLDocument::height()
    100 {
    101     updateLayoutIgnorePendingStylesheets();
    102     FrameView* frameView = view();
    103     return frameView ? frameView->contentsHeight() : 0;
    104 }
    105 
    106 String HTMLDocument::dir()
    107 {
    108     HTMLElement* b = body();
    109     if (!b)
    110         return String();
    111     return b->getAttribute(dirAttr);
    112 }
    113 
    114 void HTMLDocument::setDir(const String& value)
    115 {
    116     HTMLElement* b = body();
    117     if (b)
    118         b->setAttribute(dirAttr, value);
    119 }
    120 
    121 String HTMLDocument::designMode() const
    122 {
    123     return inDesignMode() ? "on" : "off";
    124 }
    125 
    126 void HTMLDocument::setDesignMode(const String& value)
    127 {
    128     InheritedBool mode;
    129     if (equalIgnoringCase(value, "on"))
    130         mode = on;
    131     else if (equalIgnoringCase(value, "off"))
    132         mode = off;
    133     else
    134         mode = inherit;
    135     Document::setDesignMode(mode);
    136 }
    137 
    138 Element* HTMLDocument::activeElement()
    139 {
    140     if (Node* node = focusedNode())
    141         if (node->isElementNode())
    142             return static_cast<Element*>(node);
    143     return body();
    144 }
    145 
    146 bool HTMLDocument::hasFocus()
    147 {
    148     Page* page = this->page();
    149     if (!page)
    150         return false;
    151     if (!page->focusController()->isActive())
    152         return false;
    153     if (Frame* focusedFrame = page->focusController()->focusedFrame()) {
    154         if (focusedFrame->tree()->isDescendantOf(frame()))
    155             return true;
    156     }
    157     return false;
    158 }
    159 
    160 String HTMLDocument::bgColor()
    161 {
    162     HTMLElement* b = body();
    163     HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
    164 
    165     if (!bodyElement)
    166         return String();
    167     return bodyElement->bgColor();
    168 }
    169 
    170 void HTMLDocument::setBgColor(const String& value)
    171 {
    172     HTMLElement* b = body();
    173     HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
    174 
    175     if (bodyElement)
    176         bodyElement->setBgColor(value);
    177 }
    178 
    179 String HTMLDocument::fgColor()
    180 {
    181     HTMLElement* b = body();
    182     HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
    183 
    184     if (!bodyElement)
    185         return String();
    186     return bodyElement->text();
    187 }
    188 
    189 void HTMLDocument::setFgColor(const String& value)
    190 {
    191     HTMLElement* b = body();
    192     HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
    193 
    194     if (bodyElement)
    195         bodyElement->setText(value);
    196 }
    197 
    198 String HTMLDocument::alinkColor()
    199 {
    200     HTMLElement* b = body();
    201     HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
    202 
    203     if (!bodyElement)
    204         return String();
    205     return bodyElement->aLink();
    206 }
    207 
    208 void HTMLDocument::setAlinkColor(const String& value)
    209 {
    210     HTMLElement* b = body();
    211     HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
    212 
    213     if (bodyElement) {
    214         // This check is a bit silly, but some benchmarks like to set the
    215         // document's link colors over and over to the same value and we
    216         // don't want to incur a style update each time.
    217         if (bodyElement->aLink() != value)
    218             bodyElement->setALink(value);
    219     }
    220 }
    221 
    222 String HTMLDocument::linkColor()
    223 {
    224     HTMLElement* b = body();
    225     HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
    226 
    227     if (!bodyElement)
    228         return String();
    229     return bodyElement->link();
    230 }
    231 
    232 void HTMLDocument::setLinkColor(const String& value)
    233 {
    234     HTMLElement* b = body();
    235     HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
    236 
    237     if (bodyElement) {
    238         // This check is a bit silly, but some benchmarks like to set the
    239         // document's link colors over and over to the same value and we
    240         // don't want to incur a style update each time.
    241         if (bodyElement->link() != value)
    242             bodyElement->setLink(value);
    243     }
    244 }
    245 
    246 String HTMLDocument::vlinkColor()
    247 {
    248     HTMLElement* b = body();
    249     HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
    250 
    251     if (!bodyElement)
    252         return String();
    253     return bodyElement->vLink();
    254 }
    255 
    256 void HTMLDocument::setVlinkColor(const String& value)
    257 {
    258     HTMLElement* b = body();
    259     HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
    260 
    261     if (bodyElement) {
    262         // This check is a bit silly, but some benchmarks like to set the
    263         // document's link colors over and over to the same value and we
    264         // don't want to incur a style update each time.
    265         if (bodyElement->vLink() != value)
    266             bodyElement->setVLink(value);
    267     }
    268 }
    269 
    270 void HTMLDocument::captureEvents()
    271 {
    272 }
    273 
    274 void HTMLDocument::releaseEvents()
    275 {
    276 }
    277 
    278 PassRefPtr<DocumentParser> HTMLDocument::createParser()
    279 {
    280     bool reportErrors = InspectorInstrumentation::hasFrontend(this->page());
    281     return HTMLDocumentParser::create(this, reportErrors);
    282 }
    283 
    284 // --------------------------------------------------------------------------
    285 // not part of the DOM
    286 // --------------------------------------------------------------------------
    287 
    288 PassRefPtr<Element> HTMLDocument::createElement(const AtomicString& name, ExceptionCode& ec)
    289 {
    290     if (!isValidName(name)) {
    291         ec = INVALID_CHARACTER_ERR;
    292         return 0;
    293     }
    294     return HTMLElementFactory::createHTMLElement(QualifiedName(nullAtom, name.lower(), xhtmlNamespaceURI), this, 0, false);
    295 }
    296 
    297 void HTMLDocument::addItemToMap(HashCountedSet<AtomicStringImpl*>& map, const AtomicString& name)
    298 {
    299     if (name.isEmpty())
    300         return;
    301     map.add(name.impl());
    302     if (Frame* f = frame())
    303         f->script()->namedItemAdded(this, name);
    304 }
    305 
    306 void HTMLDocument::removeItemFromMap(HashCountedSet<AtomicStringImpl*>& map, const AtomicString& name)
    307 {
    308     if (name.isEmpty())
    309         return;
    310     map.remove(name.impl());
    311     if (Frame* f = frame())
    312         f->script()->namedItemRemoved(this, name);
    313 }
    314 
    315 void HTMLDocument::addNamedItem(const AtomicString& name)
    316 {
    317     addItemToMap(m_namedItemCounts, name);
    318 }
    319 
    320 void HTMLDocument::removeNamedItem(const AtomicString& name)
    321 {
    322     removeItemFromMap(m_namedItemCounts, name);
    323 }
    324 
    325 void HTMLDocument::addExtraNamedItem(const AtomicString& name)
    326 {
    327     addItemToMap(m_extraNamedItemCounts, name);
    328 }
    329 
    330 void HTMLDocument::removeExtraNamedItem(const AtomicString& name)
    331 {
    332     removeItemFromMap(m_extraNamedItemCounts, name);
    333 }
    334 
    335 void HTMLDocument::setCompatibilityModeFromDoctype()
    336 {
    337     // There are three possible compatibility modes:
    338     // Quirks - quirks mode emulates WinIE and NS4.  CSS parsing is also relaxed in this mode, e.g., unit types can
    339     // be omitted from numbers.
    340     // Limited Quirks - This mode is identical to no-quirks mode except for its treatment of line-height in the inline box model.
    341     // No Quirks - no quirks apply.  Web pages will obey the specifications to the letter.
    342     DocumentType* docType = doctype();
    343     if (!docType)
    344         return;
    345 
    346     // Check for Quirks Mode.
    347     const String& publicId = docType->publicId();
    348     if (docType->name() != "html"
    349         || publicId.startsWith("+//Silmaril//dtd html Pro v0r11 19970101//", false)
    350         || publicId.startsWith("-//AdvaSoft Ltd//DTD HTML 3.0 asWedit + extensions//", false)
    351         || publicId.startsWith("-//AS//DTD HTML 3.0 asWedit + extensions//", false)
    352         || publicId.startsWith("-//IETF//DTD HTML 2.0 Level 1//", false)
    353         || publicId.startsWith("-//IETF//DTD HTML 2.0 Level 2//", false)
    354         || publicId.startsWith("-//IETF//DTD HTML 2.0 Strict Level 1//", false)
    355         || publicId.startsWith("-//IETF//DTD HTML 2.0 Strict Level 2//", false)
    356         || publicId.startsWith("-//IETF//DTD HTML 2.0 Strict//", false)
    357         || publicId.startsWith("-//IETF//DTD HTML 2.0//", false)
    358         || publicId.startsWith("-//IETF//DTD HTML 2.1E//", false)
    359         || publicId.startsWith("-//IETF//DTD HTML 3.0//", false)
    360         || publicId.startsWith("-//IETF//DTD HTML 3.2 Final//", false)
    361         || publicId.startsWith("-//IETF//DTD HTML 3.2//", false)
    362         || publicId.startsWith("-//IETF//DTD HTML 3//", false)
    363         || publicId.startsWith("-//IETF//DTD HTML Level 0//", false)
    364         || publicId.startsWith("-//IETF//DTD HTML Level 1//", false)
    365         || publicId.startsWith("-//IETF//DTD HTML Level 2//", false)
    366         || publicId.startsWith("-//IETF//DTD HTML Level 3//", false)
    367         || publicId.startsWith("-//IETF//DTD HTML Strict Level 0//", false)
    368         || publicId.startsWith("-//IETF//DTD HTML Strict Level 1//", false)
    369         || publicId.startsWith("-//IETF//DTD HTML Strict Level 2//", false)
    370         || publicId.startsWith("-//IETF//DTD HTML Strict Level 3//", false)
    371         || publicId.startsWith("-//IETF//DTD HTML Strict//", false)
    372         || publicId.startsWith("-//IETF//DTD HTML//", false)
    373         || publicId.startsWith("-//Metrius//DTD Metrius Presentational//", false)
    374         || publicId.startsWith("-//Microsoft//DTD Internet Explorer 2.0 HTML Strict//", false)
    375         || publicId.startsWith("-//Microsoft//DTD Internet Explorer 2.0 HTML//", false)
    376         || publicId.startsWith("-//Microsoft//DTD Internet Explorer 2.0 Tables//", false)
    377         || publicId.startsWith("-//Microsoft//DTD Internet Explorer 3.0 HTML Strict//", false)
    378         || publicId.startsWith("-//Microsoft//DTD Internet Explorer 3.0 HTML//", false)
    379         || publicId.startsWith("-//Microsoft//DTD Internet Explorer 3.0 Tables//", false)
    380         || publicId.startsWith("-//Netscape Comm. Corp.//DTD HTML//", false)
    381         || publicId.startsWith("-//Netscape Comm. Corp.//DTD Strict HTML//", false)
    382         || publicId.startsWith("-//O'Reilly and Associates//DTD HTML 2.0//", false)
    383         || publicId.startsWith("-//O'Reilly and Associates//DTD HTML Extended 1.0//", false)
    384         || publicId.startsWith("-//O'Reilly and Associates//DTD HTML Extended Relaxed 1.0//", false)
    385         || publicId.startsWith("-//SoftQuad Software//DTD HoTMetaL PRO 6.0::19990601::extensions to HTML 4.0//", false)
    386         || publicId.startsWith("-//SoftQuad//DTD HoTMetaL PRO 4.0::19971010::extensions to HTML 4.0//", false)
    387         || publicId.startsWith("-//Spyglass//DTD HTML 2.0 Extended//", false)
    388         || publicId.startsWith("-//SQ//DTD HTML 2.0 HoTMetaL + extensions//", false)
    389         || publicId.startsWith("-//Sun Microsystems Corp.//DTD HotJava HTML//", false)
    390         || publicId.startsWith("-//Sun Microsystems Corp.//DTD HotJava Strict HTML//", false)
    391         || publicId.startsWith("-//W3C//DTD HTML 3 1995-03-24//", false)
    392         || publicId.startsWith("-//W3C//DTD HTML 3.2 Draft//", false)
    393         || publicId.startsWith("-//W3C//DTD HTML 3.2 Final//", false)
    394         || publicId.startsWith("-//W3C//DTD HTML 3.2//", false)
    395         || publicId.startsWith("-//W3C//DTD HTML 3.2S Draft//", false)
    396         || publicId.startsWith("-//W3C//DTD HTML 4.0 Frameset//", false)
    397         || publicId.startsWith("-//W3C//DTD HTML 4.0 Transitional//", false)
    398         || publicId.startsWith("-//W3C//DTD HTML Experimental 19960712//", false)
    399         || publicId.startsWith("-//W3C//DTD HTML Experimental 970421//", false)
    400         || publicId.startsWith("-//W3C//DTD W3 HTML//", false)
    401         || publicId.startsWith("-//W3O//DTD W3 HTML 3.0//", false)
    402         || equalIgnoringCase(publicId, "-//W3O//DTD W3 HTML Strict 3.0//EN//")
    403         || publicId.startsWith("-//WebTechs//DTD Mozilla HTML 2.0//", false)
    404         || publicId.startsWith("-//WebTechs//DTD Mozilla HTML//", false)
    405         || equalIgnoringCase(publicId, "-/W3C/DTD HTML 4.0 Transitional/EN")
    406         || equalIgnoringCase(publicId, "HTML")
    407         || equalIgnoringCase(docType->systemId(), "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd")
    408         || (docType->systemId().isEmpty() && publicId.startsWith("-//W3C//DTD HTML 4.01 Frameset//", false))
    409         || (docType->systemId().isEmpty() && publicId.startsWith("-//W3C//DTD HTML 4.01 Transitional//", false))) {
    410         setCompatibilityMode(QuirksMode);
    411         return;
    412     }
    413 
    414     // Check for Limited Quirks Mode.
    415     if (publicId.startsWith("-//W3C//DTD XHTML 1.0 Frameset//", false)
    416         || publicId.startsWith("-//W3C//DTD XHTML 1.0 Transitional//", false)
    417         || (!docType->systemId().isEmpty() && publicId.startsWith("-//W3C//DTD HTML 4.01 Frameset//", false))
    418         || (!docType->systemId().isEmpty() && publicId.startsWith("-//W3C//DTD HTML 4.01 Transitional//", false))) {
    419         setCompatibilityMode(LimitedQuirksMode);
    420         return;
    421     }
    422 
    423     // Otherwise we are No Quirks Mode.
    424     setCompatibilityMode(NoQuirksMode);
    425     return;
    426 }
    427 
    428 void HTMLDocument::clear()
    429 {
    430     // FIXME: This does nothing, and that seems unlikely to be correct.
    431     // We've long had a comment saying that IE doesn't support this.
    432     // But I do see it in the documentation for Mozilla.
    433 }
    434 
    435 bool HTMLDocument::isFrameSet() const
    436 {
    437     HTMLElement* bodyElement = body();
    438     return bodyElement && bodyElement->hasTagName(framesetTag);
    439 }
    440 
    441 }
    442