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 "CookieJar.h" 59 #include "DocumentLoader.h" 60 #include "DocumentType.h" 61 #include "ExceptionCode.h" 62 #include "FocusController.h" 63 #include "Frame.h" 64 #include "FrameLoader.h" 65 #include "FrameTree.h" 66 #include "FrameView.h" 67 #include "HashTools.h" 68 #include "HTMLDocumentParser.h" 69 #include "HTMLBodyElement.h" 70 #include "HTMLElementFactory.h" 71 #include "HTMLNames.h" 72 #include "InspectorInstrumentation.h" 73 #include "KURL.h" 74 #include "Page.h" 75 #include "Settings.h" 76 #include <wtf/text/CString.h> 77 78 namespace WebCore { 79 80 using namespace HTMLNames; 81 82 HTMLDocument::HTMLDocument(Frame* frame, const KURL& url) 83 : Document(frame, url, false, true) 84 { 85 clearXMLVersion(); 86 } 87 88 HTMLDocument::~HTMLDocument() 89 { 90 } 91 92 int HTMLDocument::width() 93 { 94 updateLayoutIgnorePendingStylesheets(); 95 FrameView* frameView = view(); 96 return frameView ? frameView->contentsWidth() : 0; 97 } 98 99 int HTMLDocument::height() 100 { 101 updateLayoutIgnorePendingStylesheets(); 102 FrameView* frameView = view(); 103 return frameView ? frameView->contentsHeight() : 0; 104 } 105 106 String HTMLDocument::dir() 107 { 108 HTMLElement* b = body(); 109 if (!b) 110 return String(); 111 return b->getAttribute(dirAttr); 112 } 113 114 void HTMLDocument::setDir(const String& value) 115 { 116 HTMLElement* b = body(); 117 if (b) 118 b->setAttribute(dirAttr, value); 119 } 120 121 String HTMLDocument::designMode() const 122 { 123 return inDesignMode() ? "on" : "off"; 124 } 125 126 void HTMLDocument::setDesignMode(const String& value) 127 { 128 InheritedBool mode; 129 if (equalIgnoringCase(value, "on")) 130 mode = on; 131 else if (equalIgnoringCase(value, "off")) 132 mode = off; 133 else 134 mode = inherit; 135 Document::setDesignMode(mode); 136 } 137 138 Element* HTMLDocument::activeElement() 139 { 140 if (Node* node = focusedNode()) 141 if (node->isElementNode()) 142 return static_cast<Element*>(node); 143 return body(); 144 } 145 146 bool HTMLDocument::hasFocus() 147 { 148 Page* page = this->page(); 149 if (!page) 150 return false; 151 if (!page->focusController()->isActive()) 152 return false; 153 if (Frame* focusedFrame = page->focusController()->focusedFrame()) { 154 if (focusedFrame->tree()->isDescendantOf(frame())) 155 return true; 156 } 157 return false; 158 } 159 160 String HTMLDocument::bgColor() 161 { 162 HTMLElement* b = body(); 163 HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0; 164 165 if (!bodyElement) 166 return String(); 167 return bodyElement->bgColor(); 168 } 169 170 void HTMLDocument::setBgColor(const String& value) 171 { 172 HTMLElement* b = body(); 173 HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0; 174 175 if (bodyElement) 176 bodyElement->setBgColor(value); 177 } 178 179 String HTMLDocument::fgColor() 180 { 181 HTMLElement* b = body(); 182 HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0; 183 184 if (!bodyElement) 185 return String(); 186 return bodyElement->text(); 187 } 188 189 void HTMLDocument::setFgColor(const String& value) 190 { 191 HTMLElement* b = body(); 192 HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0; 193 194 if (bodyElement) 195 bodyElement->setText(value); 196 } 197 198 String HTMLDocument::alinkColor() 199 { 200 HTMLElement* b = body(); 201 HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0; 202 203 if (!bodyElement) 204 return String(); 205 return bodyElement->aLink(); 206 } 207 208 void HTMLDocument::setAlinkColor(const String& value) 209 { 210 HTMLElement* b = body(); 211 HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0; 212 213 if (bodyElement) { 214 // This check is a bit silly, but some benchmarks like to set the 215 // document's link colors over and over to the same value and we 216 // don't want to incur a style update each time. 217 if (bodyElement->aLink() != value) 218 bodyElement->setALink(value); 219 } 220 } 221 222 String HTMLDocument::linkColor() 223 { 224 HTMLElement* b = body(); 225 HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0; 226 227 if (!bodyElement) 228 return String(); 229 return bodyElement->link(); 230 } 231 232 void HTMLDocument::setLinkColor(const String& value) 233 { 234 HTMLElement* b = body(); 235 HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0; 236 237 if (bodyElement) { 238 // This check is a bit silly, but some benchmarks like to set the 239 // document's link colors over and over to the same value and we 240 // don't want to incur a style update each time. 241 if (bodyElement->link() != value) 242 bodyElement->setLink(value); 243 } 244 } 245 246 String HTMLDocument::vlinkColor() 247 { 248 HTMLElement* b = body(); 249 HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0; 250 251 if (!bodyElement) 252 return String(); 253 return bodyElement->vLink(); 254 } 255 256 void HTMLDocument::setVlinkColor(const String& value) 257 { 258 HTMLElement* b = body(); 259 HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0; 260 261 if (bodyElement) { 262 // This check is a bit silly, but some benchmarks like to set the 263 // document's link colors over and over to the same value and we 264 // don't want to incur a style update each time. 265 if (bodyElement->vLink() != value) 266 bodyElement->setVLink(value); 267 } 268 } 269 270 void HTMLDocument::captureEvents() 271 { 272 } 273 274 void HTMLDocument::releaseEvents() 275 { 276 } 277 278 PassRefPtr<DocumentParser> HTMLDocument::createParser() 279 { 280 bool reportErrors = InspectorInstrumentation::hasFrontend(this->page()); 281 return HTMLDocumentParser::create(this, reportErrors); 282 } 283 284 // -------------------------------------------------------------------------- 285 // not part of the DOM 286 // -------------------------------------------------------------------------- 287 288 PassRefPtr<Element> HTMLDocument::createElement(const AtomicString& name, ExceptionCode& ec) 289 { 290 if (!isValidName(name)) { 291 ec = INVALID_CHARACTER_ERR; 292 return 0; 293 } 294 return HTMLElementFactory::createHTMLElement(QualifiedName(nullAtom, name.lower(), xhtmlNamespaceURI), this, 0, false); 295 } 296 297 void HTMLDocument::addItemToMap(HashCountedSet<AtomicStringImpl*>& map, const AtomicString& name) 298 { 299 if (name.isEmpty()) 300 return; 301 map.add(name.impl()); 302 if (Frame* f = frame()) 303 f->script()->namedItemAdded(this, name); 304 } 305 306 void HTMLDocument::removeItemFromMap(HashCountedSet<AtomicStringImpl*>& map, const AtomicString& name) 307 { 308 if (name.isEmpty()) 309 return; 310 map.remove(name.impl()); 311 if (Frame* f = frame()) 312 f->script()->namedItemRemoved(this, name); 313 } 314 315 void HTMLDocument::addNamedItem(const AtomicString& name) 316 { 317 addItemToMap(m_namedItemCounts, name); 318 } 319 320 void HTMLDocument::removeNamedItem(const AtomicString& name) 321 { 322 removeItemFromMap(m_namedItemCounts, name); 323 } 324 325 void HTMLDocument::addExtraNamedItem(const AtomicString& name) 326 { 327 addItemToMap(m_extraNamedItemCounts, name); 328 } 329 330 void HTMLDocument::removeExtraNamedItem(const AtomicString& name) 331 { 332 removeItemFromMap(m_extraNamedItemCounts, name); 333 } 334 335 void HTMLDocument::setCompatibilityModeFromDoctype() 336 { 337 // There are three possible compatibility modes: 338 // Quirks - quirks mode emulates WinIE and NS4. CSS parsing is also relaxed in this mode, e.g., unit types can 339 // be omitted from numbers. 340 // Limited Quirks - This mode is identical to no-quirks mode except for its treatment of line-height in the inline box model. 341 // No Quirks - no quirks apply. Web pages will obey the specifications to the letter. 342 DocumentType* docType = doctype(); 343 if (!docType) 344 return; 345 346 // Check for Quirks Mode. 347 const String& publicId = docType->publicId(); 348 if (docType->name() != "html" 349 || publicId.startsWith("+//Silmaril//dtd html Pro v0r11 19970101//", false) 350 || publicId.startsWith("-//AdvaSoft Ltd//DTD HTML 3.0 asWedit + extensions//", false) 351 || publicId.startsWith("-//AS//DTD HTML 3.0 asWedit + extensions//", false) 352 || publicId.startsWith("-//IETF//DTD HTML 2.0 Level 1//", false) 353 || publicId.startsWith("-//IETF//DTD HTML 2.0 Level 2//", false) 354 || publicId.startsWith("-//IETF//DTD HTML 2.0 Strict Level 1//", false) 355 || publicId.startsWith("-//IETF//DTD HTML 2.0 Strict Level 2//", false) 356 || publicId.startsWith("-//IETF//DTD HTML 2.0 Strict//", false) 357 || publicId.startsWith("-//IETF//DTD HTML 2.0//", false) 358 || publicId.startsWith("-//IETF//DTD HTML 2.1E//", false) 359 || publicId.startsWith("-//IETF//DTD HTML 3.0//", false) 360 || publicId.startsWith("-//IETF//DTD HTML 3.2 Final//", false) 361 || publicId.startsWith("-//IETF//DTD HTML 3.2//", false) 362 || publicId.startsWith("-//IETF//DTD HTML 3//", false) 363 || publicId.startsWith("-//IETF//DTD HTML Level 0//", false) 364 || publicId.startsWith("-//IETF//DTD HTML Level 1//", false) 365 || publicId.startsWith("-//IETF//DTD HTML Level 2//", false) 366 || publicId.startsWith("-//IETF//DTD HTML Level 3//", false) 367 || publicId.startsWith("-//IETF//DTD HTML Strict Level 0//", false) 368 || publicId.startsWith("-//IETF//DTD HTML Strict Level 1//", false) 369 || publicId.startsWith("-//IETF//DTD HTML Strict Level 2//", false) 370 || publicId.startsWith("-//IETF//DTD HTML Strict Level 3//", false) 371 || publicId.startsWith("-//IETF//DTD HTML Strict//", false) 372 || publicId.startsWith("-//IETF//DTD HTML//", false) 373 || publicId.startsWith("-//Metrius//DTD Metrius Presentational//", false) 374 || publicId.startsWith("-//Microsoft//DTD Internet Explorer 2.0 HTML Strict//", false) 375 || publicId.startsWith("-//Microsoft//DTD Internet Explorer 2.0 HTML//", false) 376 || publicId.startsWith("-//Microsoft//DTD Internet Explorer 2.0 Tables//", false) 377 || publicId.startsWith("-//Microsoft//DTD Internet Explorer 3.0 HTML Strict//", false) 378 || publicId.startsWith("-//Microsoft//DTD Internet Explorer 3.0 HTML//", false) 379 || publicId.startsWith("-//Microsoft//DTD Internet Explorer 3.0 Tables//", false) 380 || publicId.startsWith("-//Netscape Comm. Corp.//DTD HTML//", false) 381 || publicId.startsWith("-//Netscape Comm. Corp.//DTD Strict HTML//", false) 382 || publicId.startsWith("-//O'Reilly and Associates//DTD HTML 2.0//", false) 383 || publicId.startsWith("-//O'Reilly and Associates//DTD HTML Extended 1.0//", false) 384 || publicId.startsWith("-//O'Reilly and Associates//DTD HTML Extended Relaxed 1.0//", false) 385 || publicId.startsWith("-//SoftQuad Software//DTD HoTMetaL PRO 6.0::19990601::extensions to HTML 4.0//", false) 386 || publicId.startsWith("-//SoftQuad//DTD HoTMetaL PRO 4.0::19971010::extensions to HTML 4.0//", false) 387 || publicId.startsWith("-//Spyglass//DTD HTML 2.0 Extended//", false) 388 || publicId.startsWith("-//SQ//DTD HTML 2.0 HoTMetaL + extensions//", false) 389 || publicId.startsWith("-//Sun Microsystems Corp.//DTD HotJava HTML//", false) 390 || publicId.startsWith("-//Sun Microsystems Corp.//DTD HotJava Strict HTML//", false) 391 || publicId.startsWith("-//W3C//DTD HTML 3 1995-03-24//", false) 392 || publicId.startsWith("-//W3C//DTD HTML 3.2 Draft//", false) 393 || publicId.startsWith("-//W3C//DTD HTML 3.2 Final//", false) 394 || publicId.startsWith("-//W3C//DTD HTML 3.2//", false) 395 || publicId.startsWith("-//W3C//DTD HTML 3.2S Draft//", false) 396 || publicId.startsWith("-//W3C//DTD HTML 4.0 Frameset//", false) 397 || publicId.startsWith("-//W3C//DTD HTML 4.0 Transitional//", false) 398 || publicId.startsWith("-//W3C//DTD HTML Experimental 19960712//", false) 399 || publicId.startsWith("-//W3C//DTD HTML Experimental 970421//", false) 400 || publicId.startsWith("-//W3C//DTD W3 HTML//", false) 401 || publicId.startsWith("-//W3O//DTD W3 HTML 3.0//", false) 402 || equalIgnoringCase(publicId, "-//W3O//DTD W3 HTML Strict 3.0//EN//") 403 || publicId.startsWith("-//WebTechs//DTD Mozilla HTML 2.0//", false) 404 || publicId.startsWith("-//WebTechs//DTD Mozilla HTML//", false) 405 || equalIgnoringCase(publicId, "-/W3C/DTD HTML 4.0 Transitional/EN") 406 || equalIgnoringCase(publicId, "HTML") 407 || equalIgnoringCase(docType->systemId(), "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd") 408 || (docType->systemId().isEmpty() && publicId.startsWith("-//W3C//DTD HTML 4.01 Frameset//", false)) 409 || (docType->systemId().isEmpty() && publicId.startsWith("-//W3C//DTD HTML 4.01 Transitional//", false))) { 410 setCompatibilityMode(QuirksMode); 411 return; 412 } 413 414 // Check for Limited Quirks Mode. 415 if (publicId.startsWith("-//W3C//DTD XHTML 1.0 Frameset//", false) 416 || publicId.startsWith("-//W3C//DTD XHTML 1.0 Transitional//", false) 417 || (!docType->systemId().isEmpty() && publicId.startsWith("-//W3C//DTD HTML 4.01 Frameset//", false)) 418 || (!docType->systemId().isEmpty() && publicId.startsWith("-//W3C//DTD HTML 4.01 Transitional//", false))) { 419 setCompatibilityMode(LimitedQuirksMode); 420 return; 421 } 422 423 // Otherwise we are No Quirks Mode. 424 setCompatibilityMode(NoQuirksMode); 425 return; 426 } 427 428 void HTMLDocument::clear() 429 { 430 // FIXME: This does nothing, and that seems unlikely to be correct. 431 // We've long had a comment saying that IE doesn't support this. 432 // But I do see it in the documentation for Mozilla. 433 } 434 435 bool HTMLDocument::isFrameSet() const 436 { 437 HTMLElement* bodyElement = body(); 438 return bodyElement && bodyElement->hasTagName(framesetTag); 439 } 440 441 } 442