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