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