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