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 "core/html/HTMLDocument.h" 55 56#include "bindings/core/v8/ScriptController.h" 57#include "core/HTMLNames.h" 58#include "core/frame/LocalDOMWindow.h" 59#include "core/frame/FrameView.h" 60#include "core/frame/LocalFrame.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 67namespace blink { 68 69using namespace HTMLNames; 70 71HTMLDocument::HTMLDocument(const DocumentInit& initializer, DocumentClassFlags extendedDocumentClasses) 72 : Document(initializer, HTMLDocumentClass | extendedDocumentClasses) 73{ 74 clearXMLVersion(); 75 if (isSrcdocDocument() || initializer.importsController()) { 76 ASSERT(inNoQuirksMode()); 77 lockCompatibilityMode(); 78 } 79} 80 81HTMLDocument::~HTMLDocument() 82{ 83} 84 85HTMLBodyElement* HTMLDocument::htmlBodyElement() const 86{ 87 HTMLElement* body = this->body(); 88 return isHTMLBodyElement(body) ? toHTMLBodyElement(body) : 0; 89} 90 91const AtomicString& HTMLDocument::bodyAttributeValue(const QualifiedName& name) const 92{ 93 if (HTMLBodyElement* body = htmlBodyElement()) 94 return body->fastGetAttribute(name); 95 return nullAtom; 96} 97 98void HTMLDocument::setBodyAttribute(const QualifiedName& name, const AtomicString& value) 99{ 100 if (HTMLBodyElement* body = htmlBodyElement()) { 101 // FIXME: This check is apparently for benchmarks that set the same value repeatedly. 102 // It's not clear what benchmarks though, it's also not clear why we don't avoid 103 // causing a style recalc when setting the same value to a presentational attribute 104 // in the common case. 105 if (body->fastGetAttribute(name) != value) 106 body->setAttribute(name, value); 107 } 108} 109 110const AtomicString& HTMLDocument::bgColor() const 111{ 112 return bodyAttributeValue(bgcolorAttr); 113} 114 115void HTMLDocument::setBgColor(const AtomicString& value) 116{ 117 setBodyAttribute(bgcolorAttr, value); 118} 119 120const AtomicString& HTMLDocument::fgColor() const 121{ 122 return bodyAttributeValue(textAttr); 123} 124 125void HTMLDocument::setFgColor(const AtomicString& value) 126{ 127 setBodyAttribute(textAttr, value); 128} 129 130const AtomicString& HTMLDocument::alinkColor() const 131{ 132 return bodyAttributeValue(alinkAttr); 133} 134 135void HTMLDocument::setAlinkColor(const AtomicString& value) 136{ 137 setBodyAttribute(alinkAttr, value); 138} 139 140const AtomicString& HTMLDocument::linkColor() const 141{ 142 return bodyAttributeValue(linkAttr); 143} 144 145void HTMLDocument::setLinkColor(const AtomicString& value) 146{ 147 setBodyAttribute(linkAttr, value); 148} 149 150const AtomicString& HTMLDocument::vlinkColor() const 151{ 152 return bodyAttributeValue(vlinkAttr); 153} 154 155void HTMLDocument::setVlinkColor(const AtomicString& value) 156{ 157 setBodyAttribute(vlinkAttr, value); 158} 159 160PassRefPtrWillBeRawPtr<Document> HTMLDocument::cloneDocumentWithoutChildren() 161{ 162 return create(DocumentInit(url()).withRegistrationContext(registrationContext())); 163} 164 165// -------------------------------------------------------------------------- 166// not part of the DOM 167// -------------------------------------------------------------------------- 168 169void HTMLDocument::addItemToMap(HashCountedSet<AtomicString>& map, const AtomicString& name) 170{ 171 if (name.isEmpty()) 172 return; 173 map.add(name); 174 if (LocalFrame* f = frame()) 175 f->script().namedItemAdded(this, name); 176} 177 178void HTMLDocument::removeItemFromMap(HashCountedSet<AtomicString>& map, const AtomicString& name) 179{ 180 if (name.isEmpty()) 181 return; 182 map.remove(name); 183 if (LocalFrame* f = frame()) 184 f->script().namedItemRemoved(this, name); 185} 186 187void HTMLDocument::addNamedItem(const AtomicString& name) 188{ 189 addItemToMap(m_namedItemCounts, name); 190} 191 192void HTMLDocument::removeNamedItem(const AtomicString& name) 193{ 194 removeItemFromMap(m_namedItemCounts, name); 195} 196 197void HTMLDocument::addExtraNamedItem(const AtomicString& name) 198{ 199 addItemToMap(m_extraNamedItemCounts, name); 200} 201 202void HTMLDocument::removeExtraNamedItem(const AtomicString& name) 203{ 204 removeItemFromMap(m_extraNamedItemCounts, name); 205} 206 207static void addLocalNameToSet(HashSet<StringImpl*>* set, const QualifiedName& qName) 208{ 209 set->add(qName.localName().impl()); 210} 211 212static HashSet<StringImpl*>* createHtmlCaseInsensitiveAttributesSet() 213{ 214 // This is the list of attributes in HTML 4.01 with values marked as "[CI]" or case-insensitive 215 // Mozilla treats all other values as case-sensitive, thus so do we. 216 HashSet<StringImpl*>* attrSet = new HashSet<StringImpl*>; 217 218 addLocalNameToSet(attrSet, accept_charsetAttr); 219 addLocalNameToSet(attrSet, acceptAttr); 220 addLocalNameToSet(attrSet, alignAttr); 221 addLocalNameToSet(attrSet, alinkAttr); 222 addLocalNameToSet(attrSet, axisAttr); 223 addLocalNameToSet(attrSet, bgcolorAttr); 224 addLocalNameToSet(attrSet, charsetAttr); 225 addLocalNameToSet(attrSet, checkedAttr); 226 addLocalNameToSet(attrSet, clearAttr); 227 addLocalNameToSet(attrSet, codetypeAttr); 228 addLocalNameToSet(attrSet, colorAttr); 229 addLocalNameToSet(attrSet, compactAttr); 230 addLocalNameToSet(attrSet, declareAttr); 231 addLocalNameToSet(attrSet, deferAttr); 232 addLocalNameToSet(attrSet, dirAttr); 233 addLocalNameToSet(attrSet, disabledAttr); 234 addLocalNameToSet(attrSet, enctypeAttr); 235 addLocalNameToSet(attrSet, faceAttr); 236 addLocalNameToSet(attrSet, frameAttr); 237 addLocalNameToSet(attrSet, hreflangAttr); 238 addLocalNameToSet(attrSet, http_equivAttr); 239 addLocalNameToSet(attrSet, langAttr); 240 addLocalNameToSet(attrSet, languageAttr); 241 addLocalNameToSet(attrSet, linkAttr); 242 addLocalNameToSet(attrSet, mediaAttr); 243 addLocalNameToSet(attrSet, methodAttr); 244 addLocalNameToSet(attrSet, multipleAttr); 245 addLocalNameToSet(attrSet, nohrefAttr); 246 addLocalNameToSet(attrSet, noresizeAttr); 247 addLocalNameToSet(attrSet, noshadeAttr); 248 addLocalNameToSet(attrSet, nowrapAttr); 249 addLocalNameToSet(attrSet, readonlyAttr); 250 addLocalNameToSet(attrSet, relAttr); 251 addLocalNameToSet(attrSet, revAttr); 252 addLocalNameToSet(attrSet, rulesAttr); 253 addLocalNameToSet(attrSet, scopeAttr); 254 addLocalNameToSet(attrSet, scrollingAttr); 255 addLocalNameToSet(attrSet, selectedAttr); 256 addLocalNameToSet(attrSet, shapeAttr); 257 addLocalNameToSet(attrSet, targetAttr); 258 addLocalNameToSet(attrSet, textAttr); 259 addLocalNameToSet(attrSet, typeAttr); 260 addLocalNameToSet(attrSet, valignAttr); 261 addLocalNameToSet(attrSet, valuetypeAttr); 262 addLocalNameToSet(attrSet, vlinkAttr); 263 264 return attrSet; 265} 266 267bool HTMLDocument::isCaseSensitiveAttribute(const QualifiedName& attributeName) 268{ 269 static HashSet<StringImpl*>* htmlCaseInsensitiveAttributesSet = createHtmlCaseInsensitiveAttributesSet(); 270 bool isPossibleHTMLAttr = !attributeName.hasPrefix() && (attributeName.namespaceURI() == nullAtom); 271 return !isPossibleHTMLAttr || !htmlCaseInsensitiveAttributesSet->contains(attributeName.localName().impl()); 272} 273 274void HTMLDocument::write(LocalDOMWindow* callingWindow, const Vector<String>& text, ExceptionState& exceptionState) 275{ 276 ASSERT(callingWindow); 277 StringBuilder builder; 278 for (size_t i = 0; i < text.size(); ++i) 279 builder.append(text[i]); 280 write(builder.toString(), callingWindow->document(), exceptionState); 281} 282 283void HTMLDocument::writeln(LocalDOMWindow* callingWindow, const Vector<String>& text, ExceptionState& exceptionState) 284{ 285 ASSERT(callingWindow); 286 StringBuilder builder; 287 for (size_t i = 0; i < text.size(); ++i) 288 builder.append(text[i]); 289 writeln(builder.toString(), callingWindow->document(), exceptionState); 290} 291 292} 293