1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2001 Dirk Mueller (mueller (at) kde.org) 5 * (C) 2006 Alexey Proskuryakov (ap (at) webkit.org) 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 7 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 8 * Copyright (C) 2008, 2009 Google Inc. All rights reserved. 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Library General Public 12 * License as published by the Free Software Foundation; either 13 * version 2 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Library General Public License for more details. 19 * 20 * You should have received a copy of the GNU Library General Public License 21 * along with this library; see the file COPYING.LIB. If not, write to 22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 23 * Boston, MA 02110-1301, USA. 24 */ 25 26 #include "config.h" 27 #include "Document.h" 28 29 #include "AXObjectCache.h" 30 #include "AnimationController.h" 31 #include "Attr.h" 32 #include "CDATASection.h" 33 #include "CSSHelper.h" 34 #include "CSSStyleSelector.h" 35 #include "CSSStyleSheet.h" 36 #include "CSSValueKeywords.h" 37 #include "CString.h" 38 #include "CachedCSSStyleSheet.h" 39 #include "Chrome.h" 40 #include "ChromeClient.h" 41 #include "Comment.h" 42 #include "Console.h" 43 #include "CookieJar.h" 44 #include "DOMImplementation.h" 45 #include "DOMWindow.h" 46 #include "DocLoader.h" 47 #include "DocumentFragment.h" 48 #include "DocumentLoader.h" 49 #include "DocumentType.h" 50 #include "EditingText.h" 51 #include "Editor.h" 52 #include "EntityReference.h" 53 #include "Event.h" 54 #include "EventHandler.h" 55 #include "EventListener.h" 56 #include "EventNames.h" 57 #include "ExceptionCode.h" 58 #include "FocusController.h" 59 #include "Frame.h" 60 #include "FrameLoader.h" 61 #include "FrameTree.h" 62 #include "FrameView.h" 63 #include "HTMLAllCollection.h" 64 #include "HTMLAnchorElement.h" 65 #include "HTMLBodyElement.h" 66 #include "HTMLCanvasElement.h" 67 #include "HTMLCollection.h" 68 #include "HTMLDocument.h" 69 #include "HTMLElementFactory.h" 70 #include "HTMLFrameOwnerElement.h" 71 #include "HTMLHeadElement.h" 72 #include "HTMLIFrameElement.h" 73 #include "HTMLInputElement.h" 74 #include "HTMLLinkElement.h" 75 #include "HTMLMapElement.h" 76 #include "HTMLNameCollection.h" 77 #include "HTMLNames.h" 78 #include "HTMLParser.h" 79 #include "HTMLStyleElement.h" 80 #include "HTMLTitleElement.h" 81 #include "HTTPParsers.h" 82 #include "HistoryItem.h" 83 #include "HitTestRequest.h" 84 #include "HitTestResult.h" 85 #include "ImageLoader.h" 86 #include "InspectorController.h" 87 #include "InspectorTimelineAgent.h" 88 #include "KeyboardEvent.h" 89 #include "Logging.h" 90 #include "MappedAttribute.h" 91 #include "MessageEvent.h" 92 #include "MouseEvent.h" 93 #include "MouseEventWithHitTestResults.h" 94 #include "MutationEvent.h" 95 #include "NameNodeList.h" 96 #include "NodeFilter.h" 97 #include "NodeIterator.h" 98 #include "NodeWithIndex.h" 99 #include "OverflowEvent.h" 100 #include "Page.h" 101 #include "PageGroup.h" 102 #include "PageTransitionEvent.h" 103 #include "PlatformKeyboardEvent.h" 104 #include "PopStateEvent.h" 105 #include "ProcessingInstruction.h" 106 #include "ProgressEvent.h" 107 #include "RegisteredEventListener.h" 108 #include "RenderArena.h" 109 #include "RenderTextControl.h" 110 #include "RenderView.h" 111 #include "RenderWidget.h" 112 #include "ScriptController.h" 113 #include "ScriptElement.h" 114 #include "ScriptEventListener.h" 115 #include "SecurityOrigin.h" 116 #include "SegmentedString.h" 117 #include "SelectionController.h" 118 #include "Settings.h" 119 #include "StringBuffer.h" 120 #include "StyleSheetList.h" 121 #include "TextEvent.h" 122 #include "TextIterator.h" 123 #include "TextResourceDecoder.h" 124 #include "Timer.h" 125 #include "TransformSource.h" 126 #include "TreeWalker.h" 127 #include "UIEvent.h" 128 #include "UserContentURLPattern.h" 129 #include "WebKitAnimationEvent.h" 130 #include "WebKitTransitionEvent.h" 131 #include "WheelEvent.h" 132 #include "XMLHttpRequest.h" 133 #include "XMLNSNames.h" 134 #include "XMLNames.h" 135 #include "XMLTokenizer.h" 136 #include "htmlediting.h" 137 #include <wtf/CurrentTime.h> 138 #include <wtf/HashFunctions.h> 139 #include <wtf/MainThread.h> 140 #include <wtf/PassRefPtr.h> 141 #include <wtf/StdLibExtras.h> 142 143 #if ENABLE(SHARED_WORKERS) 144 #include "SharedWorkerRepository.h" 145 #endif 146 147 #if ENABLE(DOM_STORAGE) 148 #include "StorageEvent.h" 149 #endif 150 151 #if ENABLE(XPATH) 152 #include "XPathEvaluator.h" 153 #include "XPathExpression.h" 154 #include "XPathNSResolver.h" 155 #include "XPathResult.h" 156 #endif 157 158 #if ENABLE(XSLT) 159 #include "XSLTProcessor.h" 160 #endif 161 162 #if ENABLE(XBL) 163 #include "XBLBindingManager.h" 164 #endif 165 166 #if ENABLE(SVG) 167 #include "SVGDocumentExtensions.h" 168 #include "SVGElementFactory.h" 169 #include "SVGNames.h" 170 #include "SVGZoomEvent.h" 171 #include "SVGStyleElement.h" 172 #endif 173 174 #if PLATFORM(ANDROID) 175 // FIXME: We shouldn't be including this from WebCore! 176 #include "WebViewCore.h" 177 #endif 178 179 #ifdef ANDROID_META_SUPPORT 180 #include "Settings.h" 181 #endif 182 183 #ifdef ANDROID_RESET_SELECTION 184 #include "CacheBuilder.h" 185 #include "HTMLTextAreaElement.h" 186 #endif 187 188 #ifdef ANDROID_INSTRUMENT 189 #include "TimeCounter.h" 190 #endif 191 192 #if ENABLE(TOUCH_EVENTS) 193 #include "TouchEvent.h" 194 #endif 195 196 #if ENABLE(WML) 197 #include "WMLDocument.h" 198 #include "WMLElement.h" 199 #include "WMLElementFactory.h" 200 #include "WMLNames.h" 201 #endif 202 203 #if ENABLE(MATHML) 204 #include "MathMLElement.h" 205 #include "MathMLElementFactory.h" 206 #include "MathMLNames.h" 207 #endif 208 209 #if ENABLE(XHTMLMP) 210 #include "HTMLNoScriptElement.h" 211 #endif 212 213 using namespace std; 214 using namespace WTF; 215 using namespace Unicode; 216 217 namespace WebCore { 218 219 using namespace HTMLNames; 220 221 // #define INSTRUMENT_LAYOUT_SCHEDULING 1 222 223 // This amount of time must have elapsed before we will even consider scheduling a layout without a delay. 224 // FIXME: For faster machines this value can really be lowered to 200. 250 is adequate, but a little high 225 // for dual G5s. :) 226 static const int cLayoutScheduleThreshold = 250; 227 228 // Use 1 to represent the document's default form. 229 static HTMLFormElement* const defaultForm = reinterpret_cast<HTMLFormElement*>(1); 230 231 // DOM Level 2 says (letters added): 232 // 233 // a) Name start characters must have one of the categories Ll, Lu, Lo, Lt, Nl. 234 // b) Name characters other than Name-start characters must have one of the categories Mc, Me, Mn, Lm, or Nd. 235 // c) Characters in the compatibility area (i.e. with character code greater than #xF900 and less than #xFFFE) are not allowed in XML names. 236 // d) Characters which have a font or compatibility decomposition (i.e. those with a "compatibility formatting tag" in field 5 of the database -- marked by field 5 beginning with a "<") are not allowed. 237 // e) The following characters are treated as name-start characters rather than name characters, because the property file classifies them as Alphabetic: [#x02BB-#x02C1], #x0559, #x06E5, #x06E6. 238 // f) Characters #x20DD-#x20E0 are excluded (in accordance with Unicode, section 5.14). 239 // g) Character #x00B7 is classified as an extender, because the property list so identifies it. 240 // h) Character #x0387 is added as a name character, because #x00B7 is its canonical equivalent. 241 // i) Characters ':' and '_' are allowed as name-start characters. 242 // j) Characters '-' and '.' are allowed as name characters. 243 // 244 // It also contains complete tables. If we decide it's better, we could include those instead of the following code. 245 246 static inline bool isValidNameStart(UChar32 c) 247 { 248 // rule (e) above 249 if ((c >= 0x02BB && c <= 0x02C1) || c == 0x559 || c == 0x6E5 || c == 0x6E6) 250 return true; 251 252 // rule (i) above 253 if (c == ':' || c == '_') 254 return true; 255 256 // rules (a) and (f) above 257 const uint32_t nameStartMask = Letter_Lowercase | Letter_Uppercase | Letter_Other | Letter_Titlecase | Number_Letter; 258 if (!(Unicode::category(c) & nameStartMask)) 259 return false; 260 261 // rule (c) above 262 if (c >= 0xF900 && c < 0xFFFE) 263 return false; 264 265 // rule (d) above 266 DecompositionType decompType = decompositionType(c); 267 if (decompType == DecompositionFont || decompType == DecompositionCompat) 268 return false; 269 270 return true; 271 } 272 273 static inline bool isValidNamePart(UChar32 c) 274 { 275 // rules (a), (e), and (i) above 276 if (isValidNameStart(c)) 277 return true; 278 279 // rules (g) and (h) above 280 if (c == 0x00B7 || c == 0x0387) 281 return true; 282 283 // rule (j) above 284 if (c == '-' || c == '.') 285 return true; 286 287 // rules (b) and (f) above 288 const uint32_t otherNamePartMask = Mark_NonSpacing | Mark_Enclosing | Mark_SpacingCombining | Letter_Modifier | Number_DecimalDigit; 289 if (!(Unicode::category(c) & otherNamePartMask)) 290 return false; 291 292 // rule (c) above 293 if (c >= 0xF900 && c < 0xFFFE) 294 return false; 295 296 // rule (d) above 297 DecompositionType decompType = decompositionType(c); 298 if (decompType == DecompositionFont || decompType == DecompositionCompat) 299 return false; 300 301 return true; 302 } 303 304 static Widget* widgetForNode(Node* focusedNode) 305 { 306 if (!focusedNode) 307 return 0; 308 RenderObject* renderer = focusedNode->renderer(); 309 if (!renderer || !renderer->isWidget()) 310 return 0; 311 return toRenderWidget(renderer)->widget(); 312 } 313 314 static bool acceptsEditingFocus(Node *node) 315 { 316 ASSERT(node); 317 ASSERT(node->isContentEditable()); 318 319 Node *root = node->rootEditableElement(); 320 Frame* frame = node->document()->frame(); 321 if (!frame || !root) 322 return false; 323 324 return frame->editor()->shouldBeginEditing(rangeOfContents(root).get()); 325 } 326 327 static bool disableRangeMutation(Page* page) 328 { 329 #if PLATFORM(MAC) 330 // Disable Range mutation on document modifications in Tiger and Leopard Mail 331 // See <rdar://problem/5865171> 332 return page && (page->settings()->needsLeopardMailQuirks() || page->settings()->needsTigerMailQuirks()); 333 #else 334 return false; 335 #endif 336 } 337 338 static HashSet<Document*>* documentsThatNeedStyleRecalc = 0; 339 340 class DocumentWeakReference : public ThreadSafeShared<DocumentWeakReference> { 341 public: 342 static PassRefPtr<DocumentWeakReference> create(Document* document) 343 { 344 return adoptRef(new DocumentWeakReference(document)); 345 } 346 347 Document* document() 348 { 349 ASSERT(isMainThread()); 350 return m_document; 351 } 352 353 void clear() 354 { 355 ASSERT(isMainThread()); 356 m_document = 0; 357 } 358 359 private: 360 DocumentWeakReference(Document* document) 361 : m_document(document) 362 { 363 ASSERT(isMainThread()); 364 } 365 366 Document* m_document; 367 }; 368 369 Document::Document(Frame* frame, bool isXHTML, bool isHTML) 370 : ContainerNode(0) 371 , m_domtree_version(0) 372 , m_styleSheets(StyleSheetList::create(this)) 373 , m_styleRecalcTimer(this, &Document::styleRecalcTimerFired) 374 , m_frameElementsShouldIgnoreScrolling(false) 375 , m_containsValidityStyleRules(false) 376 , m_updateFocusAppearanceRestoresSelection(false) 377 , m_title("") 378 , m_rawTitle("") 379 , m_titleSetExplicitly(false) 380 , m_updateFocusAppearanceTimer(this, &Document::updateFocusAppearanceTimerFired) 381 , m_startTime(currentTime()) 382 , m_overMinimumLayoutThreshold(false) 383 , m_extraLayoutDelay(0) 384 , m_executeScriptSoonTimer(this, &Document::executeScriptSoonTimerFired) 385 , m_xmlVersion("1.0") 386 , m_xmlStandalone(false) 387 #if ENABLE(XBL) 388 , m_bindingManager(new XBLBindingManager(this)) 389 #endif 390 , m_savedRenderer(0) 391 , m_designMode(inherit) 392 , m_selfOnlyRefCount(0) 393 #if ENABLE(SVG) 394 , m_svgExtensions(0) 395 #endif 396 #if ENABLE(DASHBOARD_SUPPORT) 397 , m_hasDashboardRegions(false) 398 , m_dashboardRegionsDirty(false) 399 #endif 400 , m_accessKeyMapValid(false) 401 , m_createRenderers(true) 402 , m_inPageCache(false) 403 , m_useSecureKeyboardEntryWhenActive(false) 404 , m_isXHTML(isXHTML) 405 , m_isHTML(isHTML) 406 , m_numNodeListCaches(0) 407 #if USE(JSC) 408 , m_normalWorldWrapperCache(0) 409 #endif 410 , m_usingGeolocation(false) 411 , m_storageEventTimer(this, &Document::storageEventTimerFired) 412 #if ENABLE(WML) 413 , m_containsWMLContent(false) 414 #endif 415 , m_weakReference(DocumentWeakReference::create(this)) 416 { 417 m_document = this; 418 419 m_pageGroupUserSheetCacheValid = false; 420 421 m_printing = false; 422 423 m_ignoreAutofocus = false; 424 425 m_frame = frame; 426 427 #if !PLATFORM(ANDROID) 428 m_axObjectCache = 0; 429 #endif 430 431 m_docLoader = new DocLoader(this); 432 433 m_visuallyOrdered = false; 434 m_bParsing = false; 435 m_wellFormed = false; 436 437 setParseMode(Strict); 438 439 m_textColor = Color::black; 440 m_listenerTypes = 0; 441 m_inDocument = true; 442 m_inStyleRecalc = false; 443 m_closeAfterStyleRecalc = false; 444 445 m_usesDescendantRules = false; 446 m_usesSiblingRules = false; 447 m_usesFirstLineRules = false; 448 m_usesFirstLetterRules = false; 449 m_usesBeforeAfterRules = false; 450 m_usesRemUnits = false; 451 452 m_gotoAnchorNeededAfterStylesheetsLoad = false; 453 454 m_didCalculateStyleSelector = false; 455 m_pendingStylesheets = 0; 456 m_ignorePendingStylesheets = false; 457 m_hasNodesWithPlaceholderStyle = false; 458 m_pendingSheetLayout = NoLayoutWithPendingSheets; 459 460 m_cssTarget = 0; 461 462 resetLinkColor(); 463 resetVisitedLinkColor(); 464 resetActiveLinkColor(); 465 466 m_processingLoadEvent = false; 467 468 initSecurityContext(); 469 initDNSPrefetch(); 470 471 static int docID = 0; 472 m_docID = docID++; 473 #if ENABLE(XHTMLMP) 474 m_shouldProcessNoScriptElement = settings() && !settings()->isJavaScriptEnabled(); 475 #endif 476 } 477 478 void Document::removedLastRef() 479 { 480 ASSERT(!m_deletionHasBegun); 481 if (m_selfOnlyRefCount) { 482 // If removing a child removes the last self-only ref, we don't 483 // want the document to be destructed until after 484 // removeAllChildren returns, so we guard ourselves with an 485 // extra self-only ref. 486 selfOnlyRef(); 487 488 // We must make sure not to be retaining any of our children through 489 // these extra pointers or we will create a reference cycle. 490 m_docType = 0; 491 m_focusedNode = 0; 492 m_hoverNode = 0; 493 m_activeNode = 0; 494 m_titleElement = 0; 495 m_documentElement = 0; 496 497 // removeAllChildren() doesn't always unregister IDs, do it upfront to avoid having stale references in the map. 498 m_elementsById.clear(); 499 500 removeAllChildren(); 501 502 deleteAllValues(m_markers); 503 m_markers.clear(); 504 505 m_tokenizer.clear(); 506 507 m_cssCanvasElements.clear(); 508 509 #ifndef NDEBUG 510 m_inRemovedLastRefFunction = false; 511 #endif 512 513 selfOnlyDeref(); 514 } else { 515 #ifndef NDEBUG 516 m_deletionHasBegun = true; 517 #endif 518 delete this; 519 } 520 } 521 522 Document::~Document() 523 { 524 ASSERT(!renderer()); 525 ASSERT(!m_inPageCache); 526 ASSERT(!m_savedRenderer); 527 ASSERT(m_ranges.isEmpty()); 528 ASSERT(!m_styleRecalcTimer.isActive()); 529 530 for (size_t i = 0; i < m_scriptsToExecuteSoon.size(); ++i) 531 m_scriptsToExecuteSoon[i].first->element()->deref(); // Balances ref() in executeScriptSoon(). 532 533 removeAllEventListeners(); 534 535 #if USE(JSC) 536 forgetAllDOMNodesForDocument(this); 537 #endif 538 539 m_tokenizer.clear(); 540 m_document = 0; 541 m_docLoader.clear(); 542 543 m_renderArena.clear(); 544 545 #if ENABLE(XBL) 546 m_bindingManager.clear(); 547 #endif 548 549 deleteAllValues(m_markers); 550 551 clearAXObjectCache(); 552 553 m_decoder = 0; 554 555 unsigned count = sizeof(m_nameCollectionInfo) / sizeof(m_nameCollectionInfo[0]); 556 for (unsigned i = 0; i < count; i++) 557 deleteAllValues(m_nameCollectionInfo[i]); 558 559 if (m_styleSheets) 560 m_styleSheets->documentDestroyed(); 561 562 m_weakReference->clear(); 563 } 564 565 #if USE(JSC) 566 Document::JSWrapperCache* Document::createWrapperCache(DOMWrapperWorld* world) 567 { 568 JSWrapperCache* wrapperCache = new JSWrapperCache(); 569 m_wrapperCacheMap.set(world, wrapperCache); 570 if (world->isNormal()) { 571 ASSERT(!m_normalWorldWrapperCache); 572 m_normalWorldWrapperCache = wrapperCache; 573 } 574 world->rememberDocument(this); 575 return wrapperCache; 576 } 577 #endif 578 579 void Document::resetLinkColor() 580 { 581 m_linkColor = Color(0, 0, 238); 582 } 583 584 void Document::resetVisitedLinkColor() 585 { 586 m_visitedLinkColor = Color(85, 26, 139); 587 } 588 589 void Document::resetActiveLinkColor() 590 { 591 m_activeLinkColor.setNamedColor("red"); 592 } 593 594 void Document::setDocType(PassRefPtr<DocumentType> docType) 595 { 596 // This should never be called more than once. 597 // Note: This is not a public DOM method and can only be called by the parser. 598 ASSERT(!m_docType || !docType); 599 if (m_docType && docType) 600 return; 601 m_docType = docType; 602 if (m_docType) 603 m_docType->setDocument(this); 604 #ifdef ANDROID_META_SUPPORT 605 if (m_docType && !ownerElement() 606 && m_docType->publicId().startsWith("-//wapforum//dtd xhtml mobile 1.", false)) { 607 // fit mobile sites directly in the screen 608 if (Frame *f = frame()) 609 f->settings()->setMetadataSettings("width", "device-width"); 610 if (FrameView* frameView = view()) 611 android::WebViewCore::getWebViewCore(frameView)->updateViewport(); 612 } 613 #endif 614 determineParseMode(); 615 } 616 617 DOMImplementation* Document::implementation() const 618 { 619 if (!m_implementation) 620 m_implementation = DOMImplementation::create(); 621 return m_implementation.get(); 622 } 623 624 void Document::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) 625 { 626 ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); 627 628 // Invalidate the document element we have cached in case it was replaced. 629 m_documentElement = 0; 630 } 631 632 void Document::cacheDocumentElement() const 633 { 634 ASSERT(!m_documentElement); 635 Node* n = firstChild(); 636 while (n && !n->isElementNode()) 637 n = n->nextSibling(); 638 m_documentElement = static_cast<Element*>(n); 639 } 640 641 PassRefPtr<Element> Document::createElement(const AtomicString& name, ExceptionCode& ec) 642 { 643 if (!isValidName(name)) { 644 ec = INVALID_CHARACTER_ERR; 645 return 0; 646 } 647 648 if (m_isXHTML) 649 return HTMLElementFactory::createHTMLElement(QualifiedName(nullAtom, name, xhtmlNamespaceURI), this, 0, false); 650 651 return createElement(QualifiedName(nullAtom, name, nullAtom), false); 652 } 653 654 PassRefPtr<DocumentFragment> Document::createDocumentFragment() 655 { 656 return DocumentFragment::create(document()); 657 } 658 659 PassRefPtr<Text> Document::createTextNode(const String& data) 660 { 661 return Text::create(this, data); 662 } 663 664 PassRefPtr<Comment> Document::createComment(const String& data) 665 { 666 return Comment::create(this, data); 667 } 668 669 PassRefPtr<CDATASection> Document::createCDATASection(const String& data, ExceptionCode& ec) 670 { 671 if (isHTMLDocument()) { 672 ec = NOT_SUPPORTED_ERR; 673 return 0; 674 } 675 return CDATASection::create(this, data); 676 } 677 678 PassRefPtr<ProcessingInstruction> Document::createProcessingInstruction(const String& target, const String& data, ExceptionCode& ec) 679 { 680 if (!isValidName(target)) { 681 ec = INVALID_CHARACTER_ERR; 682 return 0; 683 } 684 if (isHTMLDocument()) { 685 ec = NOT_SUPPORTED_ERR; 686 return 0; 687 } 688 return ProcessingInstruction::create(this, target, data); 689 } 690 691 PassRefPtr<EntityReference> Document::createEntityReference(const String& name, ExceptionCode& ec) 692 { 693 if (!isValidName(name)) { 694 ec = INVALID_CHARACTER_ERR; 695 return 0; 696 } 697 if (isHTMLDocument()) { 698 ec = NOT_SUPPORTED_ERR; 699 return 0; 700 } 701 return EntityReference::create(this, name); 702 } 703 704 PassRefPtr<EditingText> Document::createEditingTextNode(const String& text) 705 { 706 return EditingText::create(this, text); 707 } 708 709 PassRefPtr<CSSStyleDeclaration> Document::createCSSStyleDeclaration() 710 { 711 return CSSMutableStyleDeclaration::create(); 712 } 713 714 PassRefPtr<Node> Document::importNode(Node* importedNode, bool deep, ExceptionCode& ec) 715 { 716 ec = 0; 717 718 if (!importedNode 719 #if ENABLE(SVG) && ENABLE(DASHBOARD_SUPPORT) 720 || (importedNode->isSVGElement() && page() && page()->settings()->usesDashboardBackwardCompatibilityMode()) 721 #endif 722 ) { 723 ec = NOT_SUPPORTED_ERR; 724 return 0; 725 } 726 727 switch (importedNode->nodeType()) { 728 case TEXT_NODE: 729 return createTextNode(importedNode->nodeValue()); 730 case CDATA_SECTION_NODE: 731 return createCDATASection(importedNode->nodeValue(), ec); 732 case ENTITY_REFERENCE_NODE: 733 return createEntityReference(importedNode->nodeName(), ec); 734 case PROCESSING_INSTRUCTION_NODE: 735 return createProcessingInstruction(importedNode->nodeName(), importedNode->nodeValue(), ec); 736 case COMMENT_NODE: 737 return createComment(importedNode->nodeValue()); 738 case ELEMENT_NODE: { 739 Element* oldElement = static_cast<Element*>(importedNode); 740 RefPtr<Element> newElement = createElementNS(oldElement->namespaceURI(), oldElement->tagQName().toString(), ec); 741 742 if (ec) 743 return 0; 744 745 NamedNodeMap* attrs = oldElement->attributes(true); 746 if (attrs) { 747 unsigned length = attrs->length(); 748 for (unsigned i = 0; i < length; i++) { 749 Attribute* attr = attrs->attributeItem(i); 750 newElement->setAttribute(attr->name(), attr->value().impl(), ec); 751 if (ec) 752 return 0; 753 } 754 } 755 756 newElement->copyNonAttributeProperties(oldElement); 757 758 if (deep) { 759 for (Node* oldChild = oldElement->firstChild(); oldChild; oldChild = oldChild->nextSibling()) { 760 RefPtr<Node> newChild = importNode(oldChild, true, ec); 761 if (ec) 762 return 0; 763 newElement->appendChild(newChild.release(), ec); 764 if (ec) 765 return 0; 766 } 767 } 768 769 return newElement.release(); 770 } 771 case ATTRIBUTE_NODE: 772 return Attr::create(0, this, static_cast<Attr*>(importedNode)->attr()->clone()); 773 case DOCUMENT_FRAGMENT_NODE: { 774 DocumentFragment* oldFragment = static_cast<DocumentFragment*>(importedNode); 775 RefPtr<DocumentFragment> newFragment = createDocumentFragment(); 776 if (deep) { 777 for (Node* oldChild = oldFragment->firstChild(); oldChild; oldChild = oldChild->nextSibling()) { 778 RefPtr<Node> newChild = importNode(oldChild, true, ec); 779 if (ec) 780 return 0; 781 newFragment->appendChild(newChild.release(), ec); 782 if (ec) 783 return 0; 784 } 785 } 786 787 return newFragment.release(); 788 } 789 case ENTITY_NODE: 790 case NOTATION_NODE: 791 // FIXME: It should be possible to import these node types, however in DOM3 the DocumentType is readonly, so there isn't much sense in doing that. 792 // Ability to add these imported nodes to a DocumentType will be considered for addition to a future release of the DOM. 793 case DOCUMENT_NODE: 794 case DOCUMENT_TYPE_NODE: 795 case XPATH_NAMESPACE_NODE: 796 break; 797 } 798 799 ec = NOT_SUPPORTED_ERR; 800 return 0; 801 } 802 803 804 PassRefPtr<Node> Document::adoptNode(PassRefPtr<Node> source, ExceptionCode& ec) 805 { 806 if (!source) { 807 ec = NOT_SUPPORTED_ERR; 808 return 0; 809 } 810 811 if (source->isReadOnlyNode()) { 812 ec = NO_MODIFICATION_ALLOWED_ERR; 813 return 0; 814 } 815 816 switch (source->nodeType()) { 817 case ENTITY_NODE: 818 case NOTATION_NODE: 819 case DOCUMENT_NODE: 820 case DOCUMENT_TYPE_NODE: 821 case XPATH_NAMESPACE_NODE: 822 ec = NOT_SUPPORTED_ERR; 823 return 0; 824 case ATTRIBUTE_NODE: { 825 Attr* attr = static_cast<Attr*>(source.get()); 826 if (attr->ownerElement()) 827 attr->ownerElement()->removeAttributeNode(attr, ec); 828 attr->setSpecified(true); 829 break; 830 } 831 default: 832 if (source->hasTagName(iframeTag)) 833 static_cast<HTMLIFrameElement*>(source.get())->setRemainsAliveOnRemovalFromTree(attached()); 834 835 if (source->parentNode()) 836 source->parentNode()->removeChild(source.get(), ec); 837 } 838 839 for (Node* node = source.get(); node; node = node->traverseNextNode(source.get())) 840 node->setDocument(this); 841 842 return source; 843 } 844 845 bool Document::hasPrefixNamespaceMismatch(const QualifiedName& qName) 846 { 847 // These checks are from DOM Core Level 2, createElementNS 848 // http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-DocCrElNS 849 if (!qName.prefix().isEmpty() && qName.namespaceURI().isNull()) // createElementNS(null, "html:div") 850 return true; 851 if (qName.prefix() == xmlAtom && qName.namespaceURI() != XMLNames::xmlNamespaceURI) // createElementNS("http://www.example.com", "xml:lang") 852 return true; 853 854 // Required by DOM Level 3 Core and unspecified by DOM Level 2 Core: 855 // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-DocCrElNS 856 // createElementNS("http://www.w3.org/2000/xmlns/", "foo:bar"), createElementNS(null, "xmlns:bar") 857 if ((qName.prefix() == xmlnsAtom && qName.namespaceURI() != XMLNSNames::xmlnsNamespaceURI) || (qName.prefix() != xmlnsAtom && qName.namespaceURI() == XMLNSNames::xmlnsNamespaceURI)) 858 return true; 859 860 return false; 861 } 862 863 // FIXME: This should really be in a possible ElementFactory class 864 PassRefPtr<Element> Document::createElement(const QualifiedName& qName, bool createdByParser) 865 { 866 RefPtr<Element> e; 867 868 // FIXME: Use registered namespaces and look up in a hash to find the right factory. 869 if (qName.namespaceURI() == xhtmlNamespaceURI) 870 e = HTMLElementFactory::createHTMLElement(qName, this, 0, createdByParser); 871 #if ENABLE(SVG) 872 else if (qName.namespaceURI() == SVGNames::svgNamespaceURI) 873 e = SVGElementFactory::createSVGElement(qName, this, createdByParser); 874 #endif 875 #if ENABLE(WML) 876 else if (qName.namespaceURI() == WMLNames::wmlNamespaceURI) 877 e = WMLElementFactory::createWMLElement(qName, this, createdByParser); 878 else if (isWMLDocument()) 879 e = WMLElementFactory::createWMLElement(QualifiedName(nullAtom, qName.localName(), WMLNames::wmlNamespaceURI), this, createdByParser); 880 #endif 881 #if ENABLE(MATHML) 882 else if (qName.namespaceURI() == MathMLNames::mathmlNamespaceURI) 883 e = MathMLElementFactory::createMathMLElement(qName, this, createdByParser); 884 #endif 885 886 if (!e) 887 e = Element::create(qName, document()); 888 889 // <image> uses imgTag so we need a special rule. 890 #if ENABLE(WML) 891 if (!isWMLDocument()) 892 #endif 893 ASSERT((qName.matches(imageTag) && e->tagQName().matches(imgTag) && e->tagQName().prefix() == qName.prefix()) || qName == e->tagQName()); 894 895 return e.release(); 896 } 897 898 PassRefPtr<Element> Document::createElementNS(const String& namespaceURI, const String& qualifiedName, ExceptionCode& ec) 899 { 900 String prefix, localName; 901 if (!parseQualifiedName(qualifiedName, prefix, localName, ec)) 902 return 0; 903 904 QualifiedName qName(prefix, localName, namespaceURI); 905 if (hasPrefixNamespaceMismatch(qName)) { 906 ec = NAMESPACE_ERR; 907 return 0; 908 } 909 910 return createElement(qName, false); 911 } 912 913 Element* Document::getElementById(const AtomicString& elementId) const 914 { 915 if (elementId.isEmpty()) 916 return 0; 917 918 m_elementsById.checkConsistency(); 919 920 Element* element = m_elementsById.get(elementId.impl()); 921 if (element) 922 return element; 923 924 if (m_duplicateIds.contains(elementId.impl())) { 925 // We know there's at least one node with this id, but we don't know what the first one is. 926 for (Node *n = traverseNextNode(); n != 0; n = n->traverseNextNode()) { 927 if (n->isElementNode()) { 928 element = static_cast<Element*>(n); 929 if (element->hasID() && element->getAttribute(element->idAttributeName()) == elementId) { 930 m_duplicateIds.remove(elementId.impl()); 931 m_elementsById.set(elementId.impl(), element); 932 return element; 933 } 934 } 935 } 936 ASSERT_NOT_REACHED(); 937 } 938 return 0; 939 } 940 941 String Document::readyState() const 942 { 943 if (Frame* f = frame()) { 944 if (f->loader()->isComplete()) 945 return "complete"; 946 if (parsing()) 947 return "loading"; 948 return "loaded"; 949 // FIXME: What does "interactive" mean? 950 // FIXME: Missing support for "uninitialized". 951 } 952 return String(); 953 } 954 955 String Document::encoding() const 956 { 957 if (TextResourceDecoder* d = decoder()) 958 return d->encoding().domName(); 959 return String(); 960 } 961 962 String Document::defaultCharset() const 963 { 964 if (Settings* settings = this->settings()) 965 return settings->defaultTextEncodingName(); 966 return String(); 967 } 968 969 void Document::setCharset(const String& charset) 970 { 971 if (!decoder()) 972 return; 973 decoder()->setEncoding(charset, TextResourceDecoder::UserChosenEncoding); 974 } 975 976 void Document::setXMLVersion(const String& version, ExceptionCode& ec) 977 { 978 if (!implementation()->hasFeature("XML", String())) { 979 ec = NOT_SUPPORTED_ERR; 980 return; 981 } 982 983 // FIXME: Also raise NOT_SUPPORTED_ERR if the version is set to a value that is not supported by this Document. 984 985 m_xmlVersion = version; 986 } 987 988 void Document::setXMLStandalone(bool standalone, ExceptionCode& ec) 989 { 990 if (!implementation()->hasFeature("XML", String())) { 991 ec = NOT_SUPPORTED_ERR; 992 return; 993 } 994 995 m_xmlStandalone = standalone; 996 } 997 998 void Document::setDocumentURI(const String& uri) 999 { 1000 m_documentURI = uri; 1001 updateBaseURL(); 1002 } 1003 1004 KURL Document::baseURI() const 1005 { 1006 return m_baseURL; 1007 } 1008 1009 Element* Document::elementFromPoint(int x, int y) const 1010 { 1011 // FIXME: Share code between this and caretRangeFromPoint. 1012 if (!renderer()) 1013 return 0; 1014 Frame* frame = this->frame(); 1015 if (!frame) 1016 return 0; 1017 FrameView* frameView = frame->view(); 1018 if (!frameView) 1019 return 0; 1020 1021 float zoomFactor = frame->pageZoomFactor(); 1022 IntPoint point = roundedIntPoint(FloatPoint(x * zoomFactor + view()->scrollX(), y * zoomFactor + view()->scrollY())); 1023 1024 if (!frameView->visibleContentRect().contains(point)) 1025 return 0; 1026 1027 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active); 1028 HitTestResult result(point); 1029 renderView()->layer()->hitTest(request, result); 1030 1031 Node* n = result.innerNode(); 1032 while (n && !n->isElementNode()) 1033 n = n->parentNode(); 1034 if (n) 1035 n = n->shadowAncestorNode(); 1036 return static_cast<Element*>(n); 1037 } 1038 1039 PassRefPtr<Range> Document::caretRangeFromPoint(int x, int y) 1040 { 1041 // FIXME: Share code between this and elementFromPoint. 1042 if (!renderer()) 1043 return 0; 1044 Frame* frame = this->frame(); 1045 if (!frame) 1046 return 0; 1047 FrameView* frameView = frame->view(); 1048 if (!frameView) 1049 return 0; 1050 1051 float zoomFactor = frame->pageZoomFactor(); 1052 IntPoint point = roundedIntPoint(FloatPoint(x * zoomFactor + view()->scrollX(), y * zoomFactor + view()->scrollY())); 1053 1054 if (!frameView->visibleContentRect().contains(point)) 1055 return 0; 1056 1057 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active); 1058 HitTestResult result(point); 1059 renderView()->layer()->hitTest(request, result); 1060 1061 Node* node = result.innerNode(); 1062 if (!node) 1063 return 0; 1064 1065 Node* shadowAncestorNode = node->shadowAncestorNode(); 1066 if (shadowAncestorNode != node) { 1067 unsigned offset = shadowAncestorNode->nodeIndex(); 1068 Node* container = shadowAncestorNode->parentNode(); 1069 return Range::create(this, container, offset, container, offset); 1070 } 1071 1072 RenderObject* renderer = node->renderer(); 1073 if (!renderer) 1074 return 0; 1075 VisiblePosition visiblePosition = renderer->positionForPoint(result.localPoint()); 1076 if (visiblePosition.isNull()) 1077 return 0; 1078 1079 Position rangeCompliantPosition = rangeCompliantEquivalent(visiblePosition); 1080 return Range::create(this, rangeCompliantPosition, rangeCompliantPosition); 1081 } 1082 1083 void Document::addElementById(const AtomicString& elementId, Element* element) 1084 { 1085 typedef HashMap<AtomicStringImpl*, Element*>::iterator iterator; 1086 if (!m_duplicateIds.contains(elementId.impl())) { 1087 // Fast path. The ID is not already in m_duplicateIds, so we assume that it's 1088 // also not already in m_elementsById and do an add. If that add succeeds, we're done. 1089 pair<iterator, bool> addResult = m_elementsById.add(elementId.impl(), element); 1090 if (addResult.second) 1091 return; 1092 // The add failed, so this ID was already cached in m_elementsById. 1093 // There are multiple elements with this ID. Remove the m_elementsById 1094 // cache for this ID so getElementById searches for it next time it is called. 1095 m_elementsById.remove(addResult.first); 1096 m_duplicateIds.add(elementId.impl()); 1097 } else { 1098 // There are multiple elements with this ID. If it exists, remove the m_elementsById 1099 // cache for this ID so getElementById searches for it next time it is called. 1100 iterator cachedItem = m_elementsById.find(elementId.impl()); 1101 if (cachedItem != m_elementsById.end()) { 1102 m_elementsById.remove(cachedItem); 1103 m_duplicateIds.add(elementId.impl()); 1104 } 1105 } 1106 m_duplicateIds.add(elementId.impl()); 1107 } 1108 1109 void Document::removeElementById(const AtomicString& elementId, Element* element) 1110 { 1111 m_elementsById.checkConsistency(); 1112 1113 if (m_elementsById.get(elementId.impl()) == element) 1114 m_elementsById.remove(elementId.impl()); 1115 else 1116 m_duplicateIds.remove(elementId.impl()); 1117 } 1118 1119 Element* Document::getElementByAccessKey(const String& key) const 1120 { 1121 if (key.isEmpty()) 1122 return 0; 1123 if (!m_accessKeyMapValid) { 1124 for (Node* n = firstChild(); n; n = n->traverseNextNode()) { 1125 if (!n->isElementNode()) 1126 continue; 1127 Element* element = static_cast<Element*>(n); 1128 const AtomicString& accessKey = element->getAttribute(accesskeyAttr); 1129 if (!accessKey.isEmpty()) 1130 m_elementsByAccessKey.set(accessKey.impl(), element); 1131 } 1132 m_accessKeyMapValid = true; 1133 } 1134 return m_elementsByAccessKey.get(key.impl()); 1135 } 1136 1137 /* 1138 * Performs three operations: 1139 * 1. Convert control characters to spaces 1140 * 2. Trim leading and trailing spaces 1141 * 3. Collapse internal whitespace. 1142 */ 1143 static inline String canonicalizedTitle(Document* document, const String& title) 1144 { 1145 const UChar* characters = title.characters(); 1146 unsigned length = title.length(); 1147 unsigned i; 1148 1149 StringBuffer buffer(length); 1150 unsigned builderIndex = 0; 1151 1152 // Skip leading spaces and leading characters that would convert to spaces 1153 for (i = 0; i < length; ++i) { 1154 UChar c = characters[i]; 1155 if (!(c <= 0x20 || c == 0x7F)) 1156 break; 1157 } 1158 1159 if (i == length) 1160 return ""; 1161 1162 // Replace control characters with spaces, and backslashes with currency symbols, and collapse whitespace. 1163 bool previousCharWasWS = false; 1164 for (; i < length; ++i) { 1165 UChar c = characters[i]; 1166 if (c <= 0x20 || c == 0x7F || (WTF::Unicode::category(c) & (WTF::Unicode::Separator_Line | WTF::Unicode::Separator_Paragraph))) { 1167 if (previousCharWasWS) 1168 continue; 1169 buffer[builderIndex++] = ' '; 1170 previousCharWasWS = true; 1171 } else { 1172 buffer[builderIndex++] = c; 1173 previousCharWasWS = false; 1174 } 1175 } 1176 1177 // Strip trailing spaces 1178 while (builderIndex > 0) { 1179 --builderIndex; 1180 if (buffer[builderIndex] != ' ') 1181 break; 1182 } 1183 1184 if (!builderIndex && buffer[builderIndex] == ' ') 1185 return ""; 1186 1187 buffer.shrink(builderIndex + 1); 1188 1189 // Replace the backslashes with currency symbols if the encoding requires it. 1190 document->displayBufferModifiedByEncoding(buffer.characters(), buffer.length()); 1191 1192 return String::adopt(buffer); 1193 } 1194 1195 void Document::updateTitle() 1196 { 1197 m_title = canonicalizedTitle(this, m_rawTitle); 1198 if (Frame* f = frame()) 1199 f->loader()->setTitle(m_title); 1200 } 1201 1202 void Document::setTitle(const String& title, Element* titleElement) 1203 { 1204 if (!titleElement) { 1205 // Title set by JavaScript -- overrides any title elements. 1206 m_titleSetExplicitly = true; 1207 if (!isHTMLDocument()) 1208 m_titleElement = 0; 1209 else if (!m_titleElement) { 1210 if (HTMLElement* headElement = head()) { 1211 m_titleElement = createElement(titleTag, false); 1212 ExceptionCode ec = 0; 1213 headElement->appendChild(m_titleElement, ec); 1214 ASSERT(!ec); 1215 } 1216 } 1217 } else if (titleElement != m_titleElement) { 1218 if (m_titleElement || m_titleSetExplicitly) 1219 // Only allow the first title element to change the title -- others have no effect. 1220 return; 1221 m_titleElement = titleElement; 1222 } 1223 1224 if (m_rawTitle == title) 1225 return; 1226 1227 m_rawTitle = title; 1228 updateTitle(); 1229 1230 if (m_titleSetExplicitly && m_titleElement && m_titleElement->hasTagName(titleTag)) 1231 static_cast<HTMLTitleElement*>(m_titleElement.get())->setText(m_title); 1232 } 1233 1234 void Document::removeTitle(Element* titleElement) 1235 { 1236 if (m_titleElement != titleElement) 1237 return; 1238 1239 m_titleElement = 0; 1240 m_titleSetExplicitly = false; 1241 1242 // Update title based on first title element in the head, if one exists. 1243 if (HTMLElement* headElement = head()) { 1244 for (Node* e = headElement->firstChild(); e; e = e->nextSibling()) 1245 if (e->hasTagName(titleTag)) { 1246 HTMLTitleElement* titleElement = static_cast<HTMLTitleElement*>(e); 1247 setTitle(titleElement->text(), titleElement); 1248 break; 1249 } 1250 } 1251 1252 if (!m_titleElement && !m_rawTitle.isEmpty()) { 1253 m_rawTitle = ""; 1254 updateTitle(); 1255 } 1256 } 1257 1258 String Document::nodeName() const 1259 { 1260 return "#document"; 1261 } 1262 1263 Node::NodeType Document::nodeType() const 1264 { 1265 return DOCUMENT_NODE; 1266 } 1267 1268 FrameView* Document::view() const 1269 { 1270 return m_frame ? m_frame->view() : 0; 1271 } 1272 1273 Page* Document::page() const 1274 { 1275 return m_frame ? m_frame->page() : 0; 1276 } 1277 1278 Settings* Document::settings() const 1279 { 1280 return m_frame ? m_frame->settings() : 0; 1281 } 1282 1283 PassRefPtr<Range> Document::createRange() 1284 { 1285 return Range::create(this); 1286 } 1287 1288 PassRefPtr<NodeIterator> Document::createNodeIterator(Node* root, unsigned whatToShow, 1289 PassRefPtr<NodeFilter> filter, bool expandEntityReferences, ExceptionCode& ec) 1290 { 1291 if (!root) { 1292 ec = NOT_SUPPORTED_ERR; 1293 return 0; 1294 } 1295 return NodeIterator::create(root, whatToShow, filter, expandEntityReferences); 1296 } 1297 1298 PassRefPtr<TreeWalker> Document::createTreeWalker(Node *root, unsigned whatToShow, 1299 PassRefPtr<NodeFilter> filter, bool expandEntityReferences, ExceptionCode& ec) 1300 { 1301 if (!root) { 1302 ec = NOT_SUPPORTED_ERR; 1303 return 0; 1304 } 1305 return TreeWalker::create(root, whatToShow, filter, expandEntityReferences); 1306 } 1307 1308 void Document::scheduleStyleRecalc() 1309 { 1310 if (m_styleRecalcTimer.isActive() || inPageCache()) 1311 return; 1312 1313 ASSERT(childNeedsStyleRecalc()); 1314 1315 if (!documentsThatNeedStyleRecalc) 1316 documentsThatNeedStyleRecalc = new HashSet<Document*>; 1317 documentsThatNeedStyleRecalc->add(this); 1318 1319 // FIXME: Why on earth is this here? This is clearly misplaced. 1320 if (m_accessKeyMapValid) { 1321 m_accessKeyMapValid = false; 1322 m_elementsByAccessKey.clear(); 1323 } 1324 1325 m_styleRecalcTimer.startOneShot(0); 1326 } 1327 1328 void Document::unscheduleStyleRecalc() 1329 { 1330 ASSERT(!childNeedsStyleRecalc()); 1331 1332 if (documentsThatNeedStyleRecalc) 1333 documentsThatNeedStyleRecalc->remove(this); 1334 1335 m_styleRecalcTimer.stop(); 1336 } 1337 1338 void Document::styleRecalcTimerFired(Timer<Document>*) 1339 { 1340 updateStyleIfNeeded(); 1341 } 1342 1343 bool Document::childNeedsAndNotInStyleRecalc() 1344 { 1345 return childNeedsStyleRecalc() && !m_inStyleRecalc; 1346 } 1347 1348 void Document::recalcStyle(StyleChange change) 1349 { 1350 // we should not enter style recalc while painting 1351 if (view() && view()->isPainting()) { 1352 ASSERT(!view()->isPainting()); 1353 return; 1354 } 1355 1356 if (m_inStyleRecalc) 1357 return; // Guard against re-entrancy. -dwh 1358 1359 #if ENABLE(INSPECTOR) 1360 if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent()) 1361 timelineAgent->willRecalculateStyle(); 1362 #endif 1363 1364 m_inStyleRecalc = true; 1365 suspendPostAttachCallbacks(); 1366 RenderWidget::suspendWidgetHierarchyUpdates(); 1367 if (view()) 1368 view()->pauseScheduledEvents(); 1369 1370 #ifdef ANDROID_INSTRUMENT 1371 android::TimeCounter::start(android::TimeCounter::CalculateStyleTimeCounter); 1372 #endif 1373 1374 ASSERT(!renderer() || renderArena()); 1375 if (!renderer() || !renderArena()) 1376 goto bail_out; 1377 1378 if (change == Force) { 1379 // style selector may set this again during recalc 1380 m_hasNodesWithPlaceholderStyle = false; 1381 1382 RefPtr<RenderStyle> documentStyle = CSSStyleSelector::styleForDocument(this); 1383 StyleChange ch = diff(documentStyle.get(), renderer()->style()); 1384 if (renderer() && ch != NoChange) 1385 renderer()->setStyle(documentStyle.release()); 1386 } 1387 1388 for (Node* n = firstChild(); n; n = n->nextSibling()) 1389 if (change >= Inherit || n->childNeedsStyleRecalc() || n->needsStyleRecalc()) 1390 n->recalcStyle(change); 1391 1392 #ifdef ANDROID_INSTRUMENT 1393 android::TimeCounter::record(android::TimeCounter::CalculateStyleTimeCounter, __FUNCTION__); 1394 #endif 1395 1396 #if USE(ACCELERATED_COMPOSITING) 1397 if (view()) { 1398 bool layoutPending = view()->layoutPending() || renderer()->needsLayout(); 1399 // If we didn't update compositing layers because of layout(), we need to do so here. 1400 if (!layoutPending) 1401 view()->updateCompositingLayers(); 1402 } 1403 #endif 1404 1405 bail_out: 1406 setNeedsStyleRecalc(NoStyleChange); 1407 setChildNeedsStyleRecalc(false); 1408 unscheduleStyleRecalc(); 1409 1410 if (view()) 1411 view()->resumeScheduledEvents(); 1412 RenderWidget::resumeWidgetHierarchyUpdates(); 1413 resumePostAttachCallbacks(); 1414 m_inStyleRecalc = false; 1415 1416 // If we wanted to call implicitClose() during recalcStyle, do so now that we're finished. 1417 if (m_closeAfterStyleRecalc) { 1418 m_closeAfterStyleRecalc = false; 1419 implicitClose(); 1420 } 1421 1422 #if ENABLE(INSPECTOR) 1423 if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent()) 1424 timelineAgent->didRecalculateStyle(); 1425 #endif 1426 } 1427 1428 void Document::updateStyleIfNeeded() 1429 { 1430 if (!childNeedsStyleRecalc() || inPageCache()) 1431 return; 1432 1433 if (m_frame) 1434 m_frame->animation()->beginAnimationUpdate(); 1435 1436 recalcStyle(NoChange); 1437 1438 // Tell the animation controller that updateStyleIfNeeded is finished and it can do any post-processing 1439 if (m_frame) 1440 m_frame->animation()->endAnimationUpdate(); 1441 } 1442 1443 void Document::updateStyleForAllDocuments() 1444 { 1445 if (!documentsThatNeedStyleRecalc) 1446 return; 1447 1448 while (documentsThatNeedStyleRecalc->size()) { 1449 HashSet<Document*>::iterator it = documentsThatNeedStyleRecalc->begin(); 1450 Document* doc = *it; 1451 documentsThatNeedStyleRecalc->remove(doc); 1452 ASSERT(doc->childNeedsStyleRecalc() && !doc->inPageCache()); 1453 doc->updateStyleIfNeeded(); 1454 } 1455 } 1456 1457 void Document::updateLayout() 1458 { 1459 if (Element* oe = ownerElement()) 1460 oe->document()->updateLayout(); 1461 1462 updateStyleIfNeeded(); 1463 1464 // Only do a layout if changes have occurred that make it necessary. 1465 FrameView* v = view(); 1466 if (v && renderer() && (v->layoutPending() || renderer()->needsLayout())) 1467 v->layout(); 1468 } 1469 1470 // FIXME: This is a bad idea and needs to be removed eventually. 1471 // Other browsers load stylesheets before they continue parsing the web page. 1472 // Since we don't, we can run JavaScript code that needs answers before the 1473 // stylesheets are loaded. Doing a layout ignoring the pending stylesheets 1474 // lets us get reasonable answers. The long term solution to this problem is 1475 // to instead suspend JavaScript execution. 1476 void Document::updateLayoutIgnorePendingStylesheets() 1477 { 1478 bool oldIgnore = m_ignorePendingStylesheets; 1479 1480 if (!haveStylesheetsLoaded()) { 1481 m_ignorePendingStylesheets = true; 1482 // FIXME: We are willing to attempt to suppress painting with outdated style info only once. Our assumption is that it would be 1483 // dangerous to try to stop it a second time, after page content has already been loaded and displayed 1484 // with accurate style information. (Our suppression involves blanking the whole page at the 1485 // moment. If it were more refined, we might be able to do something better.) 1486 // It's worth noting though that this entire method is a hack, since what we really want to do is 1487 // suspend JS instead of doing a layout with inaccurate information. 1488 if (body() && !body()->renderer() && m_pendingSheetLayout == NoLayoutWithPendingSheets) { 1489 m_pendingSheetLayout = DidLayoutWithPendingSheets; 1490 updateStyleSelector(); 1491 } else if (m_hasNodesWithPlaceholderStyle) 1492 // If new nodes have been added or style recalc has been done with style sheets still pending, some nodes 1493 // may not have had their real style calculated yet. Normally this gets cleaned when style sheets arrive 1494 // but here we need up-to-date style immediately. 1495 recalcStyle(Force); 1496 } 1497 1498 updateLayout(); 1499 1500 m_ignorePendingStylesheets = oldIgnore; 1501 } 1502 1503 void Document::createStyleSelector() 1504 { 1505 bool matchAuthorAndUserStyles = true; 1506 if (Settings* docSettings = settings()) 1507 matchAuthorAndUserStyles = docSettings->authorAndUserStylesEnabled(); 1508 m_styleSelector.set(new CSSStyleSelector(this, m_styleSheets.get(), m_mappedElementSheet.get(), pageUserSheet(), pageGroupUserSheets(), 1509 !inCompatMode(), matchAuthorAndUserStyles)); 1510 } 1511 1512 void Document::attach() 1513 { 1514 ASSERT(!attached()); 1515 ASSERT(!m_inPageCache); 1516 #if !PLATFORM(ANDROID) 1517 ASSERT(!m_axObjectCache); 1518 #endif 1519 1520 if (!m_renderArena) 1521 m_renderArena = new RenderArena(); 1522 1523 // Create the rendering tree 1524 setRenderer(new (m_renderArena.get()) RenderView(this, view())); 1525 #if USE(ACCELERATED_COMPOSITING) 1526 renderView()->didMoveOnscreen(); 1527 #endif 1528 1529 recalcStyle(Force); 1530 1531 RenderObject* render = renderer(); 1532 setRenderer(0); 1533 1534 ContainerNode::attach(); 1535 1536 setRenderer(render); 1537 } 1538 1539 void Document::detach() 1540 { 1541 ASSERT(attached()); 1542 ASSERT(!m_inPageCache); 1543 1544 clearAXObjectCache(); 1545 stopActiveDOMObjects(); 1546 1547 RenderObject* render = renderer(); 1548 1549 // Send out documentWillBecomeInactive() notifications to registered elements, 1550 // in order to stop media elements 1551 documentWillBecomeInactive(); 1552 1553 #if ENABLE(SHARED_WORKERS) 1554 SharedWorkerRepository::documentDetached(this); 1555 #endif 1556 1557 if (m_frame) { 1558 FrameView* view = m_frame->view(); 1559 if (view) 1560 view->detachCustomScrollbars(); 1561 } 1562 1563 // indicate destruction mode, i.e. attached() but renderer == 0 1564 setRenderer(0); 1565 1566 m_hoverNode = 0; 1567 m_focusedNode = 0; 1568 m_activeNode = 0; 1569 1570 ContainerNode::detach(); 1571 1572 unscheduleStyleRecalc(); 1573 1574 if (render) 1575 render->destroy(); 1576 1577 // This is required, as our Frame might delete itself as soon as it detaches 1578 // us. However, this violates Node::detach() semantics, as it's never 1579 // possible to re-attach. Eventually Document::detach() should be renamed, 1580 // or this setting of the frame to 0 could be made explicit in each of the 1581 // callers of Document::detach(). 1582 m_frame = 0; 1583 m_renderArena.clear(); 1584 } 1585 1586 void Document::removeAllEventListeners() 1587 { 1588 #if ENABLE(TOUCH_EVENTS) 1589 Page* ownerPage = page(); 1590 if (!m_inPageCache && ownerPage && (m_frame == ownerPage->mainFrame()) && hasListenerType(Document::TOUCH_LISTENER)) { 1591 // Inform the Chrome Client that it no longer needs to forward touch 1592 // events to WebCore as the document removes all the event listeners. 1593 ownerPage->chrome()->client()->needTouchEvents(false); 1594 } 1595 #endif 1596 1597 EventTarget::removeAllEventListeners(); 1598 1599 if (DOMWindow* domWindow = this->domWindow()) 1600 domWindow->removeAllEventListeners(); 1601 for (Node* node = firstChild(); node; node = node->traverseNextNode()) 1602 node->removeAllEventListeners(); 1603 } 1604 1605 RenderView* Document::renderView() const 1606 { 1607 return toRenderView(renderer()); 1608 } 1609 1610 void Document::clearAXObjectCache() 1611 { 1612 #if PLATFORM(ANDROID) 1613 return; 1614 #else 1615 // clear cache in top document 1616 if (m_axObjectCache) { 1617 delete m_axObjectCache; 1618 m_axObjectCache = 0; 1619 return; 1620 } 1621 1622 // ask the top-level document to clear its cache 1623 Document* doc = topDocument(); 1624 if (doc != this) 1625 doc->clearAXObjectCache(); 1626 #endif 1627 } 1628 1629 AXObjectCache* Document::axObjectCache() const 1630 { 1631 #if PLATFORM(ANDROID) 1632 return 0; 1633 #else 1634 // The only document that actually has a AXObjectCache is the top-level 1635 // document. This is because we need to be able to get from any WebCoreAXObject 1636 // to any other WebCoreAXObject on the same page. Using a single cache allows 1637 // lookups across nested webareas (i.e. multiple documents). 1638 1639 if (m_axObjectCache) { 1640 // return already known top-level cache 1641 if (!ownerElement()) 1642 return m_axObjectCache; 1643 1644 // In some pages with frames, the cache is created before the sub-webarea is 1645 // inserted into the tree. Here, we catch that case and just toss the old 1646 // cache and start over. 1647 // NOTE: This recovery may no longer be needed. I have been unable to trigger 1648 // it again. See rdar://5794454 1649 // FIXME: Can this be fixed when inserting the subframe instead of now? 1650 // FIXME: If this function was called to get the cache in order to remove 1651 // an AXObject, we are now deleting the cache as a whole and returning a 1652 // new empty cache that does not contain the AXObject! That should actually 1653 // be OK. I am concerned about other cases like this where accessing the 1654 // cache blows away the AXObject being operated on. 1655 delete m_axObjectCache; 1656 m_axObjectCache = 0; 1657 } 1658 1659 // ask the top-level document for its cache 1660 Document* doc = topDocument(); 1661 if (doc != this) 1662 return doc->axObjectCache(); 1663 1664 // this is the top-level document, so install a new cache 1665 m_axObjectCache = new AXObjectCache; 1666 return m_axObjectCache; 1667 #endif // ANDROID 1668 } 1669 1670 void Document::setVisuallyOrdered() 1671 { 1672 m_visuallyOrdered = true; 1673 if (renderer()) 1674 renderer()->style()->setVisuallyOrdered(true); 1675 } 1676 1677 Tokenizer* Document::createTokenizer() 1678 { 1679 // FIXME: this should probably pass the frame instead 1680 return new XMLTokenizer(this, view()); 1681 } 1682 1683 void Document::open(Document* ownerDocument) 1684 { 1685 if (ownerDocument) { 1686 setURL(ownerDocument->url()); 1687 m_cookieURL = ownerDocument->cookieURL(); 1688 ScriptExecutionContext::setSecurityOrigin(ownerDocument->securityOrigin()); 1689 } 1690 1691 if (m_frame) { 1692 if (m_frame->loader()->isLoadingMainResource() || (tokenizer() && tokenizer()->executingScript())) 1693 return; 1694 1695 if (m_frame->loader()->state() == FrameStateProvisional) 1696 m_frame->loader()->stopAllLoaders(); 1697 } 1698 1699 implicitOpen(); 1700 1701 if (DOMWindow* domWindow = this->domWindow()) 1702 domWindow->removeAllEventListeners(); 1703 1704 if (m_frame) 1705 m_frame->loader()->didExplicitOpen(); 1706 } 1707 1708 void Document::cancelParsing() 1709 { 1710 if (m_tokenizer) { 1711 // We have to clear the tokenizer to avoid possibly triggering 1712 // the onload handler when closing as a side effect of a cancel-style 1713 // change, such as opening a new document or closing the window while 1714 // still parsing 1715 m_tokenizer.clear(); 1716 close(); 1717 } 1718 } 1719 1720 void Document::implicitOpen() 1721 { 1722 cancelParsing(); 1723 1724 m_tokenizer.clear(); 1725 1726 removeChildren(); 1727 1728 m_tokenizer = createTokenizer(); 1729 setParsing(true); 1730 1731 if (m_frame) 1732 m_tokenizer->setXSSAuditor(m_frame->script()->xssAuditor()); 1733 1734 // If we reload, the animation controller sticks around and has 1735 // a stale animation time. We need to update it here. 1736 if (m_frame && m_frame->animation()) 1737 m_frame->animation()->beginAnimationUpdate(); 1738 } 1739 1740 HTMLElement* Document::body() const 1741 { 1742 Node* de = documentElement(); 1743 if (!de) 1744 return 0; 1745 1746 // try to prefer a FRAMESET element over BODY 1747 Node* body = 0; 1748 for (Node* i = de->firstChild(); i; i = i->nextSibling()) { 1749 if (i->hasTagName(framesetTag)) 1750 return static_cast<HTMLElement*>(i); 1751 1752 if (i->hasTagName(bodyTag) && !body) 1753 body = i; 1754 } 1755 return static_cast<HTMLElement*>(body); 1756 } 1757 1758 void Document::setBody(PassRefPtr<HTMLElement> newBody, ExceptionCode& ec) 1759 { 1760 if (!newBody || !documentElement()) { 1761 ec = HIERARCHY_REQUEST_ERR; 1762 return; 1763 } 1764 1765 HTMLElement* b = body(); 1766 if (!b) 1767 documentElement()->appendChild(newBody, ec); 1768 else 1769 documentElement()->replaceChild(newBody, b, ec); 1770 } 1771 1772 HTMLHeadElement* Document::head() 1773 { 1774 Node* de = documentElement(); 1775 if (!de) 1776 return 0; 1777 1778 for (Node* e = de->firstChild(); e; e = e->nextSibling()) 1779 if (e->hasTagName(headTag)) 1780 return static_cast<HTMLHeadElement*>(e); 1781 1782 return 0; 1783 } 1784 1785 void Document::close() 1786 { 1787 Frame* frame = this->frame(); 1788 if (frame) { 1789 // This code calls implicitClose() if all loading has completed. 1790 FrameLoader* frameLoader = frame->loader(); 1791 frameLoader->endIfNotLoadingMainResource(); 1792 frameLoader->checkCompleted(); 1793 } else { 1794 // Because we have no frame, we don't know if all loading has completed, 1795 // so we just call implicitClose() immediately. FIXME: This might fire 1796 // the load event prematurely <http://bugs.webkit.org/show_bug.cgi?id=14568>. 1797 implicitClose(); 1798 } 1799 } 1800 1801 void Document::implicitClose() 1802 { 1803 // If we're in the middle of recalcStyle, we need to defer the close until the style information is accurate and all elements are re-attached. 1804 if (m_inStyleRecalc) { 1805 m_closeAfterStyleRecalc = true; 1806 return; 1807 } 1808 1809 bool wasLocationChangePending = frame() && frame()->redirectScheduler()->locationChangePending(); 1810 bool doload = !parsing() && m_tokenizer && !m_processingLoadEvent && !wasLocationChangePending; 1811 1812 if (!doload) 1813 return; 1814 1815 m_processingLoadEvent = true; 1816 1817 m_wellFormed = m_tokenizer && m_tokenizer->wellFormed(); 1818 1819 // We have to clear the tokenizer, in case someone document.write()s from the 1820 // onLoad event handler, as in Radar 3206524. 1821 m_tokenizer.clear(); 1822 1823 // Parser should have picked up all preloads by now 1824 m_docLoader->clearPreloads(); 1825 1826 // Create a head and a body if we don't have those yet (e.g. for about:blank). 1827 if (!this->body() && isHTMLDocument()) { 1828 if (Node* documentElement = this->documentElement()) { 1829 ExceptionCode ec = 0; 1830 1831 // The implicit <head> isn't expected in older versions of Mail - <rdar://problem/6863795> 1832 if (!head() && shouldCreateImplicitHead(this)) { 1833 documentElement->appendChild(new HTMLHeadElement(headTag, this), ec); 1834 ASSERT(!ec); 1835 } 1836 documentElement->appendChild(new HTMLBodyElement(bodyTag, this), ec); 1837 ASSERT(!ec); 1838 } 1839 } 1840 1841 // FIXME: We kick off the icon loader when the Document is done parsing. 1842 // There are earlier opportunities we could start it: 1843 // -When the <head> finishes parsing 1844 // -When any new HTMLLinkElement is inserted into the document 1845 // But those add a dynamic component to the favicon that has UI 1846 // ramifications, and we need to decide what is the Right Thing To Do(tm) 1847 Frame* f = frame(); 1848 if (f) 1849 f->loader()->startIconLoader(); 1850 1851 // Resume the animations (or start them) 1852 if (f) 1853 f->animation()->resumeAnimations(this); 1854 1855 ImageLoader::dispatchPendingBeforeLoadEvents(); 1856 ImageLoader::dispatchPendingLoadEvents(); 1857 dispatchWindowLoadEvent(); 1858 dispatchWindowEvent(PageTransitionEvent::create(eventNames().pageshowEvent, false), this); 1859 if (m_pendingStateObject) 1860 dispatchWindowEvent(PopStateEvent::create(m_pendingStateObject.release())); 1861 1862 if (f) 1863 f->loader()->handledOnloadEvents(); 1864 #ifdef INSTRUMENT_LAYOUT_SCHEDULING 1865 if (!ownerElement()) 1866 printf("onload fired at %d\n", elapsedTime()); 1867 #endif 1868 1869 m_processingLoadEvent = false; 1870 1871 // An event handler may have removed the frame 1872 if (!frame()) 1873 return; 1874 1875 // Make sure both the initial layout and reflow happen after the onload 1876 // fires. This will improve onload scores, and other browsers do it. 1877 // If they wanna cheat, we can too. -dwh 1878 1879 if (frame()->redirectScheduler()->locationChangePending() && elapsedTime() < cLayoutScheduleThreshold) { 1880 // Just bail out. Before or during the onload we were shifted to another page. 1881 // The old i-Bench suite does this. When this happens don't bother painting or laying out. 1882 view()->unscheduleRelayout(); 1883 return; 1884 } 1885 1886 frame()->loader()->checkCallImplicitClose(); 1887 RenderObject* renderObject = renderer(); 1888 1889 // We used to force a synchronous display and flush here. This really isn't 1890 // necessary and can in fact be actively harmful if pages are loading at a rate of > 60fps 1891 // (if your platform is syncing flushes and limiting them to 60fps). 1892 m_overMinimumLayoutThreshold = true; 1893 if (!ownerElement() || (ownerElement()->renderer() && !ownerElement()->renderer()->needsLayout())) { 1894 updateStyleIfNeeded(); 1895 1896 // Always do a layout after loading if needed. 1897 if (view() && renderObject && (!renderObject->firstChild() || renderObject->needsLayout())) 1898 view()->layout(); 1899 } 1900 1901 #if PLATFORM(MAC) 1902 if (f && renderObject && this == topDocument() && AXObjectCache::accessibilityEnabled()) { 1903 // The AX cache may have been cleared at this point, but we need to make sure it contains an 1904 // AX object to send the notification to. getOrCreate will make sure that an valid AX object 1905 // exists in the cache (we ignore the return value because we don't need it here). This is 1906 // only safe to call when a layout is not in progress, so it can not be used in postNotification. 1907 axObjectCache()->getOrCreate(renderObject); 1908 axObjectCache()->postNotification(renderObject, AXObjectCache::AXLoadComplete, true); 1909 } 1910 #endif 1911 1912 #if ENABLE(SVG) 1913 // FIXME: Officially, time 0 is when the outermost <svg> receives its 1914 // SVGLoad event, but we don't implement those yet. This is close enough 1915 // for now. In some cases we should have fired earlier. 1916 if (svgExtensions()) 1917 accessSVGExtensions()->startAnimations(); 1918 #endif 1919 } 1920 1921 void Document::setParsing(bool b) 1922 { 1923 m_bParsing = b; 1924 if (!m_bParsing && view()) 1925 view()->scheduleRelayout(); 1926 1927 #ifdef INSTRUMENT_LAYOUT_SCHEDULING 1928 if (!ownerElement() && !m_bParsing) 1929 printf("Parsing finished at %d\n", elapsedTime()); 1930 #endif 1931 } 1932 1933 bool Document::shouldScheduleLayout() 1934 { 1935 // This function will only be called when FrameView thinks a layout is needed. 1936 // This enforces a couple extra rules. 1937 // 1938 // (a) Only schedule a layout once the stylesheets are loaded. 1939 // (b) Only schedule layout once we have a body element. 1940 1941 return (haveStylesheetsLoaded() && body()) || 1942 (documentElement() && !documentElement()->hasTagName(htmlTag)); 1943 } 1944 1945 int Document::minimumLayoutDelay() 1946 { 1947 if (m_overMinimumLayoutThreshold) 1948 return m_extraLayoutDelay; 1949 1950 int elapsed = elapsedTime(); 1951 m_overMinimumLayoutThreshold = elapsed > cLayoutScheduleThreshold; 1952 1953 // We'll want to schedule the timer to fire at the minimum layout threshold. 1954 return max(0, cLayoutScheduleThreshold - elapsed) + m_extraLayoutDelay; 1955 } 1956 1957 int Document::elapsedTime() const 1958 { 1959 return static_cast<int>((currentTime() - m_startTime) * 1000); 1960 } 1961 1962 void Document::write(const SegmentedString& text, Document* ownerDocument) 1963 { 1964 #ifdef INSTRUMENT_LAYOUT_SCHEDULING 1965 if (!ownerElement()) 1966 printf("Beginning a document.write at %d\n", elapsedTime()); 1967 #endif 1968 1969 if (!m_tokenizer) 1970 open(ownerDocument); 1971 1972 ASSERT(m_tokenizer); 1973 m_tokenizer->write(text, false); 1974 1975 #ifdef INSTRUMENT_LAYOUT_SCHEDULING 1976 if (!ownerElement()) 1977 printf("Ending a document.write at %d\n", elapsedTime()); 1978 #endif 1979 } 1980 1981 void Document::write(const String& text, Document* ownerDocument) 1982 { 1983 write(SegmentedString(text), ownerDocument); 1984 } 1985 1986 void Document::writeln(const String& text, Document* ownerDocument) 1987 { 1988 write(text, ownerDocument); 1989 write("\n", ownerDocument); 1990 } 1991 1992 void Document::finishParsing() 1993 { 1994 #ifdef INSTRUMENT_LAYOUT_SCHEDULING 1995 if (!ownerElement()) 1996 printf("Received all data at %d\n", elapsedTime()); 1997 #endif 1998 1999 // Let the tokenizer go through as much data as it can. There will be three possible outcomes after 2000 // finish() is called: 2001 // (1) All remaining data is parsed, document isn't loaded yet 2002 // (2) All remaining data is parsed, document is loaded, tokenizer gets deleted 2003 // (3) Data is still remaining to be parsed. 2004 if (m_tokenizer) 2005 m_tokenizer->finish(); 2006 } 2007 2008 const KURL& Document::virtualURL() const 2009 { 2010 return m_url; 2011 } 2012 2013 KURL Document::virtualCompleteURL(const String& url) const 2014 { 2015 return completeURL(url); 2016 } 2017 2018 void Document::setURL(const KURL& url) 2019 { 2020 const KURL& newURL = url.isEmpty() ? blankURL() : url; 2021 if (newURL == m_url) 2022 return; 2023 2024 m_url = newURL; 2025 m_documentURI = m_url.string(); 2026 updateBaseURL(); 2027 } 2028 2029 void Document::setBaseElementURL(const KURL& baseElementURL) 2030 { 2031 m_baseElementURL = baseElementURL; 2032 updateBaseURL(); 2033 } 2034 2035 void Document::updateBaseURL() 2036 { 2037 // DOM 3 Core: When the Document supports the feature "HTML" [DOM Level 2 HTML], the base URI is computed using 2038 // first the value of the href attribute of the HTML BASE element if any, and the value of the documentURI attribute 2039 // from the Document interface otherwise. 2040 if (m_baseElementURL.isEmpty()) { 2041 // The documentURI attribute is an arbitrary string. DOM 3 Core does not specify how it should be resolved, 2042 // so we use a null base URL. 2043 m_baseURL = KURL(KURL(), documentURI()); 2044 } else 2045 m_baseURL = m_baseElementURL; 2046 if (!m_baseURL.isValid()) 2047 m_baseURL = KURL(); 2048 2049 if (m_elemSheet) 2050 m_elemSheet->setFinalURL(m_baseURL); 2051 if (m_mappedElementSheet) 2052 m_mappedElementSheet->setFinalURL(m_baseURL); 2053 } 2054 2055 String Document::userAgent(const KURL& url) const 2056 { 2057 return frame() ? frame()->loader()->userAgent(url) : String(); 2058 } 2059 2060 CSSStyleSheet* Document::pageUserSheet() 2061 { 2062 if (m_pageUserSheet) 2063 return m_pageUserSheet.get(); 2064 2065 Page* owningPage = page(); 2066 if (!owningPage) 2067 return 0; 2068 2069 String userSheetText = owningPage->userStyleSheet(); 2070 if (userSheetText.isEmpty()) 2071 return 0; 2072 2073 // Parse the sheet and cache it. 2074 m_pageUserSheet = CSSStyleSheet::createInline(this, settings()->userStyleSheetLocation()); 2075 m_pageUserSheet->setIsUserStyleSheet(true); 2076 m_pageUserSheet->parseString(userSheetText, !inCompatMode()); 2077 return m_pageUserSheet.get(); 2078 } 2079 2080 void Document::clearPageUserSheet() 2081 { 2082 m_pageUserSheet = 0; 2083 updateStyleSelector(); 2084 } 2085 2086 const Vector<RefPtr<CSSStyleSheet> >* Document::pageGroupUserSheets() const 2087 { 2088 if (m_pageGroupUserSheetCacheValid) 2089 return m_pageGroupUserSheets.get(); 2090 2091 m_pageGroupUserSheetCacheValid = true; 2092 2093 Page* owningPage = page(); 2094 if (!owningPage) 2095 return 0; 2096 2097 const PageGroup& pageGroup = owningPage->group(); 2098 const UserStyleSheetMap* sheetsMap = pageGroup.userStyleSheets(); 2099 if (!sheetsMap) 2100 return 0; 2101 2102 UserStyleSheetMap::const_iterator end = sheetsMap->end(); 2103 for (UserStyleSheetMap::const_iterator it = sheetsMap->begin(); it != end; ++it) { 2104 const UserStyleSheetVector* sheets = it->second; 2105 for (unsigned i = 0; i < sheets->size(); ++i) { 2106 const UserStyleSheet* sheet = sheets->at(i).get(); 2107 if (!UserContentURLPattern::matchesPatterns(url(), sheet->whitelist(), sheet->blacklist())) 2108 continue; 2109 RefPtr<CSSStyleSheet> parsedSheet = CSSStyleSheet::createInline(const_cast<Document*>(this), sheet->url()); 2110 parsedSheet->setIsUserStyleSheet(true); 2111 parsedSheet->parseString(sheet->source(), !inCompatMode()); 2112 if (!m_pageGroupUserSheets) 2113 m_pageGroupUserSheets.set(new Vector<RefPtr<CSSStyleSheet> >); 2114 m_pageGroupUserSheets->append(parsedSheet.release()); 2115 } 2116 } 2117 2118 return m_pageGroupUserSheets.get(); 2119 } 2120 2121 void Document::clearPageGroupUserSheets() 2122 { 2123 m_pageGroupUserSheets.clear(); 2124 m_pageGroupUserSheetCacheValid = false; 2125 updateStyleSelector(); 2126 } 2127 2128 CSSStyleSheet* Document::elementSheet() 2129 { 2130 if (!m_elemSheet) 2131 m_elemSheet = CSSStyleSheet::createInline(this, m_baseURL); 2132 return m_elemSheet.get(); 2133 } 2134 2135 CSSStyleSheet* Document::mappedElementSheet() 2136 { 2137 if (!m_mappedElementSheet) 2138 m_mappedElementSheet = CSSStyleSheet::createInline(this, m_baseURL); 2139 return m_mappedElementSheet.get(); 2140 } 2141 2142 static Node* nextNodeWithExactTabIndex(Node* start, int tabIndex, KeyboardEvent* event) 2143 { 2144 // Search is inclusive of start 2145 for (Node* n = start; n; n = n->traverseNextNode()) 2146 if (n->isKeyboardFocusable(event) && n->tabIndex() == tabIndex) 2147 return n; 2148 2149 return 0; 2150 } 2151 2152 static Node* previousNodeWithExactTabIndex(Node* start, int tabIndex, KeyboardEvent* event) 2153 { 2154 // Search is inclusive of start 2155 for (Node* n = start; n; n = n->traversePreviousNode()) 2156 if (n->isKeyboardFocusable(event) && n->tabIndex() == tabIndex) 2157 return n; 2158 2159 return 0; 2160 } 2161 2162 static Node* nextNodeWithGreaterTabIndex(Node* start, int tabIndex, KeyboardEvent* event) 2163 { 2164 // Search is inclusive of start 2165 int winningTabIndex = SHRT_MAX + 1; 2166 Node* winner = 0; 2167 for (Node* n = start; n; n = n->traverseNextNode()) 2168 if (n->isKeyboardFocusable(event) && n->tabIndex() > tabIndex && n->tabIndex() < winningTabIndex) { 2169 winner = n; 2170 winningTabIndex = n->tabIndex(); 2171 } 2172 2173 return winner; 2174 } 2175 2176 static Node* previousNodeWithLowerTabIndex(Node* start, int tabIndex, KeyboardEvent* event) 2177 { 2178 // Search is inclusive of start 2179 int winningTabIndex = 0; 2180 Node* winner = 0; 2181 for (Node* n = start; n; n = n->traversePreviousNode()) 2182 if (n->isKeyboardFocusable(event) && n->tabIndex() < tabIndex && n->tabIndex() > winningTabIndex) { 2183 winner = n; 2184 winningTabIndex = n->tabIndex(); 2185 } 2186 2187 return winner; 2188 } 2189 2190 Node* Document::nextFocusableNode(Node* start, KeyboardEvent* event) 2191 { 2192 if (start) { 2193 // If a node is excluded from the normal tabbing cycle, the next focusable node is determined by tree order 2194 if (start->tabIndex() < 0) { 2195 for (Node* n = start->traverseNextNode(); n; n = n->traverseNextNode()) 2196 if (n->isKeyboardFocusable(event) && n->tabIndex() >= 0) 2197 return n; 2198 } 2199 2200 // First try to find a node with the same tabindex as start that comes after start in the document. 2201 if (Node* winner = nextNodeWithExactTabIndex(start->traverseNextNode(), start->tabIndex(), event)) 2202 return winner; 2203 2204 if (start->tabIndex() == 0) 2205 // We've reached the last node in the document with a tabindex of 0. This is the end of the tabbing order. 2206 return 0; 2207 } 2208 2209 // Look for the first node in the document that: 2210 // 1) has the lowest tabindex that is higher than start's tabindex (or 0, if start is null), and 2211 // 2) comes first in the document, if there's a tie. 2212 if (Node* winner = nextNodeWithGreaterTabIndex(this, start ? start->tabIndex() : 0, event)) 2213 return winner; 2214 2215 // There are no nodes with a tabindex greater than start's tabindex, 2216 // so find the first node with a tabindex of 0. 2217 return nextNodeWithExactTabIndex(this, 0, event); 2218 } 2219 2220 Node* Document::previousFocusableNode(Node* start, KeyboardEvent* event) 2221 { 2222 Node* last; 2223 for (last = this; last->lastChild(); last = last->lastChild()) 2224 ; // Empty loop. 2225 2226 // First try to find the last node in the document that comes before start and has the same tabindex as start. 2227 // If start is null, find the last node in the document with a tabindex of 0. 2228 Node* startingNode; 2229 int startingTabIndex; 2230 if (start) { 2231 startingNode = start->traversePreviousNode(); 2232 startingTabIndex = start->tabIndex(); 2233 } else { 2234 startingNode = last; 2235 startingTabIndex = 0; 2236 } 2237 2238 // However, if a node is excluded from the normal tabbing cycle, the previous focusable node is determined by tree order 2239 if (startingTabIndex < 0) { 2240 for (Node* n = startingNode; n; n = n->traversePreviousNode()) 2241 if (n->isKeyboardFocusable(event) && n->tabIndex() >= 0) 2242 return n; 2243 } 2244 2245 if (Node* winner = previousNodeWithExactTabIndex(startingNode, startingTabIndex, event)) 2246 return winner; 2247 2248 // There are no nodes before start with the same tabindex as start, so look for a node that: 2249 // 1) has the highest non-zero tabindex (that is less than start's tabindex), and 2250 // 2) comes last in the document, if there's a tie. 2251 startingTabIndex = (start && start->tabIndex()) ? start->tabIndex() : SHRT_MAX; 2252 return previousNodeWithLowerTabIndex(last, startingTabIndex, event); 2253 } 2254 2255 int Document::nodeAbsIndex(Node *node) 2256 { 2257 ASSERT(node->document() == this); 2258 2259 int absIndex = 0; 2260 for (Node *n = node; n && n != this; n = n->traversePreviousNode()) 2261 absIndex++; 2262 return absIndex; 2263 } 2264 2265 Node *Document::nodeWithAbsIndex(int absIndex) 2266 { 2267 Node *n = this; 2268 for (int i = 0; n && (i < absIndex); i++) { 2269 n = n->traverseNextNode(); 2270 } 2271 return n; 2272 } 2273 2274 #ifdef ANDROID_META_SUPPORT 2275 // Though isspace() considers \t and \v to be whitespace, Win IE doesn't. 2276 static bool isSeparator(::UChar c) 2277 { 2278 return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '=' || c == ',' || c == ';' || c == '\0'; 2279 } 2280 2281 void Document::processMetadataSettings(const String& content) 2282 { 2283 ASSERT(!content.isNull()); 2284 2285 int keyBegin, keyEnd, valueBegin, valueEnd; 2286 int i = 0; 2287 int length = content.length(); 2288 String buffer = content.lower(); 2289 while (i < length) { 2290 // skip to first non-separator, but don't skip past the end of the string 2291 while (isSeparator(buffer[i])) { 2292 if (i >= length) 2293 break; 2294 i++; 2295 } 2296 keyBegin = i; 2297 2298 // skip to first separator 2299 while (!isSeparator(buffer[i])) 2300 i++; 2301 keyEnd = i; 2302 2303 // skip to first '=', but don't skip past a ',', ';' or the end of the string 2304 while (buffer[i] != '=') { 2305 if (buffer[i] == ',' || buffer[i] == ';' || i >= length) 2306 break; 2307 i++; 2308 } 2309 2310 // skip to first non-separator, but don't skip past a ',', ';' or the end of the string 2311 while (isSeparator(buffer[i])) { 2312 if (buffer[i] == ',' || buffer[i] == ';' || i >= length) 2313 break; 2314 i++; 2315 } 2316 valueBegin = i; 2317 2318 // skip to first separator 2319 while (!isSeparator(buffer[i])) 2320 i++; 2321 valueEnd = i; 2322 2323 ASSERT(i <= length); 2324 2325 String key(buffer.substring(keyBegin, keyEnd - keyBegin)); 2326 String value(buffer.substring(valueBegin, valueEnd - valueBegin)); 2327 if (frame()) 2328 frame()->settings()->setMetadataSettings(key, value); 2329 } 2330 } 2331 #endif 2332 2333 void Document::processHttpEquiv(const String& equiv, const String& content) 2334 { 2335 ASSERT(!equiv.isNull() && !content.isNull()); 2336 2337 Frame* frame = this->frame(); 2338 2339 if (equalIgnoringCase(equiv, "default-style")) { 2340 // The preferred style set has been overridden as per section 2341 // 14.3.2 of the HTML4.0 specification. We need to update the 2342 // sheet used variable and then update our style selector. 2343 // For more info, see the test at: 2344 // http://www.hixie.ch/tests/evil/css/import/main/preferred.html 2345 // -dwh 2346 m_selectedStylesheetSet = content; 2347 m_preferredStylesheetSet = content; 2348 updateStyleSelector(); 2349 } else if (equalIgnoringCase(equiv, "refresh")) { 2350 double delay; 2351 String url; 2352 if (frame && parseHTTPRefresh(content, true, delay, url)) { 2353 if (url.isEmpty()) 2354 url = frame->loader()->url().string(); 2355 else 2356 url = completeURL(url).string(); 2357 frame->redirectScheduler()->scheduleRedirect(delay, url); 2358 } 2359 } else if (equalIgnoringCase(equiv, "set-cookie")) { 2360 // FIXME: make setCookie work on XML documents too; e.g. in case of <html:meta .....> 2361 if (isHTMLDocument()) { 2362 ExceptionCode ec; // Exception (for sandboxed documents) ignored. 2363 static_cast<HTMLDocument*>(this)->setCookie(content, ec); 2364 } 2365 } else if (equalIgnoringCase(equiv, "content-language")) 2366 setContentLanguage(content); 2367 else if (equalIgnoringCase(equiv, "x-dns-prefetch-control")) 2368 parseDNSPrefetchControlHeader(content); 2369 else if (equalIgnoringCase(equiv, "x-frame-options")) { 2370 FrameLoader* frameLoader = frame->loader(); 2371 if (frameLoader->shouldInterruptLoadForXFrameOptions(content, url())) { 2372 frameLoader->stopAllLoaders(); 2373 frame->redirectScheduler()->scheduleLocationChange(blankURL(), String()); 2374 } 2375 } 2376 } 2377 2378 MouseEventWithHitTestResults Document::prepareMouseEvent(const HitTestRequest& request, const IntPoint& documentPoint, const PlatformMouseEvent& event) 2379 { 2380 ASSERT(!renderer() || renderer()->isRenderView()); 2381 2382 if (!renderer()) 2383 return MouseEventWithHitTestResults(event, HitTestResult(IntPoint())); 2384 2385 HitTestResult result(documentPoint); 2386 renderView()->layer()->hitTest(request, result); 2387 2388 if (!request.readOnly()) 2389 updateStyleIfNeeded(); 2390 2391 return MouseEventWithHitTestResults(event, result); 2392 } 2393 2394 // DOM Section 1.1.1 2395 bool Document::childTypeAllowed(NodeType type) 2396 { 2397 switch (type) { 2398 case ATTRIBUTE_NODE: 2399 case CDATA_SECTION_NODE: 2400 case DOCUMENT_FRAGMENT_NODE: 2401 case DOCUMENT_NODE: 2402 case ENTITY_NODE: 2403 case ENTITY_REFERENCE_NODE: 2404 case NOTATION_NODE: 2405 case TEXT_NODE: 2406 case XPATH_NAMESPACE_NODE: 2407 return false; 2408 case COMMENT_NODE: 2409 case PROCESSING_INSTRUCTION_NODE: 2410 return true; 2411 case DOCUMENT_TYPE_NODE: 2412 case ELEMENT_NODE: 2413 // Documents may contain no more than one of each of these. 2414 // (One Element and one DocumentType.) 2415 for (Node* c = firstChild(); c; c = c->nextSibling()) 2416 if (c->nodeType() == type) 2417 return false; 2418 return true; 2419 } 2420 return false; 2421 } 2422 2423 bool Document::canReplaceChild(Node* newChild, Node* oldChild) 2424 { 2425 if (!oldChild) 2426 // ContainerNode::replaceChild will raise a NOT_FOUND_ERR. 2427 return true; 2428 2429 if (oldChild->nodeType() == newChild->nodeType()) 2430 return true; 2431 2432 int numDoctypes = 0; 2433 int numElements = 0; 2434 2435 // First, check how many doctypes and elements we have, not counting 2436 // the child we're about to remove. 2437 for (Node* c = firstChild(); c; c = c->nextSibling()) { 2438 if (c == oldChild) 2439 continue; 2440 2441 switch (c->nodeType()) { 2442 case DOCUMENT_TYPE_NODE: 2443 numDoctypes++; 2444 break; 2445 case ELEMENT_NODE: 2446 numElements++; 2447 break; 2448 default: 2449 break; 2450 } 2451 } 2452 2453 // Then, see how many doctypes and elements might be added by the new child. 2454 if (newChild->nodeType() == DOCUMENT_FRAGMENT_NODE) { 2455 for (Node* c = firstChild(); c; c = c->nextSibling()) { 2456 switch (c->nodeType()) { 2457 case ATTRIBUTE_NODE: 2458 case CDATA_SECTION_NODE: 2459 case DOCUMENT_FRAGMENT_NODE: 2460 case DOCUMENT_NODE: 2461 case ENTITY_NODE: 2462 case ENTITY_REFERENCE_NODE: 2463 case NOTATION_NODE: 2464 case TEXT_NODE: 2465 case XPATH_NAMESPACE_NODE: 2466 return false; 2467 case COMMENT_NODE: 2468 case PROCESSING_INSTRUCTION_NODE: 2469 break; 2470 case DOCUMENT_TYPE_NODE: 2471 numDoctypes++; 2472 break; 2473 case ELEMENT_NODE: 2474 numElements++; 2475 break; 2476 } 2477 } 2478 } else { 2479 switch (newChild->nodeType()) { 2480 case ATTRIBUTE_NODE: 2481 case CDATA_SECTION_NODE: 2482 case DOCUMENT_FRAGMENT_NODE: 2483 case DOCUMENT_NODE: 2484 case ENTITY_NODE: 2485 case ENTITY_REFERENCE_NODE: 2486 case NOTATION_NODE: 2487 case TEXT_NODE: 2488 case XPATH_NAMESPACE_NODE: 2489 return false; 2490 case COMMENT_NODE: 2491 case PROCESSING_INSTRUCTION_NODE: 2492 return true; 2493 case DOCUMENT_TYPE_NODE: 2494 numDoctypes++; 2495 break; 2496 case ELEMENT_NODE: 2497 numElements++; 2498 break; 2499 } 2500 } 2501 2502 if (numElements > 1 || numDoctypes > 1) 2503 return false; 2504 2505 return true; 2506 } 2507 2508 PassRefPtr<Node> Document::cloneNode(bool /*deep*/) 2509 { 2510 // Spec says cloning Document nodes is "implementation dependent" 2511 // so we do not support it... 2512 return 0; 2513 } 2514 2515 StyleSheetList* Document::styleSheets() 2516 { 2517 return m_styleSheets.get(); 2518 } 2519 2520 String Document::preferredStylesheetSet() const 2521 { 2522 return m_preferredStylesheetSet; 2523 } 2524 2525 String Document::selectedStylesheetSet() const 2526 { 2527 return m_selectedStylesheetSet; 2528 } 2529 2530 void Document::setSelectedStylesheetSet(const String& aString) 2531 { 2532 m_selectedStylesheetSet = aString; 2533 updateStyleSelector(); 2534 if (renderer()) 2535 renderer()->repaint(); 2536 } 2537 2538 // This method is called whenever a top-level stylesheet has finished loading. 2539 void Document::removePendingSheet() 2540 { 2541 // Make sure we knew this sheet was pending, and that our count isn't out of sync. 2542 ASSERT(m_pendingStylesheets > 0); 2543 2544 m_pendingStylesheets--; 2545 2546 #ifdef INSTRUMENT_LAYOUT_SCHEDULING 2547 if (!ownerElement()) 2548 printf("Stylesheet loaded at time %d. %d stylesheets still remain.\n", elapsedTime(), m_pendingStylesheets); 2549 #endif 2550 2551 updateStyleSelector(); 2552 2553 if (!m_pendingStylesheets && m_tokenizer) 2554 m_tokenizer->executeScriptsWaitingForStylesheets(); 2555 2556 if (!m_pendingStylesheets && m_gotoAnchorNeededAfterStylesheetsLoad && view()) 2557 view()->scrollToFragment(m_frame->loader()->url()); 2558 } 2559 2560 void Document::updateStyleSelector() 2561 { 2562 // Don't bother updating, since we haven't loaded all our style info yet 2563 // and haven't calculated the style selector for the first time. 2564 if (!m_didCalculateStyleSelector && !haveStylesheetsLoaded()) 2565 return; 2566 2567 if (didLayoutWithPendingStylesheets() && m_pendingStylesheets <= 0) { 2568 m_pendingSheetLayout = IgnoreLayoutWithPendingSheets; 2569 if (renderer()) 2570 renderer()->repaint(); 2571 } 2572 2573 #ifdef INSTRUMENT_LAYOUT_SCHEDULING 2574 if (!ownerElement()) 2575 printf("Beginning update of style selector at time %d.\n", elapsedTime()); 2576 #endif 2577 2578 recalcStyleSelector(); 2579 recalcStyle(Force); 2580 2581 #ifdef INSTRUMENT_LAYOUT_SCHEDULING 2582 if (!ownerElement()) 2583 printf("Finished update of style selector at time %d\n", elapsedTime()); 2584 #endif 2585 2586 if (renderer()) { 2587 renderer()->setNeedsLayoutAndPrefWidthsRecalc(); 2588 if (view()) 2589 view()->scheduleRelayout(); 2590 } 2591 } 2592 2593 void Document::addStyleSheetCandidateNode(Node* node, bool createdByParser) 2594 { 2595 // Until the <body> exists, we have no choice but to compare document positions, 2596 // since styles outside of the body and head continue to be shunted into the head 2597 // (and thus can shift to end up before dynamically added DOM content that is also 2598 // outside the body). 2599 if ((createdByParser && body()) || m_styleSheetCandidateNodes.isEmpty()) { 2600 m_styleSheetCandidateNodes.add(node); 2601 return; 2602 } 2603 2604 // Determine an appropriate insertion point. 2605 ListHashSet<Node*>::iterator begin = m_styleSheetCandidateNodes.begin(); 2606 ListHashSet<Node*>::iterator end = m_styleSheetCandidateNodes.end(); 2607 ListHashSet<Node*>::iterator it = end; 2608 Node* followingNode = 0; 2609 do { 2610 --it; 2611 Node* n = *it; 2612 unsigned short position = n->compareDocumentPosition(node); 2613 if (position == DOCUMENT_POSITION_FOLLOWING) { 2614 m_styleSheetCandidateNodes.insertBefore(followingNode, node); 2615 return; 2616 } 2617 followingNode = n; 2618 } while (it != begin); 2619 2620 m_styleSheetCandidateNodes.insertBefore(followingNode, node); 2621 } 2622 2623 void Document::removeStyleSheetCandidateNode(Node* node) 2624 { 2625 m_styleSheetCandidateNodes.remove(node); 2626 } 2627 2628 void Document::recalcStyleSelector() 2629 { 2630 if (!renderer() || !attached()) 2631 return; 2632 2633 StyleSheetVector sheets; 2634 2635 bool matchAuthorAndUserStyles = true; 2636 if (Settings* settings = this->settings()) 2637 matchAuthorAndUserStyles = settings->authorAndUserStylesEnabled(); 2638 2639 ListHashSet<Node*>::iterator begin = m_styleSheetCandidateNodes.begin(); 2640 ListHashSet<Node*>::iterator end = m_styleSheetCandidateNodes.end(); 2641 if (!matchAuthorAndUserStyles) 2642 end = begin; 2643 for (ListHashSet<Node*>::iterator it = begin; it != end; ++it) { 2644 Node* n = *it; 2645 2646 StyleSheet* sheet = 0; 2647 2648 if (n->nodeType() == PROCESSING_INSTRUCTION_NODE) { 2649 // Processing instruction (XML documents only) 2650 ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(n); 2651 sheet = pi->sheet(); 2652 #if ENABLE(XSLT) 2653 // Don't apply XSL transforms to already transformed documents -- <rdar://problem/4132806> 2654 if (pi->isXSL() && !transformSourceDocument()) { 2655 // Don't apply XSL transforms until loading is finished. 2656 if (!parsing()) 2657 applyXSLTransform(pi); 2658 return; 2659 } 2660 #endif 2661 if (!sheet && !pi->localHref().isEmpty()) { 2662 // Processing instruction with reference to an element in this document - e.g. 2663 // <?xml-stylesheet href="#mystyle">, with the element 2664 // <foo id="mystyle">heading { color: red; }</foo> at some location in 2665 // the document 2666 Element* elem = getElementById(pi->localHref().impl()); 2667 if (elem) { 2668 String sheetText(""); 2669 for (Node* c = elem->firstChild(); c; c = c->nextSibling()) { 2670 if (c->nodeType() == TEXT_NODE || c->nodeType() == CDATA_SECTION_NODE) 2671 sheetText += c->nodeValue(); 2672 } 2673 2674 RefPtr<CSSStyleSheet> cssSheet = CSSStyleSheet::create(this); 2675 cssSheet->parseString(sheetText); 2676 pi->setCSSStyleSheet(cssSheet); 2677 sheet = cssSheet.get(); 2678 } 2679 } 2680 } else if ((n->isHTMLElement() && (n->hasTagName(linkTag) || n->hasTagName(styleTag))) 2681 #if ENABLE(SVG) 2682 || (n->isSVGElement() && n->hasTagName(SVGNames::styleTag)) 2683 #endif 2684 ) { 2685 Element* e = static_cast<Element*>(n); 2686 AtomicString title = e->getAttribute(titleAttr); 2687 bool enabledViaScript = false; 2688 if (e->hasLocalName(linkTag)) { 2689 // <LINK> element 2690 HTMLLinkElement* l = static_cast<HTMLLinkElement*>(n); 2691 if (l->isDisabled()) 2692 continue; 2693 enabledViaScript = l->isEnabledViaScript(); 2694 if (l->isLoading()) { 2695 // it is loading but we should still decide which style sheet set to use 2696 if (!enabledViaScript && !title.isEmpty() && m_preferredStylesheetSet.isEmpty()) { 2697 const AtomicString& rel = e->getAttribute(relAttr); 2698 if (!rel.contains("alternate")) { 2699 m_preferredStylesheetSet = title; 2700 m_selectedStylesheetSet = title; 2701 } 2702 } 2703 continue; 2704 } 2705 if (!l->sheet()) 2706 title = nullAtom; 2707 } 2708 2709 // Get the current preferred styleset. This is the 2710 // set of sheets that will be enabled. 2711 #if ENABLE(SVG) 2712 if (n->isSVGElement() && n->hasTagName(SVGNames::styleTag)) 2713 sheet = static_cast<SVGStyleElement*>(n)->sheet(); 2714 else 2715 #endif 2716 if (e->hasLocalName(linkTag)) 2717 sheet = static_cast<HTMLLinkElement*>(n)->sheet(); 2718 else 2719 // <STYLE> element 2720 sheet = static_cast<HTMLStyleElement*>(n)->sheet(); 2721 2722 // Check to see if this sheet belongs to a styleset 2723 // (thus making it PREFERRED or ALTERNATE rather than 2724 // PERSISTENT). 2725 if (!enabledViaScript && !title.isEmpty()) { 2726 // Yes, we have a title. 2727 if (m_preferredStylesheetSet.isEmpty()) { 2728 // No preferred set has been established. If 2729 // we are NOT an alternate sheet, then establish 2730 // us as the preferred set. Otherwise, just ignore 2731 // this sheet. 2732 AtomicString rel = e->getAttribute(relAttr); 2733 if (e->hasLocalName(styleTag) || !rel.contains("alternate")) 2734 m_preferredStylesheetSet = m_selectedStylesheetSet = title; 2735 } 2736 2737 if (title != m_preferredStylesheetSet) 2738 sheet = 0; 2739 } 2740 } 2741 2742 if (sheet) 2743 sheets.append(sheet); 2744 } 2745 2746 m_styleSheets->swap(sheets); 2747 2748 m_styleSelector.clear(); 2749 m_didCalculateStyleSelector = true; 2750 } 2751 2752 void Document::setHoverNode(PassRefPtr<Node> newHoverNode) 2753 { 2754 m_hoverNode = newHoverNode; 2755 } 2756 2757 void Document::setActiveNode(PassRefPtr<Node> newActiveNode) 2758 { 2759 m_activeNode = newActiveNode; 2760 } 2761 2762 void Document::focusedNodeRemoved() 2763 { 2764 setFocusedNode(0); 2765 } 2766 2767 void Document::removeFocusedNodeOfSubtree(Node* node, bool amongChildrenOnly) 2768 { 2769 if (!m_focusedNode || this->inPageCache()) // If the document is in the page cache, then we don't need to clear out the focused node. 2770 return; 2771 2772 bool nodeInSubtree = false; 2773 if (amongChildrenOnly) 2774 nodeInSubtree = m_focusedNode->isDescendantOf(node); 2775 else 2776 nodeInSubtree = (m_focusedNode == node) || m_focusedNode->isDescendantOf(node); 2777 2778 if (nodeInSubtree) 2779 document()->focusedNodeRemoved(); 2780 } 2781 2782 void Document::hoveredNodeDetached(Node* node) 2783 { 2784 if (!m_hoverNode || (node != m_hoverNode && (!m_hoverNode->isTextNode() || node != m_hoverNode->parent()))) 2785 return; 2786 2787 m_hoverNode = node->parent(); 2788 while (m_hoverNode && !m_hoverNode->renderer()) 2789 m_hoverNode = m_hoverNode->parent(); 2790 if (frame()) 2791 frame()->eventHandler()->scheduleHoverStateUpdate(); 2792 } 2793 2794 void Document::activeChainNodeDetached(Node* node) 2795 { 2796 if (!m_activeNode || (node != m_activeNode && (!m_activeNode->isTextNode() || node != m_activeNode->parent()))) 2797 return; 2798 2799 m_activeNode = node->parent(); 2800 while (m_activeNode && !m_activeNode->renderer()) 2801 m_activeNode = m_activeNode->parent(); 2802 } 2803 2804 #if ENABLE(DASHBOARD_SUPPORT) 2805 const Vector<DashboardRegionValue>& Document::dashboardRegions() const 2806 { 2807 return m_dashboardRegions; 2808 } 2809 2810 void Document::setDashboardRegions(const Vector<DashboardRegionValue>& regions) 2811 { 2812 m_dashboardRegions = regions; 2813 setDashboardRegionsDirty(false); 2814 } 2815 #endif 2816 2817 bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode) 2818 { 2819 // Make sure newFocusedNode is actually in this document 2820 if (newFocusedNode && (newFocusedNode->document() != this)) 2821 return true; 2822 2823 if (m_focusedNode == newFocusedNode) 2824 return true; 2825 2826 if (m_inPageCache) 2827 return false; 2828 2829 bool focusChangeBlocked = false; 2830 RefPtr<Node> oldFocusedNode = m_focusedNode; 2831 m_focusedNode = 0; 2832 2833 // Remove focus from the existing focus node (if any) 2834 if (oldFocusedNode && !oldFocusedNode->m_inDetach) { 2835 if (oldFocusedNode->active()) 2836 oldFocusedNode->setActive(false); 2837 2838 oldFocusedNode->setFocus(false); 2839 2840 // Dispatch a change event for text fields or textareas that have been edited 2841 RenderObject* r = oldFocusedNode->renderer(); 2842 if (r && r->isTextControl() && toRenderTextControl(r)->wasChangedSinceLastChangeEvent()) { 2843 static_cast<Element*>(oldFocusedNode.get())->dispatchFormControlChangeEvent(); 2844 r = oldFocusedNode->renderer(); 2845 if (r && r->isTextControl()) 2846 toRenderTextControl(r)->setChangedSinceLastChangeEvent(false); 2847 } 2848 2849 // Dispatch the blur event and let the node do any other blur related activities (important for text fields) 2850 oldFocusedNode->dispatchBlurEvent(); 2851 2852 if (m_focusedNode) { 2853 // handler shifted focus 2854 focusChangeBlocked = true; 2855 newFocusedNode = 0; 2856 } 2857 oldFocusedNode->dispatchUIEvent(eventNames().DOMFocusOutEvent, 0, 0); 2858 if (m_focusedNode) { 2859 // handler shifted focus 2860 focusChangeBlocked = true; 2861 newFocusedNode = 0; 2862 } 2863 if (oldFocusedNode == this && oldFocusedNode->hasOneRef()) 2864 return true; 2865 2866 if (oldFocusedNode == oldFocusedNode->rootEditableElement()) 2867 frame()->editor()->didEndEditing(); 2868 } 2869 2870 if (newFocusedNode) { 2871 if (newFocusedNode == newFocusedNode->rootEditableElement() && !acceptsEditingFocus(newFocusedNode.get())) { 2872 // delegate blocks focus change 2873 focusChangeBlocked = true; 2874 goto SetFocusedNodeDone; 2875 } 2876 // Set focus on the new node 2877 m_focusedNode = newFocusedNode.get(); 2878 2879 // Dispatch the focus event and let the node do any other focus related activities (important for text fields) 2880 m_focusedNode->dispatchFocusEvent(); 2881 2882 if (m_focusedNode != newFocusedNode) { 2883 // handler shifted focus 2884 focusChangeBlocked = true; 2885 goto SetFocusedNodeDone; 2886 } 2887 m_focusedNode->dispatchUIEvent(eventNames().DOMFocusInEvent, 0, 0); 2888 if (m_focusedNode != newFocusedNode) { 2889 // handler shifted focus 2890 focusChangeBlocked = true; 2891 goto SetFocusedNodeDone; 2892 } 2893 m_focusedNode->setFocus(); 2894 2895 if (m_focusedNode == m_focusedNode->rootEditableElement()) 2896 frame()->editor()->didBeginEditing(); 2897 2898 // eww, I suck. set the qt focus correctly 2899 // ### find a better place in the code for this 2900 if (view()) { 2901 Widget *focusWidget = widgetForNode(m_focusedNode.get()); 2902 if (focusWidget) { 2903 // Make sure a widget has the right size before giving it focus. 2904 // Otherwise, we are testing edge cases of the Widget code. 2905 // Specifically, in WebCore this does not work well for text fields. 2906 updateLayout(); 2907 // Re-get the widget in case updating the layout changed things. 2908 focusWidget = widgetForNode(m_focusedNode.get()); 2909 } 2910 if (focusWidget) 2911 focusWidget->setFocus(); 2912 else 2913 view()->setFocus(); 2914 } 2915 } 2916 2917 #if ((PLATFORM(MAC) || PLATFORM(WIN)) && !PLATFORM(CHROMIUM)) || PLATFORM(GTK) 2918 if (!focusChangeBlocked && m_focusedNode && AXObjectCache::accessibilityEnabled()) { 2919 RenderObject* oldFocusedRenderer = 0; 2920 RenderObject* newFocusedRenderer = 0; 2921 2922 if (oldFocusedNode) 2923 oldFocusedRenderer = oldFocusedNode->renderer(); 2924 if (newFocusedNode) 2925 newFocusedRenderer = newFocusedNode->renderer(); 2926 2927 axObjectCache()->handleFocusedUIElementChanged(oldFocusedRenderer, newFocusedRenderer); 2928 } 2929 #endif 2930 if (!focusChangeBlocked) 2931 page()->chrome()->focusedNodeChanged(m_focusedNode.get()); 2932 2933 SetFocusedNodeDone: 2934 updateStyleIfNeeded(); 2935 return !focusChangeBlocked; 2936 } 2937 2938 void Document::getFocusableNodes(Vector<RefPtr<Node> >& nodes) 2939 { 2940 updateLayout(); 2941 2942 for (Node* node = firstChild(); node; node = node->traverseNextNode()) { 2943 if (node->isFocusable()) 2944 nodes.append(node); 2945 } 2946 } 2947 2948 void Document::setCSSTarget(Element* n) 2949 { 2950 if (m_cssTarget) 2951 m_cssTarget->setNeedsStyleRecalc(); 2952 m_cssTarget = n; 2953 if (n) 2954 n->setNeedsStyleRecalc(); 2955 } 2956 2957 void Document::attachNodeIterator(NodeIterator *ni) 2958 { 2959 m_nodeIterators.add(ni); 2960 } 2961 2962 void Document::detachNodeIterator(NodeIterator *ni) 2963 { 2964 m_nodeIterators.remove(ni); 2965 } 2966 2967 void Document::nodeChildrenChanged(ContainerNode* container) 2968 { 2969 if (!disableRangeMutation(page())) { 2970 HashSet<Range*>::const_iterator end = m_ranges.end(); 2971 for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it) 2972 (*it)->nodeChildrenChanged(container); 2973 } 2974 } 2975 2976 void Document::nodeWillBeRemoved(Node* n) 2977 { 2978 HashSet<NodeIterator*>::const_iterator nodeIteratorsEnd = m_nodeIterators.end(); 2979 for (HashSet<NodeIterator*>::const_iterator it = m_nodeIterators.begin(); it != nodeIteratorsEnd; ++it) 2980 (*it)->nodeWillBeRemoved(n); 2981 2982 if (!disableRangeMutation(page())) { 2983 HashSet<Range*>::const_iterator rangesEnd = m_ranges.end(); 2984 for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != rangesEnd; ++it) 2985 (*it)->nodeWillBeRemoved(n); 2986 } 2987 2988 if (Frame* frame = this->frame()) { 2989 frame->selection()->nodeWillBeRemoved(n); 2990 frame->dragCaretController()->nodeWillBeRemoved(n); 2991 } 2992 } 2993 2994 void Document::textInserted(Node* text, unsigned offset, unsigned length) 2995 { 2996 if (!disableRangeMutation(page())) { 2997 HashSet<Range*>::const_iterator end = m_ranges.end(); 2998 for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it) 2999 (*it)->textInserted(text, offset, length); 3000 } 3001 3002 // Update the markers for spelling and grammar checking. 3003 shiftMarkers(text, offset, length); 3004 } 3005 3006 void Document::textRemoved(Node* text, unsigned offset, unsigned length) 3007 { 3008 if (!disableRangeMutation(page())) { 3009 HashSet<Range*>::const_iterator end = m_ranges.end(); 3010 for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it) 3011 (*it)->textRemoved(text, offset, length); 3012 } 3013 3014 // Update the markers for spelling and grammar checking. 3015 removeMarkers(text, offset, length); 3016 shiftMarkers(text, offset + length, 0 - length); 3017 } 3018 3019 void Document::textNodesMerged(Text* oldNode, unsigned offset) 3020 { 3021 if (!disableRangeMutation(page())) { 3022 NodeWithIndex oldNodeWithIndex(oldNode); 3023 HashSet<Range*>::const_iterator end = m_ranges.end(); 3024 for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it) 3025 (*it)->textNodesMerged(oldNodeWithIndex, offset); 3026 } 3027 3028 // FIXME: This should update markers for spelling and grammar checking. 3029 } 3030 3031 void Document::textNodeSplit(Text* oldNode) 3032 { 3033 if (!disableRangeMutation(page())) { 3034 HashSet<Range*>::const_iterator end = m_ranges.end(); 3035 for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it) 3036 (*it)->textNodeSplit(oldNode); 3037 } 3038 3039 // FIXME: This should update markers for spelling and grammar checking. 3040 } 3041 3042 // FIXME: eventually, this should return a DOMWindow stored in the document. 3043 DOMWindow* Document::domWindow() const 3044 { 3045 if (!frame()) 3046 return 0; 3047 3048 // The m_frame pointer is not (not always?) zeroed out when the document is put into b/f cache, so the frame can hold an unrelated document/window pair. 3049 // FIXME: We should always zero out the frame pointer on navigation to avoid accidentally accessing the new frame content. 3050 if (m_frame->document() != this) 3051 return 0; 3052 3053 return frame()->domWindow(); 3054 } 3055 3056 void Document::setWindowAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener) 3057 { 3058 DOMWindow* domWindow = this->domWindow(); 3059 if (!domWindow) 3060 return; 3061 domWindow->setAttributeEventListener(eventType, listener); 3062 } 3063 3064 EventListener* Document::getWindowAttributeEventListener(const AtomicString& eventType) 3065 { 3066 DOMWindow* domWindow = this->domWindow(); 3067 if (!domWindow) 3068 return 0; 3069 return domWindow->getAttributeEventListener(eventType); 3070 } 3071 3072 void Document::dispatchWindowEvent(PassRefPtr<Event> event, PassRefPtr<EventTarget> target) 3073 { 3074 ASSERT(!eventDispatchForbidden()); 3075 DOMWindow* domWindow = this->domWindow(); 3076 if (!domWindow) 3077 return; 3078 domWindow->dispatchEvent(event, target); 3079 } 3080 3081 void Document::dispatchWindowLoadEvent() 3082 { 3083 ASSERT(!eventDispatchForbidden()); 3084 DOMWindow* domWindow = this->domWindow(); 3085 if (!domWindow) 3086 return; 3087 domWindow->dispatchLoadEvent(); 3088 } 3089 3090 void Document::enqueueStorageEvent(PassRefPtr<Event> storageEvent) 3091 { 3092 m_storageEventQueue.append(storageEvent); 3093 if (!m_storageEventTimer.isActive()) 3094 m_storageEventTimer.startOneShot(0); 3095 } 3096 3097 void Document::storageEventTimerFired(Timer<Document>*) 3098 { 3099 ASSERT(!m_storageEventTimer.isActive()); 3100 Vector<RefPtr<Event> > storageEventQueue; 3101 storageEventQueue.swap(m_storageEventQueue); 3102 3103 typedef Vector<RefPtr<Event> >::const_iterator Iterator; 3104 Iterator end = storageEventQueue.end(); 3105 for (Iterator it = storageEventQueue.begin(); it != end; ++it) 3106 dispatchWindowEvent(*it); 3107 } 3108 3109 PassRefPtr<Event> Document::createEvent(const String& eventType, ExceptionCode& ec) 3110 { 3111 RefPtr<Event> event; 3112 if (eventType == "Event" || eventType == "Events" || eventType == "HTMLEvents") 3113 event = Event::create(); 3114 else if (eventType == "KeyboardEvent" || eventType == "KeyboardEvents") 3115 event = KeyboardEvent::create(); 3116 else if (eventType == "MessageEvent") 3117 event = MessageEvent::create(); 3118 else if (eventType == "MouseEvent" || eventType == "MouseEvents") 3119 event = MouseEvent::create(); 3120 else if (eventType == "MutationEvent" || eventType == "MutationEvents") 3121 event = MutationEvent::create(); 3122 else if (eventType == "OverflowEvent") 3123 event = OverflowEvent::create(); 3124 else if (eventType == "PageTransitionEvent") 3125 event = PageTransitionEvent::create(); 3126 else if (eventType == "ProgressEvent") 3127 event = ProgressEvent::create(); 3128 #if ENABLE(DOM_STORAGE) 3129 else if (eventType == "StorageEvent") 3130 event = StorageEvent::create(); 3131 #endif 3132 else if (eventType == "TextEvent") 3133 event = TextEvent::create(); 3134 else if (eventType == "UIEvent" || eventType == "UIEvents") 3135 event = UIEvent::create(); 3136 else if (eventType == "WebKitAnimationEvent") 3137 event = WebKitAnimationEvent::create(); 3138 else if (eventType == "WebKitTransitionEvent") 3139 event = WebKitTransitionEvent::create(); 3140 else if (eventType == "WheelEvent") 3141 event = WheelEvent::create(); 3142 #if ENABLE(SVG) 3143 else if (eventType == "SVGEvents") 3144 event = Event::create(); 3145 else if (eventType == "SVGZoomEvents") 3146 event = SVGZoomEvent::create(); 3147 #endif 3148 #if ENABLE(TOUCH_EVENTS) 3149 else if (eventType == "TouchEvent") 3150 event = TouchEvent::create(); 3151 #endif 3152 if (event) { 3153 event->setCreatedByDOM(true); 3154 return event.release(); 3155 } 3156 ec = NOT_SUPPORTED_ERR; 3157 return 0; 3158 } 3159 3160 void Document::addListenerTypeIfNeeded(const AtomicString& eventType) 3161 { 3162 if (eventType == eventNames().DOMSubtreeModifiedEvent) 3163 addListenerType(DOMSUBTREEMODIFIED_LISTENER); 3164 else if (eventType == eventNames().DOMNodeInsertedEvent) 3165 addListenerType(DOMNODEINSERTED_LISTENER); 3166 else if (eventType == eventNames().DOMNodeRemovedEvent) 3167 addListenerType(DOMNODEREMOVED_LISTENER); 3168 else if (eventType == eventNames().DOMNodeRemovedFromDocumentEvent) 3169 addListenerType(DOMNODEREMOVEDFROMDOCUMENT_LISTENER); 3170 else if (eventType == eventNames().DOMNodeInsertedIntoDocumentEvent) 3171 addListenerType(DOMNODEINSERTEDINTODOCUMENT_LISTENER); 3172 else if (eventType == eventNames().DOMAttrModifiedEvent) 3173 addListenerType(DOMATTRMODIFIED_LISTENER); 3174 else if (eventType == eventNames().DOMCharacterDataModifiedEvent) 3175 addListenerType(DOMCHARACTERDATAMODIFIED_LISTENER); 3176 else if (eventType == eventNames().overflowchangedEvent) 3177 addListenerType(OVERFLOWCHANGED_LISTENER); 3178 else if (eventType == eventNames().webkitAnimationStartEvent) 3179 addListenerType(ANIMATIONSTART_LISTENER); 3180 else if (eventType == eventNames().webkitAnimationEndEvent) 3181 addListenerType(ANIMATIONEND_LISTENER); 3182 else if (eventType == eventNames().webkitAnimationIterationEvent) 3183 addListenerType(ANIMATIONITERATION_LISTENER); 3184 else if (eventType == eventNames().webkitTransitionEndEvent) 3185 addListenerType(TRANSITIONEND_LISTENER); 3186 else if (eventType == eventNames().beforeloadEvent) 3187 addListenerType(BEFORELOAD_LISTENER); 3188 #if ENABLE(TOUCH_EVENTS) 3189 else if (eventType == eventNames().touchstartEvent 3190 || eventType == eventNames().touchmoveEvent 3191 || eventType == eventNames().touchendEvent 3192 || eventType == eventNames().touchcancelEvent) { 3193 addListenerType(TOUCH_LISTENER); 3194 if (Page* page = this->page()) 3195 page->chrome()->client()->needTouchEvents(true); 3196 } 3197 #endif 3198 } 3199 3200 CSSStyleDeclaration* Document::getOverrideStyle(Element*, const String&) 3201 { 3202 return 0; 3203 } 3204 3205 Element* Document::ownerElement() const 3206 { 3207 if (!frame()) 3208 return 0; 3209 return frame()->ownerElement(); 3210 } 3211 3212 String Document::cookie(ExceptionCode& ec) const 3213 { 3214 if (page() && !page()->cookieEnabled()) 3215 return String(); 3216 3217 // FIXME: The HTML5 DOM spec states that this attribute can raise an 3218 // INVALID_STATE_ERR exception on getting if the Document has no 3219 // browsing context. 3220 3221 if (!securityOrigin()->canAccessCookies()) { 3222 ec = SECURITY_ERR; 3223 return String(); 3224 } 3225 3226 KURL cookieURL = this->cookieURL(); 3227 if (cookieURL.isEmpty()) 3228 return String(); 3229 3230 return cookies(this, cookieURL); 3231 } 3232 3233 void Document::setCookie(const String& value, ExceptionCode& ec) 3234 { 3235 if (page() && !page()->cookieEnabled()) 3236 return; 3237 3238 // FIXME: The HTML5 DOM spec states that this attribute can raise an 3239 // INVALID_STATE_ERR exception on setting if the Document has no 3240 // browsing context. 3241 3242 if (!securityOrigin()->canAccessCookies()) { 3243 ec = SECURITY_ERR; 3244 return; 3245 } 3246 3247 KURL cookieURL = this->cookieURL(); 3248 if (cookieURL.isEmpty()) 3249 return; 3250 3251 setCookies(this, cookieURL, value); 3252 } 3253 3254 String Document::referrer() const 3255 { 3256 if (frame()) 3257 return frame()->loader()->referrer(); 3258 return String(); 3259 } 3260 3261 String Document::domain() const 3262 { 3263 return securityOrigin()->domain(); 3264 } 3265 3266 void Document::setDomain(const String& newDomain, ExceptionCode& ec) 3267 { 3268 if (SecurityOrigin::isDomainRelaxationForbiddenForURLScheme(securityOrigin()->protocol())) { 3269 ec = SECURITY_ERR; 3270 return; 3271 } 3272 3273 // Both NS and IE specify that changing the domain is only allowed when 3274 // the new domain is a suffix of the old domain. 3275 3276 // FIXME: We should add logging indicating why a domain was not allowed. 3277 3278 // If the new domain is the same as the old domain, still call 3279 // securityOrigin()->setDomainForDOM. This will change the 3280 // security check behavior. For example, if a page loaded on port 8000 3281 // assigns its current domain using document.domain, the page will 3282 // allow other pages loaded on different ports in the same domain that 3283 // have also assigned to access this page. 3284 if (equalIgnoringCase(domain(), newDomain)) { 3285 securityOrigin()->setDomainFromDOM(newDomain); 3286 if (m_frame) 3287 m_frame->script()->updateSecurityOrigin(); 3288 return; 3289 } 3290 3291 int oldLength = domain().length(); 3292 int newLength = newDomain.length(); 3293 // e.g. newDomain = webkit.org (10) and domain() = www.webkit.org (14) 3294 if (newLength >= oldLength) { 3295 ec = SECURITY_ERR; 3296 return; 3297 } 3298 3299 String test = domain(); 3300 // Check that it's a subdomain, not e.g. "ebkit.org" 3301 if (test[oldLength - newLength - 1] != '.') { 3302 ec = SECURITY_ERR; 3303 return; 3304 } 3305 3306 // Now test is "webkit.org" from domain() 3307 // and we check that it's the same thing as newDomain 3308 test.remove(0, oldLength - newLength); 3309 if (test != newDomain) { 3310 ec = SECURITY_ERR; 3311 return; 3312 } 3313 3314 securityOrigin()->setDomainFromDOM(newDomain); 3315 if (m_frame) 3316 m_frame->script()->updateSecurityOrigin(); 3317 } 3318 3319 String Document::lastModified() const 3320 { 3321 Frame* f = frame(); 3322 if (!f) 3323 return String(); 3324 DocumentLoader* loader = f->loader()->documentLoader(); 3325 if (!loader) 3326 return String(); 3327 return loader->response().httpHeaderField("Last-Modified"); 3328 } 3329 3330 static bool isValidNameNonASCII(const UChar* characters, unsigned length) 3331 { 3332 unsigned i = 0; 3333 3334 UChar32 c; 3335 U16_NEXT(characters, i, length, c) 3336 if (!isValidNameStart(c)) 3337 return false; 3338 3339 while (i < length) { 3340 U16_NEXT(characters, i, length, c) 3341 if (!isValidNamePart(c)) 3342 return false; 3343 } 3344 3345 return true; 3346 } 3347 3348 static inline bool isValidNameASCII(const UChar* characters, unsigned length) 3349 { 3350 UChar c = characters[0]; 3351 if (!(isASCIIAlpha(c) || c == ':' || c == '_')) 3352 return false; 3353 3354 for (unsigned i = 1; i < length; ++i) { 3355 c = characters[i]; 3356 if (!(isASCIIAlphanumeric(c) || c == ':' || c == '_' || c == '-' || c == '.')) 3357 return false; 3358 } 3359 3360 return true; 3361 } 3362 3363 bool Document::isValidName(const String& name) 3364 { 3365 unsigned length = name.length(); 3366 if (!length) 3367 return false; 3368 3369 const UChar* characters = name.characters(); 3370 return isValidNameASCII(characters, length) || isValidNameNonASCII(characters, length); 3371 } 3372 3373 bool Document::parseQualifiedName(const String& qualifiedName, String& prefix, String& localName, ExceptionCode& ec) 3374 { 3375 unsigned length = qualifiedName.length(); 3376 3377 if (length == 0) { 3378 ec = INVALID_CHARACTER_ERR; 3379 return false; 3380 } 3381 3382 bool nameStart = true; 3383 bool sawColon = false; 3384 int colonPos = 0; 3385 3386 const UChar* s = qualifiedName.characters(); 3387 for (unsigned i = 0; i < length;) { 3388 UChar32 c; 3389 U16_NEXT(s, i, length, c) 3390 if (c == ':') { 3391 if (sawColon) { 3392 ec = NAMESPACE_ERR; 3393 return false; // multiple colons: not allowed 3394 } 3395 nameStart = true; 3396 sawColon = true; 3397 colonPos = i - 1; 3398 } else if (nameStart) { 3399 if (!isValidNameStart(c)) { 3400 ec = INVALID_CHARACTER_ERR; 3401 return false; 3402 } 3403 nameStart = false; 3404 } else { 3405 if (!isValidNamePart(c)) { 3406 ec = INVALID_CHARACTER_ERR; 3407 return false; 3408 } 3409 } 3410 } 3411 3412 if (!sawColon) { 3413 prefix = String(); 3414 localName = qualifiedName; 3415 } else { 3416 prefix = qualifiedName.substring(0, colonPos); 3417 if (prefix.isEmpty()) { 3418 ec = NAMESPACE_ERR; 3419 return false; 3420 } 3421 localName = qualifiedName.substring(colonPos + 1); 3422 } 3423 3424 if (localName.isEmpty()) { 3425 ec = NAMESPACE_ERR; 3426 return false; 3427 } 3428 3429 return true; 3430 } 3431 3432 void Document::addImageMap(HTMLMapElement* imageMap) 3433 { 3434 const AtomicString& name = imageMap->getName(); 3435 if (!name.impl()) 3436 return; 3437 3438 // Add the image map, unless there's already another with that name. 3439 // "First map wins" is the rule other browsers seem to implement. 3440 m_imageMapsByName.add(name.impl(), imageMap); 3441 } 3442 3443 void Document::removeImageMap(HTMLMapElement* imageMap) 3444 { 3445 // Remove the image map by name. 3446 // But don't remove some other image map that just happens to have the same name. 3447 // FIXME: Use a HashCountedSet as we do for IDs to find the first remaining map 3448 // once a map has been removed. 3449 const AtomicString& name = imageMap->getName(); 3450 if (!name.impl()) 3451 return; 3452 3453 m_imageMapsByName.checkConsistency(); 3454 3455 ImageMapsByName::iterator it = m_imageMapsByName.find(name.impl()); 3456 if (it != m_imageMapsByName.end() && it->second == imageMap) 3457 m_imageMapsByName.remove(it); 3458 } 3459 3460 HTMLMapElement *Document::getImageMap(const String& url) const 3461 { 3462 if (url.isNull()) 3463 return 0; 3464 int hashPos = url.find('#'); 3465 String name = (hashPos < 0 ? url : url.substring(hashPos + 1)).impl(); 3466 AtomicString mapName = isHTMLDocument() ? name.lower() : name; 3467 m_imageMapsByName.checkConsistency(); 3468 return m_imageMapsByName.get(mapName.impl()); 3469 } 3470 3471 void Document::setDecoder(PassRefPtr<TextResourceDecoder> decoder) 3472 { 3473 m_decoder = decoder; 3474 } 3475 3476 KURL Document::completeURL(const String& url) const 3477 { 3478 // Always return a null URL when passed a null string. 3479 // FIXME: Should we change the KURL constructor to have this behavior? 3480 // See also [CSS]StyleSheet::completeURL(const String&) 3481 if (url.isNull()) 3482 return KURL(); 3483 const KURL& baseURL = ((m_baseURL.isEmpty() || m_baseURL == blankURL()) && parentDocument()) ? parentDocument()->baseURL() : m_baseURL; 3484 if (!m_decoder) 3485 return KURL(baseURL, url); 3486 return KURL(baseURL, url, m_decoder->encoding()); 3487 } 3488 3489 void Document::setInPageCache(bool flag) 3490 { 3491 if (m_inPageCache == flag) 3492 return; 3493 3494 m_inPageCache = flag; 3495 if (flag) { 3496 ASSERT(m_savedRenderer == 0); 3497 m_savedRenderer = renderer(); 3498 if (FrameView* v = view()) 3499 v->resetScrollbars(); 3500 unscheduleStyleRecalc(); 3501 } else { 3502 ASSERT(renderer() == 0 || renderer() == m_savedRenderer); 3503 ASSERT(m_renderArena); 3504 setRenderer(m_savedRenderer); 3505 m_savedRenderer = 0; 3506 if (childNeedsStyleRecalc()) 3507 scheduleStyleRecalc(); 3508 } 3509 } 3510 3511 void Document::documentWillBecomeInactive() 3512 { 3513 #if USE(ACCELERATED_COMPOSITING) 3514 if (renderer()) 3515 renderView()->willMoveOffscreen(); 3516 #endif 3517 3518 HashSet<Element*>::iterator end = m_documentActivationCallbackElements.end(); 3519 for (HashSet<Element*>::iterator i = m_documentActivationCallbackElements.begin(); i != end; ++i) 3520 (*i)->documentWillBecomeInactive(); 3521 } 3522 3523 void Document::documentDidBecomeActive() 3524 { 3525 HashSet<Element*>::iterator end = m_documentActivationCallbackElements.end(); 3526 for (HashSet<Element*>::iterator i = m_documentActivationCallbackElements.begin(); i != end; ++i) 3527 (*i)->documentDidBecomeActive(); 3528 3529 #if USE(ACCELERATED_COMPOSITING) 3530 if (renderer()) 3531 renderView()->didMoveOnscreen(); 3532 #endif 3533 } 3534 3535 void Document::registerForDocumentActivationCallbacks(Element* e) 3536 { 3537 m_documentActivationCallbackElements.add(e); 3538 } 3539 3540 void Document::unregisterForDocumentActivationCallbacks(Element* e) 3541 { 3542 m_documentActivationCallbackElements.remove(e); 3543 } 3544 3545 void Document::mediaVolumeDidChange() 3546 { 3547 HashSet<Element*>::iterator end = m_mediaVolumeCallbackElements.end(); 3548 for (HashSet<Element*>::iterator i = m_mediaVolumeCallbackElements.begin(); i != end; ++i) 3549 (*i)->mediaVolumeDidChange(); 3550 } 3551 3552 void Document::registerForMediaVolumeCallbacks(Element* e) 3553 { 3554 m_mediaVolumeCallbackElements.add(e); 3555 } 3556 3557 void Document::unregisterForMediaVolumeCallbacks(Element* e) 3558 { 3559 m_mediaVolumeCallbackElements.remove(e); 3560 } 3561 3562 void Document::setShouldCreateRenderers(bool f) 3563 { 3564 m_createRenderers = f; 3565 } 3566 3567 bool Document::shouldCreateRenderers() 3568 { 3569 return m_createRenderers; 3570 } 3571 3572 // Support for Javascript execCommand, and related methods 3573 3574 static Editor::Command command(Document* document, const String& commandName, bool userInterface = false) 3575 { 3576 Frame* frame = document->frame(); 3577 if (!frame || frame->document() != document) 3578 return Editor::Command(); 3579 return frame->editor()->command(commandName, 3580 userInterface ? CommandFromDOMWithUserInterface : CommandFromDOM); 3581 } 3582 3583 bool Document::execCommand(const String& commandName, bool userInterface, const String& value) 3584 { 3585 return command(this, commandName, userInterface).execute(value); 3586 } 3587 3588 bool Document::queryCommandEnabled(const String& commandName) 3589 { 3590 return command(this, commandName).isEnabled(); 3591 } 3592 3593 bool Document::queryCommandIndeterm(const String& commandName) 3594 { 3595 return command(this, commandName).state() == MixedTriState; 3596 } 3597 3598 bool Document::queryCommandState(const String& commandName) 3599 { 3600 return command(this, commandName).state() != FalseTriState; 3601 } 3602 3603 bool Document::queryCommandSupported(const String& commandName) 3604 { 3605 return command(this, commandName).isSupported(); 3606 } 3607 3608 String Document::queryCommandValue(const String& commandName) 3609 { 3610 return command(this, commandName).value(); 3611 } 3612 3613 static IntRect placeholderRectForMarker() 3614 { 3615 return IntRect(-1, -1, -1, -1); 3616 } 3617 3618 void Document::addMarker(Range *range, DocumentMarker::MarkerType type, String description) 3619 { 3620 // Use a TextIterator to visit the potentially multiple nodes the range covers. 3621 for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) { 3622 RefPtr<Range> textPiece = markedText.range(); 3623 int exception = 0; 3624 DocumentMarker marker = {type, textPiece->startOffset(exception), textPiece->endOffset(exception), description, false}; 3625 addMarker(textPiece->startContainer(exception), marker); 3626 } 3627 } 3628 3629 void Document::removeMarkers(Range* range, DocumentMarker::MarkerType markerType) 3630 { 3631 if (m_markers.isEmpty()) 3632 return; 3633 3634 ExceptionCode ec = 0; 3635 Node* startContainer = range->startContainer(ec); 3636 Node* endContainer = range->endContainer(ec); 3637 3638 Node* pastLastNode = range->pastLastNode(); 3639 for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) { 3640 int startOffset = node == startContainer ? range->startOffset(ec) : 0; 3641 int endOffset = node == endContainer ? range->endOffset(ec) : INT_MAX; 3642 int length = endOffset - startOffset; 3643 removeMarkers(node, startOffset, length, markerType); 3644 } 3645 } 3646 3647 // Markers are stored in order sorted by their start offset. 3648 // Markers of the same type do not overlap each other. 3649 3650 void Document::addMarker(Node* node, DocumentMarker newMarker) 3651 { 3652 ASSERT(newMarker.endOffset >= newMarker.startOffset); 3653 if (newMarker.endOffset == newMarker.startOffset) 3654 return; 3655 3656 MarkerMapVectorPair* vectorPair = m_markers.get(node); 3657 3658 if (!vectorPair) { 3659 vectorPair = new MarkerMapVectorPair; 3660 vectorPair->first.append(newMarker); 3661 vectorPair->second.append(placeholderRectForMarker()); 3662 m_markers.set(node, vectorPair); 3663 } else { 3664 Vector<DocumentMarker>& markers = vectorPair->first; 3665 Vector<IntRect>& rects = vectorPair->second; 3666 size_t numMarkers = markers.size(); 3667 ASSERT(numMarkers == rects.size()); 3668 size_t i; 3669 // Iterate over all markers whose start offset is less than or equal to the new marker's. 3670 // If one of them is of the same type as the new marker and touches it or intersects with it 3671 // (there is at most one), remove it and adjust the new marker's start offset to encompass it. 3672 for (i = 0; i < numMarkers; ++i) { 3673 DocumentMarker marker = markers[i]; 3674 if (marker.startOffset > newMarker.startOffset) 3675 break; 3676 if (marker.type == newMarker.type && marker.endOffset >= newMarker.startOffset) { 3677 newMarker.startOffset = marker.startOffset; 3678 markers.remove(i); 3679 rects.remove(i); 3680 numMarkers--; 3681 break; 3682 } 3683 } 3684 size_t j = i; 3685 // Iterate over all markers whose end offset is less than or equal to the new marker's, 3686 // removing markers of the same type as the new marker which touch it or intersect with it, 3687 // adjusting the new marker's end offset to cover them if necessary. 3688 while (j < numMarkers) { 3689 DocumentMarker marker = markers[j]; 3690 if (marker.startOffset > newMarker.endOffset) 3691 break; 3692 if (marker.type == newMarker.type) { 3693 markers.remove(j); 3694 rects.remove(j); 3695 if (newMarker.endOffset <= marker.endOffset) { 3696 newMarker.endOffset = marker.endOffset; 3697 break; 3698 } 3699 numMarkers--; 3700 } else 3701 j++; 3702 } 3703 // At this point i points to the node before which we want to insert. 3704 markers.insert(i, newMarker); 3705 rects.insert(i, placeholderRectForMarker()); 3706 } 3707 3708 // repaint the affected node 3709 if (node->renderer()) 3710 node->renderer()->repaint(); 3711 } 3712 3713 // copies markers from srcNode to dstNode, applying the specified shift delta to the copies. The shift is 3714 // useful if, e.g., the caller has created the dstNode from a non-prefix substring of the srcNode. 3715 void Document::copyMarkers(Node *srcNode, unsigned startOffset, int length, Node *dstNode, int delta, DocumentMarker::MarkerType markerType) 3716 { 3717 if (length <= 0) 3718 return; 3719 3720 MarkerMapVectorPair* vectorPair = m_markers.get(srcNode); 3721 if (!vectorPair) 3722 return; 3723 3724 ASSERT(vectorPair->first.size() == vectorPair->second.size()); 3725 3726 bool docDirty = false; 3727 unsigned endOffset = startOffset + length - 1; 3728 Vector<DocumentMarker>& markers = vectorPair->first; 3729 for (size_t i = 0; i != markers.size(); ++i) { 3730 DocumentMarker marker = markers[i]; 3731 3732 // stop if we are now past the specified range 3733 if (marker.startOffset > endOffset) 3734 break; 3735 3736 // skip marker that is before the specified range or is the wrong type 3737 if (marker.endOffset < startOffset || (marker.type != markerType && markerType != DocumentMarker::AllMarkers)) 3738 continue; 3739 3740 // pin the marker to the specified range and apply the shift delta 3741 docDirty = true; 3742 if (marker.startOffset < startOffset) 3743 marker.startOffset = startOffset; 3744 if (marker.endOffset > endOffset) 3745 marker.endOffset = endOffset; 3746 marker.startOffset += delta; 3747 marker.endOffset += delta; 3748 3749 addMarker(dstNode, marker); 3750 } 3751 3752 // repaint the affected node 3753 if (docDirty && dstNode->renderer()) 3754 dstNode->renderer()->repaint(); 3755 } 3756 3757 void Document::removeMarkers(Node* node, unsigned startOffset, int length, DocumentMarker::MarkerType markerType) 3758 { 3759 if (length <= 0) 3760 return; 3761 3762 MarkerMapVectorPair* vectorPair = m_markers.get(node); 3763 if (!vectorPair) 3764 return; 3765 3766 Vector<DocumentMarker>& markers = vectorPair->first; 3767 Vector<IntRect>& rects = vectorPair->second; 3768 ASSERT(markers.size() == rects.size()); 3769 bool docDirty = false; 3770 unsigned endOffset = startOffset + length; 3771 for (size_t i = 0; i < markers.size();) { 3772 DocumentMarker marker = markers[i]; 3773 3774 // markers are returned in order, so stop if we are now past the specified range 3775 if (marker.startOffset >= endOffset) 3776 break; 3777 3778 // skip marker that is wrong type or before target 3779 if (marker.endOffset < startOffset || (marker.type != markerType && markerType != DocumentMarker::AllMarkers)) { 3780 i++; 3781 continue; 3782 } 3783 3784 // at this point we know that marker and target intersect in some way 3785 docDirty = true; 3786 3787 // pitch the old marker and any associated rect 3788 markers.remove(i); 3789 rects.remove(i); 3790 3791 // add either of the resulting slices that are left after removing target 3792 if (startOffset > marker.startOffset) { 3793 DocumentMarker newLeft = marker; 3794 newLeft.endOffset = startOffset; 3795 markers.insert(i, newLeft); 3796 rects.insert(i, placeholderRectForMarker()); 3797 // i now points to the newly-inserted node, but we want to skip that one 3798 i++; 3799 } 3800 if (marker.endOffset > endOffset) { 3801 DocumentMarker newRight = marker; 3802 newRight.startOffset = endOffset; 3803 markers.insert(i, newRight); 3804 rects.insert(i, placeholderRectForMarker()); 3805 // i now points to the newly-inserted node, but we want to skip that one 3806 i++; 3807 } 3808 } 3809 3810 if (markers.isEmpty()) { 3811 ASSERT(rects.isEmpty()); 3812 m_markers.remove(node); 3813 delete vectorPair; 3814 } 3815 3816 // repaint the affected node 3817 if (docDirty && node->renderer()) 3818 node->renderer()->repaint(); 3819 } 3820 3821 DocumentMarker* Document::markerContainingPoint(const IntPoint& point, DocumentMarker::MarkerType markerType) 3822 { 3823 // outer loop: process each node that contains any markers 3824 MarkerMap::iterator end = m_markers.end(); 3825 for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) { 3826 // inner loop; process each marker in this node 3827 MarkerMapVectorPair* vectorPair = nodeIterator->second; 3828 Vector<DocumentMarker>& markers = vectorPair->first; 3829 Vector<IntRect>& rects = vectorPair->second; 3830 ASSERT(markers.size() == rects.size()); 3831 unsigned markerCount = markers.size(); 3832 for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) { 3833 DocumentMarker& marker = markers[markerIndex]; 3834 3835 // skip marker that is wrong type 3836 if (marker.type != markerType && markerType != DocumentMarker::AllMarkers) 3837 continue; 3838 3839 IntRect& r = rects[markerIndex]; 3840 3841 // skip placeholder rects 3842 if (r == placeholderRectForMarker()) 3843 continue; 3844 3845 if (r.contains(point)) 3846 return ▮ 3847 } 3848 } 3849 3850 return 0; 3851 } 3852 3853 Vector<DocumentMarker> Document::markersForNode(Node* node) 3854 { 3855 MarkerMapVectorPair* vectorPair = m_markers.get(node); 3856 if (vectorPair) 3857 return vectorPair->first; 3858 return Vector<DocumentMarker>(); 3859 } 3860 3861 Vector<IntRect> Document::renderedRectsForMarkers(DocumentMarker::MarkerType markerType) 3862 { 3863 Vector<IntRect> result; 3864 3865 // outer loop: process each node 3866 MarkerMap::iterator end = m_markers.end(); 3867 for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) { 3868 // inner loop; process each marker in this node 3869 MarkerMapVectorPair* vectorPair = nodeIterator->second; 3870 Vector<DocumentMarker>& markers = vectorPair->first; 3871 Vector<IntRect>& rects = vectorPair->second; 3872 ASSERT(markers.size() == rects.size()); 3873 unsigned markerCount = markers.size(); 3874 for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) { 3875 DocumentMarker marker = markers[markerIndex]; 3876 3877 // skip marker that is wrong type 3878 if (marker.type != markerType && markerType != DocumentMarker::AllMarkers) 3879 continue; 3880 3881 IntRect r = rects[markerIndex]; 3882 // skip placeholder rects 3883 if (r == placeholderRectForMarker()) 3884 continue; 3885 3886 result.append(r); 3887 } 3888 } 3889 3890 return result; 3891 } 3892 3893 void Document::removeMarkers(Node* node) 3894 { 3895 MarkerMap::iterator i = m_markers.find(node); 3896 if (i != m_markers.end()) { 3897 delete i->second; 3898 m_markers.remove(i); 3899 if (RenderObject* renderer = node->renderer()) 3900 renderer->repaint(); 3901 } 3902 } 3903 3904 void Document::removeMarkers(DocumentMarker::MarkerType markerType) 3905 { 3906 // outer loop: process each markered node in the document 3907 MarkerMap markerMapCopy = m_markers; 3908 MarkerMap::iterator end = markerMapCopy.end(); 3909 for (MarkerMap::iterator i = markerMapCopy.begin(); i != end; ++i) { 3910 Node* node = i->first.get(); 3911 bool nodeNeedsRepaint = false; 3912 3913 // inner loop: process each marker in the current node 3914 MarkerMapVectorPair* vectorPair = i->second; 3915 Vector<DocumentMarker>& markers = vectorPair->first; 3916 Vector<IntRect>& rects = vectorPair->second; 3917 ASSERT(markers.size() == rects.size()); 3918 for (size_t i = 0; i != markers.size();) { 3919 DocumentMarker marker = markers[i]; 3920 3921 // skip nodes that are not of the specified type 3922 if (marker.type != markerType && markerType != DocumentMarker::AllMarkers) { 3923 ++i; 3924 continue; 3925 } 3926 3927 // pitch the old marker 3928 markers.remove(i); 3929 rects.remove(i); 3930 nodeNeedsRepaint = true; 3931 // markerIterator now points to the next node 3932 } 3933 3934 // Redraw the node if it changed. Do this before the node is removed from m_markers, since 3935 // m_markers might contain the last reference to the node. 3936 if (nodeNeedsRepaint) { 3937 RenderObject* renderer = node->renderer(); 3938 if (renderer) 3939 renderer->repaint(); 3940 } 3941 3942 // delete the node's list if it is now empty 3943 if (markers.isEmpty()) { 3944 ASSERT(rects.isEmpty()); 3945 m_markers.remove(node); 3946 delete vectorPair; 3947 } 3948 } 3949 } 3950 3951 void Document::repaintMarkers(DocumentMarker::MarkerType markerType) 3952 { 3953 // outer loop: process each markered node in the document 3954 MarkerMap::iterator end = m_markers.end(); 3955 for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) { 3956 Node* node = i->first.get(); 3957 3958 // inner loop: process each marker in the current node 3959 MarkerMapVectorPair* vectorPair = i->second; 3960 Vector<DocumentMarker>& markers = vectorPair->first; 3961 bool nodeNeedsRepaint = false; 3962 for (size_t i = 0; i != markers.size(); ++i) { 3963 DocumentMarker marker = markers[i]; 3964 3965 // skip nodes that are not of the specified type 3966 if (marker.type == markerType || markerType == DocumentMarker::AllMarkers) { 3967 nodeNeedsRepaint = true; 3968 break; 3969 } 3970 } 3971 3972 if (!nodeNeedsRepaint) 3973 continue; 3974 3975 // cause the node to be redrawn 3976 if (RenderObject* renderer = node->renderer()) 3977 renderer->repaint(); 3978 } 3979 } 3980 3981 void Document::setRenderedRectForMarker(Node* node, const DocumentMarker& marker, const IntRect& r) 3982 { 3983 MarkerMapVectorPair* vectorPair = m_markers.get(node); 3984 if (!vectorPair) { 3985 ASSERT_NOT_REACHED(); // shouldn't be trying to set the rect for a marker we don't already know about 3986 return; 3987 } 3988 3989 Vector<DocumentMarker>& markers = vectorPair->first; 3990 ASSERT(markers.size() == vectorPair->second.size()); 3991 unsigned markerCount = markers.size(); 3992 for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) { 3993 DocumentMarker m = markers[markerIndex]; 3994 if (m == marker) { 3995 vectorPair->second[markerIndex] = r; 3996 return; 3997 } 3998 } 3999 4000 ASSERT_NOT_REACHED(); // shouldn't be trying to set the rect for a marker we don't already know about 4001 } 4002 4003 void Document::invalidateRenderedRectsForMarkersInRect(const IntRect& r) 4004 { 4005 // outer loop: process each markered node in the document 4006 MarkerMap::iterator end = m_markers.end(); 4007 for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) { 4008 4009 // inner loop: process each rect in the current node 4010 MarkerMapVectorPair* vectorPair = i->second; 4011 Vector<IntRect>& rects = vectorPair->second; 4012 4013 unsigned rectCount = rects.size(); 4014 for (unsigned rectIndex = 0; rectIndex < rectCount; ++rectIndex) 4015 if (rects[rectIndex].intersects(r)) 4016 rects[rectIndex] = placeholderRectForMarker(); 4017 } 4018 } 4019 4020 void Document::shiftMarkers(Node *node, unsigned startOffset, int delta, DocumentMarker::MarkerType markerType) 4021 { 4022 MarkerMapVectorPair* vectorPair = m_markers.get(node); 4023 if (!vectorPair) 4024 return; 4025 4026 Vector<DocumentMarker>& markers = vectorPair->first; 4027 Vector<IntRect>& rects = vectorPair->second; 4028 ASSERT(markers.size() == rects.size()); 4029 4030 bool docDirty = false; 4031 for (size_t i = 0; i != markers.size(); ++i) { 4032 DocumentMarker &marker = markers[i]; 4033 if (marker.startOffset >= startOffset && (markerType == DocumentMarker::AllMarkers || marker.type == markerType)) { 4034 ASSERT((int)marker.startOffset + delta >= 0); 4035 marker.startOffset += delta; 4036 marker.endOffset += delta; 4037 docDirty = true; 4038 4039 // Marker moved, so previously-computed rendered rectangle is now invalid 4040 rects[i] = placeholderRectForMarker(); 4041 } 4042 } 4043 4044 // repaint the affected node 4045 if (docDirty && node->renderer()) 4046 node->renderer()->repaint(); 4047 } 4048 4049 void Document::setMarkersActive(Range* range, bool active) 4050 { 4051 if (m_markers.isEmpty()) 4052 return; 4053 4054 ExceptionCode ec = 0; 4055 Node* startContainer = range->startContainer(ec); 4056 Node* endContainer = range->endContainer(ec); 4057 4058 Node* pastLastNode = range->pastLastNode(); 4059 for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) { 4060 int startOffset = node == startContainer ? range->startOffset(ec) : 0; 4061 int endOffset = node == endContainer ? range->endOffset(ec) : INT_MAX; 4062 setMarkersActive(node, startOffset, endOffset, active); 4063 } 4064 } 4065 4066 void Document::setMarkersActive(Node* node, unsigned startOffset, unsigned endOffset, bool active) 4067 { 4068 MarkerMapVectorPair* vectorPair = m_markers.get(node); 4069 if (!vectorPair) 4070 return; 4071 4072 Vector<DocumentMarker>& markers = vectorPair->first; 4073 ASSERT(markers.size() == vectorPair->second.size()); 4074 4075 bool docDirty = false; 4076 for (size_t i = 0; i != markers.size(); ++i) { 4077 DocumentMarker &marker = markers[i]; 4078 4079 // Markers are returned in order, so stop if we are now past the specified range. 4080 if (marker.startOffset >= endOffset) 4081 break; 4082 4083 // Skip marker that is wrong type or before target. 4084 if (marker.endOffset < startOffset || marker.type != DocumentMarker::TextMatch) 4085 continue; 4086 4087 marker.activeMatch = active; 4088 docDirty = true; 4089 } 4090 4091 // repaint the affected node 4092 if (docDirty && node->renderer()) 4093 node->renderer()->repaint(); 4094 } 4095 4096 #if ENABLE(XSLT) 4097 4098 void Document::applyXSLTransform(ProcessingInstruction* pi) 4099 { 4100 RefPtr<XSLTProcessor> processor = XSLTProcessor::create(); 4101 processor->setXSLStyleSheet(static_cast<XSLStyleSheet*>(pi->sheet())); 4102 String resultMIMEType; 4103 String newSource; 4104 String resultEncoding; 4105 if (!processor->transformToString(this, resultMIMEType, newSource, resultEncoding)) 4106 return; 4107 // FIXME: If the transform failed we should probably report an error (like Mozilla does). 4108 processor->createDocumentFromSource(newSource, resultEncoding, resultMIMEType, this, frame()); 4109 } 4110 4111 void Document::setTransformSource(PassOwnPtr<TransformSource> source) 4112 { 4113 if (m_transformSource == source) 4114 return; 4115 m_transformSource = source; 4116 } 4117 4118 #endif 4119 4120 void Document::setDesignMode(InheritedBool value) 4121 { 4122 m_designMode = value; 4123 } 4124 4125 Document::InheritedBool Document::getDesignMode() const 4126 { 4127 return m_designMode; 4128 } 4129 4130 bool Document::inDesignMode() const 4131 { 4132 for (const Document* d = this; d; d = d->parentDocument()) { 4133 if (d->m_designMode != inherit) 4134 return d->m_designMode; 4135 } 4136 return false; 4137 } 4138 4139 Document *Document::parentDocument() const 4140 { 4141 Frame *childPart = frame(); 4142 if (!childPart) 4143 return 0; 4144 Frame *parent = childPart->tree()->parent(); 4145 if (!parent) 4146 return 0; 4147 return parent->document(); 4148 } 4149 4150 Document *Document::topDocument() const 4151 { 4152 Document *doc = const_cast<Document *>(this); 4153 Element *element; 4154 while ((element = doc->ownerElement())) 4155 doc = element->document(); 4156 4157 return doc; 4158 } 4159 4160 PassRefPtr<Attr> Document::createAttribute(const String& name, ExceptionCode& ec) 4161 { 4162 return createAttributeNS(String(), name, ec, true); 4163 } 4164 4165 PassRefPtr<Attr> Document::createAttributeNS(const String& namespaceURI, const String& qualifiedName, ExceptionCode& ec, bool shouldIgnoreNamespaceChecks) 4166 { 4167 String prefix, localName; 4168 if (!parseQualifiedName(qualifiedName, prefix, localName, ec)) 4169 return 0; 4170 4171 QualifiedName qName(prefix, localName, namespaceURI); 4172 if (!shouldIgnoreNamespaceChecks && hasPrefixNamespaceMismatch(qName)) { 4173 ec = NAMESPACE_ERR; 4174 return 0; 4175 } 4176 4177 // Spec: DOM Level 2 Core: http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-DocCrAttrNS 4178 if (!shouldIgnoreNamespaceChecks && qName.localName() == xmlnsAtom && qName.namespaceURI() != XMLNSNames::xmlnsNamespaceURI) { 4179 ec = NAMESPACE_ERR; 4180 return 0; 4181 } 4182 4183 // FIXME: Assume this is a mapped attribute, since createAttribute isn't namespace-aware. There's no harm to XML 4184 // documents if we're wrong. 4185 return Attr::create(0, this, MappedAttribute::create(qName, StringImpl::empty())); 4186 } 4187 4188 #if ENABLE(SVG) 4189 const SVGDocumentExtensions* Document::svgExtensions() 4190 { 4191 return m_svgExtensions.get(); 4192 } 4193 4194 SVGDocumentExtensions* Document::accessSVGExtensions() 4195 { 4196 if (!m_svgExtensions) 4197 m_svgExtensions.set(new SVGDocumentExtensions(this)); 4198 return m_svgExtensions.get(); 4199 } 4200 #endif 4201 4202 PassRefPtr<HTMLCollection> Document::images() 4203 { 4204 return HTMLCollection::create(this, DocImages); 4205 } 4206 4207 PassRefPtr<HTMLCollection> Document::applets() 4208 { 4209 return HTMLCollection::create(this, DocApplets); 4210 } 4211 4212 PassRefPtr<HTMLCollection> Document::embeds() 4213 { 4214 return HTMLCollection::create(this, DocEmbeds); 4215 } 4216 4217 PassRefPtr<HTMLCollection> Document::plugins() 4218 { 4219 // This is an alias for embeds() required for the JS DOM bindings. 4220 return HTMLCollection::create(this, DocEmbeds); 4221 } 4222 4223 PassRefPtr<HTMLCollection> Document::objects() 4224 { 4225 return HTMLCollection::create(this, DocObjects); 4226 } 4227 4228 PassRefPtr<HTMLCollection> Document::scripts() 4229 { 4230 return HTMLCollection::create(this, DocScripts); 4231 } 4232 4233 PassRefPtr<HTMLCollection> Document::links() 4234 { 4235 return HTMLCollection::create(this, DocLinks); 4236 } 4237 4238 PassRefPtr<HTMLCollection> Document::forms() 4239 { 4240 return HTMLCollection::create(this, DocForms); 4241 } 4242 4243 PassRefPtr<HTMLCollection> Document::anchors() 4244 { 4245 return HTMLCollection::create(this, DocAnchors); 4246 } 4247 4248 PassRefPtr<HTMLAllCollection> Document::all() 4249 { 4250 return HTMLAllCollection::create(this); 4251 } 4252 4253 PassRefPtr<HTMLCollection> Document::windowNamedItems(const String &name) 4254 { 4255 return HTMLNameCollection::create(this, WindowNamedItems, name); 4256 } 4257 4258 PassRefPtr<HTMLCollection> Document::documentNamedItems(const String &name) 4259 { 4260 return HTMLNameCollection::create(this, DocumentNamedItems, name); 4261 } 4262 4263 CollectionCache* Document::nameCollectionInfo(CollectionType type, const AtomicString& name) 4264 { 4265 ASSERT(type >= FirstNamedDocumentCachedType); 4266 unsigned index = type - FirstNamedDocumentCachedType; 4267 ASSERT(index < NumNamedDocumentCachedTypes); 4268 4269 NamedCollectionMap& map = m_nameCollectionInfo[index]; 4270 NamedCollectionMap::iterator iter = map.find(name.impl()); 4271 if (iter == map.end()) 4272 iter = map.add(name.impl(), new CollectionCache).first; 4273 iter->second->checkConsistency(); 4274 return iter->second; 4275 } 4276 4277 void Document::finishedParsing() 4278 { 4279 setParsing(false); 4280 dispatchEvent(Event::create(eventNames().DOMContentLoadedEvent, true, false)); 4281 if (Frame* f = frame()) { 4282 f->loader()->finishedParsing(); 4283 4284 #if ENABLE(INSPECTOR) 4285 if (!page()) 4286 return; 4287 4288 if (InspectorController* controller = page()->inspectorController()) 4289 controller->mainResourceFiredDOMContentEvent(f->loader()->documentLoader(), url()); 4290 #endif 4291 } 4292 } 4293 4294 Vector<String> Document::formElementsState() const 4295 { 4296 Vector<String> stateVector; 4297 stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 3); 4298 typedef ListHashSet<Element*>::const_iterator Iterator; 4299 Iterator end = m_formElementsWithState.end(); 4300 for (Iterator it = m_formElementsWithState.begin(); it != end; ++it) { 4301 Element* e = *it; 4302 String value; 4303 if (e->saveFormControlState(value)) { 4304 stateVector.append(e->formControlName().string()); 4305 stateVector.append(e->formControlType().string()); 4306 stateVector.append(value); 4307 } 4308 } 4309 return stateVector; 4310 } 4311 4312 #if ENABLE(XPATH) 4313 4314 PassRefPtr<XPathExpression> Document::createExpression(const String& expression, 4315 XPathNSResolver* resolver, 4316 ExceptionCode& ec) 4317 { 4318 if (!m_xpathEvaluator) 4319 m_xpathEvaluator = XPathEvaluator::create(); 4320 return m_xpathEvaluator->createExpression(expression, resolver, ec); 4321 } 4322 4323 PassRefPtr<XPathNSResolver> Document::createNSResolver(Node* nodeResolver) 4324 { 4325 if (!m_xpathEvaluator) 4326 m_xpathEvaluator = XPathEvaluator::create(); 4327 return m_xpathEvaluator->createNSResolver(nodeResolver); 4328 } 4329 4330 PassRefPtr<XPathResult> Document::evaluate(const String& expression, 4331 Node* contextNode, 4332 XPathNSResolver* resolver, 4333 unsigned short type, 4334 XPathResult* result, 4335 ExceptionCode& ec) 4336 { 4337 if (!m_xpathEvaluator) 4338 m_xpathEvaluator = XPathEvaluator::create(); 4339 return m_xpathEvaluator->evaluate(expression, contextNode, resolver, type, result, ec); 4340 } 4341 4342 #endif // ENABLE(XPATH) 4343 4344 void Document::setStateForNewFormElements(const Vector<String>& stateVector) 4345 { 4346 // Walk the state vector backwards so that the value to use for each 4347 // name/type pair first is the one at the end of each individual vector 4348 // in the FormElementStateMap. We're using them like stacks. 4349 typedef FormElementStateMap::iterator Iterator; 4350 m_formElementsWithState.clear(); 4351 for (size_t i = stateVector.size() / 3 * 3; i; i -= 3) { 4352 AtomicString a = stateVector[i - 3]; 4353 AtomicString b = stateVector[i - 2]; 4354 const String& c = stateVector[i - 1]; 4355 FormElementKey key(a.impl(), b.impl()); 4356 Iterator it = m_stateForNewFormElements.find(key); 4357 if (it != m_stateForNewFormElements.end()) 4358 it->second.append(c); 4359 else { 4360 Vector<String> v(1); 4361 v[0] = c; 4362 m_stateForNewFormElements.set(key, v); 4363 } 4364 } 4365 } 4366 4367 bool Document::hasStateForNewFormElements() const 4368 { 4369 return !m_stateForNewFormElements.isEmpty(); 4370 } 4371 4372 bool Document::takeStateForFormElement(AtomicStringImpl* name, AtomicStringImpl* type, String& state) 4373 { 4374 typedef FormElementStateMap::iterator Iterator; 4375 Iterator it = m_stateForNewFormElements.find(FormElementKey(name, type)); 4376 if (it == m_stateForNewFormElements.end()) 4377 return false; 4378 ASSERT(it->second.size()); 4379 state = it->second.last(); 4380 if (it->second.size() > 1) 4381 it->second.removeLast(); 4382 else 4383 m_stateForNewFormElements.remove(it); 4384 return true; 4385 } 4386 4387 FormElementKey::FormElementKey(AtomicStringImpl* name, AtomicStringImpl* type) 4388 : m_name(name), m_type(type) 4389 { 4390 ref(); 4391 } 4392 4393 FormElementKey::~FormElementKey() 4394 { 4395 deref(); 4396 } 4397 4398 FormElementKey::FormElementKey(const FormElementKey& other) 4399 : m_name(other.name()), m_type(other.type()) 4400 { 4401 ref(); 4402 } 4403 4404 FormElementKey& FormElementKey::operator=(const FormElementKey& other) 4405 { 4406 other.ref(); 4407 deref(); 4408 m_name = other.name(); 4409 m_type = other.type(); 4410 return *this; 4411 } 4412 4413 void FormElementKey::ref() const 4414 { 4415 if (name()) 4416 name()->ref(); 4417 if (type()) 4418 type()->ref(); 4419 } 4420 4421 void FormElementKey::deref() const 4422 { 4423 if (name()) 4424 name()->deref(); 4425 if (type()) 4426 type()->deref(); 4427 } 4428 4429 unsigned FormElementKeyHash::hash(const FormElementKey& k) 4430 { 4431 ASSERT(sizeof(k) % (sizeof(uint16_t) * 2) == 0); 4432 4433 unsigned l = sizeof(k) / (sizeof(uint16_t) * 2); 4434 const uint16_t* s = reinterpret_cast<const uint16_t*>(&k); 4435 uint32_t hash = WTF::stringHashingStartValue; 4436 4437 // Main loop 4438 for (; l > 0; l--) { 4439 hash += s[0]; 4440 uint32_t tmp = (s[1] << 11) ^ hash; 4441 hash = (hash << 16) ^ tmp; 4442 s += 2; 4443 hash += hash >> 11; 4444 } 4445 4446 // Force "avalanching" of final 127 bits 4447 hash ^= hash << 3; 4448 hash += hash >> 5; 4449 hash ^= hash << 2; 4450 hash += hash >> 15; 4451 hash ^= hash << 10; 4452 4453 // this avoids ever returning a hash code of 0, since that is used to 4454 // signal "hash not computed yet", using a value that is likely to be 4455 // effectively the same as 0 when the low bits are masked 4456 if (hash == 0) 4457 hash = 0x80000000; 4458 4459 return hash; 4460 } 4461 4462 void Document::setIconURL(const String& iconURL, const String& type) 4463 { 4464 // FIXME - <rdar://problem/4727645> - At some point in the future, we might actually honor the "type" 4465 if (m_iconURL.isEmpty()) 4466 m_iconURL = iconURL; 4467 else if (!type.isEmpty()) 4468 m_iconURL = iconURL; 4469 } 4470 4471 void Document::setUseSecureKeyboardEntryWhenActive(bool usesSecureKeyboard) 4472 { 4473 if (m_useSecureKeyboardEntryWhenActive == usesSecureKeyboard) 4474 return; 4475 4476 m_useSecureKeyboardEntryWhenActive = usesSecureKeyboard; 4477 m_frame->updateSecureKeyboardEntryIfActive(); 4478 } 4479 4480 bool Document::useSecureKeyboardEntryWhenActive() const 4481 { 4482 return m_useSecureKeyboardEntryWhenActive; 4483 } 4484 4485 void Document::initSecurityContext() 4486 { 4487 if (securityOrigin() && !securityOrigin()->isEmpty()) 4488 return; // m_securityOrigin has already been initialized. 4489 4490 if (!m_frame) { 4491 // No source for a security context. 4492 // This can occur via document.implementation.createDocument(). 4493 m_cookieURL = KURL(ParsedURLString, ""); 4494 ScriptExecutionContext::setSecurityOrigin(SecurityOrigin::createEmpty()); 4495 return; 4496 } 4497 4498 // In the common case, create the security context from the currently 4499 // loading URL. 4500 const KURL& url = m_frame->loader()->url(); 4501 m_cookieURL = url; 4502 ScriptExecutionContext::setSecurityOrigin(SecurityOrigin::create(url, m_frame->loader()->sandboxFlags())); 4503 4504 if (SecurityOrigin::allowSubstituteDataAccessToLocal()) { 4505 // If this document was loaded with substituteData, then the document can 4506 // load local resources. See https://bugs.webkit.org/show_bug.cgi?id=16756 4507 // and https://bugs.webkit.org/show_bug.cgi?id=19760 for further 4508 // discussion. 4509 DocumentLoader* documentLoader = m_frame->loader()->documentLoader(); 4510 if (documentLoader && documentLoader->substituteData().isValid()) 4511 securityOrigin()->grantLoadLocalResources(); 4512 } 4513 4514 if (Settings* settings = this->settings()) { 4515 if (!settings->isWebSecurityEnabled()) { 4516 // Web security is turned off. We should let this document access every 4517 // other document. This is used primary by testing harnesses for web 4518 // sites. 4519 securityOrigin()->grantUniversalAccess(); 4520 4521 } else if (settings->allowUniversalAccessFromFileURLs() && securityOrigin()->isLocal()) { 4522 // Some clients want file:// URLs to have universal access, but that 4523 // setting is dangerous for other clients. 4524 securityOrigin()->grantUniversalAccess(); 4525 } 4526 } 4527 4528 if (!securityOrigin()->isEmpty()) 4529 return; 4530 4531 // If we do not obtain a meaningful origin from the URL, then we try to 4532 // find one via the frame hierarchy. 4533 4534 Frame* ownerFrame = m_frame->tree()->parent(); 4535 if (!ownerFrame) 4536 ownerFrame = m_frame->loader()->opener(); 4537 4538 if (ownerFrame) { 4539 m_cookieURL = ownerFrame->document()->cookieURL(); 4540 // We alias the SecurityOrigins to match Firefox, see Bug 15313 4541 // https://bugs.webkit.org/show_bug.cgi?id=15313 4542 ScriptExecutionContext::setSecurityOrigin(ownerFrame->document()->securityOrigin()); 4543 } 4544 } 4545 4546 void Document::setSecurityOrigin(SecurityOrigin* securityOrigin) 4547 { 4548 ScriptExecutionContext::setSecurityOrigin(securityOrigin); 4549 // FIXME: Find a better place to enable DNS prefetch, which is a loader concept, 4550 // not applicable to arbitrary documents. 4551 initDNSPrefetch(); 4552 } 4553 4554 #if ENABLE(DATABASE) 4555 4556 bool Document::isDatabaseReadOnly() const 4557 { 4558 if (!page() || page()->settings()->privateBrowsingEnabled()) 4559 return true; 4560 return false; 4561 } 4562 4563 void Document::databaseExceededQuota(const String& name) 4564 { 4565 Page* currentPage = page(); 4566 if (currentPage) 4567 currentPage->chrome()->client()->exceededDatabaseQuota(document()->frame(), name); 4568 } 4569 4570 #endif 4571 4572 bool Document::isContextThread() const 4573 { 4574 return isMainThread(); 4575 } 4576 4577 void Document::updateURLForPushOrReplaceState(const KURL& url) 4578 { 4579 Frame* f = frame(); 4580 if (!f) 4581 return; 4582 4583 setURL(url); 4584 f->loader()->documentLoader()->replaceRequestURLForSameDocumentNavigation(url); 4585 } 4586 4587 void Document::statePopped(SerializedScriptValue* stateObject) 4588 { 4589 Frame* f = frame(); 4590 if (!f) 4591 return; 4592 4593 if (f->loader()->isComplete()) 4594 dispatchWindowEvent(PopStateEvent::create(stateObject)); 4595 else 4596 m_pendingStateObject = stateObject; 4597 } 4598 4599 void Document::updateFocusAppearanceSoon(bool restorePreviousSelection) 4600 { 4601 m_updateFocusAppearanceRestoresSelection = restorePreviousSelection; 4602 if (!m_updateFocusAppearanceTimer.isActive()) 4603 m_updateFocusAppearanceTimer.startOneShot(0); 4604 } 4605 4606 void Document::cancelFocusAppearanceUpdate() 4607 { 4608 m_updateFocusAppearanceTimer.stop(); 4609 } 4610 4611 void Document::updateFocusAppearanceTimerFired(Timer<Document>*) 4612 { 4613 Node* node = focusedNode(); 4614 if (!node) 4615 return; 4616 if (!node->isElementNode()) 4617 return; 4618 4619 updateLayout(); 4620 4621 Element* element = static_cast<Element*>(node); 4622 if (element->isFocusable()) 4623 element->updateFocusAppearance(m_updateFocusAppearanceRestoresSelection); 4624 } 4625 4626 void Document::executeScriptSoonTimerFired(Timer<Document>* timer) 4627 { 4628 ASSERT_UNUSED(timer, timer == &m_executeScriptSoonTimer); 4629 4630 Vector<pair<ScriptElementData*, CachedResourceHandle<CachedScript> > > scripts; 4631 scripts.swap(m_scriptsToExecuteSoon); 4632 size_t size = scripts.size(); 4633 for (size_t i = 0; i < size; ++i) { 4634 scripts[i].first->execute(scripts[i].second.get()); 4635 scripts[i].first->element()->deref(); // Balances ref() in executeScriptSoon(). 4636 } 4637 } 4638 4639 void Document::executeScriptSoon(ScriptElementData* data, CachedResourceHandle<CachedScript> cachedScript) 4640 { 4641 ASSERT_ARG(data, data); 4642 4643 Element* element = data->element(); 4644 ASSERT(element); 4645 ASSERT(element->document() == this); 4646 ASSERT(element->inDocument()); 4647 4648 m_scriptsToExecuteSoon.append(make_pair(data, cachedScript)); 4649 element->ref(); // Balanced by deref()s in executeScriptSoonTimerFired() and ~Document(). 4650 if (!m_executeScriptSoonTimer.isActive()) 4651 m_executeScriptSoonTimer.startOneShot(0); 4652 } 4653 4654 // FF method for accessing the selection added for compatibility. 4655 DOMSelection* Document::getSelection() const 4656 { 4657 return frame() ? frame()->domWindow()->getSelection() : 0; 4658 } 4659 4660 #if ENABLE(WML) 4661 void Document::resetWMLPageState() 4662 { 4663 if (WMLPageState* pageState = wmlPageStateForDocument(this)) 4664 pageState->reset(); 4665 } 4666 4667 void Document::initializeWMLPageState() 4668 { 4669 if (!isWMLDocument()) 4670 return; 4671 4672 static_cast<WMLDocument*>(this)->initialize(); 4673 } 4674 #endif 4675 4676 void Document::attachRange(Range* range) 4677 { 4678 ASSERT(!m_ranges.contains(range)); 4679 m_ranges.add(range); 4680 } 4681 4682 void Document::detachRange(Range* range) 4683 { 4684 // We don't ASSERT m_ranges.contains(range) to allow us to call this 4685 // unconditionally to fix: https://bugs.webkit.org/show_bug.cgi?id=26044 4686 m_ranges.remove(range); 4687 } 4688 4689 CanvasRenderingContext* Document::getCSSCanvasContext(const String& type, const String& name, int width, int height) 4690 { 4691 HTMLCanvasElement* result = getCSSCanvasElement(name); 4692 if (!result) 4693 return 0; 4694 result->setSize(IntSize(width, height)); 4695 return result->getContext(type); 4696 } 4697 4698 HTMLCanvasElement* Document::getCSSCanvasElement(const String& name) 4699 { 4700 RefPtr<HTMLCanvasElement> result = m_cssCanvasElements.get(name).get(); 4701 if (!result) { 4702 result = new HTMLCanvasElement(canvasTag, this); 4703 m_cssCanvasElements.set(name, result); 4704 } 4705 return result.get(); 4706 } 4707 4708 void Document::initDNSPrefetch() 4709 { 4710 m_haveExplicitlyDisabledDNSPrefetch = false; 4711 m_isDNSPrefetchEnabled = securityOrigin()->protocol() == "http"; 4712 4713 // Inherit DNS prefetch opt-out from parent frame 4714 if (Document* parent = parentDocument()) { 4715 if (!parent->isDNSPrefetchEnabled()) 4716 m_isDNSPrefetchEnabled = false; 4717 } 4718 } 4719 4720 void Document::parseDNSPrefetchControlHeader(const String& dnsPrefetchControl) 4721 { 4722 if (equalIgnoringCase(dnsPrefetchControl, "on") && !m_haveExplicitlyDisabledDNSPrefetch) { 4723 m_isDNSPrefetchEnabled = true; 4724 return; 4725 } 4726 4727 m_isDNSPrefetchEnabled = false; 4728 m_haveExplicitlyDisabledDNSPrefetch = true; 4729 } 4730 4731 void Document::reportException(const String& errorMessage, int lineNumber, const String& sourceURL) 4732 { 4733 if (DOMWindow* window = domWindow()) 4734 window->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, errorMessage, lineNumber, sourceURL); 4735 } 4736 4737 void Document::addMessage(MessageDestination destination, MessageSource source, MessageType type, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL) 4738 { 4739 switch (destination) { 4740 #if ENABLE(INSPECTOR) 4741 case InspectorControllerDestination: 4742 if (page()) 4743 page()->inspectorController()->addMessageToConsole(source, type, level, message, lineNumber, sourceURL); 4744 return; 4745 #endif 4746 case ConsoleDestination: 4747 if (DOMWindow* window = domWindow()) 4748 window->console()->addMessage(source, type, level, message, lineNumber, sourceURL); 4749 return; 4750 } 4751 ASSERT_NOT_REACHED(); 4752 } 4753 4754 void Document::resourceRetrievedByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString) 4755 { 4756 #if ENABLE(INSPECTOR) 4757 if (page()) 4758 page()->inspectorController()->resourceRetrievedByXMLHttpRequest(identifier, sourceString); 4759 #endif 4760 Frame* frame = this->frame(); 4761 if (frame) { 4762 FrameLoader* frameLoader = frame->loader(); 4763 frameLoader->notifier()->didLoadResourceByXMLHttpRequest(identifier, sourceString); 4764 } 4765 } 4766 4767 void Document::scriptImported(unsigned long identifier, const String& sourceString) 4768 { 4769 #if ENABLE(INSPECTOR) 4770 if (page()) 4771 page()->inspectorController()->scriptImported(identifier, sourceString); 4772 #else 4773 UNUSED_PARAM(identifier); 4774 UNUSED_PARAM(sourceString); 4775 #endif 4776 } 4777 4778 class ScriptExecutionContextTaskTimer : public TimerBase { 4779 public: 4780 ScriptExecutionContextTaskTimer(PassRefPtr<Document> context, PassOwnPtr<ScriptExecutionContext::Task> task) 4781 : m_context(context) 4782 , m_task(task) 4783 { 4784 } 4785 4786 private: 4787 virtual void fired() 4788 { 4789 m_task->performTask(m_context.get()); 4790 delete this; 4791 } 4792 4793 RefPtr<Document> m_context; 4794 OwnPtr<ScriptExecutionContext::Task> m_task; 4795 }; 4796 4797 struct PerformTaskContext : Noncopyable { 4798 PerformTaskContext(PassRefPtr<DocumentWeakReference> documentReference, PassOwnPtr<ScriptExecutionContext::Task> task) 4799 : documentReference(documentReference) 4800 , task(task) 4801 { 4802 } 4803 4804 RefPtr<DocumentWeakReference> documentReference; 4805 OwnPtr<ScriptExecutionContext::Task> task; 4806 }; 4807 4808 static void performTask(void* ctx) 4809 { 4810 ASSERT(isMainThread()); 4811 4812 PerformTaskContext* context = reinterpret_cast<PerformTaskContext*>(ctx); 4813 ASSERT(context); 4814 4815 if (Document* document = context->documentReference->document()) 4816 context->task->performTask(document); 4817 4818 delete context; 4819 } 4820 4821 void Document::postTask(PassOwnPtr<Task> task) 4822 { 4823 if (isMainThread()) { 4824 ScriptExecutionContextTaskTimer* timer = new ScriptExecutionContextTaskTimer(static_cast<Document*>(this), task); 4825 timer->startOneShot(0); 4826 } else { 4827 callOnMainThread(performTask, new PerformTaskContext(m_weakReference, task)); 4828 } 4829 } 4830 4831 Element* Document::findAnchor(const String& name) 4832 { 4833 if (name.isEmpty()) 4834 return 0; 4835 if (Element* element = getElementById(name)) 4836 return element; 4837 for (Node* node = this; node; node = node->traverseNextNode()) { 4838 if (node->hasTagName(aTag)) { 4839 HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(node); 4840 if (inCompatMode()) { 4841 // Quirks mode, case insensitive comparison of names. 4842 if (equalIgnoringCase(anchor->name(), name)) 4843 return anchor; 4844 } else { 4845 // Strict mode, names need to match exactly. 4846 if (anchor->name() == name) 4847 return anchor; 4848 } 4849 } 4850 } 4851 return 0; 4852 } 4853 4854 String Document::displayStringModifiedByEncoding(const String& str) const 4855 { 4856 if (m_decoder) 4857 return m_decoder->encoding().displayString(str.impl()); 4858 return str; 4859 } 4860 4861 PassRefPtr<StringImpl> Document::displayStringModifiedByEncoding(PassRefPtr<StringImpl> str) const 4862 { 4863 if (m_decoder) 4864 return m_decoder->encoding().displayString(str); 4865 return str; 4866 } 4867 4868 void Document::displayBufferModifiedByEncoding(UChar* buffer, unsigned len) const 4869 { 4870 if (m_decoder) 4871 m_decoder->encoding().displayBuffer(buffer, len); 4872 } 4873 4874 #if ENABLE(XHTMLMP) 4875 bool Document::isXHTMLMPDocument() const 4876 { 4877 if (!frame() || !frame()->loader()) 4878 return false; 4879 // As per section 7.2 of OMA-WAP-XHTMLMP-V1_1-20061020-A.pdf, a conforming user agent 4880 // MUST accept XHTMLMP document identified as "application/vnd.wap.xhtml+xml" 4881 // and SHOULD accept it identified as "application/xhtml+xml" 4882 return frame()->loader()->responseMIMEType() == "application/vnd.wap.xhtml+xml" || frame()->loader()->responseMIMEType() == "application/xhtml+xml"; 4883 } 4884 #endif 4885 4886 #if ENABLE(INSPECTOR) 4887 InspectorTimelineAgent* Document::inspectorTimelineAgent() const 4888 { 4889 return page() ? page()->inspectorTimelineAgent() : 0; 4890 } 4891 #endif 4892 4893 } // namespace WebCore 4894