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-2015 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, 2011, 2012 Google Inc. All rights reserved.
9 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
10 * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved.
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Library General Public
14 * License as published by the Free Software Foundation; either
15 * version 2 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Library General Public License for more details.
22 * You should have received a copy of the GNU Library General Public License
23 * along with this library; see the file COPYING.LIB. If not, write to
24 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 * Boston, MA 02110-1301, USA.
31 #include "AXObjectCache.h"
32 #include "AnimationController.h"
34 #include "AuthorStyleSheets.h"
35 #include "CDATASection.h"
36 #include "CSSFontSelector.h"
37 #include "CSSStyleDeclaration.h"
38 #include "CSSStyleSheet.h"
39 #include "CachedCSSStyleSheet.h"
40 #include "CachedResourceLoader.h"
42 #include "ChromeClient.h"
44 #include "CompositionEvent.h"
45 #include "ContentSecurityPolicy.h"
46 #include "CookieJar.h"
47 #include "CustomElementDefinitions.h"
48 #include "CustomEvent.h"
49 #include "DOMImplementation.h"
50 #include "DOMNamedFlowCollection.h"
51 #include "DOMWindow.h"
52 #include "DateComponents.h"
53 #include "DebugPageOverlays.h"
54 #include "Dictionary.h"
55 #include "DocumentLoader.h"
56 #include "DocumentMarkerController.h"
57 #include "DocumentSharedObjectPool.h"
58 #include "DocumentType.h"
60 #include "ElementIterator.h"
61 #include "EntityReference.h"
62 #include "EventHandler.h"
63 #include "ExtensionStyleSheets.h"
64 #include "FocusController.h"
65 #include "FontLoader.h"
66 #include "FormController.h"
67 #include "FrameLoader.h"
68 #include "FrameLoaderClient.h"
69 #include "FrameView.h"
70 #include "GenericCachedHTMLCollection.h"
71 #include "HTMLAllCollection.h"
72 #include "HTMLAnchorElement.h"
73 #include "HTMLBaseElement.h"
74 #include "HTMLBodyElement.h"
75 #include "HTMLCanvasElement.h"
76 #include "HTMLDocument.h"
77 #include "HTMLElementFactory.h"
78 #include "HTMLFormControlElement.h"
79 #include "HTMLFrameOwnerElement.h"
80 #include "HTMLFrameSetElement.h"
81 #include "HTMLHeadElement.h"
82 #include "HTMLIFrameElement.h"
83 #include "HTMLImageElement.h"
84 #include "HTMLLinkElement.h"
85 #include "HTMLMediaElement.h"
86 #include "HTMLNameCollection.h"
87 #include "HTMLParserIdioms.h"
88 #include "HTMLPictureElement.h"
89 #include "HTMLPlugInElement.h"
90 #include "HTMLScriptElement.h"
91 #include "HTMLStyleElement.h"
92 #include "HTMLTitleElement.h"
93 #include "HTMLUnknownElement.h"
94 #include "HTTPHeaderNames.h"
95 #include "HTTPParsers.h"
96 #include "HashChangeEvent.h"
98 #include "HitTestResult.h"
99 #include "IconController.h"
100 #include "ImageLoader.h"
101 #include "InspectorInstrumentation.h"
102 #include "JSLazyEventListener.h"
103 #include "JSModuleLoader.h"
104 #include "KeyboardEvent.h"
105 #include "Language.h"
106 #include "LoaderStrategy.h"
108 #include "MainFrame.h"
109 #include "MediaCanStartListener.h"
110 #include "MediaProducer.h"
111 #include "MediaQueryList.h"
112 #include "MediaQueryMatcher.h"
113 #include "MessageEvent.h"
114 #include "MouseEventWithHitTestResults.h"
115 #include "MutationEvent.h"
116 #include "NameNodeList.h"
117 #include "NestingLevelIncrementer.h"
118 #include "NodeIterator.h"
119 #include "NodeRareData.h"
120 #include "NodeWithIndex.h"
121 #include "OverflowEvent.h"
122 #include "PageConsoleClient.h"
123 #include "PageGroup.h"
124 #include "PageTransitionEvent.h"
125 #include "PlatformLocale.h"
126 #include "PlatformMediaSessionManager.h"
127 #include "PlatformStrategies.h"
128 #include "PlugInsResources.h"
129 #include "PluginDocument.h"
130 #include "PointerLockController.h"
131 #include "PopStateEvent.h"
132 #include "ProcessingInstruction.h"
133 #include "RenderChildIterator.h"
134 #include "RenderLayerCompositor.h"
135 #include "RenderView.h"
136 #include "RenderWidget.h"
137 #include "ResourceLoadObserver.h"
138 #include "RuntimeEnabledFeatures.h"
139 #include "SVGDocumentExtensions.h"
140 #include "SVGElement.h"
141 #include "SVGElementFactory.h"
142 #include "SVGNames.h"
143 #include "SVGTitleElement.h"
144 #include "SVGZoomEvent.h"
145 #include "SchemeRegistry.h"
146 #include "ScopedEventQueue.h"
147 #include "ScriptController.h"
148 #include "ScriptRunner.h"
149 #include "ScriptSourceCode.h"
150 #include "ScrollingCoordinator.h"
151 #include "SecurityOrigin.h"
152 #include "SecurityOriginPolicy.h"
153 #include "SecurityPolicy.h"
154 #include "SegmentedString.h"
155 #include "SelectorQuery.h"
156 #include "Settings.h"
157 #include "ShadowRoot.h"
158 #include "StorageEvent.h"
159 #include "StyleProperties.h"
160 #include "StyleResolveForDocument.h"
161 #include "StyleResolver.h"
162 #include "StyleSheetContents.h"
163 #include "StyleSheetList.h"
164 #include "StyleTreeResolver.h"
165 #include "SubresourceLoader.h"
166 #include "TextEvent.h"
167 #include "TextNodeTraversal.h"
168 #include "TransformSource.h"
169 #include "TreeWalker.h"
170 #include "VisitedLinkState.h"
171 #include "WheelEvent.h"
172 #include "WindowFeatures.h"
173 #include "XMLDocument.h"
174 #include "XMLDocumentParser.h"
175 #include "XMLNSNames.h"
176 #include "XMLNames.h"
177 #include "XPathEvaluator.h"
178 #include "XPathExpression.h"
179 #include "XPathNSResolver.h"
180 #include "XPathResult.h"
181 #include "htmlediting.h"
182 #include <JavaScriptCore/Profile.h>
184 #include <inspector/ScriptCallStack.h>
185 #include <wtf/CurrentTime.h>
186 #include <wtf/NeverDestroyed.h>
187 #include <wtf/SystemTracing.h>
188 #include <wtf/TemporaryChange.h>
189 #include <wtf/text/StringBuffer.h>
190 #include <yarr/RegularExpression.h>
193 #include "DOMSecurityPolicy.h"
196 #if ENABLE(DEVICE_ORIENTATION)
197 #include "DeviceMotionEvent.h"
198 #include "DeviceOrientationEvent.h"
201 #if ENABLE(FULLSCREEN_API)
202 #include "RenderFullScreen.h"
206 #include "CSSFontSelector.h"
207 #include "DeviceMotionClientIOS.h"
208 #include "DeviceMotionController.h"
209 #include "DeviceOrientationClientIOS.h"
210 #include "DeviceOrientationController.h"
211 #include "Geolocation.h"
212 #include "Navigator.h"
213 #include "NavigatorGeolocation.h"
214 #include "WKContentObservation.h"
215 #include "WebCoreSystemInterface.h"
218 #if ENABLE(IOS_GESTURE_EVENTS)
219 #include "GestureEvent.h"
222 #if ENABLE(IOS_TEXT_AUTOSIZING)
223 #include "TextAutoSizing.h"
227 #include "MathMLElement.h"
228 #include "MathMLElementFactory.h"
229 #include "MathMLNames.h"
232 #if ENABLE(MEDIA_SESSION)
233 #include "MediaSession.h"
236 #if ENABLE(REQUEST_ANIMATION_FRAME)
237 #include "RequestAnimationFrameCallback.h"
238 #include "ScriptedAnimationController.h"
241 #if ENABLE(TEXT_AUTOSIZING)
242 #include "TextAutosizer.h"
245 #if ENABLE(TOUCH_EVENTS)
246 #include "TouchEvent.h"
247 #include "TouchList.h"
250 #if ENABLE(VIDEO_TRACK)
251 #include "CaptionUserPreferences.h"
254 #if ENABLE(WEB_REPLAY)
255 #include "WebReplayInputs.h"
256 #include <replay/EmptyInputCursor.h>
257 #include <replay/InputCursor.h>
260 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
261 #include "MediaPlaybackTargetClient.h"
265 #include "XSLTProcessor.h"
269 using namespace Unicode;
273 using namespace HTMLNames;
275 // #define INSTRUMENT_LAYOUT_SCHEDULING 1
277 static const unsigned cMaxWriteRecursionDepth = 21;
279 // DOM Level 2 says (letters added):
281 // a) Name start characters must have one of the categories Ll, Lu, Lo, Lt, Nl.
282 // b) Name characters other than Name-start characters must have one of the categories Mc, Me, Mn, Lm, or Nd.
283 // c) Characters in the compatibility area (i.e. with character code greater than #xF900 and less than #xFFFE) are not allowed in XML names.
284 // 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.
285 // 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.
286 // f) Characters #x20DD-#x20E0 are excluded (in accordance with Unicode, section 5.14).
287 // g) Character #x00B7 is classified as an extender, because the property list so identifies it.
288 // h) Character #x0387 is added as a name character, because #x00B7 is its canonical equivalent.
289 // i) Characters ':' and '_' are allowed as name-start characters.
290 // j) Characters '-' and '.' are allowed as name characters.
292 // It also contains complete tables. If we decide it's better, we could include those instead of the following code.
294 static inline bool isValidNameStart(UChar32 c)
297 if ((c >= 0x02BB && c <= 0x02C1) || c == 0x559 || c == 0x6E5 || c == 0x6E6)
301 if (c == ':' || c == '_')
304 // rules (a) and (f) above
305 if (!(U_GET_GC_MASK(c) & (U_GC_LL_MASK | U_GC_LU_MASK | U_GC_LO_MASK | U_GC_LT_MASK | U_GC_NL_MASK)))
309 if (c >= 0xF900 && c < 0xFFFE)
313 int type = u_getIntPropertyValue(c, UCHAR_DECOMPOSITION_TYPE);
314 if (type == U_DT_FONT || type == U_DT_COMPAT)
320 static inline bool isValidNamePart(UChar32 c)
322 // rules (a), (e), and (i) above
323 if (isValidNameStart(c))
326 // rules (g) and (h) above
327 if (c == 0x00B7 || c == 0x0387)
331 if (c == '-' || c == '.')
334 // rules (b) and (f) above
335 if (!(U_GET_GC_MASK(c) & (U_GC_M_MASK | U_GC_LM_MASK | U_GC_ND_MASK)))
339 if (c >= 0xF900 && c < 0xFFFE)
343 int type = u_getIntPropertyValue(c, UCHAR_DECOMPOSITION_TYPE);
344 if (type == U_DT_FONT || type == U_DT_COMPAT)
350 static bool shouldInheritSecurityOriginFromOwner(const URL& url)
352 // http://www.whatwg.org/specs/web-apps/current-work/#origin-0
354 // If a Document has the address "about:blank"
355 // The origin of the Document is the origin it was assigned when its browsing context was created.
357 // Note: We generalize this to all "blank" URLs and invalid URLs because we
358 // treat all of these URLs as about:blank.
360 return url.isEmpty() || url.isBlankURL();
363 static Widget* widgetForElement(Element* focusedElement)
367 auto* renderer = focusedElement->renderer();
368 if (!is<RenderWidget>(renderer))
370 return downcast<RenderWidget>(*renderer).widget();
373 static bool acceptsEditingFocus(Node* node)
376 ASSERT(node->hasEditableStyle());
378 Node* root = node->rootEditableElement();
379 Frame* frame = node->document().frame();
383 return frame->editor().shouldBeginEditing(rangeOfContents(*root).ptr());
386 static bool canAccessAncestor(const SecurityOrigin* activeSecurityOrigin, Frame* targetFrame)
388 // targetFrame can be 0 when we're trying to navigate a top-level frame
389 // that has a 0 opener.
393 const bool isLocalActiveOrigin = activeSecurityOrigin->isLocal();
394 for (Frame* ancestorFrame = targetFrame; ancestorFrame; ancestorFrame = ancestorFrame->tree().parent()) {
395 Document* ancestorDocument = ancestorFrame->document();
396 // FIXME: Should be an ASSERT? Frames should alway have documents.
397 if (!ancestorDocument)
400 const SecurityOrigin* ancestorSecurityOrigin = ancestorDocument->securityOrigin();
401 if (activeSecurityOrigin->canAccess(ancestorSecurityOrigin))
404 // Allow file URL descendant navigation even when allowFileAccessFromFileURLs is false.
405 // FIXME: It's a bit strange to special-case local origins here. Should we be doing
406 // something more general instead?
407 if (isLocalActiveOrigin && ancestorSecurityOrigin->isLocal())
414 static void printNavigationErrorMessage(Frame* frame, const URL& activeURL, const char* reason)
416 String message = "Unsafe JavaScript attempt to initiate navigation for frame with URL '" + frame->document()->url().string() + "' from frame with URL '" + activeURL.string() + "'. " + reason + "\n";
418 // FIXME: should we print to the console of the document performing the navigation instead?
419 frame->document()->domWindow()->printErrorMessage(message);
422 uint64_t Document::s_globalTreeVersion = 0;
424 #if ENABLE(IOS_TEXT_AUTOSIZING)
425 void TextAutoSizingTraits::constructDeletedValue(TextAutoSizingKey& slot)
427 new (&slot) TextAutoSizingKey(TextAutoSizingKey::deletedKeyStyle(), TextAutoSizingKey::deletedKeyDoc());
430 bool TextAutoSizingTraits::isDeletedValue(const TextAutoSizingKey& value)
432 return value.style() == TextAutoSizingKey::deletedKeyStyle() && value.doc() == TextAutoSizingKey::deletedKeyDoc();
436 HashSet<Document*>& Document::allDocuments()
438 static NeverDestroyed<HashSet<Document*>> documents;
442 Document::Document(Frame* frame, const URL& url, unsigned documentClasses, unsigned constructionFlags)
443 : ContainerNode(*this, CreateDocument)
445 #if ENABLE(IOS_TOUCH_EVENTS)
446 , m_handlingTouchEvent(false)
447 , m_touchEventRegionsDirty(false)
448 , m_touchEventsChangedTimer(*this, &Document::touchEventsChangedTimerFired)
450 , m_referencingNodeCount(0)
451 , m_didCalculateStyleResolver(false)
452 , m_hasNodesWithPlaceholderStyle(false)
453 , m_needsNotifyRemoveAllPendingStylesheet(false)
454 , m_ignorePendingStylesheets(false)
455 , m_pendingSheetLayout(NoLayoutWithPendingSheets)
457 , m_cachedResourceLoader(m_frame ? Ref<CachedResourceLoader>(m_frame->loader().activeDocumentLoader()->cachedResourceLoader()) : CachedResourceLoader::create(nullptr))
458 , m_activeParserCount(0)
459 , m_wellFormed(false)
461 , m_paginatedForScreen(false)
462 , m_compatibilityMode(DocumentCompatibilityMode::NoQuirksMode)
463 , m_compatibilityModeLocked(false)
464 , m_textColor(Color::black)
465 , m_domTreeVersion(++s_globalTreeVersion)
467 , m_mutationObserverTypes(0)
468 , m_authorStyleSheets(std::make_unique<AuthorStyleSheets>(*this))
469 , m_extensionStyleSheets(std::make_unique<ExtensionStyleSheets>(*this))
470 , m_visitedLinkState(std::make_unique<VisitedLinkState>(*this))
471 , m_visuallyOrdered(false)
472 , m_readyState(Complete)
474 , m_optimizedStyleSheetUpdateTimer(*this, &Document::optimizedStyleSheetUpdateTimerFired)
475 , m_styleRecalcTimer(*this, &Document::updateStyleIfNeeded)
476 , m_pendingStyleRecalcShouldForce(false)
477 , m_inStyleRecalc(false)
478 , m_closeAfterStyleRecalc(false)
479 , m_gotoAnchorNeededAfterStylesheetsLoad(false)
480 , m_frameElementsShouldIgnoreScrolling(false)
481 , m_updateFocusAppearanceRestoresSelection(SelectionRestorationMode::SetDefault)
482 , m_markers(std::make_unique<DocumentMarkerController>(*this))
483 , m_updateFocusAppearanceTimer(*this, &Document::updateFocusAppearanceTimerFired)
484 , m_cssTarget(nullptr)
485 , m_processingLoadEvent(false)
486 , m_loadEventFinished(false)
487 , m_startTime(std::chrono::steady_clock::now())
488 , m_overMinimumLayoutThreshold(false)
489 , m_scriptRunner(std::make_unique<ScriptRunner>(*this))
490 , m_moduleLoader(std::make_unique<JSModuleLoader>(*this))
491 , m_xmlVersion(ASCIILiteral("1.0"))
492 , m_xmlStandalone(StandaloneUnspecified)
493 , m_hasXMLDeclaration(false)
494 , m_designMode(inherit)
496 , m_inInvalidateNodeListAndCollectionCaches(false)
498 #if ENABLE(DASHBOARD_SUPPORT)
499 , m_hasAnnotatedRegions(false)
500 , m_annotatedRegionsDirty(false)
502 , m_createRenderers(true)
503 , m_inPageCache(false)
504 , m_accessKeyMapValid(false)
505 , m_documentClasses(documentClasses)
506 , m_isSynthesized(constructionFlags & Synthesized)
507 , m_isNonRenderedPlaceholder(constructionFlags & NonRenderedPlaceholder)
508 , m_sawElementsInKnownNamespaces(false)
509 , m_isSrcdocDocument(false)
510 , m_eventQueue(*this)
511 , m_weakFactory(this)
512 #if ENABLE(FULLSCREEN_API)
513 , m_areKeysEnabledInFullScreen(0)
514 , m_fullScreenRenderer(nullptr)
515 , m_fullScreenChangeDelayTimer(*this, &Document::fullScreenChangeDelayTimerFired)
516 , m_isAnimatingFullScreen(false)
518 , m_loadEventDelayCount(0)
519 , m_loadEventDelayTimer(*this, &Document::loadEventDelayTimerFired)
520 , m_referrerPolicy(ReferrerPolicyDefault)
521 , m_writeRecursionIsTooDeep(false)
522 , m_writeRecursionDepth(0)
523 , m_lastHandledUserGestureTimestamp(0)
525 #if ENABLE(DEVICE_ORIENTATION)
526 , m_deviceMotionClient(std::make_unique<DeviceMotionClientIOS>())
527 , m_deviceMotionController(std::make_unique<DeviceMotionController>(m_deviceMotionClient.get()))
528 , m_deviceOrientationClient(std::make_unique<DeviceOrientationClientIOS>())
529 , m_deviceOrientationController(std::make_unique<DeviceOrientationController>(m_deviceOrientationClient.get()))
532 #if ENABLE(TELEPHONE_NUMBER_DETECTION)
533 , m_isTelephoneNumberParsingAllowed(true)
535 , m_pendingTasksTimer(*this, &Document::pendingTasksTimerFired)
536 , m_scheduledTasksAreSuspended(false)
537 , m_visualUpdatesAllowed(true)
538 , m_visualUpdatesSuppressionTimer(*this, &Document::visualUpdatesSuppressionTimerFired)
539 , m_sharedObjectPoolClearTimer(*this, &Document::sharedObjectPoolClearTimerFired)
541 , m_didDispatchViewportPropertiesChanged(false)
543 #if ENABLE(TEMPLATE_ELEMENT)
544 , m_templateDocumentHost(nullptr)
546 #if ENABLE(WEB_REPLAY)
547 , m_inputCursor(EmptyInputCursor::create())
549 , m_didAssociateFormControlsTimer(*this, &Document::didAssociateFormControlsTimerFired)
550 , m_cookieCacheExpiryTimer(*this, &Document::invalidateDOMCookieCache)
551 , m_disabledFieldsetElementsCount(0)
552 , m_hasInjectedPlugInsScript(false)
553 , m_renderTreeBeingDestroyed(false)
554 , m_hasPreparedForDestruction(false)
555 , m_hasStyleWithViewportUnits(false)
557 allDocuments().add(this);
559 // We depend on the url getting immediately set in subframes, but we
560 // also depend on the url NOT getting immediately set in opened windows.
561 // See fast/dom/early-frame-url.html
562 // and fast/dom/location-new-window-no-crash.html, respectively.
563 // FIXME: Can/should we unify this behavior?
564 if ((frame && frame->ownerElement()) || !url.isEmpty())
567 m_cachedResourceLoader->setDocument(this);
569 #if ENABLE(TEXT_AUTOSIZING)
570 m_textAutosizer = std::make_unique<TextAutosizer>(this);
574 resetVisitedLinkColor();
575 resetActiveLinkColor();
577 initSecurityContext();
580 for (auto& nodeListAndCollectionCount : m_nodeListAndCollectionCounts)
581 nodeListAndCollectionCount = 0;
584 #if ENABLE(FULLSCREEN_API)
585 static bool isAttributeOnAllOwners(const WebCore::QualifiedName& attribute, const WebCore::QualifiedName& prefixedAttribute, const HTMLFrameOwnerElement* owner)
590 if (!(owner->hasAttribute(attribute) || owner->hasAttribute(prefixedAttribute)))
592 } while ((owner = owner->document().ownerElement()));
597 Ref<Document> Document::create(ScriptExecutionContext& context)
599 Ref<Document> document = adoptRef(*new Document(nullptr, URL()));
600 document->setSecurityOriginPolicy(context.securityOriginPolicy());
605 Document::~Document()
607 allDocuments().remove(this);
609 ASSERT(!renderView());
610 ASSERT(!m_inPageCache);
611 ASSERT(m_ranges.isEmpty());
612 ASSERT(!m_parentTreeScope);
613 ASSERT(!m_disabledFieldsetElementsCount);
615 #if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS)
616 m_deviceMotionClient->deviceMotionControllerDestroyed();
617 m_deviceOrientationClient->deviceOrientationControllerDestroyed();
620 #if ENABLE(TEMPLATE_ELEMENT)
621 if (m_templateDocument)
622 m_templateDocument->setTemplateDocumentHost(nullptr); // balanced in templateDocument().
625 // FIXME: Should we reset m_domWindow when we detach from the Frame?
627 m_domWindow->resetUnlessSuspendedForDocumentSuspension();
629 m_scriptRunner = nullptr;
630 m_moduleLoader = nullptr;
632 removeAllEventListeners();
634 // Currently we believe that Document can never outlive the parser.
635 // Although the Document may be replaced synchronously, DocumentParsers
636 // generally keep at least one reference to an Element which would in turn
637 // has a reference to the Document. If you hit this ASSERT, then that
638 // assumption is wrong. DocumentParser::detach() should ensure that even
639 // if the DocumentParser outlives the Document it won't cause badness.
640 ASSERT(!m_parser || m_parser->refCount() == 1);
643 if (this == &topDocument())
644 clearAXObjectCache();
648 if (m_styleSheetList)
649 m_styleSheetList->detachFromDocument();
652 m_elementSheet->detachFromDocument();
653 extensionStyleSheets().detachFromDocument();
655 clearStyleResolver(); // We need to destroy CSSFontSelector before destroying m_cachedResourceLoader.
657 // It's possible for multiple Documents to end up referencing the same CachedResourceLoader (e.g., SVGImages
658 // load the initial empty document and the SVGDocument with the same DocumentLoader).
659 if (m_cachedResourceLoader->document() == this)
660 m_cachedResourceLoader->setDocument(nullptr);
663 if (auto* platformMediaSessionManager = PlatformMediaSessionManager::sharedManagerIfExists())
664 platformMediaSessionManager->stopAllMediaPlaybackForDocument(this);
667 // We must call clearRareData() here since a Document class inherits TreeScope
668 // as well as Node. See a comment on TreeScope.h for the reason.
672 ASSERT(!m_listsInvalidatedAtDocument.size());
673 ASSERT(!m_collectionsInvalidatedAtDocument.size());
675 for (unsigned i = 0; i < WTF_ARRAY_LENGTH(m_nodeListAndCollectionCounts); ++i)
676 ASSERT(!m_nodeListAndCollectionCounts[i]);
679 void Document::removedLastRef()
681 ASSERT(!m_deletionHasBegun);
682 if (m_referencingNodeCount) {
683 // If removing a child removes the last node reference, we don't want the scope to be destroyed
684 // until after removeDetachedChildren returns, so we protect ourselves.
685 incrementReferencingNodeCount();
687 // We must make sure not to be retaining any of our children through
688 // these extra pointers or we will create a reference cycle.
689 m_focusedElement = nullptr;
690 m_hoveredElement = nullptr;
691 m_activeElement = nullptr;
692 m_titleElement = nullptr;
693 m_documentElement = nullptr;
694 m_userActionElements.documentDidRemoveLastRef();
695 #if ENABLE(FULLSCREEN_API)
696 m_fullScreenElement = nullptr;
697 m_fullScreenElementStack.clear();
702 // removeDetachedChildren() doesn't always unregister IDs,
703 // so tear down scope information up front to avoid having
704 // stale references in the map.
706 destroyTreeScopeData();
707 removeDetachedChildren();
708 m_formController = nullptr;
712 m_cssCanvasElements.clear();
717 // We need to do this right now since selfOnlyDeref() can delete this.
718 m_inRemovedLastRefFunction = false;
720 decrementReferencingNodeCount();
723 m_inRemovedLastRefFunction = false;
724 m_deletionHasBegun = true;
730 void Document::commonTeardown()
733 accessSVGExtensions().pauseAnimations();
735 #if ENABLE(REQUEST_ANIMATION_FRAME)
736 clearScriptedAnimationController();
740 Element* Document::getElementByAccessKey(const String& key)
744 if (!m_accessKeyMapValid) {
745 buildAccessKeyMap(this);
746 m_accessKeyMapValid = true;
748 return m_elementsByAccessKey.get(key.impl());
751 void Document::buildAccessKeyMap(TreeScope* scope)
754 for (auto& element : descendantsOfType<Element>(scope->rootNode())) {
755 const AtomicString& accessKey = element.fastGetAttribute(accesskeyAttr);
756 if (!accessKey.isEmpty())
757 m_elementsByAccessKey.set(accessKey.impl(), &element);
759 if (ShadowRoot* root = element.shadowRoot())
760 buildAccessKeyMap(root);
764 void Document::invalidateAccessKeyMap()
766 m_accessKeyMapValid = false;
767 m_elementsByAccessKey.clear();
770 void Document::addImageElementByCaseFoldedUsemap(const AtomicStringImpl& name, HTMLImageElement& element)
772 return m_imagesByUsemap.add(name, element, *this);
775 void Document::removeImageElementByCaseFoldedUsemap(const AtomicStringImpl& name, HTMLImageElement& element)
777 return m_imagesByUsemap.remove(name, element);
780 HTMLImageElement* Document::imageElementByCaseFoldedUsemap(const AtomicStringImpl& name) const
782 return m_imagesByUsemap.getElementByCaseFoldedUsemap(name, *this);
785 SelectorQuery* Document::selectorQueryForString(const String& selectorString, ExceptionCode& ec)
787 if (selectorString.isEmpty()) {
792 if (!m_selectorQueryCache)
793 m_selectorQueryCache = std::make_unique<SelectorQueryCache>();
794 return m_selectorQueryCache->add(selectorString, *this, ec);
797 void Document::clearSelectorQueryCache()
799 m_selectorQueryCache = nullptr;
802 MediaQueryMatcher& Document::mediaQueryMatcher()
804 if (!m_mediaQueryMatcher)
805 m_mediaQueryMatcher = MediaQueryMatcher::create(this);
806 return *m_mediaQueryMatcher;
809 void Document::setCompatibilityMode(DocumentCompatibilityMode mode)
811 if (m_compatibilityModeLocked || mode == m_compatibilityMode)
813 bool wasInQuirksMode = inQuirksMode();
814 m_compatibilityMode = mode;
816 clearSelectorQueryCache();
818 if (inQuirksMode() != wasInQuirksMode) {
819 // All user stylesheets have to reparse using the different mode.
820 extensionStyleSheets().clearPageUserSheet();
821 extensionStyleSheets().invalidateInjectedStyleSheetCache();
825 String Document::compatMode() const
827 return inQuirksMode() ? "BackCompat" : "CSS1Compat";
830 void Document::resetLinkColor()
832 m_linkColor = Color(0, 0, 238);
835 void Document::resetVisitedLinkColor()
837 m_visitedLinkColor = Color(85, 26, 139);
840 void Document::resetActiveLinkColor()
842 m_activeLinkColor.setNamedColor("red");
845 DOMImplementation& Document::implementation()
847 if (!m_implementation)
848 m_implementation = std::make_unique<DOMImplementation>(*this);
849 return *m_implementation;
852 bool Document::hasManifest() const
854 return documentElement() && documentElement()->hasTagName(htmlTag) && documentElement()->fastHasAttribute(manifestAttr);
857 DocumentType* Document::doctype() const
859 for (Node* node = firstChild(); node; node = node->nextSibling()) {
860 if (node->isDocumentTypeNode())
861 return static_cast<DocumentType*>(node);
866 void Document::childrenChanged(const ChildChange& change)
868 ContainerNode::childrenChanged(change);
871 // FIXME: Chrome::didReceiveDocType() used to be called only when the doctype changed. We need to check the
872 // impact of calling this systematically. If the overhead is negligible, we need to rename didReceiveDocType,
873 // otherwise, we need to detect the doc type changes before updating the viewport.
874 if (Page* page = this->page())
875 page->chrome().didReceiveDocType(frame());
878 Element* newDocumentElement = childrenOfType<Element>(*this).first();
879 if (newDocumentElement == m_documentElement)
881 m_documentElement = newDocumentElement;
882 // The root style used for media query matching depends on the document element.
883 clearStyleResolver();
886 static RefPtr<Element> createHTMLElementWithNameValidation(Document& document, const QualifiedName qualifiedName, ExceptionCode& ec)
888 RefPtr<HTMLElement> element = HTMLElementFactory::createKnownElement(qualifiedName, document);
892 #if ENABLE(CUSTOM_ELEMENTS)
893 auto* definitions = document.customElementDefinitions();
894 if (UNLIKELY(definitions)) {
895 if (auto* interface = definitions->findInterface(qualifiedName))
896 return interface->constructElement(qualifiedName.localName());
900 if (UNLIKELY(!Document::isValidName(qualifiedName.localName()))) {
901 ec = INVALID_CHARACTER_ERR;
905 return HTMLUnknownElement::create(qualifiedName, document);
908 RefPtr<Element> Document::createElementForBindings(const AtomicString& name, ExceptionCode& ec)
910 if (isHTMLDocument())
911 return createHTMLElementWithNameValidation(*this, QualifiedName(nullAtom, name.convertToASCIILowercase(), xhtmlNamespaceURI), ec);
913 if (isXHTMLDocument())
914 return createHTMLElementWithNameValidation(*this, QualifiedName(nullAtom, name, xhtmlNamespaceURI), ec);
916 if (!isValidName(name)) {
917 ec = INVALID_CHARACTER_ERR;
921 return createElement(QualifiedName(nullAtom, name, nullAtom), false);
924 Ref<DocumentFragment> Document::createDocumentFragment()
926 return DocumentFragment::create(document());
929 Ref<Text> Document::createTextNode(const String& data)
931 return Text::create(*this, data);
934 Ref<Comment> Document::createComment(const String& data)
936 return Comment::create(*this, data);
939 RefPtr<CDATASection> Document::createCDATASection(const String& data, ExceptionCode& ec)
941 if (isHTMLDocument()) {
942 ec = NOT_SUPPORTED_ERR;
945 return CDATASection::create(*this, data);
948 RefPtr<ProcessingInstruction> Document::createProcessingInstruction(const String& target, const String& data, ExceptionCode& ec)
950 if (!isValidName(target)) {
951 ec = INVALID_CHARACTER_ERR;
955 if (data.contains("?>")) {
956 ec = INVALID_CHARACTER_ERR;
960 return ProcessingInstruction::create(*this, target, data);
963 RefPtr<EntityReference> Document::createEntityReference(const String&, ExceptionCode& ec)
965 ec = NOT_SUPPORTED_ERR;
969 Ref<Text> Document::createEditingTextNode(const String& text)
971 return Text::createEditingText(*this, text);
974 Ref<CSSStyleDeclaration> Document::createCSSStyleDeclaration()
976 Ref<MutableStyleProperties> propertySet(MutableStyleProperties::create());
977 return *propertySet->ensureCSSStyleDeclaration();
980 RefPtr<Node> Document::importNode(Node* importedNode, bool deep, ExceptionCode& ec)
983 ec = NOT_SUPPORTED_ERR;
987 switch (importedNode->nodeType()) {
990 case CDATA_SECTION_NODE:
991 case PROCESSING_INSTRUCTION_NODE:
993 case DOCUMENT_FRAGMENT_NODE:
994 return importedNode->cloneNodeInternal(document(), deep ? CloningOperation::Everything : CloningOperation::OnlySelf);
997 // FIXME: This will "Attr::normalize" child nodes of Attr.
998 return Attr::create(*this, QualifiedName(nullAtom, downcast<Attr>(*importedNode).name(), nullAtom), downcast<Attr>(*importedNode).value());
1000 case DOCUMENT_NODE: // Can't import a document into another document.
1001 case DOCUMENT_TYPE_NODE: // FIXME: Support cloning a DocumentType node per DOM4.
1005 ec = NOT_SUPPORTED_ERR;
1010 RefPtr<Node> Document::adoptNode(Node* source, ExceptionCode& ec)
1013 ec = NOT_SUPPORTED_ERR;
1017 EventQueueScope scope;
1019 switch (source->nodeType()) {
1021 ec = NOT_SUPPORTED_ERR;
1023 case ATTRIBUTE_NODE: {
1024 Attr& attr = downcast<Attr>(*source);
1025 if (attr.ownerElement())
1026 attr.ownerElement()->removeAttributeNode(&attr, ec);
1030 if (source->isShadowRoot()) {
1031 // ShadowRoot cannot disconnect itself from the host node.
1032 ec = HIERARCHY_REQUEST_ERR;
1035 if (is<HTMLFrameOwnerElement>(*source)) {
1036 HTMLFrameOwnerElement& frameOwnerElement = downcast<HTMLFrameOwnerElement>(*source);
1037 if (frame() && frame()->tree().isDescendantOf(frameOwnerElement.contentFrame())) {
1038 ec = HIERARCHY_REQUEST_ERR;
1042 if (source->parentNode()) {
1043 source->parentNode()->removeChild(*source, ec);
1049 adoptIfNeeded(source);
1054 bool Document::hasValidNamespaceForElements(const QualifiedName& qName)
1056 // These checks are from DOM Core Level 2, createElementNS
1057 // http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-DocCrElNS
1058 if (!qName.prefix().isEmpty() && qName.namespaceURI().isNull()) // createElementNS(null, "html:div")
1060 if (qName.prefix() == xmlAtom && qName.namespaceURI() != XMLNames::xmlNamespaceURI) // createElementNS("http://www.example.com", "xml:lang")
1063 // Required by DOM Level 3 Core and unspecified by DOM Level 2 Core:
1064 // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-DocCrElNS
1065 // createElementNS("http://www.w3.org/2000/xmlns/", "foo:bar"), createElementNS(null, "xmlns:bar"), createElementNS(null, "xmlns")
1066 if (qName.prefix() == xmlnsAtom || (qName.prefix().isEmpty() && qName.localName() == xmlnsAtom))
1067 return qName.namespaceURI() == XMLNSNames::xmlnsNamespaceURI;
1068 return qName.namespaceURI() != XMLNSNames::xmlnsNamespaceURI;
1071 bool Document::hasValidNamespaceForAttributes(const QualifiedName& qName)
1073 return hasValidNamespaceForElements(qName);
1076 // FIXME: This should really be in a possible ElementFactory class.
1077 Ref<Element> Document::createElement(const QualifiedName& name, bool createdByParser)
1079 RefPtr<Element> element;
1081 // FIXME: Use registered namespaces and look up in a hash to find the right factory.
1082 if (name.namespaceURI() == xhtmlNamespaceURI)
1083 element = HTMLElementFactory::createElement(name, *this, nullptr, createdByParser);
1084 else if (name.namespaceURI() == SVGNames::svgNamespaceURI)
1085 element = SVGElementFactory::createElement(name, *this, createdByParser);
1087 else if (name.namespaceURI() == MathMLNames::mathmlNamespaceURI)
1088 element = MathMLElementFactory::createElement(name, *this, createdByParser);
1092 m_sawElementsInKnownNamespaces = true;
1094 element = Element::create(name, document());
1096 // <image> uses imgTag so we need a special rule.
1097 ASSERT((name.matches(imageTag) && element->tagQName().matches(imgTag) && element->tagQName().prefix() == name.prefix()) || name == element->tagQName());
1099 return element.releaseNonNull();
1102 bool Document::cssRegionsEnabled() const
1104 return RuntimeEnabledFeatures::sharedFeatures().cssRegionsEnabled();
1107 bool Document::cssCompositingEnabled() const
1109 return RuntimeEnabledFeatures::sharedFeatures().cssCompositingEnabled();
1112 #if ENABLE(CSS_REGIONS)
1114 RefPtr<DOMNamedFlowCollection> Document::webkitGetNamedFlows()
1116 if (!cssRegionsEnabled() || !renderView())
1119 updateStyleIfNeeded();
1121 return namedFlows().createCSSOMSnapshot();
1126 NamedFlowCollection& Document::namedFlows()
1129 m_namedFlows = NamedFlowCollection::create(this);
1131 return *m_namedFlows;
1134 RefPtr<Element> Document::createElementNS(const String& namespaceURI, const String& qualifiedName, ExceptionCode& ec)
1136 String prefix, localName;
1137 if (!parseQualifiedName(qualifiedName, prefix, localName, ec))
1140 QualifiedName qName(prefix, localName, namespaceURI);
1141 if (!hasValidNamespaceForElements(qName)) {
1146 return createElement(qName, false);
1149 String Document::readyState() const
1151 static NeverDestroyed<const String> loading(ASCIILiteral("loading"));
1152 static NeverDestroyed<const String> interactive(ASCIILiteral("interactive"));
1153 static NeverDestroyed<const String> complete(ASCIILiteral("complete"));
1155 switch (m_readyState) {
1164 ASSERT_NOT_REACHED();
1168 void Document::setReadyState(ReadyState readyState)
1170 if (readyState == m_readyState)
1173 #if ENABLE(WEB_TIMING)
1174 switch (readyState) {
1176 if (!m_documentTiming.domLoading)
1177 m_documentTiming.domLoading = monotonicallyIncreasingTime();
1180 if (!m_documentTiming.domInteractive)
1181 m_documentTiming.domInteractive = monotonicallyIncreasingTime();
1184 if (!m_documentTiming.domComplete)
1185 m_documentTiming.domComplete = monotonicallyIncreasingTime();
1190 m_readyState = readyState;
1191 dispatchEvent(Event::create(eventNames().readystatechangeEvent, false, false));
1193 if (settings() && settings()->suppressesIncrementalRendering())
1194 setVisualUpdatesAllowed(readyState);
1197 void Document::setVisualUpdatesAllowed(ReadyState readyState)
1199 ASSERT(settings() && settings()->suppressesIncrementalRendering());
1200 switch (readyState) {
1202 ASSERT(!m_visualUpdatesSuppressionTimer.isActive());
1203 ASSERT(m_visualUpdatesAllowed);
1204 setVisualUpdatesAllowed(false);
1207 ASSERT(m_visualUpdatesSuppressionTimer.isActive() || m_visualUpdatesAllowed);
1210 if (m_visualUpdatesSuppressionTimer.isActive()) {
1211 ASSERT(!m_visualUpdatesAllowed);
1213 if (!view()->visualUpdatesAllowedByClient())
1216 setVisualUpdatesAllowed(true);
1218 ASSERT(m_visualUpdatesAllowed);
1223 void Document::setVisualUpdatesAllowed(bool visualUpdatesAllowed)
1225 if (m_visualUpdatesAllowed == visualUpdatesAllowed)
1228 m_visualUpdatesAllowed = visualUpdatesAllowed;
1230 if (visualUpdatesAllowed)
1231 m_visualUpdatesSuppressionTimer.stop();
1233 m_visualUpdatesSuppressionTimer.startOneShot(settings()->incrementalRenderingSuppressionTimeoutInSeconds());
1235 if (!visualUpdatesAllowed)
1238 FrameView* frameView = view();
1239 bool needsLayout = frameView && renderView() && (frameView->layoutPending() || renderView()->needsLayout());
1243 if (Page* page = this->page()) {
1244 if (frame()->isMainFrame()) {
1245 frameView->addPaintPendingMilestones(DidFirstPaintAfterSuppressedIncrementalRendering);
1246 if (page->requestedLayoutMilestones() & DidFirstLayoutAfterSuppressedIncrementalRendering)
1247 frame()->loader().didLayout(DidFirstLayoutAfterSuppressedIncrementalRendering);
1252 view()->updateCompositingLayersAfterLayout();
1254 if (RenderView* renderView = this->renderView())
1255 renderView->repaintViewAndCompositedLayers();
1257 if (Frame* frame = this->frame())
1258 frame->loader().forcePageTransitionIfNeeded();
1261 void Document::visualUpdatesSuppressionTimerFired()
1263 ASSERT(!m_visualUpdatesAllowed);
1265 // If the client is extending the visual update suppression period explicitly, the
1266 // watchdog should not re-enable visual updates itself, but should wait for the client.
1267 if (!view()->visualUpdatesAllowedByClient())
1270 setVisualUpdatesAllowed(true);
1273 void Document::setVisualUpdatesAllowedByClient(bool visualUpdatesAllowedByClient)
1275 // We should only re-enable visual updates if ReadyState is Completed or the watchdog timer has fired,
1276 // both of which we can determine by looking at the timer.
1278 if (visualUpdatesAllowedByClient && !m_visualUpdatesSuppressionTimer.isActive() && !visualUpdatesAllowed())
1279 setVisualUpdatesAllowed(true);
1282 String Document::characterSetWithUTF8Fallback() const
1284 AtomicString name = encoding();
1287 return UTF8Encoding().domName();
1290 String Document::defaultCharset() const
1292 if (Settings* settings = this->settings())
1293 return settings->defaultTextEncodingName();
1297 void Document::setCharset(const String& charset)
1301 decoder()->setEncoding(charset, TextResourceDecoder::UserChosenEncoding);
1304 void Document::setContentLanguage(const String& language)
1306 if (m_contentLanguage == language)
1308 m_contentLanguage = language;
1310 // Recalculate style so language is used when selecting the initial font.
1311 styleResolverChanged(DeferRecalcStyle);
1314 void Document::setXMLVersion(const String& version, ExceptionCode& ec)
1316 if (!implementation().hasFeature("XML", String())) {
1317 ec = NOT_SUPPORTED_ERR;
1321 if (!XMLDocumentParser::supportsXMLVersion(version)) {
1322 ec = NOT_SUPPORTED_ERR;
1326 m_xmlVersion = version;
1329 void Document::setXMLStandalone(bool standalone, ExceptionCode& ec)
1331 if (!implementation().hasFeature("XML", String())) {
1332 ec = NOT_SUPPORTED_ERR;
1336 m_xmlStandalone = standalone ? Standalone : NotStandalone;
1339 void Document::setDocumentURI(const String& uri)
1341 // This property is read-only from JavaScript, but writable from Objective-C.
1342 m_documentURI = uri;
1346 void Document::setContent(const String& content)
1349 // FIXME: This should probably use insert(), but that's (intentionally)
1350 // not implemented for the XML parser as it's normally synonymous with
1351 // document.write(). append() will end up yielding, but close() will
1352 // pump the tokenizer syncrhonously and finish the parse.
1353 m_parser->append(content.impl());
1357 String Document::suggestedMIMEType() const
1359 if (isXHTMLDocument())
1360 return ASCIILiteral("application/xhtml+xml");
1361 if (isSVGDocument())
1362 return ASCIILiteral("image/svg+xml");
1363 if (xmlStandalone())
1364 return ASCIILiteral("text/xml");
1365 if (isHTMLDocument())
1366 return ASCIILiteral("text/html");
1367 if (DocumentLoader* loader = this->loader())
1368 return loader->responseMIMEType();
1372 void Document::overrideMIMEType(const String& mimeType)
1374 m_overriddenMIMEType = mimeType;
1377 String Document::contentType() const
1379 if (!m_overriddenMIMEType.isNull())
1380 return m_overriddenMIMEType;
1382 if (DocumentLoader* documentLoader = loader())
1383 return documentLoader->currentContentType();
1385 String mimeType = suggestedMIMEType();
1386 if (!mimeType.isNull())
1389 return ASCIILiteral("application/xml");
1392 Node* Document::nodeFromPoint(const LayoutPoint& clientPoint, LayoutPoint* localPoint)
1394 if (!frame() || !view())
1397 Frame& frame = *this->frame();
1399 float scaleFactor = frame.pageZoomFactor() * frame.frameScaleFactor();
1401 LayoutPoint contentsPoint = clientPoint;
1402 contentsPoint.scale(scaleFactor, scaleFactor);
1403 contentsPoint.moveBy(view()->contentsScrollPosition());
1405 LayoutRect visibleRect;
1407 visibleRect = view()->unobscuredContentRect();
1409 visibleRect = view()->visibleContentRect();
1411 if (!visibleRect.contains(contentsPoint))
1414 HitTestResult result(contentsPoint);
1415 renderView()->hitTest(HitTestRequest(), result);
1418 *localPoint = result.localPoint();
1420 return result.innerNode();
1423 Element* Document::elementFromPoint(const LayoutPoint& clientPoint)
1425 if (!hasLivingRenderTree())
1428 Node* node = nodeFromPoint(clientPoint);
1429 while (node && !is<Element>(*node))
1430 node = node->parentNode();
1433 node = ancestorInThisScope(node);
1435 return downcast<Element>(node);
1438 RefPtr<Range> Document::caretRangeFromPoint(int x, int y)
1440 return caretRangeFromPoint(LayoutPoint(x, y));
1443 RefPtr<Range> Document::caretRangeFromPoint(const LayoutPoint& clientPoint)
1445 if (!hasLivingRenderTree())
1448 LayoutPoint localPoint;
1449 Node* node = nodeFromPoint(clientPoint, &localPoint);
1453 Node* shadowAncestorNode = ancestorInThisScope(node);
1454 if (shadowAncestorNode != node) {
1455 unsigned offset = shadowAncestorNode->computeNodeIndex();
1456 ContainerNode* container = shadowAncestorNode->parentNode();
1457 return Range::create(*this, container, offset, container, offset);
1460 RenderObject* renderer = node->renderer();
1463 VisiblePosition visiblePosition = renderer->positionForPoint(localPoint, nullptr);
1464 if (visiblePosition.isNull())
1467 Position rangeCompliantPosition = visiblePosition.deepEquivalent().parentAnchoredEquivalent();
1468 return Range::create(*this, rangeCompliantPosition, rangeCompliantPosition);
1471 Element* Document::scrollingElement()
1473 // FIXME: When we fix https://bugs.webkit.org/show_bug.cgi?id=106133, this should be replaced with the full implementation
1474 // of Document.scrollingElement() as specified at http://dev.w3.org/csswg/cssom-view/#dom-document-scrollingelement.
1480 * Performs three operations:
1481 * 1. Convert control characters to spaces
1482 * 2. Trim leading and trailing spaces
1483 * 3. Collapse internal whitespace.
1485 template <typename CharacterType>
1486 static inline StringWithDirection canonicalizedTitle(Document* document, const StringWithDirection& titleWithDirection)
1488 const String& title = titleWithDirection.string();
1489 const CharacterType* characters = title.characters<CharacterType>();
1490 unsigned length = title.length();
1493 StringBuffer<CharacterType> buffer(length);
1494 unsigned builderIndex = 0;
1496 // Skip leading spaces and leading characters that would convert to spaces
1497 for (i = 0; i < length; ++i) {
1498 CharacterType c = characters[i];
1499 if (!(c <= 0x20 || c == 0x7F))
1504 return StringWithDirection();
1506 // Replace control characters with spaces, and backslashes with currency symbols, and collapse whitespace.
1507 bool previousCharWasWS = false;
1508 for (; i < length; ++i) {
1509 CharacterType c = characters[i];
1510 if (c <= 0x20 || c == 0x7F || (U_GET_GC_MASK(c) & (U_GC_ZL_MASK | U_GC_ZP_MASK))) {
1511 if (previousCharWasWS)
1513 buffer[builderIndex++] = ' ';
1514 previousCharWasWS = true;
1516 buffer[builderIndex++] = c;
1517 previousCharWasWS = false;
1521 // Strip trailing spaces
1522 while (builderIndex > 0) {
1524 if (buffer[builderIndex] != ' ')
1528 if (!builderIndex && buffer[builderIndex] == ' ')
1529 return StringWithDirection();
1531 buffer.shrink(builderIndex + 1);
1533 // Replace the backslashes with currency symbols if the encoding requires it.
1534 document->displayBufferModifiedByEncoding(buffer.characters(), buffer.length());
1536 return StringWithDirection(String::adopt(buffer), titleWithDirection.direction());
1539 void Document::updateTitle(const StringWithDirection& title)
1541 if (m_rawTitle == title)
1546 if (m_rawTitle.string().isEmpty())
1547 m_title = StringWithDirection();
1549 if (m_rawTitle.string().is8Bit())
1550 m_title = canonicalizedTitle<LChar>(this, m_rawTitle);
1552 m_title = canonicalizedTitle<UChar>(this, m_rawTitle);
1554 if (DocumentLoader* loader = this->loader())
1555 loader->setTitle(m_title);
1558 void Document::updateTitleFromTitleElement()
1560 if (!m_titleElement) {
1561 updateTitle(StringWithDirection());
1565 if (is<HTMLTitleElement>(*m_titleElement))
1566 updateTitle(downcast<HTMLTitleElement>(*m_titleElement).textWithDirection());
1567 else if (is<SVGTitleElement>(*m_titleElement)) {
1568 // FIXME: does SVG have a title text direction?
1569 updateTitle(StringWithDirection(downcast<SVGTitleElement>(*m_titleElement).textContent(), LTR));
1573 void Document::setTitle(const String& title)
1575 if (!isHTMLDocument() && !isXHTMLDocument())
1576 m_titleElement = nullptr;
1577 else if (!m_titleElement) {
1578 auto* headElement = head();
1581 m_titleElement = createElement(titleTag, false);
1582 headElement->appendChild(*m_titleElement, ASSERT_NO_EXCEPTION);
1585 // The DOM API has no method of specifying direction, so assume LTR.
1586 updateTitle(StringWithDirection(title, LTR));
1588 if (is<HTMLTitleElement>(m_titleElement.get()))
1589 downcast<HTMLTitleElement>(*m_titleElement).setText(title);
1592 void Document::updateTitleElement(Element* newTitleElement)
1594 // Only allow the first title element in tree order to change the title -- others have no effect.
1595 if (m_titleElement) {
1596 if (isHTMLDocument() || isXHTMLDocument())
1597 m_titleElement = descendantsOfType<HTMLTitleElement>(*this).first();
1598 else if (isSVGDocument())
1599 m_titleElement = descendantsOfType<SVGTitleElement>(*this).first();
1601 m_titleElement = newTitleElement;
1603 updateTitleFromTitleElement();
1606 void Document::titleElementAdded(Element& titleElement)
1608 if (m_titleElement == &titleElement)
1611 updateTitleElement(&titleElement);
1614 void Document::titleElementRemoved(Element& titleElement)
1616 if (m_titleElement != &titleElement)
1619 updateTitleElement(nullptr);
1622 void Document::titleElementTextChanged(Element& titleElement)
1624 if (m_titleElement != &titleElement)
1627 updateTitleFromTitleElement();
1630 void Document::registerForVisibilityStateChangedCallbacks(Element* element)
1632 m_visibilityStateCallbackElements.add(element);
1635 void Document::unregisterForVisibilityStateChangedCallbacks(Element* element)
1637 m_visibilityStateCallbackElements.remove(element);
1640 void Document::visibilityStateChanged()
1642 dispatchEvent(Event::create(eventNames().visibilitychangeEvent, false, false));
1643 for (auto* element : m_visibilityStateCallbackElements)
1644 element->visibilityStateChanged();
1647 PageVisibilityState Document::pageVisibilityState() const
1649 // The visibility of the document is inherited from the visibility of the
1650 // page. If there is no page associated with the document, we will assume
1651 // that the page is hidden, as specified by the spec:
1652 // http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/PageVisibility/Overview.html#dom-document-hidden
1653 if (!m_frame || !m_frame->page())
1654 return PageVisibilityStateHidden;
1655 return m_frame->page()->visibilityState();
1658 String Document::visibilityState() const
1660 return pageVisibilityStateString(pageVisibilityState());
1663 bool Document::hidden() const
1665 return pageVisibilityState() != PageVisibilityStateVisible;
1670 void Document::registerForAllowsMediaDocumentInlinePlaybackChangedCallbacks(HTMLMediaElement& element)
1672 m_allowsMediaDocumentInlinePlaybackElements.add(&element);
1675 void Document::unregisterForAllowsMediaDocumentInlinePlaybackChangedCallbacks(HTMLMediaElement& element)
1677 m_allowsMediaDocumentInlinePlaybackElements.remove(&element);
1680 void Document::allowsMediaDocumentInlinePlaybackChanged()
1682 for (auto* element : m_allowsMediaDocumentInlinePlaybackElements)
1683 element->allowsMediaDocumentInlinePlaybackChanged();
1687 #if ENABLE(CSP_NEXT)
1688 DOMSecurityPolicy& Document::securityPolicy()
1690 if (!m_domSecurityPolicy)
1691 m_domSecurityPolicy = DOMSecurityPolicy::create(this);
1692 return *m_domSecurityPolicy;
1696 String Document::nodeName() const
1701 Node::NodeType Document::nodeType() const
1703 return DOCUMENT_NODE;
1706 FormController& Document::formController()
1708 if (!m_formController)
1709 m_formController = std::make_unique<FormController>();
1710 return *m_formController;
1713 Vector<String> Document::formElementsState() const
1715 if (!m_formController)
1716 return Vector<String>();
1717 return m_formController->formElementsState();
1720 void Document::setStateForNewFormElements(const Vector<String>& stateVector)
1722 if (!stateVector.size() && !m_formController)
1724 formController().setStateForNewFormElements(stateVector);
1727 FrameView* Document::view() const
1729 return m_frame ? m_frame->view() : nullptr;
1732 Page* Document::page() const
1734 return m_frame ? m_frame->page() : nullptr;
1737 Settings* Document::settings() const
1739 return m_frame ? &m_frame->settings() : nullptr;
1742 Ref<Range> Document::createRange()
1744 return Range::create(*this);
1747 RefPtr<NodeIterator> Document::createNodeIterator(Node* root, unsigned long whatToShow, RefPtr<NodeFilter>&& filter, bool, ExceptionCode& ec)
1749 return createNodeIterator(root, whatToShow, WTFMove(filter), ec);
1752 RefPtr<NodeIterator> Document::createNodeIterator(Node* root, unsigned long whatToShow, RefPtr<NodeFilter>&& filter, ExceptionCode& ec)
1758 return NodeIterator::create(root, whatToShow, WTFMove(filter));
1761 RefPtr<NodeIterator> Document::createNodeIterator(Node* root, unsigned long whatToShow, ExceptionCode& ec)
1763 return createNodeIterator(root, whatToShow, nullptr, ec);
1766 RefPtr<NodeIterator> Document::createNodeIterator(Node* root, ExceptionCode& ec)
1768 return createNodeIterator(root, 0xFFFFFFFF, nullptr, ec);
1771 RefPtr<TreeWalker> Document::createTreeWalker(Node* root, unsigned long whatToShow, RefPtr<NodeFilter>&& filter, bool, ExceptionCode& ec)
1773 return createTreeWalker(root, whatToShow, WTFMove(filter), ec);
1776 RefPtr<TreeWalker> Document::createTreeWalker(Node* root, unsigned long whatToShow, RefPtr<NodeFilter>&& filter, ExceptionCode& ec)
1782 return TreeWalker::create(*root, whatToShow, WTFMove(filter));
1785 RefPtr<TreeWalker> Document::createTreeWalker(Node* root, unsigned long whatToShow, ExceptionCode& ec)
1787 return createTreeWalker(root, whatToShow, nullptr, ec);
1790 RefPtr<TreeWalker> Document::createTreeWalker(Node* root, ExceptionCode& ec)
1792 return createTreeWalker(root, 0xFFFFFFFF, nullptr, ec);
1795 void Document::scheduleForcedStyleRecalc()
1797 m_pendingStyleRecalcShouldForce = true;
1798 scheduleStyleRecalc();
1801 void Document::scheduleStyleRecalc()
1803 if (m_styleRecalcTimer.isActive() || inPageCache())
1806 ASSERT(childNeedsStyleRecalc() || m_pendingStyleRecalcShouldForce);
1808 // FIXME: Why on earth is this here? This is clearly misplaced.
1809 invalidateAccessKeyMap();
1811 m_styleRecalcTimer.startOneShot(0);
1813 InspectorInstrumentation::didScheduleStyleRecalculation(*this);
1816 void Document::unscheduleStyleRecalc()
1818 ASSERT(!childNeedsStyleRecalc());
1820 m_styleRecalcTimer.stop();
1821 m_pendingStyleRecalcShouldForce = false;
1824 bool Document::hasPendingStyleRecalc() const
1826 return m_styleRecalcTimer.isActive() && !m_inStyleRecalc;
1829 bool Document::hasPendingForcedStyleRecalc() const
1831 return m_styleRecalcTimer.isActive() && m_pendingStyleRecalcShouldForce;
1834 void Document::recalcStyle(Style::Change change)
1836 ASSERT(!view() || !view()->isPainting());
1838 // NOTE: XSL code seems to be the only client stumbling in here without a RenderView.
1842 FrameView& frameView = m_renderView->frameView();
1843 Ref<FrameView> protect(frameView);
1844 if (frameView.isPainting())
1847 if (m_inStyleRecalc)
1848 return; // Guard against re-entrancy. -dwh
1850 TraceScope tracingScope(StyleRecalcStart, StyleRecalcEnd);
1852 RenderView::RepaintRegionAccumulator repaintRegionAccumulator(renderView());
1853 AnimationUpdateBlock animationUpdateBlock(&m_frame->animation());
1855 // FIXME: We should update style on our ancestor chain before proceeding (especially for seamless),
1856 // however doing so currently causes several tests to crash, as Frame::setDocument calls Document::attach
1857 // before setting the DOMWindow on the Frame, or the SecurityOrigin on the document. The attach, in turn
1858 // resolves style (here) and then when we resolve style on the parent chain, we may end up
1859 // re-attaching our containing iframe, which when asked HTMLFrameElementBase::isURLAllowed
1860 // hits a null-dereference due to security code always assuming the document has a SecurityOrigin.
1862 authorStyleSheets().flushPendingUpdates();
1864 frameView.willRecalcStyle();
1866 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willRecalculateStyle(*this);
1868 // FIXME: We never reset this flags.
1869 if (m_elementSheet && m_elementSheet->contents().usesRemUnits())
1870 authorStyleSheets().setUsesRemUnit(true);
1871 // We don't call setUsesStyleBasedEditability here because the whole point of the flag is to avoid style recalc.
1872 // i.e. updating the flag here would be too late.
1874 m_inStyleRecalc = true;
1875 bool updatedCompositingLayers = false;
1877 Style::PostResolutionCallbackDisabler disabler(*this);
1878 WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
1880 if (m_pendingStyleRecalcShouldForce)
1881 change = Style::Force;
1883 if (change == Style::Force) {
1884 // This may get set again during style resolve.
1885 m_hasNodesWithPlaceholderStyle = false;
1887 auto documentStyle = Style::resolveForDocument(*this);
1889 // Inserting the pictograph font at the end of the font fallback list is done by the
1890 // font selector, so set a font selector if needed.
1891 if (Settings* settings = this->settings()) {
1892 if (settings->fontFallbackPrefersPictographs())
1893 documentStyle.get().fontCascade().update(&fontSelector());
1896 auto documentChange = Style::determineChange(documentStyle.get(), m_renderView->style());
1897 if (documentChange != Style::NoChange)
1898 renderView()->setStyle(WTFMove(documentStyle));
1901 Style::TreeResolver resolver(*this);
1902 resolver.resolve(change);
1904 updatedCompositingLayers = frameView.updateCompositingLayersAfterStyleChange();
1906 clearNeedsStyleRecalc();
1907 clearChildNeedsStyleRecalc();
1908 unscheduleStyleRecalc();
1910 m_inStyleRecalc = false;
1913 // If we wanted to call implicitClose() during recalcStyle, do so now that we're finished.
1914 if (m_closeAfterStyleRecalc) {
1915 m_closeAfterStyleRecalc = false;
1919 ++m_styleRecalcCount;
1921 InspectorInstrumentation::didRecalculateStyle(cookie);
1923 // Some animated images may now be inside the viewport due to style recalc,
1924 // resume them if necessary if there is no layout pending. Otherwise, we'll
1925 // check if they need to be resumed after layout.
1926 if (updatedCompositingLayers && !frameView.needsLayout())
1927 frameView.viewportContentsChanged();
1929 if (!frameView.needsLayout())
1930 frameView.frame().selection().updateAppearanceAfterLayout();
1932 // As a result of the style recalculation, the currently hovered element might have been
1933 // detached (for example, by setting display:none in the :hover style), schedule another mouseMove event
1934 // to check if any other elements ended up under the mouse pointer due to re-layout.
1935 if (m_hoveredElement && !m_hoveredElement->renderer())
1936 frameView.frame().mainFrame().eventHandler().dispatchFakeMouseMoveEventSoon();
1939 void Document::updateStyleIfNeeded()
1941 ASSERT(isMainThread());
1942 ASSERT(!view() || !view()->isPainting());
1944 if (!view() || view()->isInLayout())
1947 if (m_optimizedStyleSheetUpdateTimer.isActive())
1948 styleResolverChanged(RecalcStyleIfNeeded);
1950 if (!needsStyleRecalc())
1953 recalcStyle(Style::NoChange);
1956 void Document::updateLayout()
1958 ASSERT(isMainThread());
1960 FrameView* frameView = view();
1961 if (frameView && frameView->isInLayout()) {
1962 // View layout should not be re-entrant.
1963 ASSERT_NOT_REACHED();
1967 RenderView::RepaintRegionAccumulator repaintRegionAccumulator(renderView());
1969 if (HTMLFrameOwnerElement* owner = ownerElement())
1970 owner->document().updateLayout();
1972 updateStyleIfNeeded();
1974 StackStats::LayoutCheckPoint layoutCheckPoint;
1976 // Only do a layout if changes have occurred that make it necessary.
1977 if (frameView && renderView() && (frameView->layoutPending() || renderView()->needsLayout()))
1978 frameView->layout();
1981 // FIXME: This is a bad idea and needs to be removed eventually.
1982 // Other browsers load stylesheets before they continue parsing the web page.
1983 // Since we don't, we can run JavaScript code that needs answers before the
1984 // stylesheets are loaded. Doing a layout ignoring the pending stylesheets
1985 // lets us get reasonable answers. The long term solution to this problem is
1986 // to instead suspend JavaScript execution.
1987 void Document::updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasks runPostLayoutTasks)
1989 bool oldIgnore = m_ignorePendingStylesheets;
1991 if (!haveStylesheetsLoaded()) {
1992 m_ignorePendingStylesheets = true;
1993 // FIXME: We are willing to attempt to suppress painting with outdated style info only once. Our assumption is that it would be
1994 // dangerous to try to stop it a second time, after page content has already been loaded and displayed
1995 // with accurate style information. (Our suppression involves blanking the whole page at the
1996 // moment. If it were more refined, we might be able to do something better.)
1997 // It's worth noting though that this entire method is a hack, since what we really want to do is
1998 // suspend JS instead of doing a layout with inaccurate information.
1999 HTMLElement* bodyElement = bodyOrFrameset();
2000 if (bodyElement && !bodyElement->renderer() && m_pendingSheetLayout == NoLayoutWithPendingSheets) {
2001 m_pendingSheetLayout = DidLayoutWithPendingSheets;
2002 styleResolverChanged(RecalcStyleImmediately);
2003 } else if (m_hasNodesWithPlaceholderStyle)
2004 // If new nodes have been added or style recalc has been done with style sheets still pending, some nodes
2005 // may not have had their real style calculated yet. Normally this gets cleaned when style sheets arrive
2006 // but here we need up-to-date style immediately.
2007 recalcStyle(Style::Force);
2012 if (runPostLayoutTasks == RunPostLayoutTasks::Synchronously && view())
2013 view()->flushAnyPendingPostLayoutTasks();
2015 m_ignorePendingStylesheets = oldIgnore;
2018 Ref<RenderStyle> Document::styleForElementIgnoringPendingStylesheets(Element& element, RenderStyle* parentStyle)
2020 ASSERT(&element.document() == this);
2022 // On iOS request delegates called during styleForElement may result in re-entering WebKit and killing the style resolver.
2023 ResourceLoadSuspender suspender;
2025 TemporaryChange<bool> change(m_ignorePendingStylesheets, true);
2026 return element.resolveStyle(parentStyle);
2029 bool Document::updateLayoutIfDimensionsOutOfDate(Element& element, DimensionsCheck dimensionsCheck)
2031 ASSERT(isMainThread());
2033 // If the stylesheets haven't loaded, just give up and do a full layout ignoring pending stylesheets.
2034 if (!haveStylesheetsLoaded()) {
2035 updateLayoutIgnorePendingStylesheets();
2039 // Check for re-entrancy and assert (same code that is in updateLayout()).
2040 FrameView* frameView = view();
2041 if (frameView && frameView->isInLayout()) {
2042 // View layout should not be re-entrant.
2043 ASSERT_NOT_REACHED();
2047 RenderView::RepaintRegionAccumulator repaintRegionAccumulator(renderView());
2049 // Mimic the structure of updateLayout(), but at each step, see if we have been forced into doing a full
2051 bool requireFullLayout = false;
2052 if (HTMLFrameOwnerElement* owner = ownerElement()) {
2053 if (owner->document().updateLayoutIfDimensionsOutOfDate(*owner))
2054 requireFullLayout = true;
2057 updateStyleIfNeeded();
2059 RenderObject* renderer = element.renderer();
2060 if (!renderer || renderer->needsLayout() || element.renderNamedFlowFragment()) {
2061 // If we don't have a renderer or if the renderer needs layout for any reason, give up.
2062 // Named flows can have auto height, so don't try to enforce the optimization in this case.
2063 // The 2-pass nature of auto height named flow layout means the region may not be dirty yet.
2064 requireFullLayout = true;
2067 bool isVertical = renderer && !renderer->isHorizontalWritingMode();
2068 bool checkingLogicalWidth = ((dimensionsCheck & WidthDimensionsCheck) && !isVertical) || ((dimensionsCheck & HeightDimensionsCheck) && isVertical);
2069 bool checkingLogicalHeight = ((dimensionsCheck & HeightDimensionsCheck) && !isVertical) || ((dimensionsCheck & WidthDimensionsCheck) && isVertical);
2070 bool hasSpecifiedLogicalHeight = renderer && renderer->style().logicalMinHeight() == Length(0, Fixed) && renderer->style().logicalHeight().isFixed() && renderer->style().logicalMaxHeight().isAuto();
2072 if (!requireFullLayout) {
2073 RenderBox* previousBox = nullptr;
2074 RenderBox* currentBox = nullptr;
2076 // Check our containing block chain. If anything in the chain needs a layout, then require a full layout.
2077 for (RenderObject* currRenderer = element.renderer(); currRenderer && !currRenderer->isRenderView(); currRenderer = currRenderer->container()) {
2079 // Require the entire container chain to be boxes.
2080 if (!is<RenderBox>(currRenderer)) {
2081 requireFullLayout = true;
2085 previousBox = currentBox;
2086 currentBox = downcast<RenderBox>(currRenderer);
2088 // If a box needs layout for itself or if a box has changed children and sizes its width to
2089 // its content, then require a full layout.
2090 if (currentBox->selfNeedsLayout() ||
2091 (checkingLogicalWidth && currRenderer->needsLayout() && currentBox->sizesLogicalWidthToFitContent(MainOrPreferredSize))) {
2092 requireFullLayout = true;
2096 // If a block contains floats and the child's height isn't specified, then
2097 // give up also, since our height could end up being influenced by the floats.
2098 if (checkingLogicalHeight && !hasSpecifiedLogicalHeight && currentBox->isRenderBlockFlow()) {
2099 RenderBlockFlow* currentBlockFlow = downcast<RenderBlockFlow>(currentBox);
2100 if (currentBlockFlow->containsFloats() && previousBox && !previousBox->isFloatingOrOutOfFlowPositioned()) {
2101 requireFullLayout = true;
2106 if (!currentBox->isRenderBlockFlow() || currentBox->flowThreadContainingBlock() || currentBox->isWritingModeRoot()) {
2107 // FIXME: For now require only block flows all the way back to the root. This limits the optimization
2108 // for now, and we'll expand it in future patches to apply to more and more scenarios.
2109 // Disallow regions/columns from having the optimization.
2110 // Give up if the writing mode changes at all in the containing block chain.
2111 requireFullLayout = true;
2115 if (currRenderer == frameView->layoutRoot())
2120 StackStats::LayoutCheckPoint layoutCheckPoint;
2122 // Only do a layout if changes have occurred that make it necessary.
2123 if (requireFullLayout && frameView && renderView() && (frameView->layoutPending() || renderView()->needsLayout()))
2124 frameView->layout();
2126 return requireFullLayout;
2129 bool Document::isPageBoxVisible(int pageIndex)
2131 Ref<RenderStyle> pageStyle(ensureStyleResolver().styleForPage(pageIndex));
2132 return pageStyle->visibility() != HIDDEN; // display property doesn't apply to @page.
2135 void Document::pageSizeAndMarginsInPixels(int pageIndex, IntSize& pageSize, int& marginTop, int& marginRight, int& marginBottom, int& marginLeft)
2137 RefPtr<RenderStyle> style = ensureStyleResolver().styleForPage(pageIndex);
2139 int width = pageSize.width();
2140 int height = pageSize.height();
2141 switch (style->pageSizeType()) {
2142 case PAGE_SIZE_AUTO:
2144 case PAGE_SIZE_AUTO_LANDSCAPE:
2146 std::swap(width, height);
2148 case PAGE_SIZE_AUTO_PORTRAIT:
2150 std::swap(width, height);
2152 case PAGE_SIZE_RESOLVED: {
2153 LengthSize size = style->pageSize();
2154 ASSERT(size.width().isFixed());
2155 ASSERT(size.height().isFixed());
2156 width = valueForLength(size.width(), 0);
2157 height = valueForLength(size.height(), 0);
2161 ASSERT_NOT_REACHED();
2163 pageSize = IntSize(width, height);
2165 // The percentage is calculated with respect to the width even for margin top and bottom.
2166 // http://www.w3.org/TR/CSS2/box.html#margin-properties
2167 marginTop = style->marginTop().isAuto() ? marginTop : intValueForLength(style->marginTop(), width);
2168 marginRight = style->marginRight().isAuto() ? marginRight : intValueForLength(style->marginRight(), width);
2169 marginBottom = style->marginBottom().isAuto() ? marginBottom : intValueForLength(style->marginBottom(), width);
2170 marginLeft = style->marginLeft().isAuto() ? marginLeft : intValueForLength(style->marginLeft(), width);
2173 void Document::createStyleResolver()
2175 m_styleResolver = std::make_unique<StyleResolver>(*this);
2176 m_styleResolver->appendAuthorStyleSheets(authorStyleSheets().activeStyleSheets());
2179 StyleResolver& Document::userAgentShadowTreeStyleResolver()
2181 if (!m_userAgentShadowTreeStyleResolver) {
2182 m_userAgentShadowTreeStyleResolver = std::make_unique<StyleResolver>(*this);
2184 // FIXME: Filter out shadow pseudo elements we don't want to expose to authors.
2185 auto& documentAuthorStyle = *ensureStyleResolver().ruleSets().authorStyle();
2186 if (documentAuthorStyle.hasShadowPseudoElementRules())
2187 m_userAgentShadowTreeStyleResolver->ruleSets().authorStyle()->copyShadowPseudoElementRulesFrom(documentAuthorStyle);
2190 return *m_userAgentShadowTreeStyleResolver;
2193 void Document::fontsNeedUpdate(FontSelector&)
2195 if (m_styleResolver)
2196 m_styleResolver->invalidateMatchedPropertiesCache();
2197 if (inPageCache() || !renderView())
2199 scheduleForcedStyleRecalc();
2202 CSSFontSelector& Document::fontSelector()
2204 if (!m_fontSelector) {
2205 m_fontSelector = CSSFontSelector::create(*this);
2206 m_fontSelector->registerForInvalidationCallbacks(*this);
2208 return *m_fontSelector;
2211 void Document::clearStyleResolver()
2213 m_styleResolver = nullptr;
2214 m_userAgentShadowTreeStyleResolver = nullptr;
2216 // FIXME: It would be better if the FontSelector could survive this operation.
2217 if (m_fontSelector) {
2218 m_fontSelector->clearDocument();
2219 m_fontSelector->unregisterForInvalidationCallbacks(*this);
2220 m_fontSelector = nullptr;
2224 void Document::createRenderTree()
2226 ASSERT(!renderView());
2227 ASSERT(!m_inPageCache);
2228 ASSERT(!m_axObjectCache || this != &topDocument());
2230 if (m_isNonRenderedPlaceholder)
2233 // FIXME: It would be better if we could pass the resolved document style directly here.
2234 m_renderView = createRenderer<RenderView>(*this, RenderStyle::create());
2235 Node::setRenderer(m_renderView.get());
2237 renderView()->setIsInWindow(true);
2239 recalcStyle(Style::Force);
2242 void Document::didBecomeCurrentDocumentInFrame()
2244 // FIXME: Are there cases where the document can be dislodged from the frame during the event handling below?
2245 // If so, then m_frame could become 0, and we need to do something about that.
2247 m_frame->script().updateDocument();
2249 if (!hasLivingRenderTree())
2252 updateViewportArguments();
2254 // FIXME: Doing this only for the main frame is insufficient.
2255 // Changing a subframe can also change the wheel event handler count.
2256 // FIXME: Doing this only when a document goes into the frame is insufficient.
2257 // Removing a document can also change the wheel event handler count.
2258 // FIXME: Doing this every time is a waste. If the current document and its
2259 // subframes' documents have no wheel event handlers, then the count did not change,
2260 // unless the documents they are replacing had wheel event handlers.
2261 if (page() && m_frame->isMainFrame())
2262 wheelEventHandlersChanged();
2264 #if ENABLE(TOUCH_EVENTS)
2265 // FIXME: Doing this only for the main frame is insufficient.
2266 // A subframe could have touch event handlers.
2267 if (hasTouchEventHandlers() && page() && m_frame->isMainFrame())
2268 page()->chrome().client().needTouchEvents(true);
2271 // Ensure that the scheduled task state of the document matches the DOM suspension state of the frame. It can
2272 // be out of sync if the DOM suspension state changed while the document was not in the frame (possibly in the
2273 // page cache, or simply newly created).
2274 if (m_frame->activeDOMObjectsAndAnimationsSuspended()) {
2275 m_frame->animation().suspendAnimationsForDocument(this);
2276 suspendScheduledTasks(ActiveDOMObject::PageWillBeSuspended);
2278 resumeScheduledTasks(ActiveDOMObject::PageWillBeSuspended);
2279 m_frame->animation().resumeAnimationsForDocument(this);
2283 void Document::disconnectFromFrame()
2288 void Document::destroyRenderTree()
2290 ASSERT(hasLivingRenderTree());
2291 ASSERT(!m_inPageCache);
2293 TemporaryChange<bool> change(m_renderTreeBeingDestroyed, true);
2295 if (this == &topDocument())
2296 clearAXObjectCache();
2298 documentWillBecomeInactive();
2300 if (FrameView* frameView = view())
2301 frameView->detachCustomScrollbars();
2303 #if ENABLE(FULLSCREEN_API)
2304 if (m_fullScreenRenderer)
2305 setFullScreenRenderer(nullptr);
2308 m_hoveredElement = nullptr;
2309 m_focusedElement = nullptr;
2310 m_activeElement = nullptr;
2312 if (m_documentElement)
2313 Style::detachRenderTree(*m_documentElement);
2315 clearChildNeedsStyleRecalc();
2317 unscheduleStyleRecalc();
2319 m_renderView = nullptr;
2320 Node::setRenderer(nullptr);
2322 #if ENABLE(IOS_TEXT_AUTOSIZING)
2323 // Do this before the arena is cleared, which is needed to deref the RenderStyle on TextAutoSizingKey.
2324 m_textAutoSizedNodes.clear();
2328 void Document::prepareForDestruction()
2330 if (m_hasPreparedForDestruction)
2333 #if ENABLE(IOS_TOUCH_EVENTS)
2334 clearTouchEventListeners();
2337 #if HAVE(ACCESSIBILITY)
2338 // Sub-frames need to cleanup Nodes in the text marker cache when the Document disappears.
2339 if (this != &topDocument()) {
2340 if (AXObjectCache* cache = existingAXObjectCache())
2341 cache->clearTextMarkerNodesInUse(this);
2345 disconnectDescendantFrames();
2346 if (m_domWindow && m_frame)
2347 m_domWindow->willDetachDocumentFromFrame();
2349 if (hasLivingRenderTree())
2350 destroyRenderTree();
2352 if (is<PluginDocument>(*this))
2353 downcast<PluginDocument>(*this).detachFromPluginElement();
2355 #if ENABLE(POINTER_LOCK)
2357 page()->pointerLockController().documentDetached(this);
2360 InspectorInstrumentation::documentDetached(*this);
2362 stopActiveDOMObjects();
2363 m_eventQueue.close();
2364 #if ENABLE(FULLSCREEN_API)
2365 m_fullScreenChangeEventTargetQueue.clear();
2366 m_fullScreenErrorEventTargetQueue.clear();
2371 #if ENABLE(TOUCH_EVENTS)
2372 if (m_touchEventTargets && m_touchEventTargets->size() && parentDocument())
2373 parentDocument()->didRemoveEventTargetNode(*this);
2376 if (m_wheelEventTargets && m_wheelEventTargets->size() && parentDocument())
2377 parentDocument()->didRemoveEventTargetNode(*this);
2379 if (m_mediaQueryMatcher)
2380 m_mediaQueryMatcher->documentDestroyed();
2382 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
2383 if (!m_clientToIDMap.isEmpty() && page()) {
2384 Vector<WebCore::MediaPlaybackTargetClient*> clients;
2385 copyKeysToVector(m_clientToIDMap, clients);
2386 for (auto* client : clients)
2387 removePlaybackTargetPickerClient(*client);
2391 disconnectFromFrame();
2393 m_hasPreparedForDestruction = true;
2396 void Document::removeAllEventListeners()
2398 EventTarget::removeAllEventListeners();
2401 m_domWindow->removeAllEventListeners();
2402 #if ENABLE(IOS_TOUCH_EVENTS)
2403 clearTouchEventListeners();
2405 for (Node* node = firstChild(); node; node = NodeTraversal::next(*node))
2406 node->removeAllEventListeners();
2409 void Document::suspendDeviceMotionAndOrientationUpdates()
2411 if (m_areDeviceMotionAndOrientationUpdatesSuspended)
2413 m_areDeviceMotionAndOrientationUpdatesSuspended = true;
2414 #if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS)
2415 if (m_deviceMotionController)
2416 m_deviceMotionController->suspendUpdates();
2417 if (m_deviceOrientationController)
2418 m_deviceOrientationController->suspendUpdates();
2422 void Document::resumeDeviceMotionAndOrientationUpdates()
2424 if (!m_areDeviceMotionAndOrientationUpdatesSuspended)
2426 m_areDeviceMotionAndOrientationUpdatesSuspended = false;
2427 #if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS)
2428 if (m_deviceMotionController)
2429 m_deviceMotionController->resumeUpdates();
2430 if (m_deviceOrientationController)
2431 m_deviceOrientationController->resumeUpdates();
2435 bool Document::shouldBypassMainWorldContentSecurityPolicy() const
2437 JSC::CallFrame* callFrame = JSDOMWindow::commonVM().topCallFrame;
2438 if (callFrame == JSC::CallFrame::noCaller())
2440 DOMWrapperWorld& domWrapperWorld = currentWorld(callFrame);
2441 if (domWrapperWorld.isNormal())
2446 void Document::platformSuspendOrStopActiveDOMObjects()
2449 if (WebThreadCountOfObservedContentModifiers() > 0) {
2450 Frame* frame = this->frame();
2451 if (Page* page = frame ? frame->page() : nullptr)
2452 page->chrome().client().clearContentChangeObservers(frame);
2457 void Document::suspendActiveDOMObjects(ActiveDOMObject::ReasonForSuspension why)
2459 ScriptExecutionContext::suspendActiveDOMObjects(why);
2460 suspendDeviceMotionAndOrientationUpdates();
2461 platformSuspendOrStopActiveDOMObjects();
2464 void Document::resumeActiveDOMObjects(ActiveDOMObject::ReasonForSuspension why)
2466 ScriptExecutionContext::resumeActiveDOMObjects(why);
2467 resumeDeviceMotionAndOrientationUpdates();
2468 // FIXME: For iOS, do we need to add content change observers that were removed in Document::suspendActiveDOMObjects()?
2471 void Document::stopActiveDOMObjects()
2473 ScriptExecutionContext::stopActiveDOMObjects();
2474 platformSuspendOrStopActiveDOMObjects();
2477 void Document::clearAXObjectCache()
2479 ASSERT(&topDocument() == this);
2480 // Clear the cache member variable before calling delete because attempts
2481 // are made to access it during destruction.
2482 m_axObjectCache = nullptr;
2485 AXObjectCache* Document::existingAXObjectCache() const
2487 Document& topDocument = this->topDocument();
2488 if (!topDocument.hasLivingRenderTree())
2490 return topDocument.m_axObjectCache.get();
2493 AXObjectCache* Document::axObjectCache() const
2495 if (!AXObjectCache::accessibilityEnabled())
2498 // The only document that actually has a AXObjectCache is the top-level
2499 // document. This is because we need to be able to get from any WebCoreAXObject
2500 // to any other WebCoreAXObject on the same page. Using a single cache allows
2501 // lookups across nested webareas (i.e. multiple documents).
2502 Document& topDocument = this->topDocument();
2504 // If the document has already been detached, do not make a new axObjectCache.
2505 if (!topDocument.hasLivingRenderTree())
2508 ASSERT(&topDocument == this || !m_axObjectCache);
2509 if (!topDocument.m_axObjectCache)
2510 topDocument.m_axObjectCache = std::make_unique<AXObjectCache>(topDocument);
2511 return topDocument.m_axObjectCache.get();
2514 void Document::setVisuallyOrdered()
2516 m_visuallyOrdered = true;
2518 renderView()->style().setRTLOrdering(VisualOrder);
2521 Ref<DocumentParser> Document::createParser()
2523 // FIXME: this should probably pass the frame instead
2524 return XMLDocumentParser::create(*this, view());
2527 ScriptableDocumentParser* Document::scriptableDocumentParser() const
2529 return parser() ? parser()->asScriptableDocumentParser() : nullptr;
2532 void Document::open(Document* ownerDocument)
2534 if (m_ignoreOpensDuringUnloadCount)
2537 if (ownerDocument) {
2538 setURL(ownerDocument->url());
2539 setCookieURL(ownerDocument->cookieURL());
2540 setSecurityOriginPolicy(ownerDocument->securityOriginPolicy());
2544 if (ScriptableDocumentParser* parser = scriptableDocumentParser()) {
2545 if (parser->isParsing()) {
2546 // FIXME: HTML5 doesn't tell us to check this, it might not be correct.
2547 if (parser->isExecutingScript())
2550 if (!parser->wasCreatedByScript() && parser->hasInsertionPoint())
2555 if (m_frame->loader().state() == FrameStateProvisional)
2556 m_frame->loader().stopAllLoaders();
2559 removeAllEventListeners();
2561 if (ScriptableDocumentParser* parser = scriptableDocumentParser())
2562 parser->setWasCreatedByScript(true);
2565 m_frame->loader().didExplicitOpen();
2568 void Document::detachParser()
2576 void Document::cancelParsing()
2581 // We have to clear the parser to avoid possibly triggering
2582 // the onload handler when closing as a side effect of a cancel-style
2583 // change, such as opening a new document or closing the window while
2589 void Document::implicitOpen()
2595 setCompatibilityMode(DocumentCompatibilityMode::NoQuirksMode);
2597 m_parser = createParser();
2599 setReadyState(Loading);
2602 HTMLBodyElement* Document::body() const
2604 auto* element = documentElement();
2607 return childrenOfType<HTMLBodyElement>(*element).first();
2610 HTMLElement* Document::bodyOrFrameset() const
2612 // Return the first body or frameset child of the html element.
2613 auto* element = documentElement();
2616 for (auto& child : childrenOfType<HTMLElement>(*element)) {
2617 if (is<HTMLBodyElement>(child) || is<HTMLFrameSetElement>(child))
2623 void Document::setBodyOrFrameset(RefPtr<HTMLElement>&& newBody, ExceptionCode& ec)
2625 // FIXME: This does not support setting a <frameset> Element, only a <body>. This does
2626 // not match the HTML specification:
2627 // https://html.spec.whatwg.org/multipage/dom.html#dom-document-body
2628 if (!newBody || !documentElement() || !newBody->hasTagName(bodyTag)) {
2629 ec = HIERARCHY_REQUEST_ERR;
2633 if (&newBody->document() != this) {
2635 RefPtr<Node> node = importNode(newBody.get(), true, ec);
2639 newBody = downcast<HTMLElement>(node.get());
2642 if (auto* body = bodyOrFrameset())
2643 documentElement()->replaceChild(newBody.releaseNonNull(), *body, ec);
2645 documentElement()->appendChild(newBody.releaseNonNull(), ec);
2648 Location* Document::location() const
2650 auto* window = domWindow();
2654 return window->location();
2657 HTMLHeadElement* Document::head()
2659 if (auto element = documentElement())
2660 return childrenOfType<HTMLHeadElement>(*element).first();
2664 void Document::close()
2666 // FIXME: We should follow the specification more closely:
2667 // http://www.whatwg.org/specs/web-apps/current-work/#dom-document-close
2669 if (!scriptableDocumentParser() || !scriptableDocumentParser()->wasCreatedByScript() || !scriptableDocumentParser()->isParsing())
2675 void Document::explicitClose()
2677 if (RefPtr<DocumentParser> parser = m_parser)
2681 // Because we have no frame, we don't know if all loading has completed,
2682 // so we just call implicitClose() immediately. FIXME: This might fire
2683 // the load event prematurely <http://bugs.webkit.org/show_bug.cgi?id=14568>.
2688 m_frame->loader().checkCompleted();
2691 void Document::implicitClose()
2693 // 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.
2694 if (m_inStyleRecalc) {
2695 m_closeAfterStyleRecalc = true;
2699 bool wasLocationChangePending = frame() && frame()->navigationScheduler().locationChangePending();
2700 bool doload = !parsing() && m_parser && !m_processingLoadEvent && !wasLocationChangePending;
2705 // Call to dispatchWindowLoadEvent can blow us from underneath.
2706 Ref<Document> protect(*this);
2708 m_processingLoadEvent = true;
2710 ScriptableDocumentParser* parser = scriptableDocumentParser();
2711 m_wellFormed = parser && parser->wellFormed();
2713 // We have to clear the parser, in case someone document.write()s from the
2714 // onLoad event handler, as in Radar 3206524.
2717 // FIXME: We kick off the icon loader when the Document is done parsing.
2718 // There are earlier opportunities we could start it:
2719 // -When the <head> finishes parsing
2720 // -When any new HTMLLinkElement is inserted into the document
2721 // But those add a dynamic component to the favicon that has UI
2722 // ramifications, and we need to decide what is the Right Thing To Do(tm)
2725 f->loader().icon().startLoader();
2726 f->animation().startAnimationsIfNotSuspended(this);
2728 // FIXME: We shouldn't be dispatching pending events globally on all Documents here.
2729 // For now, only do this when there is a Frame, otherwise this could cause JS reentrancy
2730 // below SVG font parsing, for example. <https://webkit.org/b/136269>
2731 ImageLoader::dispatchPendingBeforeLoadEvents();
2732 ImageLoader::dispatchPendingLoadEvents();
2733 ImageLoader::dispatchPendingErrorEvents();
2734 HTMLLinkElement::dispatchPendingLoadEvents();
2735 HTMLStyleElement::dispatchPendingLoadEvents();
2738 // To align the HTML load event and the SVGLoad event for the outermost <svg> element, fire it from
2739 // here, instead of doing it from SVGElement::finishedParsingChildren (if externalResourcesRequired="false",
2740 // which is the default, for ='true' its fired at a later time, once all external resources finished loading).
2741 if (svgExtensions())
2742 accessSVGExtensions().dispatchSVGLoadEventToOutermostSVGElements();
2744 dispatchWindowLoadEvent();
2745 enqueuePageshowEvent(PageshowEventNotPersisted);
2746 if (m_pendingStateObject)
2747 enqueuePopstateEvent(WTFMove(m_pendingStateObject));
2750 f->loader().dispatchOnloadEvents();
2751 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2752 if (!ownerElement())
2753 printf("onload fired at %lld\n", elapsedTime().count());
2756 // An event handler may have removed the frame
2758 m_processingLoadEvent = false;
2762 // Make sure both the initial layout and reflow happen after the onload
2763 // fires. This will improve onload scores, and other browsers do it.
2764 // If they wanna cheat, we can too. -dwh
2766 if (frame()->navigationScheduler().locationChangePending() && elapsedTime() < settings()->layoutInterval()) {
2767 // Just bail out. Before or during the onload we were shifted to another page.
2768 // The old i-Bench suite does this. When this happens don't bother painting or laying out.
2769 m_processingLoadEvent = false;
2770 view()->unscheduleRelayout();
2774 frame()->loader().checkCallImplicitClose();
2776 // We used to force a synchronous display and flush here. This really isn't
2777 // necessary and can in fact be actively harmful if pages are loading at a rate of > 60fps
2778 // (if your platform is syncing flushes and limiting them to 60fps).
2779 m_overMinimumLayoutThreshold = true;
2780 if (!ownerElement() || (ownerElement()->renderer() && !ownerElement()->renderer()->needsLayout())) {
2781 updateStyleIfNeeded();
2783 // Always do a layout after loading if needed.
2784 if (view() && renderView() && (!renderView()->firstChild() || renderView()->needsLayout()))
2788 m_processingLoadEvent = false;
2790 #if PLATFORM(COCOA) || PLATFORM(WIN) || PLATFORM(GTK) || PLATFORM(EFL)
2791 if (f && hasLivingRenderTree() && AXObjectCache::accessibilityEnabled()) {
2792 // The AX cache may have been cleared at this point, but we need to make sure it contains an
2793 // AX object to send the notification to. getOrCreate will make sure that an valid AX object
2794 // exists in the cache (we ignore the return value because we don't need it here). This is
2795 // only safe to call when a layout is not in progress, so it can not be used in postNotification.
2797 // This notification is now called AXNewDocumentLoadComplete because there are other handlers that will
2798 // catch new AND page history loads, and that uses AXLoadComplete
2800 axObjectCache()->getOrCreate(renderView());
2801 if (this == &topDocument())
2802 axObjectCache()->postNotification(renderView(), AXObjectCache::AXNewDocumentLoadComplete);
2804 // AXLoadComplete can only be posted on the top document, so if it's a document
2805 // in an iframe that just finished loading, post AXLayoutComplete instead.
2806 axObjectCache()->postNotification(renderView(), AXObjectCache::AXLayoutComplete);
2811 if (svgExtensions())
2812 accessSVGExtensions().startAnimations();
2815 void Document::setParsing(bool b)
2819 if (m_bParsing && !m_sharedObjectPool)
2820 m_sharedObjectPool = std::make_unique<DocumentSharedObjectPool>();
2822 if (!m_bParsing && view() && !view()->needsLayout())
2823 view()->fireLayoutRelatedMilestonesIfNeeded();
2825 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2826 if (!ownerElement() && !m_bParsing)
2827 printf("Parsing finished at %lld\n", elapsedTime().count());
2831 bool Document::shouldScheduleLayout()
2833 // This function will only be called when FrameView thinks a layout is needed.
2834 // This enforces a couple extra rules.
2836 // (a) Only schedule a layout once the stylesheets are loaded.
2837 // (b) Only schedule layout once we have a body element.
2839 return (haveStylesheetsLoaded() && bodyOrFrameset())
2840 || (documentElement() && !is<HTMLHtmlElement>(*documentElement()));
2843 bool Document::isLayoutTimerActive()
2845 return view() && view()->layoutPending() && !minimumLayoutDelay().count();
2848 std::chrono::milliseconds Document::minimumLayoutDelay()
2850 if (m_overMinimumLayoutThreshold)
2851 return std::chrono::milliseconds(0);
2853 std::chrono::milliseconds elapsed = elapsedTime();
2854 m_overMinimumLayoutThreshold = elapsed > settings()->layoutInterval();
2856 // We'll want to schedule the timer to fire at the minimum layout threshold.
2857 return std::max(std::chrono::milliseconds(0), settings()->layoutInterval() - elapsed);
2860 std::chrono::milliseconds Document::elapsedTime() const
2862 auto elapsedTime = std::chrono::steady_clock::now() - m_startTime;
2864 return std::chrono::duration_cast<std::chrono::milliseconds>(elapsedTime);
2867 void Document::write(const SegmentedString& text, Document* ownerDocument)
2869 NestingLevelIncrementer nestingLevelIncrementer(m_writeRecursionDepth);
2871 m_writeRecursionIsTooDeep = (m_writeRecursionDepth > 1) && m_writeRecursionIsTooDeep;
2872 m_writeRecursionIsTooDeep = (m_writeRecursionDepth > cMaxWriteRecursionDepth) || m_writeRecursionIsTooDeep;
2874 if (m_writeRecursionIsTooDeep)
2877 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2878 if (!ownerElement())
2879 printf("Beginning a document.write at %lld\n", elapsedTime().count());
2882 bool hasInsertionPoint = m_parser && m_parser->hasInsertionPoint();
2883 if (!hasInsertionPoint && (m_ignoreOpensDuringUnloadCount || m_ignoreDestructiveWriteCount))
2886 if (!hasInsertionPoint)
2887 open(ownerDocument);
2890 m_parser->insert(text);
2892 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2893 if (!ownerElement())
2894 printf("Ending a document.write at %lld\n", elapsedTime().count());
2898 void Document::write(const String& text, Document* ownerDocument)
2900 write(SegmentedString(text), ownerDocument);
2903 void Document::writeln(const String& text, Document* ownerDocument)
2905 write(text, ownerDocument);
2906 write("\n", ownerDocument);
2909 double Document::minimumTimerInterval() const
2911 Page* page = this->page();
2913 return ScriptExecutionContext::minimumTimerInterval();
2914 return page->settings().minimumDOMTimerInterval();
2917 void Document::setTimerThrottlingEnabled(bool shouldThrottle)
2919 if (m_isTimerThrottlingEnabled == shouldThrottle)
2922 m_isTimerThrottlingEnabled = shouldThrottle;
2923 didChangeTimerAlignmentInterval();
2926 double Document::timerAlignmentInterval(bool hasReachedMaxNestingLevel) const
2928 // Apply Document-level DOMTimer throttling only if timers have reached their maximum nesting level as the Page may still be visible.
2929 if (m_isTimerThrottlingEnabled && hasReachedMaxNestingLevel)
2930 return DOMTimer::hiddenPageAlignmentInterval();
2932 Page* page = this->page();
2934 return ScriptExecutionContext::timerAlignmentInterval(hasReachedMaxNestingLevel);
2935 return page->settings().domTimerAlignmentInterval();
2938 EventTarget* Document::errorEventTarget()
2940 return m_domWindow.get();
2943 void Document::logExceptionToConsole(const String& errorMessage, const String& sourceURL, int lineNumber, int columnNumber, RefPtr<Inspector::ScriptCallStack>&& callStack)
2945 addMessage(MessageSource::JS, MessageLevel::Error, errorMessage, sourceURL, lineNumber, columnNumber, WTFMove(callStack));
2948 void Document::setURL(const URL& url)
2950 const URL& newURL = url.isEmpty() ? blankURL() : url;
2951 if (newURL == m_url)
2955 m_documentURI = m_url.string();
2959 void Document::updateBaseURL()
2961 URL oldBaseURL = m_baseURL;
2962 // DOM 3 Core: When the Document supports the feature "HTML" [DOM Level 2 HTML], the base URI is computed using
2963 // first the value of the href attribute of the HTML BASE element if any, and the value of the documentURI attribute
2964 // from the Document interface otherwise.
2965 if (!m_baseElementURL.isEmpty())
2966 m_baseURL = m_baseElementURL;
2967 else if (!m_baseURLOverride.isEmpty())
2968 m_baseURL = m_baseURLOverride;
2970 // The documentURI attribute is read-only from JavaScript, but writable from Objective C, so we need to retain
2971 // this fallback behavior. We use a null base URL, since the documentURI attribute is an arbitrary string
2972 // and DOM 3 Core does not specify how it should be resolved.
2973 m_baseURL = URL(ParsedURLString, documentURI());
2976 clearSelectorQueryCache();
2978 if (!m_baseURL.isValid())
2981 if (m_elementSheet) {
2982 // Element sheet is silly. It never contains anything.
2983 ASSERT(!m_elementSheet->contents().ruleCount());
2984 bool usesRemUnits = m_elementSheet->contents().usesRemUnits();
2985 bool usesStyleBasedEditability = m_elementSheet->contents().usesStyleBasedEditability();
2986 m_elementSheet = CSSStyleSheet::createInline(*this, m_baseURL);
2987 // FIXME: So we are not really the parser. The right fix is to eliminate the element sheet completely.
2989 m_elementSheet->contents().parserSetUsesRemUnits();
2990 if (usesStyleBasedEditability)
2991 m_elementSheet->contents().parserSetUsesStyleBasedEditability();
2994 if (!equalIgnoringFragmentIdentifier(oldBaseURL, m_baseURL)) {
2995 // Base URL change changes any relative visited links.
2996 // FIXME: There are other URLs in the tree that would need to be re-evaluated on dynamic base URL change. Style should be invalidated too.
2997 for (auto& anchor : descendantsOfType<HTMLAnchorElement>(*this))
2998 anchor.invalidateCachedVisitedLinkHash();
3002 void Document::setBaseURLOverride(const URL& url)
3004 m_baseURLOverride = url;
3008 void Document::processBaseElement()
3010 // Find the first href attribute in a base element and the first target attribute in a base element.
3011 const AtomicString* href = nullptr;
3012 const AtomicString* target = nullptr;
3013 auto baseDescendants = descendantsOfType<HTMLBaseElement>(*this);
3014 for (auto& base : baseDescendants) {
3016 const AtomicString& value = base.fastGetAttribute(hrefAttr);
3017 if (!value.isNull()) {
3024 const AtomicString& value = base.fastGetAttribute(targetAttr);
3025 if (!value.isNull()) {
3033 // FIXME: Since this doesn't share code with completeURL it may not handle encodings correctly.
3036 String strippedHref = stripLeadingAndTrailingHTMLSpaces(*href);
3037 if (!strippedHref.isEmpty())
3038 baseElementURL = URL(url(), strippedHref);
3040 if (m_baseElementURL != baseElementURL && contentSecurityPolicy()->allowBaseURI(baseElementURL)) {
3041 m_baseElementURL = baseElementURL;
3045 m_baseTarget = target ? *target : nullAtom;
3048 String Document::userAgent(const URL& url) const
3050 return frame() ? frame()->loader().userAgent(url) : String();
3053 void Document::disableEval(const String& errorMessage)
3058 frame()->script().disableEval(errorMessage);
3061 bool Document::canNavigate(Frame* targetFrame)
3066 // FIXME: We shouldn't call this function without a target frame, but
3067 // fast/forms/submit-to-blank-multiple-times.html depends on this function
3068 // returning true when supplied with a 0 targetFrame.
3072 // Frame-busting is generally allowed, but blocked for sandboxed frames lacking the 'allow-top-navigation' flag.
3073 if (!isSandboxed(SandboxTopNavigation) && targetFrame == &m_frame->tree().top())
3076 if (isSandboxed(SandboxNavigation)) {
3077 if (targetFrame->tree().isDescendantOf(m_frame))
3080 const char* reason = "The frame attempting navigation is sandboxed, and is therefore disallowed from navigating its ancestors.";
3081 if (isSandboxed(SandboxTopNavigation) && targetFrame == &m_frame->tree().top())
3082 reason = "The frame attempting navigation of the top-level window is sandboxed, but the 'allow-top-navigation' flag is not set.";
3084 printNavigationErrorMessage(targetFrame, url(), reason);
3088 // This is the normal case. A document can navigate its decendant frames,
3089 // or, more generally, a document can navigate a frame if the document is
3090 // in the same origin as any of that frame's ancestors (in the frame
3093 // See http://www.adambarth.com/papers/2008/barth-jackson-mitchell.pdf for
3094 // historical information about this security check.
3095 if (canAccessAncestor(securityOrigin(), targetFrame))
3098 // Top-level frames are easier to navigate than other frames because they
3099 // display their URLs in the address bar (in most browsers). However, there
3100 // are still some restrictions on navigation to avoid nuisance attacks.
3101 // Specifically, a document can navigate a top-level frame if that frame
3102 // opened the document or if the document is the same-origin with any of
3103 // the top-level frame's opener's ancestors (in the frame hierarchy).
3105 // In both of these cases, the document performing the navigation is in
3106 // some way related to the frame being navigate (e.g., by the "opener"
3107 // and/or "parent" relation). Requiring some sort of relation prevents a
3108 // document from navigating arbitrary, unrelated top-level frames.
3109 if (!targetFrame->tree().parent()) {
3110 if (targetFrame == m_frame->loader().opener())
3113 if (canAccessAncestor(securityOrigin(), targetFrame->loader().opener()))
3117 printNavigationErrorMessage(targetFrame, url(), "The frame attempting navigation is neither same-origin with the target, nor is it the target's parent or opener.");
3121 Frame* Document::findUnsafeParentScrollPropagationBoundary()
3123 Frame* currentFrame = m_frame;
3127 Frame* ancestorFrame = currentFrame->tree().parent();
3129 while (ancestorFrame) {
3130 if (!ancestorFrame->document()->securityOrigin()->canAccess(securityOrigin()))
3131 return currentFrame;
3132 currentFrame = ancestorFrame;
3133 ancestorFrame = ancestorFrame->tree().parent();
3138 void Document::didRemoveAllPendingStylesheet()
3140 m_needsNotifyRemoveAllPendingStylesheet = false;
3142 styleResolverChanged(DeferRecalcStyleIfNeeded);
3144 if (m_pendingSheetLayout == DidLayoutWithPendingSheets) {
3145 m_pendingSheetLayout = IgnoreLayoutWithPendingSheets;
3147 renderView()->repaintViewAndCompositedLayers();
3150 if (ScriptableDocumentParser* parser = scriptableDocumentParser())
3151 parser->executeScriptsWaitingForStylesheets();
3153 if (m_gotoAnchorNeededAfterStylesheetsLoad && view())
3154 view()->scrollToFragment(m_url);
3157 CSSStyleSheet& Document::elementSheet()
3159 if (!m_elementSheet)
3160 m_elementSheet = CSSStyleSheet::createInline(*this, m_baseURL);
3161 return *m_elementSheet;
3164 bool Document::usesStyleBasedEditability() const
3166 if (m_elementSheet && m_elementSheet->contents().usesStyleBasedEditability())
3169 ASSERT(!m_renderView || !m_renderView->frameView().isPainting());
3170 ASSERT(!m_inStyleRecalc);
3172 auto& authorSheets = const_cast<AuthorStyleSheets&>(authorStyleSheets());
3173 authorSheets.flushPendingUpdates();
3174 return authorSheets.usesStyleBasedEditability();
3177 void Document::processHttpEquiv(const String& equiv, const String& content)
3179 ASSERT(!equiv.isNull() && !content.isNull());
3181 HttpEquivPolicy policy = httpEquivPolicy();
3182 if (policy != HttpEquivPolicy::Enabled) {
3185 case HttpEquivPolicy::Enabled:
3186 ASSERT_NOT_REACHED();
3188 case HttpEquivPolicy::DisabledBySettings:
3189 reason = "by the embedder.";
3191 case HttpEquivPolicy::DisabledByContentDispositionAttachmentSandbox:
3192 reason = "for documents with Content-Disposition: attachment.";
3195 String message = "http-equiv '" + equiv + "' is disabled " + reason;
3196 addConsoleMessage(MessageSource::Security, MessageLevel::Error, message);
3200 Frame* frame = this->frame();
3202 HTTPHeaderName headerName;
3203 if (!findHTTPHeaderName(equiv, headerName))
3206 switch (headerName) {
3207 case HTTPHeaderName::DefaultStyle:
3208 // The preferred style set has been overridden as per section
3209 // 14.3.2 of the HTML4.0 specification. We need to update the
3210 // sheet used variable and then update our style selector.
3211 // For more info, see the test at:
3212 // http://www.hixie.ch/tests/evil/css/import/main/preferred.html
3214 authorStyleSheets().setSelectedStylesheetSetName(content);
3215 authorStyleSheets().setPreferredStylesheetSetName(content);
3216 styleResolverChanged(DeferRecalcStyle);
3219 case HTTPHeaderName::Refresh: {
3222 if (frame && parseHTTPRefresh(content, true, delay, urlString)) {
3224 if (urlString.isEmpty())
3225 completedURL = m_url;
3227 completedURL = completeURL(urlString);
3228 if (!protocolIsJavaScript(completedURL))
3229 frame->navigationScheduler().scheduleRedirect(this, delay, completedURL);
3231 String message = "Refused to refresh " + m_url.stringCenterEllipsizedToLength() + " to a javascript: URL";
3232 addConsoleMessage(MessageSource::Security, MessageLevel::Error, message);
3239 case HTTPHeaderName::SetCookie:
3240 // FIXME: make setCookie work on XML documents too; e.g. in case of <html:meta .....>
3241 if (is<HTMLDocument>(*this)) {
3242 // Exception (for sandboxed documents) ignored.
3243 downcast<HTMLDocument>(*this).setCookie(content, IGNORE_EXCEPTION);
3247 case HTTPHeaderName::ContentLanguage:
3248 setContentLanguage(content);
3251 case HTTPHeaderName::XDNSPrefetchControl:
3252 parseDNSPrefetchControlHeader(content);
3255 case HTTPHeaderName::XFrameOptions:
3257 FrameLoader& frameLoader = frame->loader();
3258 unsigned long requestIdentifier = 0;
3259 if (frameLoader.activeDocumentLoader() && frameLoader.activeDocumentLoader()->mainResourceLoader())
3260 requestIdentifier = frameLoader.activeDocumentLoader()->mainResourceLoader()->identifier();
3261 if (frameLoader.shouldInterruptLoadForXFrameOptions(content, url(), requestIdentifier)) {
3262 String message = "Refused to display '" + url().stringCenterEllipsizedToLength() + "' in a frame because it set 'X-Frame-Options' to '" + content + "'.";
3263 frameLoader.stopAllLoaders();
3264 // Stopping the loader isn't enough, as we're already parsing the document; to honor the header's
3265 // intent, we must navigate away from the possibly partially-rendered document to a location that
3266 // doesn't inherit the parent's SecurityOrigin.
3267 frame->navigationScheduler().scheduleLocationChange(this, securityOrigin(), SecurityOrigin::urlWithUniqueSecurityOrigin(), String());
3268 addConsoleMessage(MessageSource::Security, MessageLevel::Error, message, requestIdentifier);
3273 case HTTPHeaderName::ContentSecurityPolicy:
3274 contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicyHeaderType::Enforce);
3277 case HTTPHeaderName::ContentSecurityPolicyReportOnly:
3278 contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicyHeaderType::Report);
3281 case HTTPHeaderName::XWebKitCSP:
3282 contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicyHeaderType::PrefixedEnforce);
3285 case HTTPHeaderName::XWebKitCSPReportOnly:
3286 contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicyHeaderType::PrefixedReport);
3294 void Document::processViewport(const String& features, ViewportArguments::Type origin)
3296 ASSERT(!features.isNull());
3298 if (origin < m_viewportArguments.type)
3301 m_viewportArguments = ViewportArguments(origin);
3303 processFeaturesString(features, [this](StringView key, StringView value) {
3304 setViewportFeature(m_viewportArguments, *this, key, value);
3307 updateViewportArguments();
3310 void Document::updateViewportArguments()
3312 if (page() && frame()->isMainFrame()) {
3314 m_didDispatchViewportPropertiesChanged = true;
3316 page()->chrome().dispatchViewportPropertiesDidChange(m_viewportArguments);
3318 page()->chrome().didReceiveDocType(frame());
3325 void Document::processFormatDetection(const String& features)
3327 // FIXME: Find a better place for this function.
3328 processFeaturesString(features, [this](StringView key, StringView value) {
3329 if (equalLettersIgnoringASCIICase(key, "telephone") && equalLettersIgnoringASCIICase(value, "no"))
3330 setIsTelephoneNumberParsingAllowed(false);
3334 void Document::processWebAppOrientations()
3336 if (Page* page = this->page())
3337 page->chrome().client().webAppOrientationsUpdated();
3342 void Document::processReferrerPolicy(const String& policy)
3344 ASSERT(!policy.isNull());
3346 // Documents in a Content-Disposition: attachment sandbox should never send a Referer header,
3347 // even if the document has a meta tag saying otherwise.
3348 if (shouldEnforceContentDispositionAttachmentSandbox())
3351 // Note that we're supporting both the standard and legacy keywords for referrer
3352 // policies, as defined by http://www.w3.org/TR/referrer-policy/#referrer-policy-delivery-meta
3353 if (equalLettersIgnoringASCIICase(policy, "no-referrer") || equalLettersIgnoringASCIICase(policy, "never"))
3354 setReferrerPolicy(ReferrerPolicyNever);
3355 else if (equalLettersIgnoringASCIICase(policy, "unsafe-url") || equalLettersIgnoringASCIICase(policy, "always"))
3356 setReferrerPolicy(ReferrerPolicyAlways);
3357 else if (equalLettersIgnoringASCIICase(policy, "origin"))
3358 setReferrerPolicy(ReferrerPolicyOrigin);
3359 else if (equalLettersIgnoringASCIICase(policy, "no-referrer-when-downgrade") || equalLettersIgnoringASCIICase(policy, "default"))
3360 setReferrerPolicy(ReferrerPolicyDefault);
3362 addConsoleMessage(MessageSource::Rendering, MessageLevel::Error, "Failed to set referrer policy: The value '" + policy + "' is not one of 'no-referrer', 'origin', 'no-referrer-when-downgrade', or 'unsafe-url'. Defaulting to 'no-referrer'.");
3363 setReferrerPolicy(ReferrerPolicyNever);
3367 MouseEventWithHitTestResults Document::prepareMouseEvent(const HitTestRequest& request, const LayoutPoint& documentPoint, const PlatformMouseEvent& event)
3369 if (!hasLivingRenderTree())
3370 return MouseEventWithHitTestResults(event, HitTestResult(LayoutPoint()));
3372 HitTestResult result(documentPoint);
3373 renderView()->hitTest(request, result);
3375 if (!request.readOnly())
3376 updateHoverActiveState(request, result.innerElement());
3378 return MouseEventWithHitTestResults(event, result);
3381 // DOM Section 1.1.1
3382 bool Document::childTypeAllowed(NodeType type) const
3385 case ATTRIBUTE_NODE:
3386 case CDATA_SECTION_NODE:
3387 case DOCUMENT_FRAGMENT_NODE:
3392 case PROCESSING_INSTRUCTION_NODE:
3394 case DOCUMENT_TYPE_NODE:
3396 // Documents may contain no more than one of each of these.
3397 // (One Element and one DocumentType.)
3398 for (Node* c = firstChild(); c; c = c->nextSibling())
3399 if (c->nodeType() == type)
3406 bool Document::canAcceptChild(const Node& newChild, const Node* refChild, AcceptChildOperation operation) const
3408 if (operation == AcceptChildOperation::Replace && refChild->nodeType() == newChild.nodeType())
3411 switch (newChild.nodeType()) {
3412 case ATTRIBUTE_NODE:
3413 case CDATA_SECTION_NODE:
3418 case PROCESSING_INSTRUCTION_NODE:
3420 case DOCUMENT_FRAGMENT_NODE: {
3421 bool hasSeenElementChild = false;
3422 for (auto* node = downcast<DocumentFragment>(newChild).firstChild(); node; node = node->nextSibling()) {
3423 if (is<Element>(*node)) {
3424 if (hasSeenElementChild)
3426 hasSeenElementChild = true;
3428 if (!canAcceptChild(*node, refChild, operation))
3433 case DOCUMENT_TYPE_NODE: {
3434 auto* existingDocType = childrenOfType<DocumentType>(*this).first();
3435 if (operation == AcceptChildOperation::Replace) {
3436 // parent has a doctype child that is not child, or an element is preceding child.
3437 if (existingDocType && existingDocType != refChild)
3439 if (refChild->previousElementSibling())
3442 ASSERT(operation == AcceptChildOperation::InsertOrAdd);
3443 if (existingDocType)
3445 if ((refChild && refChild->previousElementSibling()) || (!refChild && firstElementChild()))
3450 case ELEMENT_NODE: {
3451 auto* existingElementChild = firstElementChild();
3452 if (operation == AcceptChildOperation::Replace) {
3453 if (existingElementChild && existingElementChild != refChild)
3455 for (auto* child = refChild->nextSibling(); child; child = child->nextSibling()) {
3456 if (is<DocumentType>(*child))
3460 ASSERT(operation == AcceptChildOperation::InsertOrAdd);
3461 if (existingElementChild)
3463 for (auto* child = refChild; child; child = child->nextSibling()) {
3464 if (is<DocumentType>(*child))
3474 Ref<Node> Document::cloneNodeInternal(Document&, CloningOperation type)
3476 Ref<Document> clone = cloneDocumentWithoutChildren();
3477 clone->cloneDataFromDocument(*this);
3479 case CloningOperation::OnlySelf:
3480 case CloningOperation::SelfWithTemplateContent:
3482 case CloningOperation::Everything:
3483 cloneChildNodes(clone);
3486 return WTFMove(clone);
3489 Ref<Document> Document::cloneDocumentWithoutChildren() const
3491 if (isXMLDocument()) {
3492 if (isXHTMLDocument())
3493 return XMLDocument::createXHTML(nullptr, url());
3494 return XMLDocument::create(nullptr, url());
3496 return create(nullptr, url());
3499 void Document::cloneDataFromDocument(const Document& other)
3501 ASSERT(m_url == other.url());
3502 m_baseURL = other.baseURL();
3503 m_baseURLOverride = other.baseURLOverride();
3504 m_documentURI = other.documentURI();
3506 setCompatibilityMode(other.m_compatibilityMode);
3507 setSecurityOriginPolicy(other.securityOriginPolicy());
3508 overrideMIMEType(other.contentType());
3509 setDecoder(other.decoder());
3512 StyleSheetList& Document::styleSheets()
3514 if (!m_styleSheetList)
3515 m_styleSheetList = StyleSheetList::create(this);
3516 return *m_styleSheetList;
3519 String Document::preferredStylesheetSet() const
3521 return authorStyleSheets().preferredStylesheetSetName();
3524 String Document::selectedStylesheetSet() const
3526 return authorStyleSheets().selectedStylesheetSetName();
3529 void Document::setSelectedStylesheetSet(const String& aString)
3531 authorStyleSheets().setSelectedStylesheetSetName(aString);
3532 styleResolverChanged(DeferRecalcStyle);
3535 void Document::evaluateMediaQueryList()
3537 if (m_mediaQueryMatcher)
3538 m_mediaQueryMatcher->styleResolverChanged();
3540 checkViewportDependentPictures();
3543 void Document::checkViewportDependentPictures()
3545 Vector<HTMLPictureElement*, 16> changedPictures;
3546 HashSet<HTMLPictureElement*>::iterator end = m_viewportDependentPictures.end();
3547 for (HashSet<HTMLPictureElement*>::iterator it = m_viewportDependentPictures.begin(); it != end; ++it) {
3548 if ((*it)->viewportChangeAffectedPicture())
3549 changedPictures.append(*it);
3551 for (auto* picture : changedPictures)
3552 picture->sourcesChanged();
3555 void Document::optimizedStyleSheetUpdateTimerFired()
3557 styleResolverChanged(RecalcStyleIfNeeded);
3560 void Document::scheduleOptimizedStyleSheetUpdate()
3562 if (m_optimizedStyleSheetUpdateTimer.isActive())
3564 authorStyleSheets().setPendingUpdateType(AuthorStyleSheets::OptimizedUpdate);
3565 m_optimizedStyleSheetUpdateTimer.startOneShot(0);
3568 void Document::updateViewportUnitsOnResize()
3570 if (!hasStyleWithViewportUnits())
3573 ensureStyleResolver().clearCachedPropertiesAffectedByViewportUnits();
3575 // FIXME: Ideally, we should save the list of elements that have viewport units and only iterate over those.
3576 for (Element* element = ElementTraversal::firstWithin(rootNode()); element; element = ElementTraversal::nextIncludingPseudo(*element)) {
3577 auto* renderer = element->renderer();
3578 if (renderer && renderer->style().hasViewportUnits())
3579 element->setNeedsStyleRecalc(InlineStyleChange);
3583 void Document::addAudioProducer(MediaProducer* audioProducer)
3585 m_audioProducers.add(audioProducer);
3586 updateIsPlayingMedia();
3589 void Document::removeAudioProducer(MediaProducer* audioProducer)
3591 m_audioProducers.remove(audioProducer);
3592 updateIsPlayingMedia();
3595 void Document::updateIsPlayingMedia(uint64_t sourceElementID)
3597 MediaProducer::MediaStateFlags state = MediaProducer::IsNotPlaying;
3598 for (auto* audioProducer : m_audioProducers)
3599 state |= audioProducer->mediaState();
3601 #if ENABLE(MEDIA_SESSION)
3602 if (HTMLMediaElement* sourceElement = HTMLMediaElement::elementWithID(sourceElementID)) {
3603 if (sourceElement->isPlaying())
3604 state |= MediaProducer::IsSourceElementPlaying;
3606 if (auto* session = sourceElement->session()) {
3607 if (auto* controls = session->controls()) {
3608 if (controls->previousTrackEnabled())
3609 state |= MediaProducer::IsPreviousTrackControlEnabled;
3610 if (controls->nextTrackEnabled())
3611 state |= MediaProducer::IsNextTrackControlEnabled;
3617 if (state == m_mediaState)
3620 m_mediaState = state;
3623 page()->updateIsPlayingMedia(sourceElementID);
3626 void Document::pageMutedStateDidChange()
3628 for (auto* audioProducer : m_audioProducers)
3629 audioProducer->pageMutedStateDidChange();
3632 void Document::styleResolverChanged(StyleResolverUpdateFlag updateFlag)
3634 if (m_optimizedStyleSheetUpdateTimer.isActive())
3635 m_optimizedStyleSheetUpdateTimer.stop();
3637 // Don't bother updating, since we haven't loaded all our style info yet
3638 // and haven't calculated the style selector for the first time.
3639 if (!hasLivingRenderTree() || (!m_didCalculateStyleResolver && !haveStylesheetsLoaded())) {
3640 m_styleResolver = nullptr;
3643 m_didCalculateStyleResolver = true;
3645 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
3646 if (!ownerElement())
3647 printf("Beginning update of style selector at time %lld.\n", elapsedTime().count());
3650 auto styleSheetUpdate = (updateFlag == RecalcStyleIfNeeded || updateFlag == DeferRecalcStyleIfNeeded)
3651 ? AuthorStyleSheets::OptimizedUpdate
3652 : AuthorStyleSheets::FullUpdate;
3653 bool stylesheetChangeRequiresStyleRecalc = authorStyleSheets().updateActiveStyleSheets(styleSheetUpdate);
3655 if (updateFlag == DeferRecalcStyle) {
3656 scheduleForcedStyleRecalc();