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 "core/html/HTMLDocument.h"
     55 
     56 #include "HTMLNames.h"
     57 #include "bindings/v8/ScriptController.h"
     58 #include "core/frame/DOMWindow.h"
     59 #include "core/frame/Frame.h"
     60 #include "core/frame/FrameView.h"
     61 #include "core/html/HTMLBodyElement.h"
     62 #include "core/page/FocusController.h"
     63 #include "core/page/FrameTree.h"
     64 #include "core/page/Page.h"
     65 #include "wtf/text/StringBuilder.h"
     66 
     67 namespace WebCore {
     68 
     69 using namespace HTMLNames;
     70 
     71 HTMLDocument::HTMLDocument(const DocumentInit& initializer, DocumentClassFlags extendedDocumentClasses)
     72     : Document(initializer, HTMLDocumentClass | extendedDocumentClasses)
     73 {
     74     ScriptWrappable::init(this);
     75     clearXMLVersion();
     76 }
     77 
     78 HTMLDocument::~HTMLDocument()
     79 {
     80 }
     81 
     82 const AtomicString& HTMLDocument::dir()
     83 {
     84     HTMLElement* b = body();
     85     if (!b)
     86         return nullAtom;
     87     return b->getAttribute(dirAttr);
     88 }
     89 
     90 void HTMLDocument::setDir(const AtomicString& value)
     91 {
     92     HTMLElement* b = body();
     93     if (b)
     94         b->setAttribute(dirAttr, value);
     95 }
     96 
     97 String HTMLDocument::designMode() const
     98 {
     99     return inDesignMode() ? "on" : "off";
    100 }
    101 
    102 void HTMLDocument::setDesignMode(const String& value)
    103 {
    104     InheritedBool mode;
    105     if (equalIgnoringCase(value, "on"))
    106         mode = on;
    107     else if (equalIgnoringCase(value, "off"))
    108         mode = off;
    109     else
    110         mode = inherit;
    111     Document::setDesignMode(mode);
    112 }
    113 
    114 Element* HTMLDocument::activeElement()
    115 {
    116     if (Element* element = treeScope().adjustedFocusedElement())
    117         return element;
    118     return body();
    119 }
    120 
    121 bool HTMLDocument::hasFocus()
    122 {
    123     Page* page = this->page();
    124     if (!page)
    125         return false;
    126     if (!page->focusController().isActive() || !page->focusController().isFocused())
    127         return false;
    128     if (Frame* focusedFrame = page->focusController().focusedFrame()) {
    129         if (focusedFrame->tree().isDescendantOf(frame()))
    130             return true;
    131     }
    132     return false;
    133 }
    134 
    135 HTMLBodyElement* HTMLDocument::htmlBodyElement() const
    136 {
    137     HTMLElement* body = this->body();
    138     return (body && body->hasTagName(bodyTag)) ? toHTMLBodyElement(body) : 0;
    139 }
    140 
    141 const AtomicString& HTMLDocument::bodyAttributeValue(const QualifiedName& name) const
    142 {
    143     if (HTMLBodyElement* body = htmlBodyElement())
    144         return body->fastGetAttribute(name);
    145     return nullAtom;
    146 }
    147 
    148 void HTMLDocument::setBodyAttribute(const QualifiedName& name, const AtomicString& value)
    149 {
    150     if (HTMLBodyElement* body = htmlBodyElement()) {
    151         // FIXME: This check is apparently for benchmarks that set the same value repeatedly.
    152         // It's not clear what benchmarks though, it's also not clear why we don't avoid
    153         // causing a style recalc when setting the same value to a presentational attribute
    154         // in the common case.
    155         if (body->fastGetAttribute(name) != value)
    156             body->setAttribute(name, value);
    157     }
    158 }
    159 
    160 const AtomicString& HTMLDocument::bgColor() const
    161 {
    162     return bodyAttributeValue(bgcolorAttr);
    163 }
    164 
    165 void HTMLDocument::setBgColor(const AtomicString& value)
    166 {
    167     setBodyAttribute(bgcolorAttr, value);
    168 }
    169 
    170 const AtomicString& HTMLDocument::fgColor() const
    171 {
    172     return bodyAttributeValue(textAttr);
    173 }
    174 
    175 void HTMLDocument::setFgColor(const AtomicString& value)
    176 {
    177     setBodyAttribute(textAttr, value);
    178 }
    179 
    180 const AtomicString& HTMLDocument::alinkColor() const
    181 {
    182     return bodyAttributeValue(alinkAttr);
    183 }
    184 
    185 void HTMLDocument::setAlinkColor(const AtomicString& value)
    186 {
    187     setBodyAttribute(alinkAttr, value);
    188 }
    189 
    190 const AtomicString& HTMLDocument::linkColor() const
    191 {
    192     return bodyAttributeValue(linkAttr);
    193 }
    194 
    195 void HTMLDocument::setLinkColor(const AtomicString& value)
    196 {
    197     setBodyAttribute(linkAttr, value);
    198 }
    199 
    200 const AtomicString& HTMLDocument::vlinkColor() const
    201 {
    202     return bodyAttributeValue(vlinkAttr);
    203 }
    204 
    205 void HTMLDocument::setVlinkColor(const AtomicString& value)
    206 {
    207     setBodyAttribute(vlinkAttr, value);
    208 }
    209 
    210 PassRefPtr<Document> HTMLDocument::cloneDocumentWithoutChildren()
    211 {
    212     return create(DocumentInit(url()).withRegistrationContext(registrationContext()));
    213 }
    214 
    215 // --------------------------------------------------------------------------
    216 // not part of the DOM
    217 // --------------------------------------------------------------------------
    218 
    219 void HTMLDocument::addItemToMap(HashCountedSet<AtomicString>& map, const AtomicString& name)
    220 {
    221     if (name.isEmpty())
    222         return;
    223     map.add(name);
    224     if (Frame* f = frame())
    225         f->script().namedItemAdded(this, name);
    226 }
    227 
    228 void HTMLDocument::removeItemFromMap(HashCountedSet<AtomicString>& map, const AtomicString& name)
    229 {
    230     if (name.isEmpty())
    231         return;
    232     map.remove(name);
    233     if (Frame* f = frame())
    234         f->script().namedItemRemoved(this, name);
    235 }
    236 
    237 void HTMLDocument::addNamedItem(const AtomicString& name)
    238 {
    239     addItemToMap(m_namedItemCounts, name);
    240 }
    241 
    242 void HTMLDocument::removeNamedItem(const AtomicString& name)
    243 {
    244     removeItemFromMap(m_namedItemCounts, name);
    245 }
    246 
    247 void HTMLDocument::addExtraNamedItem(const AtomicString& name)
    248 {
    249     addItemToMap(m_extraNamedItemCounts, name);
    250 }
    251 
    252 void HTMLDocument::removeExtraNamedItem(const AtomicString& name)
    253 {
    254     removeItemFromMap(m_extraNamedItemCounts, name);
    255 }
    256 
    257 static void addLocalNameToSet(HashSet<StringImpl*>* set, const QualifiedName& qName)
    258 {
    259     set->add(qName.localName().impl());
    260 }
    261 
    262 static HashSet<StringImpl*>* createHtmlCaseInsensitiveAttributesSet()
    263 {
    264     // This is the list of attributes in HTML 4.01 with values marked as "[CI]" or case-insensitive
    265     // Mozilla treats all other values as case-sensitive, thus so do we.
    266     HashSet<StringImpl*>* attrSet = new HashSet<StringImpl*>;
    267 
    268     addLocalNameToSet(attrSet, accept_charsetAttr);
    269     addLocalNameToSet(attrSet, acceptAttr);
    270     addLocalNameToSet(attrSet, alignAttr);
    271     addLocalNameToSet(attrSet, alinkAttr);
    272     addLocalNameToSet(attrSet, axisAttr);
    273     addLocalNameToSet(attrSet, bgcolorAttr);
    274     addLocalNameToSet(attrSet, charsetAttr);
    275     addLocalNameToSet(attrSet, checkedAttr);
    276     addLocalNameToSet(attrSet, clearAttr);
    277     addLocalNameToSet(attrSet, codetypeAttr);
    278     addLocalNameToSet(attrSet, colorAttr);
    279     addLocalNameToSet(attrSet, compactAttr);
    280     addLocalNameToSet(attrSet, declareAttr);
    281     addLocalNameToSet(attrSet, deferAttr);
    282     addLocalNameToSet(attrSet, dirAttr);
    283     addLocalNameToSet(attrSet, disabledAttr);
    284     addLocalNameToSet(attrSet, enctypeAttr);
    285     addLocalNameToSet(attrSet, faceAttr);
    286     addLocalNameToSet(attrSet, frameAttr);
    287     addLocalNameToSet(attrSet, hreflangAttr);
    288     addLocalNameToSet(attrSet, http_equivAttr);
    289     addLocalNameToSet(attrSet, langAttr);
    290     addLocalNameToSet(attrSet, languageAttr);
    291     addLocalNameToSet(attrSet, linkAttr);
    292     addLocalNameToSet(attrSet, mediaAttr);
    293     addLocalNameToSet(attrSet, methodAttr);
    294     addLocalNameToSet(attrSet, multipleAttr);
    295     addLocalNameToSet(attrSet, nohrefAttr);
    296     addLocalNameToSet(attrSet, noresizeAttr);
    297     addLocalNameToSet(attrSet, noshadeAttr);
    298     addLocalNameToSet(attrSet, nowrapAttr);
    299     addLocalNameToSet(attrSet, readonlyAttr);
    300     addLocalNameToSet(attrSet, relAttr);
    301     addLocalNameToSet(attrSet, revAttr);
    302     addLocalNameToSet(attrSet, rulesAttr);
    303     addLocalNameToSet(attrSet, scopeAttr);
    304     addLocalNameToSet(attrSet, scrollingAttr);
    305     addLocalNameToSet(attrSet, selectedAttr);
    306     addLocalNameToSet(attrSet, shapeAttr);
    307     addLocalNameToSet(attrSet, targetAttr);
    308     addLocalNameToSet(attrSet, textAttr);
    309     addLocalNameToSet(attrSet, typeAttr);
    310     addLocalNameToSet(attrSet, valignAttr);
    311     addLocalNameToSet(attrSet, valuetypeAttr);
    312     addLocalNameToSet(attrSet, vlinkAttr);
    313 
    314     return attrSet;
    315 }
    316 
    317 bool HTMLDocument::isCaseSensitiveAttribute(const QualifiedName& attributeName)
    318 {
    319     static HashSet<StringImpl*>* htmlCaseInsensitiveAttributesSet = createHtmlCaseInsensitiveAttributesSet();
    320     bool isPossibleHTMLAttr = !attributeName.hasPrefix() && (attributeName.namespaceURI() == nullAtom);
    321     return !isPossibleHTMLAttr || !htmlCaseInsensitiveAttributesSet->contains(attributeName.localName().impl());
    322 }
    323 
    324 void HTMLDocument::clear()
    325 {
    326     // FIXME: This does nothing, and that seems unlikely to be correct.
    327     // We've long had a comment saying that IE doesn't support this.
    328     // But I do see it in the documentation for Mozilla.
    329 }
    330 
    331 void HTMLDocument::write(DOMWindow* activeWindow, const Vector<String>& text)
    332 {
    333     ASSERT(activeWindow);
    334     StringBuilder builder;
    335     for (size_t i = 0; i < text.size(); ++i)
    336         builder.append(text[i]);
    337     write(builder.toString(), activeWindow->document());
    338 }
    339 
    340 void HTMLDocument::writeln(DOMWindow* activeWindow, const Vector<String>& text)
    341 {
    342     ASSERT(activeWindow);
    343     StringBuilder builder;
    344     for (size_t i = 0; i < text.size(); ++i)
    345         builder.append(text[i]);
    346     writeln(builder.toString(), activeWindow->document());
    347 }
    348 
    349 }
    350