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 "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 
     82 HTMLDocument::HTMLDocument(Frame* frame)
     83     : Document(frame, false, true)
     84 {
     85     clearXMLVersion();
     86     setParseMode(Compat);
     87 }
     88 
     89 HTMLDocument::~HTMLDocument()
     90 {
     91 }
     92 
     93 int HTMLDocument::width()
     94 {
     95     updateLayoutIgnorePendingStylesheets();
     96     FrameView* frameView = view();
     97     return frameView ? frameView->contentsWidth() : 0;
     98 }
     99 
    100 int HTMLDocument::height()
    101 {
    102     updateLayoutIgnorePendingStylesheets();
    103     FrameView* frameView = view();
    104     return frameView ? frameView->contentsHeight() : 0;
    105 }
    106 
    107 String HTMLDocument::dir()
    108 {
    109     HTMLElement* b = body();
    110     if (!b)
    111         return String();
    112     return b->getAttribute(dirAttr);
    113 }
    114 
    115 void HTMLDocument::setDir(const String& value)
    116 {
    117     HTMLElement* b = body();
    118     if (b)
    119         b->setAttribute(dirAttr, value);
    120 }
    121 
    122 String HTMLDocument::designMode() const
    123 {
    124     return inDesignMode() ? "on" : "off";
    125 }
    126 
    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 
    139 String HTMLDocument::compatMode() const
    140 {
    141     return inCompatMode() ? "BackCompat" : "CSS1Compat";
    142 }
    143 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    276 void HTMLDocument::captureEvents()
    277 {
    278 }
    279 
    280 void HTMLDocument::releaseEvents()
    281 {
    282 }
    283 
    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 
    299 bool HTMLDocument::childAllowed(Node *newChild)
    300 {
    301     return newChild->hasTagName(htmlTag) || newChild->isCommentNode() || (newChild->nodeType() == DOCUMENT_TYPE_NODE && !doctype());
    302 }
    303 
    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 
    313 static void addItemToMap(HashCountedSet<AtomicStringImpl*>& map, const AtomicString& name)
    314 {
    315     if (name.isEmpty())
    316         return;
    317     map.add(name.impl());
    318 }
    319 
    320 static void removeItemFromMap(HashCountedSet<AtomicStringImpl*>& map, const AtomicString& name)
    321 {
    322     if (name.isEmpty())
    323         return;
    324     map.remove(name.impl());
    325 }
    326 
    327 void HTMLDocument::addNamedItem(const AtomicString& name)
    328 {
    329     addItemToMap(m_namedItemCounts, name);
    330 }
    331 
    332 void HTMLDocument::removeNamedItem(const AtomicString& name)
    333 {
    334     removeItemFromMap(m_namedItemCounts, name);
    335 }
    336 
    337 void HTMLDocument::addExtraNamedItem(const AtomicString& name)
    338 {
    339     addItemToMap(m_extraNamedItemCounts, name);
    340 }
    341 
    342 void HTMLDocument::removeExtraNamedItem(const AtomicString& name)
    343 {
    344     removeItemFromMap(m_extraNamedItemCounts, name);
    345 }
    346 
    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 
    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 
    415 bool HTMLDocument::isFrameSet() const
    416 {
    417     HTMLElement* bodyElement = body();
    418     return bodyElement && bodyElement->renderer() && bodyElement->hasTagName(framesetTag);
    419 }
    420 
    421 #ifdef ANDROID_INSTRUMENT
    422 void* HTMLDocument::operator new(size_t size)
    423 {
    424     return Node::operator new(size);
    425 }
    426 
    427 void* HTMLDocument::operator new[](size_t size)
    428 {
    429     return Node::operator new[](size);
    430 }
    431 
    432 void HTMLDocument::operator delete(void* p, size_t size)
    433 {
    434     Node::operator delete(p, size);
    435 }
    436 
    437 void HTMLDocument::operator delete[](void* p, size_t size)
    438 {
    439     Node::operator delete[](p, size);
    440 }
    441 #endif
    442 
    443 }
    444