1/*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4 *           (C) 2001 Dirk Mueller (mueller@kde.org)
5 *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012, 2013 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.
11 *
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.
16 *
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.
21 *
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.
26 */
27
28#include "config.h"
29#include "Document.h"
30
31#include "AXObjectCache.h"
32#include "AnimationController.h"
33#include "Attr.h"
34#include "CDATASection.h"
35#include "CSSStyleDeclaration.h"
36#include "CSSStyleSheet.h"
37#include "CachedCSSStyleSheet.h"
38#include "CachedResourceLoader.h"
39#include "Chrome.h"
40#include "ChromeClient.h"
41#include "Comment.h"
42#include "ContentSecurityPolicy.h"
43#include "CookieJar.h"
44#include "DOMImplementation.h"
45#include "DOMNamedFlowCollection.h"
46#include "DOMWindow.h"
47#include "DateComponents.h"
48#include "Dictionary.h"
49#include "DocumentLoader.h"
50#include "DocumentMarkerController.h"
51#include "DocumentSharedObjectPool.h"
52#include "DocumentType.h"
53#include "Editor.h"
54#include "ElementIterator.h"
55#include "EntityReference.h"
56#include "EventFactory.h"
57#include "EventHandler.h"
58#include "FocusController.h"
59#include "FontLoader.h"
60#include "FormController.h"
61#include "FrameLoader.h"
62#include "FrameLoaderClient.h"
63#include "FrameView.h"
64#include "HTMLAllCollection.h"
65#include "HTMLAnchorElement.h"
66#include "HTMLBaseElement.h"
67#include "HTMLBodyElement.h"
68#include "HTMLCanvasElement.h"
69#include "HTMLCollection.h"
70#include "HTMLDocument.h"
71#include "HTMLElementFactory.h"
72#include "HTMLFormControlElement.h"
73#include "HTMLFrameOwnerElement.h"
74#include "HTMLFrameSetElement.h"
75#include "HTMLHeadElement.h"
76#include "HTMLIFrameElement.h"
77#include "HTMLImageElement.h"
78#include "HTMLLinkElement.h"
79#include "HTMLMediaElement.h"
80#include "HTMLNameCollection.h"
81#include "HTMLParserIdioms.h"
82#include "HTMLPlugInElement.h"
83#include "HTMLScriptElement.h"
84#include "HTMLStyleElement.h"
85#include "HTMLTitleElement.h"
86#include "HTTPHeaderNames.h"
87#include "HTTPParsers.h"
88#include "HashChangeEvent.h"
89#include "History.h"
90#include "HitTestResult.h"
91#include "IconController.h"
92#include "ImageLoader.h"
93#include "InspectorInstrumentation.h"
94#include "JSLazyEventListener.h"
95#include "Language.h"
96#include "LoaderStrategy.h"
97#include "Logging.h"
98#include "MainFrame.h"
99#include "MediaCanStartListener.h"
100#include "MediaQueryList.h"
101#include "MediaQueryMatcher.h"
102#include "MouseEventWithHitTestResults.h"
103#include "NameNodeList.h"
104#include "NestingLevelIncrementer.h"
105#include "NodeIterator.h"
106#include "NodeRareData.h"
107#include "NodeWithIndex.h"
108#include "PageConsole.h"
109#include "PageGroup.h"
110#include "PageTransitionEvent.h"
111#include "PlatformLocale.h"
112#include "PlatformStrategies.h"
113#include "PlugInsResources.h"
114#include "PluginDocument.h"
115#include "PointerLockController.h"
116#include "PopStateEvent.h"
117#include "ProcessingInstruction.h"
118#include "RenderChildIterator.h"
119#include "RenderLayerCompositor.h"
120#include "RenderView.h"
121#include "RenderWidget.h"
122#include "ResourceLoadScheduler.h"
123#include "ResourceLoader.h"
124#include "RuntimeEnabledFeatures.h"
125#include "SVGDocumentExtensions.h"
126#include "SVGElementFactory.h"
127#include "SVGNames.h"
128#include "SVGSVGElement.h"
129#include "SchemeRegistry.h"
130#include "ScopedEventQueue.h"
131#include "ScriptController.h"
132#include "ScriptRunner.h"
133#include "ScriptSourceCode.h"
134#include "ScrollingCoordinator.h"
135#include "SecurityOrigin.h"
136#include "SecurityPolicy.h"
137#include "SegmentedString.h"
138#include "SelectorQuery.h"
139#include "Settings.h"
140#include "ShadowRoot.h"
141#include "StyleProperties.h"
142#include "StyleResolver.h"
143#include "StyleSheetContents.h"
144#include "StyleSheetList.h"
145#include "TextResourceDecoder.h"
146#include "TransformSource.h"
147#include "TreeWalker.h"
148#include "VisitedLinkState.h"
149#include "XMLDocumentParser.h"
150#include "XMLNSNames.h"
151#include "XMLNames.h"
152#include "XPathEvaluator.h"
153#include "XPathExpression.h"
154#include "XPathNSResolver.h"
155#include "XPathResult.h"
156#include "htmlediting.h"
157#include <inspector/ScriptCallStack.h>
158#include <wtf/CurrentTime.h>
159#include <wtf/TemporaryChange.h>
160#include <wtf/text/StringBuffer.h>
161#include <yarr/RegularExpression.h>
162
163#if ENABLE(SHARED_WORKERS)
164#include "SharedWorkerRepository.h"
165#endif
166
167#if ENABLE(XSLT)
168#include "XSLTProcessor.h"
169#endif
170
171
172#if ENABLE(TOUCH_EVENTS)
173#include "TouchList.h"
174#endif
175
176#if PLATFORM(IOS)
177#include "CSSFontSelector.h"
178#include "DeviceMotionClientIOS.h"
179#include "DeviceMotionController.h"
180#include "DeviceOrientationClientIOS.h"
181#include "DeviceOrientationController.h"
182#include "Geolocation.h"
183#include "Navigator.h"
184#include "NavigatorGeolocation.h"
185#include "WKContentObservation.h"
186#include "WebCoreSystemInterface.h"
187#endif
188
189#if ENABLE(IOS_GESTURE_EVENTS)
190#include "GestureEvent.h"
191#endif
192
193#if ENABLE(MATHML)
194#include "MathMLElement.h"
195#include "MathMLElementFactory.h"
196#include "MathMLNames.h"
197#endif
198
199#if ENABLE(FULLSCREEN_API)
200#include "RenderFullScreen.h"
201#endif
202
203#if ENABLE(REQUEST_ANIMATION_FRAME)
204#include "RequestAnimationFrameCallback.h"
205#include "ScriptedAnimationController.h"
206#endif
207
208#if ENABLE(IOS_TEXT_AUTOSIZING)
209#include "TextAutoSizing.h"
210#endif
211
212#if ENABLE(TEXT_AUTOSIZING)
213#include "TextAutosizer.h"
214#endif
215
216#if ENABLE(CSP_NEXT)
217#include "DOMSecurityPolicy.h"
218#endif
219
220#if ENABLE(VIDEO_TRACK)
221#include "CaptionUserPreferences.h"
222#endif
223
224#if ENABLE(WEB_REPLAY)
225#include "WebReplayInputs.h"
226#include <replay/EmptyInputCursor.h>
227#include <replay/InputCursor.h>
228#endif
229
230using namespace WTF;
231using namespace Unicode;
232
233namespace WebCore {
234
235using namespace HTMLNames;
236
237// #define INSTRUMENT_LAYOUT_SCHEDULING 1
238
239static const unsigned cMaxWriteRecursionDepth = 21;
240
241// DOM Level 2 says (letters added):
242//
243// a) Name start characters must have one of the categories Ll, Lu, Lo, Lt, Nl.
244// b) Name characters other than Name-start characters must have one of the categories Mc, Me, Mn, Lm, or Nd.
245// c) Characters in the compatibility area (i.e. with character code greater than #xF900 and less than #xFFFE) are not allowed in XML names.
246// 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.
247// 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.
248// f) Characters #x20DD-#x20E0 are excluded (in accordance with Unicode, section 5.14).
249// g) Character #x00B7 is classified as an extender, because the property list so identifies it.
250// h) Character #x0387 is added as a name character, because #x00B7 is its canonical equivalent.
251// i) Characters ':' and '_' are allowed as name-start characters.
252// j) Characters '-' and '.' are allowed as name characters.
253//
254// It also contains complete tables. If we decide it's better, we could include those instead of the following code.
255
256static inline bool isValidNameStart(UChar32 c)
257{
258    // rule (e) above
259    if ((c >= 0x02BB && c <= 0x02C1) || c == 0x559 || c == 0x6E5 || c == 0x6E6)
260        return true;
261
262    // rule (i) above
263    if (c == ':' || c == '_')
264        return true;
265
266    // rules (a) and (f) above
267    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)))
268        return false;
269
270    // rule (c) above
271    if (c >= 0xF900 && c < 0xFFFE)
272        return false;
273
274    // rule (d) above
275    int type = u_getIntPropertyValue(c, UCHAR_DECOMPOSITION_TYPE);
276    if (type == U_DT_FONT || type == U_DT_COMPAT)
277        return false;
278
279    return true;
280}
281
282static inline bool isValidNamePart(UChar32 c)
283{
284    // rules (a), (e), and (i) above
285    if (isValidNameStart(c))
286        return true;
287
288    // rules (g) and (h) above
289    if (c == 0x00B7 || c == 0x0387)
290        return true;
291
292    // rule (j) above
293    if (c == '-' || c == '.')
294        return true;
295
296    // rules (b) and (f) above
297    if (!(U_GET_GC_MASK(c) & (U_GC_M_MASK | U_GC_LM_MASK | U_GC_ND_MASK)))
298        return false;
299
300    // rule (c) above
301    if (c >= 0xF900 && c < 0xFFFE)
302        return false;
303
304    // rule (d) above
305    int type = u_getIntPropertyValue(c, UCHAR_DECOMPOSITION_TYPE);
306    if (type == U_DT_FONT || type == U_DT_COMPAT)
307        return false;
308
309    return true;
310}
311
312static bool shouldInheritSecurityOriginFromOwner(const URL& url)
313{
314    // http://www.whatwg.org/specs/web-apps/current-work/#origin-0
315    //
316    // If a Document has the address "about:blank"
317    //     The origin of the Document is the origin it was assigned when its browsing context was created.
318    //
319    // Note: We generalize this to all "blank" URLs and invalid URLs because we
320    // treat all of these URLs as about:blank.
321    //
322    return url.isEmpty() || url.isBlankURL();
323}
324
325static Widget* widgetForElement(Element* focusedElement)
326{
327    if (!focusedElement)
328        return nullptr;
329    auto renderer = focusedElement->renderer();
330    if (!renderer || !renderer->isWidget())
331        return nullptr;
332    return toRenderWidget(renderer)->widget();
333}
334
335static bool acceptsEditingFocus(Node* node)
336{
337    ASSERT(node);
338    ASSERT(node->hasEditableStyle());
339
340    Node* root = node->rootEditableElement();
341    Frame* frame = node->document().frame();
342    if (!frame || !root)
343        return false;
344
345    return frame->editor().shouldBeginEditing(rangeOfContents(*root).get());
346}
347
348static bool canAccessAncestor(const SecurityOrigin* activeSecurityOrigin, Frame* targetFrame)
349{
350    // targetFrame can be 0 when we're trying to navigate a top-level frame
351    // that has a 0 opener.
352    if (!targetFrame)
353        return false;
354
355    const bool isLocalActiveOrigin = activeSecurityOrigin->isLocal();
356    for (Frame* ancestorFrame = targetFrame; ancestorFrame; ancestorFrame = ancestorFrame->tree().parent()) {
357        Document* ancestorDocument = ancestorFrame->document();
358        // FIXME: Should be an ASSERT? Frames should alway have documents.
359        if (!ancestorDocument)
360            return true;
361
362        const SecurityOrigin* ancestorSecurityOrigin = ancestorDocument->securityOrigin();
363        if (activeSecurityOrigin->canAccess(ancestorSecurityOrigin))
364            return true;
365
366        // Allow file URL descendant navigation even when allowFileAccessFromFileURLs is false.
367        // FIXME: It's a bit strange to special-case local origins here. Should we be doing
368        // something more general instead?
369        if (isLocalActiveOrigin && ancestorSecurityOrigin->isLocal())
370            return true;
371    }
372
373    return false;
374}
375
376static void printNavigationErrorMessage(Frame* frame, const URL& activeURL, const char* reason)
377{
378    String message = "Unsafe JavaScript attempt to initiate navigation for frame with URL '" + frame->document()->url().string() + "' from frame with URL '" + activeURL.string() + "'. " + reason + "\n";
379
380    // FIXME: should we print to the console of the document performing the navigation instead?
381    frame->document()->domWindow()->printErrorMessage(message);
382}
383
384uint64_t Document::s_globalTreeVersion = 0;
385
386#if ENABLE(IOS_TEXT_AUTOSIZING)
387void TextAutoSizingTraits::constructDeletedValue(TextAutoSizingKey& slot)
388{
389    new (&slot) TextAutoSizingKey(TextAutoSizingKey::deletedKeyStyle(), TextAutoSizingKey::deletedKeyDoc());
390}
391
392bool TextAutoSizingTraits::isDeletedValue(const TextAutoSizingKey& value)
393{
394    return value.style() == TextAutoSizingKey::deletedKeyStyle() && value.doc() == TextAutoSizingKey::deletedKeyDoc();
395}
396#endif
397
398HashSet<Document*>& Document::allDocuments()
399{
400    static NeverDestroyed<HashSet<Document*>> documents;
401    return documents;
402}
403
404Document::Document(Frame* frame, const URL& url, unsigned documentClasses, unsigned constructionFlags)
405    : ContainerNode(*this, CreateDocument)
406    , TreeScope(*this)
407#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS)
408    , m_handlingTouchEvent(false)
409    , m_touchEventRegionsDirty(false)
410    , m_touchEventsChangedTimer(this, &Document::touchEventsChangedTimerFired)
411#endif
412    , m_referencingNodeCount(0)
413    , m_didCalculateStyleResolver(false)
414    , m_hasNodesWithPlaceholderStyle(false)
415    , m_needsNotifyRemoveAllPendingStylesheet(false)
416    , m_ignorePendingStylesheets(false)
417    , m_pendingSheetLayout(NoLayoutWithPendingSheets)
418    , m_frame(frame)
419    , m_activeParserCount(0)
420    , m_wellFormed(false)
421    , m_printing(false)
422    , m_paginatedForScreen(false)
423    , m_ignoreAutofocus(false)
424    , m_compatibilityMode(DocumentCompatibilityMode::NoQuirksMode)
425    , m_compatibilityModeLocked(false)
426    , m_textColor(Color::black)
427    , m_domTreeVersion(++s_globalTreeVersion)
428    , m_listenerTypes(0)
429    , m_mutationObserverTypes(0)
430    , m_styleSheetCollection(*this)
431    , m_visitedLinkState(std::make_unique<VisitedLinkState>(*this))
432    , m_visuallyOrdered(false)
433    , m_readyState(Complete)
434    , m_bParsing(false)
435    , m_optimizedStyleSheetUpdateTimer(this, &Document::optimizedStyleSheetUpdateTimerFired)
436    , m_styleRecalcTimer(this, &Document::styleRecalcTimerFired)
437    , m_pendingStyleRecalcShouldForce(false)
438    , m_inStyleRecalc(false)
439    , m_closeAfterStyleRecalc(false)
440    , m_gotoAnchorNeededAfterStylesheetsLoad(false)
441    , m_frameElementsShouldIgnoreScrolling(false)
442    , m_containsValidityStyleRules(false)
443    , m_updateFocusAppearanceRestoresSelection(false)
444    , m_ignoreDestructiveWriteCount(0)
445    , m_titleSetExplicitly(false)
446    , m_markers(std::make_unique<DocumentMarkerController>())
447    , m_updateFocusAppearanceTimer(this, &Document::updateFocusAppearanceTimerFired)
448    , m_cssTarget(nullptr)
449    , m_processingLoadEvent(false)
450    , m_loadEventFinished(false)
451    , m_startTime(std::chrono::steady_clock::now())
452    , m_overMinimumLayoutThreshold(false)
453    , m_scriptRunner(std::make_unique<ScriptRunner>(*this))
454    , m_xmlVersion(ASCIILiteral("1.0"))
455    , m_xmlStandalone(StandaloneUnspecified)
456    , m_hasXMLDeclaration(false)
457    , m_designMode(inherit)
458#if !ASSERT_DISABLED
459    , m_inInvalidateNodeListAndCollectionCaches(false)
460#endif
461#if ENABLE(DASHBOARD_SUPPORT)
462    , m_hasAnnotatedRegions(false)
463    , m_annotatedRegionsDirty(false)
464#endif
465    , m_createRenderers(true)
466    , m_inPageCache(false)
467    , m_accessKeyMapValid(false)
468    , m_documentClasses(documentClasses)
469    , m_isSynthesized(constructionFlags & Synthesized)
470    , m_isNonRenderedPlaceholder(constructionFlags & NonRenderedPlaceholder)
471    , m_sawElementsInKnownNamespaces(false)
472    , m_isSrcdocDocument(false)
473    , m_eventQueue(*this)
474    , m_weakFactory(this)
475#if ENABLE(FULLSCREEN_API)
476    , m_areKeysEnabledInFullScreen(0)
477    , m_fullScreenRenderer(nullptr)
478    , m_fullScreenChangeDelayTimer(this, &Document::fullScreenChangeDelayTimerFired)
479    , m_isAnimatingFullScreen(false)
480#endif
481    , m_loadEventDelayCount(0)
482    , m_loadEventDelayTimer(this, &Document::loadEventDelayTimerFired)
483    , m_referrerPolicy(ReferrerPolicyDefault)
484    , m_directionSetOnDocumentElement(false)
485    , m_writingModeSetOnDocumentElement(false)
486    , m_writeRecursionIsTooDeep(false)
487    , m_writeRecursionDepth(0)
488    , m_wheelEventHandlerCount(0)
489    , m_lastHandledUserGestureTimestamp(0)
490#if PLATFORM(IOS)
491#if ENABLE(DEVICE_ORIENTATION)
492    , m_deviceMotionClient(std::make_unique<DeviceMotionClientIOS>())
493    , m_deviceMotionController(std::make_unique<DeviceMotionController>(m_deviceMotionClient.get()))
494    , m_deviceOrientationClient(std::make_unique<DeviceOrientationClientIOS>())
495    , m_deviceOrientationController(std::make_unique<DeviceOrientationController>(m_deviceOrientationClient.get()))
496#endif
497#endif
498#if ENABLE(TELEPHONE_NUMBER_DETECTION)
499    , m_isTelephoneNumberParsingAllowed(true)
500#endif
501    , m_pendingTasksTimer(this, &Document::pendingTasksTimerFired)
502    , m_scheduledTasksAreSuspended(false)
503    , m_visualUpdatesAllowed(true)
504    , m_visualUpdatesSuppressionTimer(this, &Document::visualUpdatesSuppressionTimerFired)
505    , m_sharedObjectPoolClearTimer(this, &Document::sharedObjectPoolClearTimerFired)
506#ifndef NDEBUG
507    , m_didDispatchViewportPropertiesChanged(false)
508#endif
509#if ENABLE(TEMPLATE_ELEMENT)
510    , m_templateDocumentHost(nullptr)
511#endif
512#if ENABLE(WEB_REPLAY)
513    , m_inputCursor(EmptyInputCursor::create())
514#endif
515    , m_didAssociateFormControlsTimer(this, &Document::didAssociateFormControlsTimerFired)
516    , m_disabledFieldsetElementsCount(0)
517    , m_hasInjectedPlugInsScript(false)
518    , m_renderTreeBeingDestroyed(false)
519    , m_hasPreparedForDestruction(false)
520    , m_hasStyleWithViewportUnits(false)
521{
522    allDocuments().add(this);
523
524    // We depend on the url getting immediately set in subframes, but we
525    // also depend on the url NOT getting immediately set in opened windows.
526    // See fast/dom/early-frame-url.html
527    // and fast/dom/location-new-window-no-crash.html, respectively.
528    // FIXME: Can/should we unify this behavior?
529    if ((frame && frame->ownerElement()) || !url.isEmpty())
530        setURL(url);
531
532    if (m_frame)
533        m_cachedResourceLoader = &m_frame->loader().activeDocumentLoader()->cachedResourceLoader();
534    if (!m_cachedResourceLoader)
535        m_cachedResourceLoader = CachedResourceLoader::create(nullptr);
536    m_cachedResourceLoader->setDocument(this);
537
538#if ENABLE(TEXT_AUTOSIZING)
539    m_textAutosizer = std::make_unique<TextAutosizer>(this);
540#endif
541
542    resetLinkColor();
543    resetVisitedLinkColor();
544    resetActiveLinkColor();
545
546    initSecurityContext();
547    initDNSPrefetch();
548
549    for (unsigned i = 0; i < WTF_ARRAY_LENGTH(m_nodeListAndCollectionCounts); ++i)
550        m_nodeListAndCollectionCounts[i] = 0;
551}
552
553#if ENABLE(FULLSCREEN_API)
554static bool isAttributeOnAllOwners(const WebCore::QualifiedName& attribute, const WebCore::QualifiedName& prefixedAttribute, const HTMLFrameOwnerElement* owner)
555{
556    if (!owner)
557        return true;
558    do {
559        if (!(owner->hasAttribute(attribute) || owner->hasAttribute(prefixedAttribute)))
560            return false;
561    } while ((owner = owner->document().ownerElement()));
562    return true;
563}
564#endif
565
566PassRefPtr<Document> Document::create(ScriptExecutionContext& context)
567{
568    RefPtr<Document> document = adoptRef(new Document(nullptr, URL()));
569    document->setSecurityOrigin(context.securityOrigin());
570    return document.release();
571}
572
573Document::~Document()
574{
575    allDocuments().remove(this);
576
577    ASSERT(!renderView());
578    ASSERT(!m_inPageCache);
579    ASSERT(m_ranges.isEmpty());
580    ASSERT(!m_parentTreeScope);
581    ASSERT(!m_disabledFieldsetElementsCount);
582
583#if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS)
584    m_deviceMotionClient->deviceMotionControllerDestroyed();
585    m_deviceOrientationClient->deviceOrientationControllerDestroyed();
586#endif
587
588#if ENABLE(TEMPLATE_ELEMENT)
589    if (m_templateDocument)
590        m_templateDocument->setTemplateDocumentHost(nullptr); // balanced in templateDocument().
591#endif
592
593    // FIXME: Should we reset m_domWindow when we detach from the Frame?
594    if (m_domWindow)
595        m_domWindow->resetUnlessSuspendedForPageCache();
596
597    m_scriptRunner = nullptr;
598
599    removeAllEventListeners();
600
601    // Currently we believe that Document can never outlive the parser.
602    // Although the Document may be replaced synchronously, DocumentParsers
603    // generally keep at least one reference to an Element which would in turn
604    // has a reference to the Document.  If you hit this ASSERT, then that
605    // assumption is wrong.  DocumentParser::detach() should ensure that even
606    // if the DocumentParser outlives the Document it won't cause badness.
607    ASSERT(!m_parser || m_parser->refCount() == 1);
608    detachParser();
609
610    if (this == &topDocument())
611        clearAXObjectCache();
612
613    m_decoder = nullptr;
614
615    if (m_styleSheetList)
616        m_styleSheetList->detachFromDocument();
617
618    if (m_elementSheet)
619        m_elementSheet->detachFromDocument();
620    m_styleSheetCollection.detachFromDocument();
621
622    clearStyleResolver(); // We need to destroy CSSFontSelector before destroying m_cachedResourceLoader.
623
624    // It's possible for multiple Documents to end up referencing the same CachedResourceLoader (e.g., SVGImages
625    // load the initial empty document and the SVGDocument with the same DocumentLoader).
626    if (m_cachedResourceLoader->document() == this)
627        m_cachedResourceLoader->setDocument(nullptr);
628    m_cachedResourceLoader.clear();
629
630    // We must call clearRareData() here since a Document class inherits TreeScope
631    // as well as Node. See a comment on TreeScope.h for the reason.
632    if (hasRareData())
633        clearRareData();
634
635    ASSERT(!m_listsInvalidatedAtDocument.size());
636    ASSERT(!m_collectionsInvalidatedAtDocument.size());
637
638    for (unsigned i = 0; i < WTF_ARRAY_LENGTH(m_nodeListAndCollectionCounts); ++i)
639        ASSERT(!m_nodeListAndCollectionCounts[i]);
640}
641
642void Document::removedLastRef()
643{
644    ASSERT(!m_deletionHasBegun);
645    if (m_referencingNodeCount) {
646        // If removing a child removes the last node reference, we don't want the scope to be destroyed
647        // until after removeDetachedChildren returns, so we protect ourselves.
648        incrementReferencingNodeCount();
649
650        // We must make sure not to be retaining any of our children through
651        // these extra pointers or we will create a reference cycle.
652        m_focusedElement = nullptr;
653        m_hoveredElement = nullptr;
654        m_activeElement = nullptr;
655        m_titleElement = nullptr;
656        m_documentElement = nullptr;
657        m_userActionElements.documentDidRemoveLastRef();
658#if ENABLE(FULLSCREEN_API)
659        m_fullScreenElement = nullptr;
660        m_fullScreenElementStack.clear();
661#endif
662
663        detachParser();
664
665        // removeDetachedChildren() doesn't always unregister IDs,
666        // so tear down scope information up front to avoid having
667        // stale references in the map.
668
669        destroyTreeScopeData();
670        removeDetachedChildren();
671        m_formController = nullptr;
672
673        m_markers->detach();
674
675        m_cssCanvasElements.clear();
676
677        commonTeardown();
678
679#ifndef NDEBUG
680        // We need to do this right now since selfOnlyDeref() can delete this.
681        m_inRemovedLastRefFunction = false;
682#endif
683        decrementReferencingNodeCount();
684    } else {
685#ifndef NDEBUG
686        m_inRemovedLastRefFunction = false;
687        m_deletionHasBegun = true;
688#endif
689        delete this;
690    }
691}
692
693void Document::commonTeardown()
694{
695    if (svgExtensions())
696        accessSVGExtensions()->pauseAnimations();
697
698#if ENABLE(REQUEST_ANIMATION_FRAME)
699    clearScriptedAnimationController();
700#endif
701}
702
703Element* Document::getElementByAccessKey(const String& key)
704{
705    if (key.isEmpty())
706        return nullptr;
707    if (!m_accessKeyMapValid) {
708        buildAccessKeyMap(this);
709        m_accessKeyMapValid = true;
710    }
711    return m_elementsByAccessKey.get(key.impl());
712}
713
714void Document::buildAccessKeyMap(TreeScope* scope)
715{
716    ASSERT(scope);
717    for (auto& element : descendantsOfType<Element>(scope->rootNode())) {
718        const AtomicString& accessKey = element.fastGetAttribute(accesskeyAttr);
719        if (!accessKey.isEmpty())
720            m_elementsByAccessKey.set(accessKey.impl(), &element);
721
722        if (ShadowRoot* root = element.shadowRoot())
723            buildAccessKeyMap(root);
724    }
725}
726
727void Document::invalidateAccessKeyMap()
728{
729    m_accessKeyMapValid = false;
730    m_elementsByAccessKey.clear();
731}
732
733void Document::addImageElementByLowercasedUsemap(const AtomicStringImpl& name, HTMLImageElement& element)
734{
735    return m_imagesByUsemap.add(name, element, *this);
736}
737
738void Document::removeImageElementByLowercasedUsemap(const AtomicStringImpl& name, HTMLImageElement& element)
739{
740    return m_imagesByUsemap.remove(name, element);
741}
742
743HTMLImageElement* Document::imageElementByLowercasedUsemap(const AtomicStringImpl& name) const
744{
745    return m_imagesByUsemap.getElementByLowercasedUsemap(name, *this);
746}
747
748SelectorQuery* Document::selectorQueryForString(const String& selectorString, ExceptionCode& ec)
749{
750    if (selectorString.isEmpty()) {
751        ec = SYNTAX_ERR;
752        return nullptr;
753    }
754
755    if (!m_selectorQueryCache)
756        m_selectorQueryCache = std::make_unique<SelectorQueryCache>();
757    return m_selectorQueryCache->add(selectorString, *this, ec);
758}
759
760void Document::clearSelectorQueryCache()
761{
762    m_selectorQueryCache = nullptr;
763}
764
765MediaQueryMatcher& Document::mediaQueryMatcher()
766{
767    if (!m_mediaQueryMatcher)
768        m_mediaQueryMatcher = MediaQueryMatcher::create(this);
769    return *m_mediaQueryMatcher;
770}
771
772void Document::setCompatibilityMode(DocumentCompatibilityMode mode)
773{
774    if (m_compatibilityModeLocked || mode == m_compatibilityMode)
775        return;
776    bool wasInQuirksMode = inQuirksMode();
777    m_compatibilityMode = mode;
778
779    clearSelectorQueryCache();
780
781    if (inQuirksMode() != wasInQuirksMode) {
782        // All user stylesheets have to reparse using the different mode.
783        m_styleSheetCollection.clearPageUserSheet();
784        m_styleSheetCollection.invalidateInjectedStyleSheetCache();
785    }
786}
787
788String Document::compatMode() const
789{
790    return inQuirksMode() ? "BackCompat" : "CSS1Compat";
791}
792
793void Document::resetLinkColor()
794{
795    m_linkColor = Color(0, 0, 238);
796}
797
798void Document::resetVisitedLinkColor()
799{
800    m_visitedLinkColor = Color(85, 26, 139);
801}
802
803void Document::resetActiveLinkColor()
804{
805    m_activeLinkColor.setNamedColor("red");
806}
807
808DOMImplementation* Document::implementation()
809{
810    if (!m_implementation)
811        m_implementation = std::make_unique<DOMImplementation>(*this);
812    return m_implementation.get();
813}
814
815bool Document::hasManifest() const
816{
817    return documentElement() && documentElement()->hasTagName(htmlTag) && documentElement()->hasAttribute(manifestAttr);
818}
819
820DocumentType* Document::doctype() const
821{
822    for (Node* node = firstChild(); node; node = node->nextSibling()) {
823        if (node->isDocumentTypeNode())
824            return static_cast<DocumentType*>(node);
825    }
826    return nullptr;
827}
828
829void Document::childrenChanged(const ChildChange& change)
830{
831    ContainerNode::childrenChanged(change);
832
833#if PLATFORM(IOS)
834    // FIXME: Chrome::didReceiveDocType() used to be called only when the doctype changed. We need to check the
835    // impact of calling this systematically. If the overhead is negligible, we need to rename didReceiveDocType,
836    // otherwise, we need to detect the doc type changes before updating the viewport.
837    if (Page* page = this->page())
838        page->chrome().didReceiveDocType(frame());
839#endif
840
841    Element* newDocumentElement = childrenOfType<Element>(*this).first();
842    if (newDocumentElement == m_documentElement)
843        return;
844    m_documentElement = newDocumentElement;
845    // The root style used for media query matching depends on the document element.
846    clearStyleResolver();
847}
848
849PassRefPtr<Element> Document::createElement(const AtomicString& name, ExceptionCode& ec)
850{
851    if (!isValidName(name)) {
852        ec = INVALID_CHARACTER_ERR;
853        return nullptr;
854    }
855
856    if (isXHTMLDocument())
857        return HTMLElementFactory::createElement(QualifiedName(nullAtom, name, xhtmlNamespaceURI), *this);
858
859    return createElement(QualifiedName(nullAtom, name, nullAtom), false);
860}
861
862PassRefPtr<DocumentFragment> Document::createDocumentFragment()
863{
864    return DocumentFragment::create(document());
865}
866
867PassRefPtr<Text> Document::createTextNode(const String& data)
868{
869    return Text::create(*this, data);
870}
871
872PassRefPtr<Comment> Document::createComment(const String& data)
873{
874    return Comment::create(*this, data);
875}
876
877PassRefPtr<CDATASection> Document::createCDATASection(const String& data, ExceptionCode& ec)
878{
879    if (isHTMLDocument()) {
880        ec = NOT_SUPPORTED_ERR;
881        return nullptr;
882    }
883    return CDATASection::create(*this, data);
884}
885
886PassRefPtr<ProcessingInstruction> Document::createProcessingInstruction(const String& target, const String& data, ExceptionCode& ec)
887{
888    if (!isValidName(target)) {
889        ec = INVALID_CHARACTER_ERR;
890        return nullptr;
891    }
892    if (isHTMLDocument()) {
893        ec = NOT_SUPPORTED_ERR;
894        return nullptr;
895    }
896    return ProcessingInstruction::create(*this, target, data);
897}
898
899PassRefPtr<EntityReference> Document::createEntityReference(const String& name, ExceptionCode& ec)
900{
901    if (!isValidName(name)) {
902        ec = INVALID_CHARACTER_ERR;
903        return nullptr;
904    }
905    if (isHTMLDocument()) {
906        ec = NOT_SUPPORTED_ERR;
907        return nullptr;
908    }
909    return EntityReference::create(*this, name);
910}
911
912PassRefPtr<Text> Document::createEditingTextNode(const String& text)
913{
914    return Text::createEditingText(*this, text);
915}
916
917PassRefPtr<CSSStyleDeclaration> Document::createCSSStyleDeclaration()
918{
919    Ref<MutableStyleProperties> propertySet(MutableStyleProperties::create());
920    return propertySet->ensureCSSStyleDeclaration();
921}
922
923PassRefPtr<Node> Document::importNode(Node* importedNode, bool deep, ExceptionCode& ec)
924{
925    ec = 0;
926
927    if (!importedNode) {
928        ec = NOT_SUPPORTED_ERR;
929        return nullptr;
930    }
931
932    switch (importedNode->nodeType()) {
933    case TEXT_NODE:
934        return createTextNode(importedNode->nodeValue());
935    case CDATA_SECTION_NODE:
936        return createCDATASection(importedNode->nodeValue(), ec);
937    case ENTITY_REFERENCE_NODE:
938        return createEntityReference(importedNode->nodeName(), ec);
939    case PROCESSING_INSTRUCTION_NODE:
940        return createProcessingInstruction(importedNode->nodeName(), importedNode->nodeValue(), ec);
941    case COMMENT_NODE:
942        return createComment(importedNode->nodeValue());
943    case ELEMENT_NODE: {
944        Element& oldElement = toElement(*importedNode);
945        // FIXME: The following check might be unnecessary. Is it possible that
946        // oldElement has mismatched prefix/namespace?
947        if (!hasValidNamespaceForElements(oldElement.tagQName())) {
948            ec = NAMESPACE_ERR;
949            return nullptr;
950        }
951
952        RefPtr<Element> newElement = createElement(oldElement.tagQName(), false);
953        newElement->cloneDataFromElement(oldElement);
954
955        if (deep) {
956            for (Node* oldChild = oldElement.firstChild(); oldChild; oldChild = oldChild->nextSibling()) {
957                RefPtr<Node> newChild = importNode(oldChild, true, ec);
958                if (ec)
959                    return nullptr;
960                newElement->appendChild(newChild.release(), ec);
961                if (ec)
962                    return nullptr;
963            }
964        }
965
966        return newElement.release();
967    }
968    case ATTRIBUTE_NODE:
969        return Attr::create(*this, QualifiedName(nullAtom, toAttr(*importedNode).name(), nullAtom), toAttr(*importedNode).value());
970    case DOCUMENT_FRAGMENT_NODE: {
971        if (importedNode->isShadowRoot()) {
972            // ShadowRoot nodes should not be explicitly importable.
973            // Either they are imported along with their host node, or created implicitly.
974            break;
975        }
976        DocumentFragment& oldFragment = toDocumentFragment(*importedNode);
977        RefPtr<DocumentFragment> newFragment = createDocumentFragment();
978        if (deep) {
979            for (Node* oldChild = oldFragment.firstChild(); oldChild; oldChild = oldChild->nextSibling()) {
980                RefPtr<Node> newChild = importNode(oldChild, true, ec);
981                if (ec)
982                    return nullptr;
983                newFragment->appendChild(newChild.release(), ec);
984                if (ec)
985                    return nullptr;
986            }
987        }
988
989        return newFragment.release();
990    }
991    case ENTITY_NODE:
992    case NOTATION_NODE:
993        // FIXME: It should be possible to import these node types, however in DOM3 the DocumentType is readonly, so there isn't much sense in doing that.
994        // Ability to add these imported nodes to a DocumentType will be considered for addition to a future release of the DOM.
995    case DOCUMENT_NODE:
996    case DOCUMENT_TYPE_NODE:
997    case XPATH_NAMESPACE_NODE:
998        break;
999    }
1000    ec = NOT_SUPPORTED_ERR;
1001    return nullptr;
1002}
1003
1004
1005PassRefPtr<Node> Document::adoptNode(PassRefPtr<Node> source, ExceptionCode& ec)
1006{
1007    if (!source) {
1008        ec = NOT_SUPPORTED_ERR;
1009        return nullptr;
1010    }
1011
1012    if (source->isReadOnlyNode()) {
1013        ec = NO_MODIFICATION_ALLOWED_ERR;
1014        return nullptr;
1015    }
1016
1017    EventQueueScope scope;
1018
1019    switch (source->nodeType()) {
1020    case ENTITY_NODE:
1021    case NOTATION_NODE:
1022    case DOCUMENT_NODE:
1023    case DOCUMENT_TYPE_NODE:
1024    case XPATH_NAMESPACE_NODE:
1025        ec = NOT_SUPPORTED_ERR;
1026        return nullptr;
1027    case ATTRIBUTE_NODE: {
1028        Attr& attr = toAttr(*source);
1029        if (attr.ownerElement())
1030            attr.ownerElement()->removeAttributeNode(&attr, ec);
1031        break;
1032    }
1033    default:
1034        if (source->isShadowRoot()) {
1035            // ShadowRoot cannot disconnect itself from the host node.
1036            ec = HIERARCHY_REQUEST_ERR;
1037            return nullptr;
1038        }
1039        if (source->isFrameOwnerElement()) {
1040            HTMLFrameOwnerElement& frameOwnerElement = toHTMLFrameOwnerElement(*source);
1041            if (frame() && frame()->tree().isDescendantOf(frameOwnerElement.contentFrame())) {
1042                ec = HIERARCHY_REQUEST_ERR;
1043                return nullptr;
1044            }
1045        }
1046        if (source->parentNode()) {
1047            source->parentNode()->removeChild(source.get(), ec);
1048            if (ec)
1049                return nullptr;
1050        }
1051    }
1052
1053    adoptIfNeeded(source.get());
1054
1055    return source;
1056}
1057
1058bool Document::hasValidNamespaceForElements(const QualifiedName& qName)
1059{
1060    // These checks are from DOM Core Level 2, createElementNS
1061    // http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-DocCrElNS
1062    if (!qName.prefix().isEmpty() && qName.namespaceURI().isNull()) // createElementNS(null, "html:div")
1063        return false;
1064    if (qName.prefix() == xmlAtom && qName.namespaceURI() != XMLNames::xmlNamespaceURI) // createElementNS("http://www.example.com", "xml:lang")
1065        return false;
1066
1067    // Required by DOM Level 3 Core and unspecified by DOM Level 2 Core:
1068    // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-DocCrElNS
1069    // createElementNS("http://www.w3.org/2000/xmlns/", "foo:bar"), createElementNS(null, "xmlns:bar"), createElementNS(null, "xmlns")
1070    if (qName.prefix() == xmlnsAtom || (qName.prefix().isEmpty() && qName.localName() == xmlnsAtom))
1071        return qName.namespaceURI() == XMLNSNames::xmlnsNamespaceURI;
1072    return qName.namespaceURI() != XMLNSNames::xmlnsNamespaceURI;
1073}
1074
1075bool Document::hasValidNamespaceForAttributes(const QualifiedName& qName)
1076{
1077    return hasValidNamespaceForElements(qName);
1078}
1079
1080// FIXME: This should really be in a possible ElementFactory class.
1081PassRefPtr<Element> Document::createElement(const QualifiedName& name, bool createdByParser)
1082{
1083    RefPtr<Element> element;
1084
1085    // FIXME: Use registered namespaces and look up in a hash to find the right factory.
1086    if (name.namespaceURI() == xhtmlNamespaceURI)
1087        element = HTMLElementFactory::createElement(name, *this, nullptr, createdByParser);
1088    else if (name.namespaceURI() == SVGNames::svgNamespaceURI)
1089        element = SVGElementFactory::createElement(name, *this, createdByParser);
1090#if ENABLE(MATHML)
1091    else if (name.namespaceURI() == MathMLNames::mathmlNamespaceURI)
1092        element = MathMLElementFactory::createElement(name, *this, createdByParser);
1093#endif
1094
1095    if (element)
1096        m_sawElementsInKnownNamespaces = true;
1097    else
1098        element = Element::create(name, document());
1099
1100    // <image> uses imgTag so we need a special rule.
1101    ASSERT((name.matches(imageTag) && element->tagQName().matches(imgTag) && element->tagQName().prefix() == name.prefix()) || name == element->tagQName());
1102
1103    return element.release();
1104}
1105
1106bool Document::cssRegionsEnabled() const
1107{
1108    return RuntimeEnabledFeatures::sharedFeatures().cssRegionsEnabled();
1109}
1110
1111bool Document::cssCompositingEnabled() const
1112{
1113    return RuntimeEnabledFeatures::sharedFeatures().cssCompositingEnabled();
1114}
1115
1116#if ENABLE(CSS_REGIONS)
1117
1118PassRefPtr<DOMNamedFlowCollection> Document::webkitGetNamedFlows()
1119{
1120    if (!cssRegionsEnabled() || !renderView())
1121        return nullptr;
1122
1123    updateStyleIfNeeded();
1124
1125    return namedFlows()->createCSSOMSnapshot();
1126}
1127
1128#endif
1129
1130NamedFlowCollection* Document::namedFlows()
1131{
1132    if (!m_namedFlows)
1133        m_namedFlows = NamedFlowCollection::create(this);
1134
1135    return m_namedFlows.get();
1136}
1137
1138PassRefPtr<Element> Document::createElementNS(const String& namespaceURI, const String& qualifiedName, ExceptionCode& ec)
1139{
1140    String prefix, localName;
1141    if (!parseQualifiedName(qualifiedName, prefix, localName, ec))
1142        return nullptr;
1143
1144    QualifiedName qName(prefix, localName, namespaceURI);
1145    if (!hasValidNamespaceForElements(qName)) {
1146        ec = NAMESPACE_ERR;
1147        return nullptr;
1148    }
1149
1150    return createElement(qName, false);
1151}
1152
1153String Document::readyState() const
1154{
1155    DEPRECATED_DEFINE_STATIC_LOCAL(const String, loading, (ASCIILiteral("loading")));
1156    DEPRECATED_DEFINE_STATIC_LOCAL(const String, interactive, (ASCIILiteral("interactive")));
1157    DEPRECATED_DEFINE_STATIC_LOCAL(const String, complete, (ASCIILiteral("complete")));
1158
1159    switch (m_readyState) {
1160    case Loading:
1161        return loading;
1162    case Interactive:
1163        return interactive;
1164    case Complete:
1165        return complete;
1166    }
1167
1168    ASSERT_NOT_REACHED();
1169    return String();
1170}
1171
1172void Document::setReadyState(ReadyState readyState)
1173{
1174    if (readyState == m_readyState)
1175        return;
1176
1177#if ENABLE(WEB_TIMING)
1178    switch (readyState) {
1179    case Loading:
1180        if (!m_documentTiming.domLoading)
1181            m_documentTiming.domLoading = monotonicallyIncreasingTime();
1182        break;
1183    case Interactive:
1184        if (!m_documentTiming.domInteractive)
1185            m_documentTiming.domInteractive = monotonicallyIncreasingTime();
1186        break;
1187    case Complete:
1188        if (!m_documentTiming.domComplete)
1189            m_documentTiming.domComplete = monotonicallyIncreasingTime();
1190        break;
1191    }
1192#endif
1193
1194    m_readyState = readyState;
1195    dispatchEvent(Event::create(eventNames().readystatechangeEvent, false, false));
1196
1197    if (settings() && settings()->suppressesIncrementalRendering())
1198        setVisualUpdatesAllowed(readyState);
1199}
1200
1201void Document::setVisualUpdatesAllowed(ReadyState readyState)
1202{
1203    ASSERT(settings() && settings()->suppressesIncrementalRendering());
1204    switch (readyState) {
1205    case Loading:
1206        ASSERT(!m_visualUpdatesSuppressionTimer.isActive());
1207        ASSERT(m_visualUpdatesAllowed);
1208        setVisualUpdatesAllowed(false);
1209        break;
1210    case Interactive:
1211        ASSERT(m_visualUpdatesSuppressionTimer.isActive() || m_visualUpdatesAllowed);
1212        break;
1213    case Complete:
1214        if (m_visualUpdatesSuppressionTimer.isActive()) {
1215            ASSERT(!m_visualUpdatesAllowed);
1216
1217            if (!view()->visualUpdatesAllowedByClient())
1218                return;
1219
1220            setVisualUpdatesAllowed(true);
1221        } else
1222            ASSERT(m_visualUpdatesAllowed);
1223        break;
1224    }
1225}
1226
1227void Document::setVisualUpdatesAllowed(bool visualUpdatesAllowed)
1228{
1229    if (m_visualUpdatesAllowed == visualUpdatesAllowed)
1230        return;
1231
1232    m_visualUpdatesAllowed = visualUpdatesAllowed;
1233
1234    if (visualUpdatesAllowed)
1235        m_visualUpdatesSuppressionTimer.stop();
1236    else
1237        m_visualUpdatesSuppressionTimer.startOneShot(settings()->incrementalRenderingSuppressionTimeoutInSeconds());
1238
1239    if (!visualUpdatesAllowed)
1240        return;
1241
1242    FrameView* frameView = view();
1243    bool needsLayout = frameView && renderView() && (frameView->layoutPending() || renderView()->needsLayout());
1244    if (needsLayout)
1245        updateLayout();
1246
1247    if (Page* page = this->page()) {
1248        if (frame()->isMainFrame()) {
1249            frameView->addPaintPendingMilestones(DidFirstPaintAfterSuppressedIncrementalRendering);
1250            if (page->requestedLayoutMilestones() & DidFirstLayoutAfterSuppressedIncrementalRendering)
1251                frame()->loader().didLayout(DidFirstLayoutAfterSuppressedIncrementalRendering);
1252        }
1253    }
1254
1255    if (view())
1256        view()->updateCompositingLayersAfterLayout();
1257
1258    if (RenderView* renderView = this->renderView())
1259        renderView->repaintViewAndCompositedLayers();
1260
1261    if (Frame* frame = this->frame())
1262        frame->loader().forcePageTransitionIfNeeded();
1263}
1264
1265void Document::visualUpdatesSuppressionTimerFired(Timer<Document>&)
1266{
1267    ASSERT(!m_visualUpdatesAllowed);
1268
1269    // If the client is extending the visual update suppression period explicitly, the
1270    // watchdog should not re-enable visual updates itself, but should wait for the client.
1271    if (!view()->visualUpdatesAllowedByClient())
1272        return;
1273
1274    setVisualUpdatesAllowed(true);
1275}
1276
1277void Document::setVisualUpdatesAllowedByClient(bool visualUpdatesAllowedByClient)
1278{
1279    // We should only re-enable visual updates if ReadyState is Completed or the watchdog timer has fired,
1280    // both of which we can determine by looking at the timer.
1281
1282    if (visualUpdatesAllowedByClient && !m_visualUpdatesSuppressionTimer.isActive() && !visualUpdatesAllowed())
1283        setVisualUpdatesAllowed(true);
1284}
1285
1286AtomicString Document::encoding() const
1287{
1288    if (TextResourceDecoder* d = decoder())
1289        return d->encoding().domName();
1290    return String();
1291}
1292
1293String Document::defaultCharset() const
1294{
1295    if (Settings* settings = this->settings())
1296        return settings->defaultTextEncodingName();
1297    return String();
1298}
1299
1300void Document::setCharset(const String& charset)
1301{
1302    if (!decoder())
1303        return;
1304    decoder()->setEncoding(charset, TextResourceDecoder::UserChosenEncoding);
1305}
1306
1307void Document::setContentLanguage(const String& language)
1308{
1309    if (m_contentLanguage == language)
1310        return;
1311    m_contentLanguage = language;
1312
1313    // Recalculate style so language is used when selecting the initial font.
1314    styleResolverChanged(DeferRecalcStyle);
1315}
1316
1317void Document::setXMLVersion(const String& version, ExceptionCode& ec)
1318{
1319    if (!implementation()->hasFeature("XML", String())) {
1320        ec = NOT_SUPPORTED_ERR;
1321        return;
1322    }
1323
1324    if (!XMLDocumentParser::supportsXMLVersion(version)) {
1325        ec = NOT_SUPPORTED_ERR;
1326        return;
1327    }
1328
1329    m_xmlVersion = version;
1330}
1331
1332void Document::setXMLStandalone(bool standalone, ExceptionCode& ec)
1333{
1334    if (!implementation()->hasFeature("XML", String())) {
1335        ec = NOT_SUPPORTED_ERR;
1336        return;
1337    }
1338
1339    m_xmlStandalone = standalone ? Standalone : NotStandalone;
1340}
1341
1342void Document::setDocumentURI(const String& uri)
1343{
1344    // This property is read-only from JavaScript, but writable from Objective-C.
1345    m_documentURI = uri;
1346    updateBaseURL();
1347}
1348
1349URL Document::baseURI() const
1350{
1351    return m_baseURL;
1352}
1353
1354void Document::setContent(const String& content)
1355{
1356    open();
1357    // FIXME: This should probably use insert(), but that's (intentionally)
1358    // not implemented for the XML parser as it's normally synonymous with
1359    // document.write(). append() will end up yielding, but close() will
1360    // pump the tokenizer syncrhonously and finish the parse.
1361    m_parser->append(content.impl());
1362    close();
1363}
1364
1365String Document::suggestedMIMEType() const
1366{
1367    if (isXHTMLDocument())
1368        return ASCIILiteral("application/xhtml+xml");
1369    if (isSVGDocument())
1370        return ASCIILiteral("image/svg+xml");
1371    if (xmlStandalone())
1372        return ASCIILiteral("text/xml");
1373    if (isHTMLDocument())
1374        return ASCIILiteral("text/html");
1375    if (DocumentLoader* loader = this->loader())
1376        return loader->responseMIMEType();
1377    return String();
1378}
1379
1380Element* Document::elementFromPoint(int x, int y) const
1381{
1382    if (!hasLivingRenderTree())
1383        return nullptr;
1384
1385    return TreeScope::elementFromPoint(x, y);
1386}
1387
1388PassRefPtr<Range> Document::caretRangeFromPoint(int x, int y)
1389{
1390    if (!hasLivingRenderTree())
1391        return nullptr;
1392    LayoutPoint localPoint;
1393    Node* node = nodeFromPoint(this, x, y, &localPoint);
1394    if (!node)
1395        return nullptr;
1396
1397    Node* shadowAncestorNode = ancestorInThisScope(node);
1398    if (shadowAncestorNode != node) {
1399        unsigned offset = shadowAncestorNode->nodeIndex();
1400        ContainerNode* container = shadowAncestorNode->parentNode();
1401        return Range::create(*this, container, offset, container, offset);
1402    }
1403
1404    RenderObject* renderer = node->renderer();
1405    if (!renderer)
1406        return nullptr;
1407    VisiblePosition visiblePosition = renderer->positionForPoint(localPoint, nullptr);
1408    if (visiblePosition.isNull())
1409        return nullptr;
1410
1411    Position rangeCompliantPosition = visiblePosition.deepEquivalent().parentAnchoredEquivalent();
1412    return Range::create(*this, rangeCompliantPosition, rangeCompliantPosition);
1413}
1414
1415/*
1416 * Performs three operations:
1417 *  1. Convert control characters to spaces
1418 *  2. Trim leading and trailing spaces
1419 *  3. Collapse internal whitespace.
1420 */
1421template <typename CharacterType>
1422static inline StringWithDirection canonicalizedTitle(Document* document, const StringWithDirection& titleWithDirection)
1423{
1424    const String& title = titleWithDirection.string();
1425    const CharacterType* characters = title.characters<CharacterType>();
1426    unsigned length = title.length();
1427    unsigned i;
1428
1429    StringBuffer<CharacterType> buffer(length);
1430    unsigned builderIndex = 0;
1431
1432    // Skip leading spaces and leading characters that would convert to spaces
1433    for (i = 0; i < length; ++i) {
1434        CharacterType c = characters[i];
1435        if (!(c <= 0x20 || c == 0x7F))
1436            break;
1437    }
1438
1439    if (i == length)
1440        return StringWithDirection();
1441
1442    // Replace control characters with spaces, and backslashes with currency symbols, and collapse whitespace.
1443    bool previousCharWasWS = false;
1444    for (; i < length; ++i) {
1445        CharacterType c = characters[i];
1446        if (c <= 0x20 || c == 0x7F || (U_GET_GC_MASK(c) & (U_GC_ZL_MASK | U_GC_ZP_MASK))) {
1447            if (previousCharWasWS)
1448                continue;
1449            buffer[builderIndex++] = ' ';
1450            previousCharWasWS = true;
1451        } else {
1452            buffer[builderIndex++] = c;
1453            previousCharWasWS = false;
1454        }
1455    }
1456
1457    // Strip trailing spaces
1458    while (builderIndex > 0) {
1459        --builderIndex;
1460        if (buffer[builderIndex] != ' ')
1461            break;
1462    }
1463
1464    if (!builderIndex && buffer[builderIndex] == ' ')
1465        return StringWithDirection();
1466
1467    buffer.shrink(builderIndex + 1);
1468
1469    // Replace the backslashes with currency symbols if the encoding requires it.
1470    document->displayBufferModifiedByEncoding(buffer.characters(), buffer.length());
1471
1472    return StringWithDirection(String::adopt(buffer), titleWithDirection.direction());
1473}
1474
1475void Document::updateTitle(const StringWithDirection& title)
1476{
1477    if (m_rawTitle == title)
1478        return;
1479
1480    m_rawTitle = title;
1481
1482    if (m_rawTitle.string().isEmpty())
1483        m_title = StringWithDirection();
1484    else {
1485        if (m_rawTitle.string().is8Bit())
1486            m_title = canonicalizedTitle<LChar>(this, m_rawTitle);
1487        else
1488            m_title = canonicalizedTitle<UChar>(this, m_rawTitle);
1489    }
1490    if (DocumentLoader* loader = this->loader())
1491        loader->setTitle(m_title);
1492}
1493
1494void Document::setTitle(const String& title)
1495{
1496    // Title set by JavaScript -- overrides any title elements.
1497    m_titleSetExplicitly = true;
1498    if (!isHTMLDocument() && !isXHTMLDocument())
1499        m_titleElement = nullptr;
1500    else if (!m_titleElement) {
1501        if (HTMLElement* headElement = head()) {
1502            m_titleElement = createElement(titleTag, false);
1503            headElement->appendChild(m_titleElement, ASSERT_NO_EXCEPTION);
1504        }
1505    }
1506
1507    // The DOM API has no method of specifying direction, so assume LTR.
1508    updateTitle(StringWithDirection(title, LTR));
1509
1510    if (m_titleElement && isHTMLTitleElement(m_titleElement.get()))
1511        toHTMLTitleElement(m_titleElement.get())->setText(title);
1512}
1513
1514void Document::setTitleElement(const StringWithDirection& title, Element* titleElement)
1515{
1516    if (titleElement != m_titleElement) {
1517        if (m_titleElement || m_titleSetExplicitly) {
1518            // Only allow the first title element to change the title -- others have no effect.
1519            return;
1520        }
1521        m_titleElement = titleElement;
1522    }
1523
1524    updateTitle(title);
1525}
1526
1527void Document::removeTitle(Element* titleElement)
1528{
1529    if (m_titleElement != titleElement)
1530        return;
1531
1532    m_titleElement = nullptr;
1533    m_titleSetExplicitly = false;
1534
1535    // Update title based on first title element in the head, if one exists.
1536    if (HTMLElement* headElement = head()) {
1537        if (auto firstTitle = childrenOfType<HTMLTitleElement>(*headElement).first())
1538            setTitleElement(firstTitle->textWithDirection(), firstTitle);
1539    }
1540
1541    if (!m_titleElement)
1542        updateTitle(StringWithDirection());
1543}
1544
1545void Document::registerForVisibilityStateChangedCallbacks(Element* element)
1546{
1547    m_visibilityStateCallbackElements.add(element);
1548}
1549
1550void Document::unregisterForVisibilityStateChangedCallbacks(Element* element)
1551{
1552    m_visibilityStateCallbackElements.remove(element);
1553}
1554
1555void Document::visibilityStateChanged()
1556{
1557    dispatchEvent(Event::create(eventNames().visibilitychangeEvent, false, false));
1558    for (auto it = m_visibilityStateCallbackElements.begin(); it != m_visibilityStateCallbackElements.end(); ++it)
1559        (*it)->visibilityStateChanged();
1560}
1561
1562PageVisibilityState Document::pageVisibilityState() const
1563{
1564    // The visibility of the document is inherited from the visibility of the
1565    // page. If there is no page associated with the document, we will assume
1566    // that the page is hidden, as specified by the spec:
1567    // http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/PageVisibility/Overview.html#dom-document-hidden
1568    if (!m_frame || !m_frame->page())
1569        return PageVisibilityStateHidden;
1570    return m_frame->page()->visibilityState();
1571}
1572
1573String Document::visibilityState() const
1574{
1575    return pageVisibilityStateString(pageVisibilityState());
1576}
1577
1578bool Document::hidden() const
1579{
1580    return pageVisibilityState() != PageVisibilityStateVisible;
1581}
1582
1583#if ENABLE(CSP_NEXT)
1584DOMSecurityPolicy* Document::securityPolicy()
1585{
1586    if (!m_domSecurityPolicy)
1587        m_domSecurityPolicy = DOMSecurityPolicy::create(this);
1588    return m_domSecurityPolicy.get();
1589}
1590#endif
1591
1592String Document::nodeName() const
1593{
1594    return "#document";
1595}
1596
1597Node::NodeType Document::nodeType() const
1598{
1599    return DOCUMENT_NODE;
1600}
1601
1602FormController& Document::formController()
1603{
1604    if (!m_formController)
1605        m_formController = std::make_unique<FormController>();
1606    return *m_formController;
1607}
1608
1609Vector<String> Document::formElementsState() const
1610{
1611    if (!m_formController)
1612        return Vector<String>();
1613    return m_formController->formElementsState();
1614}
1615
1616void Document::setStateForNewFormElements(const Vector<String>& stateVector)
1617{
1618    if (!stateVector.size() && !m_formController)
1619        return;
1620    formController().setStateForNewFormElements(stateVector);
1621}
1622
1623FrameView* Document::view() const
1624{
1625    return m_frame ? m_frame->view() : nullptr;
1626}
1627
1628Page* Document::page() const
1629{
1630    return m_frame ? m_frame->page() : nullptr;
1631}
1632
1633Settings* Document::settings() const
1634{
1635    return m_frame ? &m_frame->settings() : nullptr;
1636}
1637
1638PassRefPtr<Range> Document::createRange()
1639{
1640    return Range::create(*this);
1641}
1642
1643PassRefPtr<NodeIterator> Document::createNodeIterator(Node* root, unsigned whatToShow,
1644    PassRefPtr<NodeFilter> filter, bool expandEntityReferences, ExceptionCode& ec)
1645{
1646    if (!root) {
1647        ec = NOT_SUPPORTED_ERR;
1648        return nullptr;
1649    }
1650    return NodeIterator::create(root, whatToShow, filter, expandEntityReferences);
1651}
1652
1653PassRefPtr<TreeWalker> Document::createTreeWalker(Node* root, unsigned whatToShow,
1654    PassRefPtr<NodeFilter> filter, bool expandEntityReferences, ExceptionCode& ec)
1655{
1656    if (!root) {
1657        ec = NOT_SUPPORTED_ERR;
1658        return nullptr;
1659    }
1660    return TreeWalker::create(root, whatToShow, filter, expandEntityReferences);
1661}
1662
1663void Document::scheduleForcedStyleRecalc()
1664{
1665    m_pendingStyleRecalcShouldForce = true;
1666    scheduleStyleRecalc();
1667}
1668
1669void Document::scheduleStyleRecalc()
1670{
1671    if (m_styleRecalcTimer.isActive() || inPageCache())
1672        return;
1673
1674    ASSERT(childNeedsStyleRecalc() || m_pendingStyleRecalcShouldForce);
1675
1676    // FIXME: Why on earth is this here? This is clearly misplaced.
1677    invalidateAccessKeyMap();
1678
1679    m_styleRecalcTimer.startOneShot(0);
1680
1681    InspectorInstrumentation::didScheduleStyleRecalculation(this);
1682}
1683
1684void Document::unscheduleStyleRecalc()
1685{
1686    ASSERT(!childNeedsStyleRecalc());
1687
1688    m_styleRecalcTimer.stop();
1689    m_pendingStyleRecalcShouldForce = false;
1690}
1691
1692bool Document::hasPendingStyleRecalc() const
1693{
1694    return m_styleRecalcTimer.isActive() && !m_inStyleRecalc;
1695}
1696
1697bool Document::hasPendingForcedStyleRecalc() const
1698{
1699    return m_styleRecalcTimer.isActive() && m_pendingStyleRecalcShouldForce;
1700}
1701
1702void Document::styleRecalcTimerFired(Timer<Document>&)
1703{
1704    updateStyleIfNeeded();
1705}
1706
1707void Document::recalcStyle(Style::Change change)
1708{
1709    ASSERT(!view() || !view()->isPainting());
1710
1711    // NOTE: XSL code seems to be the only client stumbling in here without a RenderView.
1712    if (!m_renderView)
1713        return;
1714
1715    FrameView& frameView = m_renderView->frameView();
1716    if (frameView.isPainting())
1717        return;
1718
1719    if (m_inStyleRecalc)
1720        return; // Guard against re-entrancy. -dwh
1721
1722    RenderView::RepaintRegionAccumulator repaintRegionAccumulator(renderView());
1723
1724    // FIXME: We should update style on our ancestor chain before proceeding (especially for seamless),
1725    // however doing so currently causes several tests to crash, as Frame::setDocument calls Document::attach
1726    // before setting the DOMWindow on the Frame, or the SecurityOrigin on the document. The attach, in turn
1727    // resolves style (here) and then when we resolve style on the parent chain, we may end up
1728    // re-attaching our containing iframe, which when asked HTMLFrameElementBase::isURLAllowed
1729    // hits a null-dereference due to security code always assuming the document has a SecurityOrigin.
1730
1731    m_styleSheetCollection.flushPendingUpdates();
1732
1733    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willRecalculateStyle(this);
1734
1735    if (m_elementSheet && m_elementSheet->contents().usesRemUnits())
1736        m_styleSheetCollection.setUsesRemUnit(true);
1737
1738    m_inStyleRecalc = true;
1739    {
1740        Style::PostResolutionCallbackDisabler disabler(*this);
1741        WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
1742
1743        if (m_pendingStyleRecalcShouldForce)
1744            change = Style::Force;
1745
1746        if (change == Style::Force) {
1747            // This may get set again during style resolve.
1748            m_hasNodesWithPlaceholderStyle = false;
1749        }
1750
1751        Style::resolveTree(*this, change);
1752
1753        frameView.updateCompositingLayersAfterStyleChange();
1754
1755        clearNeedsStyleRecalc();
1756        clearChildNeedsStyleRecalc();
1757        unscheduleStyleRecalc();
1758
1759        m_inStyleRecalc = false;
1760
1761        // Pseudo element removal and similar may only work with these flags still set. Reset them after the style recalc.
1762        if (m_styleResolver)
1763            m_styleSheetCollection.resetCSSFeatureFlags();
1764    }
1765
1766    // If we wanted to call implicitClose() during recalcStyle, do so now that we're finished.
1767    if (m_closeAfterStyleRecalc) {
1768        m_closeAfterStyleRecalc = false;
1769        implicitClose();
1770    }
1771
1772    InspectorInstrumentation::didRecalculateStyle(cookie);
1773
1774    // As a result of the style recalculation, the currently hovered element might have been
1775    // detached (for example, by setting display:none in the :hover style), schedule another mouseMove event
1776    // to check if any other elements ended up under the mouse pointer due to re-layout.
1777    if (m_hoveredElement && !m_hoveredElement->renderer())
1778        frameView.frame().mainFrame().eventHandler().dispatchFakeMouseMoveEventSoon();
1779}
1780
1781void Document::updateStyleIfNeeded()
1782{
1783    ASSERT(isMainThread());
1784    ASSERT(!view() || !view()->isPainting());
1785
1786    if (!view() || view()->isInLayout())
1787        return;
1788
1789    if (m_optimizedStyleSheetUpdateTimer.isActive())
1790        styleResolverChanged(RecalcStyleIfNeeded);
1791
1792    if ((!m_pendingStyleRecalcShouldForce && !childNeedsStyleRecalc()) || inPageCache())
1793        return;
1794
1795    AnimationUpdateBlock animationUpdateBlock(m_frame ? &m_frame->animation() : nullptr);
1796    recalcStyle(Style::NoChange);
1797}
1798
1799void Document::updateLayout()
1800{
1801    ASSERT(isMainThread());
1802
1803    FrameView* frameView = view();
1804    if (frameView && frameView->isInLayout()) {
1805        // View layout should not be re-entrant.
1806        ASSERT_NOT_REACHED();
1807        return;
1808    }
1809
1810    RenderView::RepaintRegionAccumulator repaintRegionAccumulator(renderView());
1811
1812    if (Element* oe = ownerElement())
1813        oe->document().updateLayout();
1814
1815    updateStyleIfNeeded();
1816
1817    StackStats::LayoutCheckPoint layoutCheckPoint;
1818
1819    // Only do a layout if changes have occurred that make it necessary.
1820    if (frameView && renderView() && (frameView->layoutPending() || renderView()->needsLayout()))
1821        frameView->layout();
1822}
1823
1824// FIXME: This is a bad idea and needs to be removed eventually.
1825// Other browsers load stylesheets before they continue parsing the web page.
1826// Since we don't, we can run JavaScript code that needs answers before the
1827// stylesheets are loaded. Doing a layout ignoring the pending stylesheets
1828// lets us get reasonable answers. The long term solution to this problem is
1829// to instead suspend JavaScript execution.
1830void Document::updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasks runPostLayoutTasks)
1831{
1832    bool oldIgnore = m_ignorePendingStylesheets;
1833
1834    if (!haveStylesheetsLoaded()) {
1835        m_ignorePendingStylesheets = true;
1836        // FIXME: We are willing to attempt to suppress painting with outdated style info only once.  Our assumption is that it would be
1837        // dangerous to try to stop it a second time, after page content has already been loaded and displayed
1838        // with accurate style information.  (Our suppression involves blanking the whole page at the
1839        // moment.  If it were more refined, we might be able to do something better.)
1840        // It's worth noting though that this entire method is a hack, since what we really want to do is
1841        // suspend JS instead of doing a layout with inaccurate information.
1842        HTMLElement* bodyElement = body();
1843        if (bodyElement && !bodyElement->renderer() && m_pendingSheetLayout == NoLayoutWithPendingSheets) {
1844            m_pendingSheetLayout = DidLayoutWithPendingSheets;
1845            styleResolverChanged(RecalcStyleImmediately);
1846        } else if (m_hasNodesWithPlaceholderStyle)
1847            // If new nodes have been added or style recalc has been done with style sheets still pending, some nodes
1848            // may not have had their real style calculated yet. Normally this gets cleaned when style sheets arrive
1849            // but here we need up-to-date style immediately.
1850            recalcStyle(Style::Force);
1851    }
1852
1853    updateLayout();
1854
1855    if (runPostLayoutTasks == RunPostLayoutTasksSynchronously && view())
1856        view()->flushAnyPendingPostLayoutTasks();
1857
1858    m_ignorePendingStylesheets = oldIgnore;
1859}
1860
1861PassRef<RenderStyle> Document::styleForElementIgnoringPendingStylesheets(Element* element)
1862{
1863    ASSERT_ARG(element, &element->document() == this);
1864
1865    // On iOS request delegates called during styleForElement may result in re-entering WebKit and killing the style resolver.
1866    ResourceLoadScheduler::Suspender suspender(*platformStrategies()->loaderStrategy()->resourceLoadScheduler());
1867
1868    TemporaryChange<bool> change(m_ignorePendingStylesheets, true);
1869    return ensureStyleResolver().styleForElement(element, element->parentNode() ? element->parentNode()->computedStyle() : nullptr);
1870}
1871
1872bool Document::isPageBoxVisible(int pageIndex)
1873{
1874    Ref<RenderStyle> pageStyle(ensureStyleResolver().styleForPage(pageIndex));
1875    return pageStyle->visibility() != HIDDEN; // display property doesn't apply to @page.
1876}
1877
1878void Document::pageSizeAndMarginsInPixels(int pageIndex, IntSize& pageSize, int& marginTop, int& marginRight, int& marginBottom, int& marginLeft)
1879{
1880    RefPtr<RenderStyle> style = ensureStyleResolver().styleForPage(pageIndex);
1881
1882    int width = pageSize.width();
1883    int height = pageSize.height();
1884    switch (style->pageSizeType()) {
1885    case PAGE_SIZE_AUTO:
1886        break;
1887    case PAGE_SIZE_AUTO_LANDSCAPE:
1888        if (width < height)
1889            std::swap(width, height);
1890        break;
1891    case PAGE_SIZE_AUTO_PORTRAIT:
1892        if (width > height)
1893            std::swap(width, height);
1894        break;
1895    case PAGE_SIZE_RESOLVED: {
1896        LengthSize size = style->pageSize();
1897        ASSERT(size.width().isFixed());
1898        ASSERT(size.height().isFixed());
1899        width = valueForLength(size.width(), 0);
1900        height = valueForLength(size.height(), 0);
1901        break;
1902    }
1903    default:
1904        ASSERT_NOT_REACHED();
1905    }
1906    pageSize = IntSize(width, height);
1907
1908    // The percentage is calculated with respect to the width even for margin top and bottom.
1909    // http://www.w3.org/TR/CSS2/box.html#margin-properties
1910    marginTop = style->marginTop().isAuto() ? marginTop : intValueForLength(style->marginTop(), width);
1911    marginRight = style->marginRight().isAuto() ? marginRight : intValueForLength(style->marginRight(), width);
1912    marginBottom = style->marginBottom().isAuto() ? marginBottom : intValueForLength(style->marginBottom(), width);
1913    marginLeft = style->marginLeft().isAuto() ? marginLeft : intValueForLength(style->marginLeft(), width);
1914}
1915
1916void Document::createStyleResolver()
1917{
1918    bool matchAuthorAndUserStyles = true;
1919    if (Settings* settings = this->settings())
1920        matchAuthorAndUserStyles = settings->authorAndUserStylesEnabled();
1921    m_styleResolver = std::make_unique<StyleResolver>(*this, matchAuthorAndUserStyles);
1922    m_styleSheetCollection.combineCSSFeatureFlags();
1923}
1924
1925void Document::clearStyleResolver()
1926{
1927    m_styleResolver = nullptr;
1928}
1929
1930void Document::createRenderTree()
1931{
1932    ASSERT(!renderView());
1933    ASSERT(!m_inPageCache);
1934    ASSERT(!m_axObjectCache || this != &topDocument());
1935
1936    if (m_isNonRenderedPlaceholder)
1937        return;
1938
1939    // FIXME: It would be better if we could pass the resolved document style directly here.
1940    m_renderView = createRenderer<RenderView>(*this, RenderStyle::create());
1941    Node::setRenderer(m_renderView.get());
1942
1943    renderView()->setIsInWindow(true);
1944
1945    recalcStyle(Style::Force);
1946}
1947
1948static void pageWheelEventHandlerCountChanged(Page& page)
1949{
1950    unsigned count = 0;
1951    for (const Frame* frame = &page.mainFrame(); frame; frame = frame->tree().traverseNext()) {
1952        if (Document* document = frame->document())
1953            count += document->wheelEventHandlerCount();
1954    }
1955    page.chrome().client().numWheelEventHandlersChanged(count);
1956}
1957
1958void Document::didBecomeCurrentDocumentInFrame()
1959{
1960    // FIXME: Are there cases where the document can be dislodged from the frame during the event handling below?
1961    // If so, then m_frame could become 0, and we need to do something about that.
1962
1963    m_frame->script().updateDocument();
1964
1965    if (!hasLivingRenderTree())
1966        createRenderTree();
1967
1968    updateViewportArguments();
1969
1970    // FIXME: Doing this only for the main frame is insufficient.
1971    // Changing a subframe can also change the wheel event handler count.
1972    // FIXME: Doing this only when a document goes into the frame is insufficient.
1973    // Removing a document can also change the wheel event handler count.
1974    // FIXME: Doing this every time is a waste. If the current document and its
1975    // subframes' documents have no wheel event handlers, then the count did not change,
1976    // unless the documents they are replacing had wheel event handlers.
1977    if (page() && m_frame->isMainFrame())
1978        pageWheelEventHandlerCountChanged(*page());
1979
1980#if ENABLE(TOUCH_EVENTS)
1981    // FIXME: Doing this only for the main frame is insufficient.
1982    // A subframe could have touch event handlers.
1983    if (hasTouchEventHandlers() && page() && m_frame->isMainFrame())
1984        page()->chrome().client().needTouchEvents(true);
1985#endif
1986
1987#if PLATFORM(IOS)
1988    // Ensure that document scheduled task state matches frame timer state. It can be out of sync
1989    // if timers state changed while the document was not in the frame (possibly in page cache,
1990    // or simply newly created).
1991    // FIXME: How does this interact with cross-platform code below?
1992    if (m_frame->timersPaused())
1993        suspendScheduledTasks(ActiveDOMObject::DocumentWillBePaused);
1994    else
1995        resumeScheduledTasks(ActiveDOMObject::DocumentWillBePaused);
1996#endif
1997
1998    if (m_frame->activeDOMObjectsAndAnimationsSuspended()) {
1999        suspendScriptedAnimationControllerCallbacks();
2000        m_frame->animation().suspendAnimationsForDocument(this);
2001        suspendActiveDOMObjects(ActiveDOMObject::PageWillBeSuspended);
2002    }
2003}
2004
2005void Document::disconnectFromFrame()
2006{
2007    m_frame = nullptr;
2008}
2009
2010void Document::destroyRenderTree()
2011{
2012    ASSERT(hasLivingRenderTree());
2013    ASSERT(!m_inPageCache);
2014
2015    TemporaryChange<bool> change(m_renderTreeBeingDestroyed, true);
2016
2017    if (this == &topDocument())
2018        clearAXObjectCache();
2019
2020    documentWillBecomeInactive();
2021
2022    if (FrameView* frameView = view())
2023        frameView->detachCustomScrollbars();
2024
2025#if ENABLE(FULLSCREEN_API)
2026    if (m_fullScreenRenderer)
2027        setFullScreenRenderer(nullptr);
2028#endif
2029
2030    m_hoveredElement = nullptr;
2031    m_focusedElement = nullptr;
2032    m_activeElement = nullptr;
2033
2034    if (m_documentElement)
2035        Style::detachRenderTree(*m_documentElement);
2036
2037    clearChildNeedsStyleRecalc();
2038
2039    unscheduleStyleRecalc();
2040
2041    m_renderView = nullptr;
2042    Node::setRenderer(nullptr);
2043
2044#if ENABLE(IOS_TEXT_AUTOSIZING)
2045    // Do this before the arena is cleared, which is needed to deref the RenderStyle on TextAutoSizingKey.
2046    m_textAutoSizedNodes.clear();
2047#endif
2048}
2049
2050void Document::prepareForDestruction()
2051{
2052    if (m_hasPreparedForDestruction)
2053        return;
2054
2055#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS)
2056    clearTouchEventListeners();
2057#endif
2058
2059    disconnectDescendantFrames();
2060    if (m_domWindow && m_frame)
2061        m_domWindow->willDetachDocumentFromFrame();
2062
2063    if (hasLivingRenderTree())
2064        destroyRenderTree();
2065
2066    if (isPluginDocument())
2067        toPluginDocument(this)->detachFromPluginElement();
2068
2069#if ENABLE(POINTER_LOCK)
2070    if (page())
2071        page()->pointerLockController().documentDetached(this);
2072#endif
2073
2074    stopActiveDOMObjects();
2075    m_eventQueue.close();
2076#if ENABLE(FULLSCREEN_API)
2077    m_fullScreenChangeEventTargetQueue.clear();
2078    m_fullScreenErrorEventTargetQueue.clear();
2079#endif
2080
2081    commonTeardown();
2082
2083#if ENABLE(SHARED_WORKERS)
2084    SharedWorkerRepository::documentDetached(this);
2085#endif
2086
2087#if ENABLE(TOUCH_EVENTS)
2088    if (m_touchEventTargets && m_touchEventTargets->size() && parentDocument())
2089        parentDocument()->didRemoveEventTargetNode(this);
2090#endif
2091
2092    if (m_mediaQueryMatcher)
2093        m_mediaQueryMatcher->documentDestroyed();
2094
2095    disconnectFromFrame();
2096
2097    m_hasPreparedForDestruction = true;
2098}
2099
2100void Document::removeAllEventListeners()
2101{
2102    EventTarget::removeAllEventListeners();
2103
2104    if (m_domWindow)
2105        m_domWindow->removeAllEventListeners();
2106#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS)
2107    clearTouchEventListeners();
2108#endif
2109    for (Node* node = firstChild(); node; node = NodeTraversal::next(node))
2110        node->removeAllEventListeners();
2111}
2112
2113void Document::platformSuspendOrStopActiveDOMObjects()
2114{
2115#if PLATFORM(IOS)
2116#if ENABLE(DEVICE_ORIENTATION)
2117    if (m_deviceMotionController)
2118        m_deviceMotionController->suspendUpdates();
2119    if (m_deviceOrientationController)
2120        m_deviceOrientationController->suspendUpdates();
2121#endif
2122
2123    if (WebThreadCountOfObservedContentModifiers() > 0) {
2124        Frame* frame = this->frame();
2125        if (Page* page = frame ? frame->page() : nullptr)
2126            page->chrome().client().clearContentChangeObservers(frame);
2127    }
2128#endif
2129}
2130
2131void Document::suspendActiveDOMObjects(ActiveDOMObject::ReasonForSuspension why)
2132{
2133    ScriptExecutionContext::suspendActiveDOMObjects(why);
2134    platformSuspendOrStopActiveDOMObjects();
2135}
2136
2137void Document::resumeActiveDOMObjects(ActiveDOMObject::ReasonForSuspension why)
2138{
2139    ScriptExecutionContext::resumeActiveDOMObjects(why);
2140
2141#if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS)
2142    if (m_deviceMotionController)
2143        m_deviceMotionController->resumeUpdates();
2144    if (m_deviceOrientationController)
2145        m_deviceOrientationController->resumeUpdates();
2146#endif
2147    // FIXME: For iOS, do we need to add content change observers that were removed in Document::suspendActiveDOMObjects()?
2148}
2149
2150void Document::stopActiveDOMObjects()
2151{
2152    ScriptExecutionContext::stopActiveDOMObjects();
2153    platformSuspendOrStopActiveDOMObjects();
2154}
2155
2156void Document::clearAXObjectCache()
2157{
2158    ASSERT(&topDocument() == this);
2159    // Clear the cache member variable before calling delete because attempts
2160    // are made to access it during destruction.
2161    m_axObjectCache = nullptr;
2162}
2163
2164AXObjectCache* Document::existingAXObjectCache() const
2165{
2166    Document& topDocument = this->topDocument();
2167    if (!topDocument.hasLivingRenderTree())
2168        return nullptr;
2169    return topDocument.m_axObjectCache.get();
2170}
2171
2172AXObjectCache* Document::axObjectCache() const
2173{
2174    if (!AXObjectCache::accessibilityEnabled())
2175        return nullptr;
2176
2177    // The only document that actually has a AXObjectCache is the top-level
2178    // document.  This is because we need to be able to get from any WebCoreAXObject
2179    // to any other WebCoreAXObject on the same page.  Using a single cache allows
2180    // lookups across nested webareas (i.e. multiple documents).
2181    Document& topDocument = this->topDocument();
2182
2183    // If the document has already been detached, do not make a new axObjectCache.
2184    if (!topDocument.hasLivingRenderTree())
2185        return nullptr;
2186
2187    ASSERT(&topDocument == this || !m_axObjectCache);
2188    if (!topDocument.m_axObjectCache)
2189        topDocument.m_axObjectCache = std::make_unique<AXObjectCache>(topDocument);
2190    return topDocument.m_axObjectCache.get();
2191}
2192
2193void Document::setVisuallyOrdered()
2194{
2195    m_visuallyOrdered = true;
2196    if (renderView())
2197        renderView()->style().setRTLOrdering(VisualOrder);
2198}
2199
2200PassRefPtr<DocumentParser> Document::createParser()
2201{
2202    // FIXME: this should probably pass the frame instead
2203    return XMLDocumentParser::create(*this, view());
2204}
2205
2206ScriptableDocumentParser* Document::scriptableDocumentParser() const
2207{
2208    return parser() ? parser()->asScriptableDocumentParser() : nullptr;
2209}
2210
2211void Document::open(Document* ownerDocument)
2212{
2213    if (ownerDocument) {
2214        setURL(ownerDocument->url());
2215        m_cookieURL = ownerDocument->cookieURL();
2216        setSecurityOrigin(ownerDocument->securityOrigin());
2217    }
2218
2219    if (m_frame) {
2220        if (ScriptableDocumentParser* parser = scriptableDocumentParser()) {
2221            if (parser->isParsing()) {
2222                // FIXME: HTML5 doesn't tell us to check this, it might not be correct.
2223                if (parser->isExecutingScript())
2224                    return;
2225
2226                if (!parser->wasCreatedByScript() && parser->hasInsertionPoint())
2227                    return;
2228            }
2229        }
2230
2231        if (m_frame->loader().state() == FrameStateProvisional)
2232            m_frame->loader().stopAllLoaders();
2233    }
2234
2235    removeAllEventListeners();
2236    implicitOpen();
2237    if (ScriptableDocumentParser* parser = scriptableDocumentParser())
2238        parser->setWasCreatedByScript(true);
2239
2240    if (m_frame)
2241        m_frame->loader().didExplicitOpen();
2242}
2243
2244void Document::detachParser()
2245{
2246    if (!m_parser)
2247        return;
2248    m_parser->detach();
2249    m_parser.clear();
2250}
2251
2252void Document::cancelParsing()
2253{
2254    if (!m_parser)
2255        return;
2256
2257    // We have to clear the parser to avoid possibly triggering
2258    // the onload handler when closing as a side effect of a cancel-style
2259    // change, such as opening a new document or closing the window while
2260    // still parsing
2261    detachParser();
2262    explicitClose();
2263}
2264
2265void Document::implicitOpen()
2266{
2267    cancelParsing();
2268
2269    removeChildren();
2270
2271    setCompatibilityMode(DocumentCompatibilityMode::NoQuirksMode);
2272
2273    m_parser = createParser();
2274    setParsing(true);
2275    setReadyState(Loading);
2276}
2277
2278HTMLElement* Document::body() const
2279{
2280    // If the document element contains both a frameset and a body, the frameset wins.
2281    auto element = documentElement();
2282    if (!element)
2283        return nullptr;
2284    if (auto frameset = childrenOfType<HTMLFrameSetElement>(*element).first())
2285        return frameset;
2286    return childrenOfType<HTMLBodyElement>(*element).first();
2287}
2288
2289void Document::setBody(PassRefPtr<HTMLElement> prpNewBody, ExceptionCode& ec)
2290{
2291    RefPtr<HTMLElement> newBody = prpNewBody;
2292
2293    if (!newBody || !documentElement() || !newBody->hasTagName(bodyTag)) {
2294        ec = HIERARCHY_REQUEST_ERR;
2295        return;
2296    }
2297
2298    if (&newBody->document() != this) {
2299        ec = 0;
2300        RefPtr<Node> node = importNode(newBody.get(), true, ec);
2301        if (ec)
2302            return;
2303
2304        newBody = toHTMLElement(node.get());
2305    }
2306
2307    HTMLElement* b = body();
2308    if (!b)
2309        documentElement()->appendChild(newBody.release(), ec);
2310    else
2311        documentElement()->replaceChild(newBody.release(), b, ec);
2312}
2313
2314HTMLHeadElement* Document::head()
2315{
2316    if (auto element = documentElement())
2317        return childrenOfType<HTMLHeadElement>(*element).first();
2318    return nullptr;
2319}
2320
2321void Document::close()
2322{
2323    // FIXME: We should follow the specification more closely:
2324    //        http://www.whatwg.org/specs/web-apps/current-work/#dom-document-close
2325
2326    if (!scriptableDocumentParser() || !scriptableDocumentParser()->wasCreatedByScript() || !scriptableDocumentParser()->isParsing())
2327        return;
2328
2329    explicitClose();
2330}
2331
2332void Document::explicitClose()
2333{
2334    if (RefPtr<DocumentParser> parser = m_parser)
2335        parser->finish();
2336
2337    if (!m_frame) {
2338        // Because we have no frame, we don't know if all loading has completed,
2339        // so we just call implicitClose() immediately. FIXME: This might fire
2340        // the load event prematurely <http://bugs.webkit.org/show_bug.cgi?id=14568>.
2341        implicitClose();
2342        return;
2343    }
2344
2345    m_frame->loader().checkCompleted();
2346}
2347
2348void Document::implicitClose()
2349{
2350    // 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.
2351    if (m_inStyleRecalc) {
2352        m_closeAfterStyleRecalc = true;
2353        return;
2354    }
2355
2356    bool wasLocationChangePending = frame() && frame()->navigationScheduler().locationChangePending();
2357    bool doload = !parsing() && m_parser && !m_processingLoadEvent && !wasLocationChangePending;
2358
2359    if (!doload)
2360        return;
2361
2362    // Call to dispatchWindowLoadEvent can blow us from underneath.
2363    Ref<Document> protect(*this);
2364
2365    m_processingLoadEvent = true;
2366
2367    ScriptableDocumentParser* parser = scriptableDocumentParser();
2368    m_wellFormed = parser && parser->wellFormed();
2369
2370    // We have to clear the parser, in case someone document.write()s from the
2371    // onLoad event handler, as in Radar 3206524.
2372    detachParser();
2373
2374    // FIXME: We kick off the icon loader when the Document is done parsing.
2375    // There are earlier opportunities we could start it:
2376    //  -When the <head> finishes parsing
2377    //  -When any new HTMLLinkElement is inserted into the document
2378    // But those add a dynamic component to the favicon that has UI
2379    // ramifications, and we need to decide what is the Right Thing To Do(tm)
2380    Frame* f = frame();
2381    if (f) {
2382        f->loader().icon().startLoader();
2383        f->animation().startAnimationsIfNotSuspended(this);
2384
2385        // FIXME: We shouldn't be dispatching pending events globally on all Documents here.
2386        // For now, only do this when there is a Frame, otherwise this could cause JS reentrancy
2387        // below SVG font parsing, for example. <https://webkit.org/b/136269>
2388        ImageLoader::dispatchPendingBeforeLoadEvents();
2389        ImageLoader::dispatchPendingLoadEvents();
2390        ImageLoader::dispatchPendingErrorEvents();
2391        HTMLLinkElement::dispatchPendingLoadEvents();
2392        HTMLStyleElement::dispatchPendingLoadEvents();
2393    }
2394
2395    // To align the HTML load event and the SVGLoad event for the outermost <svg> element, fire it from
2396    // here, instead of doing it from SVGElement::finishedParsingChildren (if externalResourcesRequired="false",
2397    // which is the default, for ='true' its fired at a later time, once all external resources finished loading).
2398    if (svgExtensions())
2399        accessSVGExtensions()->dispatchSVGLoadEventToOutermostSVGElements();
2400
2401    dispatchWindowLoadEvent();
2402    enqueuePageshowEvent(PageshowEventNotPersisted);
2403    enqueuePopstateEvent(m_pendingStateObject ? m_pendingStateObject.release() : SerializedScriptValue::nullValue());
2404
2405    if (f)
2406        f->loader().handledOnloadEvents();
2407#ifdef INSTRUMENT_LAYOUT_SCHEDULING
2408    if (!ownerElement())
2409        printf("onload fired at %lld\n", elapsedTime().count());
2410#endif
2411
2412    // An event handler may have removed the frame
2413    if (!frame()) {
2414        m_processingLoadEvent = false;
2415        return;
2416    }
2417
2418    // Make sure both the initial layout and reflow happen after the onload
2419    // fires. This will improve onload scores, and other browsers do it.
2420    // If they wanna cheat, we can too. -dwh
2421
2422    if (frame()->navigationScheduler().locationChangePending() && elapsedTime() < settings()->layoutInterval()) {
2423        // Just bail out. Before or during the onload we were shifted to another page.
2424        // The old i-Bench suite does this. When this happens don't bother painting or laying out.
2425        m_processingLoadEvent = false;
2426        view()->unscheduleRelayout();
2427        return;
2428    }
2429
2430    frame()->loader().checkCallImplicitClose();
2431
2432    // We used to force a synchronous display and flush here.  This really isn't
2433    // necessary and can in fact be actively harmful if pages are loading at a rate of > 60fps
2434    // (if your platform is syncing flushes and limiting them to 60fps).
2435    m_overMinimumLayoutThreshold = true;
2436    if (!ownerElement() || (ownerElement()->renderer() && !ownerElement()->renderer()->needsLayout())) {
2437        updateStyleIfNeeded();
2438
2439        // Always do a layout after loading if needed.
2440        if (view() && renderView() && (!renderView()->firstChild() || renderView()->needsLayout()))
2441            view()->layout();
2442    }
2443
2444    m_processingLoadEvent = false;
2445
2446#if PLATFORM(COCOA) || PLATFORM(WIN) || PLATFORM(GTK) || PLATFORM(EFL)
2447    if (f && hasLivingRenderTree() && AXObjectCache::accessibilityEnabled()) {
2448        // The AX cache may have been cleared at this point, but we need to make sure it contains an
2449        // AX object to send the notification to. getOrCreate will make sure that an valid AX object
2450        // exists in the cache (we ignore the return value because we don't need it here). This is
2451        // only safe to call when a layout is not in progress, so it can not be used in postNotification.
2452        axObjectCache()->getOrCreate(renderView());
2453        if (this == &topDocument())
2454            axObjectCache()->postNotification(renderView(), AXObjectCache::AXLoadComplete);
2455        else {
2456            // AXLoadComplete can only be posted on the top document, so if it's a document
2457            // in an iframe that just finished loading, post AXLayoutComplete instead.
2458            axObjectCache()->postNotification(renderView(), AXObjectCache::AXLayoutComplete);
2459        }
2460    }
2461#endif
2462
2463    if (svgExtensions())
2464        accessSVGExtensions()->startAnimations();
2465}
2466
2467void Document::setParsing(bool b)
2468{
2469    m_bParsing = b;
2470
2471    if (m_bParsing && !m_sharedObjectPool)
2472        m_sharedObjectPool = std::make_unique<DocumentSharedObjectPool>();
2473
2474    if (!m_bParsing && view() && !view()->needsLayout())
2475        view()->fireLayoutRelatedMilestonesIfNeeded();
2476
2477#ifdef INSTRUMENT_LAYOUT_SCHEDULING
2478    if (!ownerElement() && !m_bParsing)
2479        printf("Parsing finished at %lld\n", elapsedTime().count());
2480#endif
2481}
2482
2483bool Document::shouldScheduleLayout()
2484{
2485    // This function will only be called when FrameView thinks a layout is needed.
2486    // This enforces a couple extra rules.
2487    //
2488    //    (a) Only schedule a layout once the stylesheets are loaded.
2489    //    (b) Only schedule layout once we have a body element.
2490
2491    return (haveStylesheetsLoaded() && body())
2492        || (documentElement() && !documentElement()->hasTagName(htmlTag));
2493}
2494
2495bool Document::isLayoutTimerActive()
2496{
2497    return view() && view()->layoutPending() && !minimumLayoutDelay().count();
2498}
2499
2500std::chrono::milliseconds Document::minimumLayoutDelay()
2501{
2502    if (m_overMinimumLayoutThreshold)
2503        return std::chrono::milliseconds(0);
2504
2505    std::chrono::milliseconds elapsed = elapsedTime();
2506    m_overMinimumLayoutThreshold = elapsed > settings()->layoutInterval();
2507
2508    // We'll want to schedule the timer to fire at the minimum layout threshold.
2509    return std::max(std::chrono::milliseconds(0), settings()->layoutInterval() - elapsed);
2510}
2511
2512std::chrono::milliseconds Document::elapsedTime() const
2513{
2514    auto elapsedTime = std::chrono::steady_clock::now() - m_startTime;
2515
2516    return std::chrono::duration_cast<std::chrono::milliseconds>(elapsedTime);
2517}
2518
2519void Document::write(const SegmentedString& text, Document* ownerDocument)
2520{
2521    NestingLevelIncrementer nestingLevelIncrementer(m_writeRecursionDepth);
2522
2523    m_writeRecursionIsTooDeep = (m_writeRecursionDepth > 1) && m_writeRecursionIsTooDeep;
2524    m_writeRecursionIsTooDeep = (m_writeRecursionDepth > cMaxWriteRecursionDepth) || m_writeRecursionIsTooDeep;
2525
2526    if (m_writeRecursionIsTooDeep)
2527       return;
2528
2529#ifdef INSTRUMENT_LAYOUT_SCHEDULING
2530    if (!ownerElement())
2531        printf("Beginning a document.write at %lld\n", elapsedTime().count());
2532#endif
2533
2534    bool hasInsertionPoint = m_parser && m_parser->hasInsertionPoint();
2535    if (!hasInsertionPoint && m_ignoreDestructiveWriteCount)
2536        return;
2537
2538    if (!hasInsertionPoint)
2539        open(ownerDocument);
2540
2541    ASSERT(m_parser);
2542    m_parser->insert(text);
2543
2544#ifdef INSTRUMENT_LAYOUT_SCHEDULING
2545    if (!ownerElement())
2546        printf("Ending a document.write at %lld\n", elapsedTime().count());
2547#endif
2548}
2549
2550void Document::write(const String& text, Document* ownerDocument)
2551{
2552    write(SegmentedString(text), ownerDocument);
2553}
2554
2555void Document::writeln(const String& text, Document* ownerDocument)
2556{
2557    write(text, ownerDocument);
2558    write("\n", ownerDocument);
2559}
2560
2561double Document::minimumTimerInterval() const
2562{
2563    Page* p = page();
2564    if (!p)
2565        return ScriptExecutionContext::minimumTimerInterval();
2566    return p->settings().minDOMTimerInterval();
2567}
2568
2569double Document::timerAlignmentInterval() const
2570{
2571    Page* p = page();
2572    if (!p)
2573        return ScriptExecutionContext::timerAlignmentInterval();
2574    return p->settings().domTimerAlignmentInterval();
2575}
2576
2577EventTarget* Document::errorEventTarget()
2578{
2579    return m_domWindow.get();
2580}
2581
2582void Document::logExceptionToConsole(const String& errorMessage, const String& sourceURL, int lineNumber, int columnNumber, PassRefPtr<Inspector::ScriptCallStack> callStack)
2583{
2584    addMessage(MessageSource::JS, MessageLevel::Error, errorMessage, sourceURL, lineNumber, columnNumber, callStack);
2585}
2586
2587void Document::setURL(const URL& url)
2588{
2589    const URL& newURL = url.isEmpty() ? blankURL() : url;
2590    if (newURL == m_url)
2591        return;
2592
2593    m_url = newURL;
2594    m_documentURI = m_url.string();
2595    updateBaseURL();
2596}
2597
2598void Document::updateBaseURL()
2599{
2600    URL oldBaseURL = m_baseURL;
2601    // DOM 3 Core: When the Document supports the feature "HTML" [DOM Level 2 HTML], the base URI is computed using
2602    // first the value of the href attribute of the HTML BASE element if any, and the value of the documentURI attribute
2603    // from the Document interface otherwise.
2604    if (!m_baseElementURL.isEmpty())
2605        m_baseURL = m_baseElementURL;
2606    else if (!m_baseURLOverride.isEmpty())
2607        m_baseURL = m_baseURLOverride;
2608    else {
2609        // The documentURI attribute is read-only from JavaScript, but writable from Objective C, so we need to retain
2610        // this fallback behavior. We use a null base URL, since the documentURI attribute is an arbitrary string
2611        // and DOM 3 Core does not specify how it should be resolved.
2612        m_baseURL = URL(ParsedURLString, documentURI());
2613    }
2614
2615    clearSelectorQueryCache();
2616
2617    if (!m_baseURL.isValid())
2618        m_baseURL = URL();
2619
2620    if (m_elementSheet) {
2621        // Element sheet is silly. It never contains anything.
2622        ASSERT(!m_elementSheet->contents().ruleCount());
2623        bool usesRemUnits = m_elementSheet->contents().usesRemUnits();
2624        m_elementSheet = CSSStyleSheet::createInline(*this, m_baseURL);
2625        // FIXME: So we are not really the parser. The right fix is to eliminate the element sheet completely.
2626        m_elementSheet->contents().parserSetUsesRemUnits(usesRemUnits);
2627    }
2628
2629    if (!equalIgnoringFragmentIdentifier(oldBaseURL, m_baseURL)) {
2630        // Base URL change changes any relative visited links.
2631        // 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.
2632        for (auto& anchor : descendantsOfType<HTMLAnchorElement>(*this))
2633            anchor.invalidateCachedVisitedLinkHash();
2634    }
2635}
2636
2637void Document::setBaseURLOverride(const URL& url)
2638{
2639    m_baseURLOverride = url;
2640    updateBaseURL();
2641}
2642
2643void Document::processBaseElement()
2644{
2645    // Find the first href attribute in a base element and the first target attribute in a base element.
2646    const AtomicString* href = nullptr;
2647    const AtomicString* target = nullptr;
2648    auto baseDescendants = descendantsOfType<HTMLBaseElement>(*this);
2649    for (auto base = baseDescendants.begin(), end = baseDescendants.end(); base != end && (!href || !target); ++base) {
2650        if (!href) {
2651            const AtomicString& value = base->fastGetAttribute(hrefAttr);
2652            if (!value.isNull())
2653                href = &value;
2654        }
2655        if (!target) {
2656            const AtomicString& value = base->fastGetAttribute(targetAttr);
2657            if (!value.isNull())
2658                target = &value;
2659        }
2660    }
2661
2662    // FIXME: Since this doesn't share code with completeURL it may not handle encodings correctly.
2663    URL baseElementURL;
2664    if (href) {
2665        String strippedHref = stripLeadingAndTrailingHTMLSpaces(*href);
2666        if (!strippedHref.isEmpty())
2667            baseElementURL = URL(url(), strippedHref);
2668    }
2669    if (m_baseElementURL != baseElementURL && contentSecurityPolicy()->allowBaseURI(baseElementURL)) {
2670        m_baseElementURL = baseElementURL;
2671        updateBaseURL();
2672    }
2673
2674    m_baseTarget = target ? *target : nullAtom;
2675}
2676
2677String Document::userAgent(const URL& url) const
2678{
2679    return frame() ? frame()->loader().userAgent(url) : String();
2680}
2681
2682void Document::disableEval(const String& errorMessage)
2683{
2684    if (!frame())
2685        return;
2686
2687    frame()->script().disableEval(errorMessage);
2688}
2689
2690bool Document::canNavigate(Frame* targetFrame)
2691{
2692    if (!m_frame)
2693        return false;
2694
2695    // FIXME: We shouldn't call this function without a target frame, but
2696    // fast/forms/submit-to-blank-multiple-times.html depends on this function
2697    // returning true when supplied with a 0 targetFrame.
2698    if (!targetFrame)
2699        return true;
2700
2701    // Frame-busting is generally allowed, but blocked for sandboxed frames lacking the 'allow-top-navigation' flag.
2702    if (!isSandboxed(SandboxTopNavigation) && targetFrame == &m_frame->tree().top())
2703        return true;
2704
2705    if (isSandboxed(SandboxNavigation)) {
2706        if (targetFrame->tree().isDescendantOf(m_frame))
2707            return true;
2708
2709        const char* reason = "The frame attempting navigation is sandboxed, and is therefore disallowed from navigating its ancestors.";
2710        if (isSandboxed(SandboxTopNavigation) && targetFrame == &m_frame->tree().top())
2711            reason = "The frame attempting navigation of the top-level window is sandboxed, but the 'allow-top-navigation' flag is not set.";
2712
2713        printNavigationErrorMessage(targetFrame, url(), reason);
2714        return false;
2715    }
2716
2717    // This is the normal case. A document can navigate its decendant frames,
2718    // or, more generally, a document can navigate a frame if the document is
2719    // in the same origin as any of that frame's ancestors (in the frame
2720    // hierarchy).
2721    //
2722    // See http://www.adambarth.com/papers/2008/barth-jackson-mitchell.pdf for
2723    // historical information about this security check.
2724    if (canAccessAncestor(securityOrigin(), targetFrame))
2725        return true;
2726
2727    // Top-level frames are easier to navigate than other frames because they
2728    // display their URLs in the address bar (in most browsers). However, there
2729    // are still some restrictions on navigation to avoid nuisance attacks.
2730    // Specifically, a document can navigate a top-level frame if that frame
2731    // opened the document or if the document is the same-origin with any of
2732    // the top-level frame's opener's ancestors (in the frame hierarchy).
2733    //
2734    // In both of these cases, the document performing the navigation is in
2735    // some way related to the frame being navigate (e.g., by the "opener"
2736    // and/or "parent" relation). Requiring some sort of relation prevents a
2737    // document from navigating arbitrary, unrelated top-level frames.
2738    if (!targetFrame->tree().parent()) {
2739        if (targetFrame == m_frame->loader().opener())
2740            return true;
2741
2742        if (canAccessAncestor(securityOrigin(), targetFrame->loader().opener()))
2743            return true;
2744    }
2745
2746    printNavigationErrorMessage(targetFrame, url(), "The frame attempting navigation is neither same-origin with the target, nor is it the target's parent or opener.");
2747    return false;
2748}
2749
2750Frame* Document::findUnsafeParentScrollPropagationBoundary()
2751{
2752    Frame* currentFrame = m_frame;
2753    if (!currentFrame)
2754        return nullptr;
2755
2756    Frame* ancestorFrame = currentFrame->tree().parent();
2757
2758    while (ancestorFrame) {
2759        if (!ancestorFrame->document()->securityOrigin()->canAccess(securityOrigin()))
2760            return currentFrame;
2761        currentFrame = ancestorFrame;
2762        ancestorFrame = ancestorFrame->tree().parent();
2763    }
2764    return nullptr;
2765}
2766
2767void Document::didRemoveAllPendingStylesheet()
2768{
2769    m_needsNotifyRemoveAllPendingStylesheet = false;
2770
2771    styleResolverChanged(DeferRecalcStyleIfNeeded);
2772
2773    if (m_pendingSheetLayout == DidLayoutWithPendingSheets) {
2774        m_pendingSheetLayout = IgnoreLayoutWithPendingSheets;
2775        if (renderView())
2776            renderView()->repaintViewAndCompositedLayers();
2777    }
2778
2779    if (ScriptableDocumentParser* parser = scriptableDocumentParser())
2780        parser->executeScriptsWaitingForStylesheets();
2781
2782    if (m_gotoAnchorNeededAfterStylesheetsLoad && view())
2783        view()->scrollToFragment(m_url);
2784}
2785
2786CSSStyleSheet& Document::elementSheet()
2787{
2788    if (!m_elementSheet)
2789        m_elementSheet = CSSStyleSheet::createInline(*this, m_baseURL);
2790    return *m_elementSheet;
2791}
2792
2793void Document::processHttpEquiv(const String& equiv, const String& content)
2794{
2795    ASSERT(!equiv.isNull() && !content.isNull());
2796
2797    Frame* frame = this->frame();
2798
2799    HTTPHeaderName headerName;
2800    if (!findHTTPHeaderName(equiv, headerName))
2801        return;
2802
2803    switch (headerName) {
2804    case HTTPHeaderName::DefaultStyle:
2805        // The preferred style set has been overridden as per section
2806        // 14.3.2 of the HTML4.0 specification.  We need to update the
2807        // sheet used variable and then update our style selector.
2808        // For more info, see the test at:
2809        // http://www.hixie.ch/tests/evil/css/import/main/preferred.html
2810        // -dwh
2811        m_styleSheetCollection.setSelectedStylesheetSetName(content);
2812        m_styleSheetCollection.setPreferredStylesheetSetName(content);
2813        styleResolverChanged(DeferRecalcStyle);
2814        break;
2815
2816    case HTTPHeaderName::Refresh: {
2817        double delay;
2818        String urlString;
2819        if (frame && parseHTTPRefresh(content, true, delay, urlString)) {
2820            URL completedURL;
2821            if (urlString.isEmpty())
2822                completedURL = m_url;
2823            else
2824                completedURL = completeURL(urlString);
2825            if (!protocolIsJavaScript(completedURL))
2826                frame->navigationScheduler().scheduleRedirect(delay, completedURL);
2827            else {
2828                String message = "Refused to refresh " + m_url.stringCenterEllipsizedToLength() + " to a javascript: URL";
2829                addConsoleMessage(MessageSource::Security, MessageLevel::Error, message);
2830            }
2831        }
2832
2833        break;
2834    }
2835
2836    case HTTPHeaderName::SetCookie:
2837        // FIXME: make setCookie work on XML documents too; e.g. in case of <html:meta .....>
2838        if (isHTMLDocument()) {
2839            // Exception (for sandboxed documents) ignored.
2840            toHTMLDocument(this)->setCookie(content, IGNORE_EXCEPTION);
2841        }
2842        break;
2843
2844    case HTTPHeaderName::ContentLanguage:
2845        setContentLanguage(content);
2846        break;
2847
2848    case HTTPHeaderName::XDNSPrefetchControl:
2849        parseDNSPrefetchControlHeader(content);
2850        break;
2851
2852    case HTTPHeaderName::XFrameOptions:
2853        if (frame) {
2854            FrameLoader& frameLoader = frame->loader();
2855            unsigned long requestIdentifier = 0;
2856            if (frameLoader.activeDocumentLoader() && frameLoader.activeDocumentLoader()->mainResourceLoader())
2857                requestIdentifier = frameLoader.activeDocumentLoader()->mainResourceLoader()->identifier();
2858            if (frameLoader.shouldInterruptLoadForXFrameOptions(content, url(), requestIdentifier)) {
2859                String message = "Refused to display '" + url().stringCenterEllipsizedToLength() + "' in a frame because it set 'X-Frame-Options' to '" + content + "'.";
2860                frameLoader.stopAllLoaders();
2861                // Stopping the loader isn't enough, as we're already parsing the document; to honor the header's
2862                // intent, we must navigate away from the possibly partially-rendered document to a location that
2863                // doesn't inherit the parent's SecurityOrigin.
2864                frame->navigationScheduler().scheduleLocationChange(securityOrigin(), SecurityOrigin::urlWithUniqueSecurityOrigin(), String());
2865                addConsoleMessage(MessageSource::Security, MessageLevel::Error, message, requestIdentifier);
2866            }
2867        }
2868        break;
2869
2870    case HTTPHeaderName::ContentSecurityPolicy:
2871        contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicy::Enforce);
2872        break;
2873
2874    case HTTPHeaderName::ContentSecurityPolicyReportOnly:
2875        contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicy::Report);
2876        break;
2877
2878    case HTTPHeaderName::XWebKitCSP:
2879        contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicy::PrefixedEnforce);
2880        break;
2881
2882    case HTTPHeaderName::XWebKitCSPReportOnly:
2883        contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicy::PrefixedReport);
2884        break;
2885
2886    default:
2887        break;
2888    }
2889}
2890
2891// Though isspace() considers \t and \v to be whitespace, Win IE doesn't.
2892static bool isSeparator(UChar c)
2893{
2894    return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '=' || c == ',' || c == '\0';
2895}
2896
2897void Document::processArguments(const String& features, void* data, ArgumentsCallback callback)
2898{
2899    // Tread lightly in this code -- it was specifically designed to mimic Win IE's parsing behavior.
2900    unsigned keyBegin, keyEnd;
2901    unsigned valueBegin, valueEnd;
2902
2903    String buffer = features.lower();
2904    unsigned length = buffer.length();
2905    for (unsigned i = 0; i < length; ) {
2906        // skip to first non-separator, but don't skip past the end of the string
2907        while (isSeparator(buffer[i])) {
2908            if (i >= length)
2909                break;
2910            i++;
2911        }
2912        keyBegin = i;
2913
2914        // skip to first separator
2915        while (!isSeparator(buffer[i]))
2916            i++;
2917        keyEnd = i;
2918
2919        // skip to first '=', but don't skip past a ',' or the end of the string
2920        while (buffer[i] != '=') {
2921            if (buffer[i] == ',' || i >= length)
2922                break;
2923            i++;
2924        }
2925
2926        // skip to first non-separator, but don't skip past a ',' or the end of the string
2927        while (isSeparator(buffer[i])) {
2928            if (buffer[i] == ',' || i >= length)
2929                break;
2930            i++;
2931        }
2932        valueBegin = i;
2933
2934        // skip to first separator
2935        while (!isSeparator(buffer[i]))
2936            i++;
2937        valueEnd = i;
2938
2939        ASSERT_WITH_SECURITY_IMPLICATION(i <= length);
2940
2941        String keyString = buffer.substring(keyBegin, keyEnd - keyBegin);
2942        String valueString = buffer.substring(valueBegin, valueEnd - valueBegin);
2943        callback(keyString, valueString, this, data);
2944    }
2945}
2946
2947void Document::processViewport(const String& features, ViewportArguments::Type origin)
2948{
2949    ASSERT(!features.isNull());
2950
2951    if (origin < m_viewportArguments.type)
2952        return;
2953
2954    m_viewportArguments = ViewportArguments(origin);
2955    processArguments(features, (void*)&m_viewportArguments, &setViewportFeature);
2956
2957#if PLATFORM(IOS)
2958    // FIXME: <rdar://problem/8955959> Investigate moving to ToT WebKit's extended Viewport Implementation
2959    // Moving to ToT's implementation would mean calling findConfigurationForViewportData, which does
2960    // bounds checking and determining concrete values for ValueAuto which we already do in UIKit.
2961    // To maintain old behavior, we just need to update a few values, leaving Auto's for UIKit.
2962    if (Page* page = this->page())
2963        finalizeViewportArguments(m_viewportArguments, page->chrome().screenSize());
2964#endif
2965
2966    updateViewportArguments();
2967}
2968
2969void Document::updateViewportArguments()
2970{
2971    if (page() && frame()->isMainFrame()) {
2972#ifndef NDEBUG
2973        m_didDispatchViewportPropertiesChanged = true;
2974#endif
2975        page()->chrome().dispatchViewportPropertiesDidChange(m_viewportArguments);
2976#if PLATFORM(IOS)
2977        page()->chrome().didReceiveDocType(frame());
2978#endif
2979    }
2980}
2981
2982#if PLATFORM(IOS)
2983// FIXME: Find a better place for this functionality.
2984void setParserFeature(const String& key, const String& value, Document* document, void*)
2985{
2986    if (key == "telephone" && equalIgnoringCase(value, "no"))
2987        document->setIsTelephoneNumberParsingAllowed(false);
2988}
2989
2990void Document::processFormatDetection(const String& features)
2991{
2992    ASSERT(!features.isNull());
2993    processArguments(features, nullptr, &setParserFeature);
2994}
2995
2996void Document::processWebAppOrientations()
2997{
2998    if (Page* page = this->page())
2999        page->chrome().client().webAppOrientationsUpdated();
3000}
3001#endif
3002
3003void Document::processReferrerPolicy(const String& policy)
3004{
3005    ASSERT(!policy.isNull());
3006
3007    if (equalIgnoringCase(policy, "never"))
3008        m_referrerPolicy = ReferrerPolicyNever;
3009    else if (equalIgnoringCase(policy, "always"))
3010        m_referrerPolicy = ReferrerPolicyAlways;
3011    else if (equalIgnoringCase(policy, "origin"))
3012        m_referrerPolicy = ReferrerPolicyOrigin;
3013    else if (equalIgnoringCase(policy, "default"))
3014        m_referrerPolicy = ReferrerPolicyDefault;
3015    else {
3016        addConsoleMessage(MessageSource::Rendering, MessageLevel::Error, "Failed to set referrer policy: The value '" + policy + "' is not one of 'always', 'default', 'never', or 'origin'. Defaulting to 'never'.");
3017        m_referrerPolicy = ReferrerPolicyNever;
3018    }
3019}
3020
3021MouseEventWithHitTestResults Document::prepareMouseEvent(const HitTestRequest& request, const LayoutPoint& documentPoint, const PlatformMouseEvent& event)
3022{
3023    if (!hasLivingRenderTree())
3024        return MouseEventWithHitTestResults(event, HitTestResult(LayoutPoint()));
3025
3026    HitTestResult result(documentPoint);
3027    renderView()->hitTest(request, result);
3028
3029    if (!request.readOnly())
3030        updateHoverActiveState(request, result.innerElement());
3031
3032    return MouseEventWithHitTestResults(event, result);
3033}
3034
3035// DOM Section 1.1.1
3036bool Document::childTypeAllowed(NodeType type) const
3037{
3038    switch (type) {
3039    case ATTRIBUTE_NODE:
3040    case CDATA_SECTION_NODE:
3041    case DOCUMENT_FRAGMENT_NODE:
3042    case DOCUMENT_NODE:
3043    case ENTITY_NODE:
3044    case ENTITY_REFERENCE_NODE:
3045    case NOTATION_NODE:
3046    case TEXT_NODE:
3047    case XPATH_NAMESPACE_NODE:
3048        return false;
3049    case COMMENT_NODE:
3050    case PROCESSING_INSTRUCTION_NODE:
3051        return true;
3052    case DOCUMENT_TYPE_NODE:
3053    case ELEMENT_NODE:
3054        // Documents may contain no more than one of each of these.
3055        // (One Element and one DocumentType.)
3056        for (Node* c = firstChild(); c; c = c->nextSibling())
3057            if (c->nodeType() == type)
3058                return false;
3059        return true;
3060    }
3061    return false;
3062}
3063
3064bool Document::canReplaceChild(Node* newChild, Node* oldChild)
3065{
3066    if (!oldChild)
3067        // ContainerNode::replaceChild will raise a NOT_FOUND_ERR.
3068        return true;
3069
3070    if (oldChild->nodeType() == newChild->nodeType())
3071        return true;
3072
3073    int numDoctypes = 0;
3074    int numElements = 0;
3075
3076    // First, check how many doctypes and elements we have, not counting
3077    // the child we're about to remove.
3078    for (Node* c = firstChild(); c; c = c->nextSibling()) {
3079        if (c == oldChild)
3080            continue;
3081
3082        switch (c->nodeType()) {
3083        case DOCUMENT_TYPE_NODE:
3084            numDoctypes++;
3085            break;
3086        case ELEMENT_NODE:
3087            numElements++;
3088            break;
3089        default:
3090            break;
3091        }
3092    }
3093
3094    // Then, see how many doctypes and elements might be added by the new child.
3095    if (newChild->isDocumentFragment()) {
3096        for (Node* c = newChild->firstChild(); c; c = c->nextSibling()) {
3097            switch (c->nodeType()) {
3098            case ATTRIBUTE_NODE:
3099            case CDATA_SECTION_NODE:
3100            case DOCUMENT_FRAGMENT_NODE:
3101            case DOCUMENT_NODE:
3102            case ENTITY_NODE:
3103            case ENTITY_REFERENCE_NODE:
3104            case NOTATION_NODE:
3105            case TEXT_NODE:
3106            case XPATH_NAMESPACE_NODE:
3107                return false;
3108            case COMMENT_NODE:
3109            case PROCESSING_INSTRUCTION_NODE:
3110                break;
3111            case DOCUMENT_TYPE_NODE:
3112                numDoctypes++;
3113                break;
3114            case ELEMENT_NODE:
3115                numElements++;
3116                break;
3117            }
3118        }
3119    } else {
3120        switch (newChild->nodeType()) {
3121        case ATTRIBUTE_NODE:
3122        case CDATA_SECTION_NODE:
3123        case DOCUMENT_FRAGMENT_NODE:
3124        case DOCUMENT_NODE:
3125        case ENTITY_NODE:
3126        case ENTITY_REFERENCE_NODE:
3127        case NOTATION_NODE:
3128        case TEXT_NODE:
3129        case XPATH_NAMESPACE_NODE:
3130            return false;
3131        case COMMENT_NODE:
3132        case PROCESSING_INSTRUCTION_NODE:
3133            return true;
3134        case DOCUMENT_TYPE_NODE:
3135            numDoctypes++;
3136            break;
3137        case ELEMENT_NODE:
3138            numElements++;
3139            break;
3140        }
3141    }
3142
3143    if (numElements > 1 || numDoctypes > 1)
3144        return false;
3145
3146    return true;
3147}
3148
3149PassRefPtr<Node> Document::cloneNode(bool deep)
3150{
3151    RefPtr<Document> clone = cloneDocumentWithoutChildren();
3152    clone->cloneDataFromDocument(*this);
3153    if (deep)
3154        cloneChildNodes(clone.get());
3155    return clone.release();
3156}
3157
3158PassRefPtr<Document> Document::cloneDocumentWithoutChildren() const
3159{
3160    return isXHTMLDocument() ? createXHTML(nullptr, url()) : create(nullptr, url());
3161}
3162
3163void Document::cloneDataFromDocument(const Document& other)
3164{
3165    ASSERT(m_url == other.url());
3166    m_baseURL = other.baseURL();
3167    m_baseURLOverride = other.baseURLOverride();
3168    m_documentURI = other.documentURI();
3169
3170    setCompatibilityMode(other.m_compatibilityMode);
3171    setSecurityOrigin(other.securityOrigin());
3172    setDecoder(other.decoder());
3173}
3174
3175StyleSheetList* Document::styleSheets()
3176{
3177    if (!m_styleSheetList)
3178        m_styleSheetList = StyleSheetList::create(this);
3179    return m_styleSheetList.get();
3180}
3181
3182String Document::preferredStylesheetSet() const
3183{
3184    return m_styleSheetCollection.preferredStylesheetSetName();
3185}
3186
3187String Document::selectedStylesheetSet() const
3188{
3189    return m_styleSheetCollection.selectedStylesheetSetName();
3190}
3191
3192void Document::setSelectedStylesheetSet(const String& aString)
3193{
3194    m_styleSheetCollection.setSelectedStylesheetSetName(aString);
3195    styleResolverChanged(DeferRecalcStyle);
3196}
3197
3198void Document::evaluateMediaQueryList()
3199{
3200    if (m_mediaQueryMatcher)
3201        m_mediaQueryMatcher->styleResolverChanged();
3202}
3203
3204void Document::optimizedStyleSheetUpdateTimerFired(Timer<Document>&)
3205{
3206    styleResolverChanged(RecalcStyleIfNeeded);
3207}
3208
3209void Document::scheduleOptimizedStyleSheetUpdate()
3210{
3211    if (m_optimizedStyleSheetUpdateTimer.isActive())
3212        return;
3213    m_styleSheetCollection.setPendingUpdateType(DocumentStyleSheetCollection::OptimizedUpdate);
3214    m_optimizedStyleSheetUpdateTimer.startOneShot(0);
3215}
3216
3217void Document::updateViewportUnitsOnResize()
3218{
3219    if (!hasStyleWithViewportUnits())
3220        return;
3221
3222    ensureStyleResolver().clearCachedPropertiesAffectedByViewportUnits();
3223
3224    // FIXME: Ideally, we should save the list of elements that have viewport units and only iterate over those.
3225    for (Element* element = ElementTraversal::firstWithin(&rootNode()); element; element = ElementTraversal::nextIncludingPseudo(element)) {
3226        auto* renderer = element->renderer();
3227        if (renderer && renderer->style().hasViewportUnits())
3228            element->setNeedsStyleRecalc(InlineStyleChange);
3229    }
3230}
3231
3232void Document::styleResolverChanged(StyleResolverUpdateFlag updateFlag)
3233{
3234    if (m_optimizedStyleSheetUpdateTimer.isActive())
3235        m_optimizedStyleSheetUpdateTimer.stop();
3236
3237    // Don't bother updating, since we haven't loaded all our style info yet
3238    // and haven't calculated the style selector for the first time.
3239    if (!hasLivingRenderTree() || (!m_didCalculateStyleResolver && !haveStylesheetsLoaded())) {
3240        m_styleResolver = nullptr;
3241        return;
3242    }
3243    m_didCalculateStyleResolver = true;
3244
3245#ifdef INSTRUMENT_LAYOUT_SCHEDULING
3246    if (!ownerElement())
3247        printf("Beginning update of style selector at time %lld.\n", elapsedTime().count());
3248#endif
3249
3250    DocumentStyleSheetCollection::UpdateFlag styleSheetUpdate = (updateFlag == RecalcStyleIfNeeded || updateFlag == DeferRecalcStyleIfNeeded)
3251        ? DocumentStyleSheetCollection::OptimizedUpdate
3252        : DocumentStyleSheetCollection::FullUpdate;
3253    bool stylesheetChangeRequiresStyleRecalc = m_styleSheetCollection.updateActiveStyleSheets(styleSheetUpdate);
3254
3255    if (updateFlag == DeferRecalcStyle) {
3256        scheduleForcedStyleRecalc();
3257        return;
3258    }
3259
3260    if (updateFlag == DeferRecalcStyleIfNeeded) {
3261        if (stylesheetChangeRequiresStyleRecalc)
3262            scheduleForcedStyleRecalc();
3263        return;
3264    }
3265
3266    if (!stylesheetChangeRequiresStyleRecalc)
3267        return;
3268
3269    // This recalcStyle initiates a new recalc cycle. We need to bracket it to
3270    // make sure animations get the correct update time
3271    {
3272        AnimationUpdateBlock animationUpdateBlock(m_frame ? &m_frame->animation() : nullptr);
3273        recalcStyle(Style::Force);
3274    }
3275
3276#ifdef INSTRUMENT_LAYOUT_SCHEDULING
3277    if (!ownerElement())
3278        printf("Finished update of style selector at time %lld\n", elapsedTime().count());
3279#endif
3280
3281    if (renderView()) {
3282        renderView()->setNeedsLayoutAndPrefWidthsRecalc();
3283        if (view())
3284            view()->scheduleRelayout();
3285    }
3286
3287    evaluateMediaQueryList();
3288}
3289
3290void Document::removeFocusedNodeOfSubtree(Node* node, bool amongChildrenOnly)
3291{
3292    if (!m_focusedElement || this->inPageCache()) // If the document is in the page cache, then we don't need to clear out the focused node.
3293        return;
3294
3295    Element* focusedElement = node->treeScope().focusedElement();
3296    if (!focusedElement)
3297        return;
3298
3299    bool nodeInSubtree = false;
3300    if (amongChildrenOnly)
3301        nodeInSubtree = focusedElement->isDescendantOf(node);
3302    else
3303        nodeInSubtree = (focusedElement == node) || focusedElement->isDescendantOf(node);
3304
3305    if (nodeInSubtree)
3306        setFocusedElement(nullptr);
3307}
3308
3309void Document::hoveredElementDidDetach(Element* element)
3310{
3311    if (!m_hoveredElement || element != m_hoveredElement)
3312        return;
3313
3314    m_hoveredElement = element->parentElement();
3315    while (m_hoveredElement && !m_hoveredElement->renderer())
3316        m_hoveredElement = m_hoveredElement->parentElement();
3317    if (frame())
3318        frame()->eventHandler().scheduleHoverStateUpdate();
3319}
3320
3321void Document::elementInActiveChainDidDetach(Element* element)
3322{
3323    if (!m_activeElement || element != m_activeElement)
3324        return;
3325
3326    m_activeElement = element->parentElement();
3327    while (m_activeElement && !m_activeElement->renderer())
3328        m_activeElement = m_activeElement->parentElement();
3329}
3330
3331#if ENABLE(DASHBOARD_SUPPORT)
3332const Vector<AnnotatedRegionValue>& Document::annotatedRegions() const
3333{
3334    return m_annotatedRegions;
3335}
3336
3337void Document::setAnnotatedRegions(const Vector<AnnotatedRegionValue>& regions)
3338{
3339    m_annotatedRegions = regions;
3340    setAnnotatedRegionsDirty(false);
3341}
3342#endif
3343
3344bool Document::setFocusedElement(PassRefPtr<Element> prpNewFocusedElement, FocusDirection direction)
3345{
3346    RefPtr<Element> newFocusedElement = prpNewFocusedElement;
3347
3348    // Make sure newFocusedElement is actually in this document
3349    if (newFocusedElement && (&newFocusedElement->document() != this))
3350        return true;
3351
3352    if (m_focusedElement == newFocusedElement)
3353        return true;
3354
3355    if (m_inPageCache)
3356        return false;
3357
3358    bool focusChangeBlocked = false;
3359    RefPtr<Element> oldFocusedElement = m_focusedElement.release();
3360
3361    // Remove focus from the existing focus node (if any)
3362    if (oldFocusedElement) {
3363        if (oldFocusedElement->active())
3364            oldFocusedElement->setActive(false);
3365
3366        oldFocusedElement->setFocus(false);
3367
3368        // Dispatch a change event for form control elements that have been edited.
3369        if (oldFocusedElement->isFormControlElement()) {
3370            HTMLFormControlElement* formControlElement = toHTMLFormControlElement(oldFocusedElement.get());
3371            if (formControlElement->wasChangedSinceLastFormControlChangeEvent())
3372                formControlElement->dispatchFormControlChangeEvent();
3373        }
3374
3375        // Dispatch the blur event and let the node do any other blur related activities (important for text fields)
3376        oldFocusedElement->dispatchBlurEvent(newFocusedElement);
3377
3378        if (m_focusedElement) {
3379            // handler shifted focus
3380            focusChangeBlocked = true;
3381            newFocusedElement = nullptr;
3382        }
3383
3384        oldFocusedElement->dispatchFocusOutEvent(eventNames().focusoutEvent, newFocusedElement); // DOM level 3 name for the bubbling blur event.
3385        // FIXME: We should remove firing DOMFocusOutEvent event when we are sure no content depends
3386        // on it, probably when <rdar://problem/8503958> is resolved.
3387        oldFocusedElement->dispatchFocusOutEvent(eventNames().DOMFocusOutEvent, newFocusedElement); // DOM level 2 name for compatibility.
3388
3389        if (m_focusedElement) {
3390            // handler shifted focus
3391            focusChangeBlocked = true;
3392            newFocusedElement = nullptr;
3393        }
3394
3395        if (oldFocusedElement->isRootEditableElement())
3396            frame()->editor().didEndEditing();
3397
3398        if (view()) {
3399            if (Widget* oldWidget = widgetForElement(oldFocusedElement.get()))
3400                oldWidget->setFocus(false);
3401            else
3402                view()->setFocus(false);
3403        }
3404    }
3405
3406    if (newFocusedElement && newFocusedElement->isFocusable()) {
3407        if (newFocusedElement->isRootEditableElement() && !acceptsEditingFocus(newFocusedElement.get())) {
3408            // delegate blocks focus change
3409            focusChangeBlocked = true;
3410            goto SetFocusedNodeDone;
3411        }
3412        // Set focus on the new node
3413        m_focusedElement = newFocusedElement;
3414
3415        // Dispatch the focus event and let the node do any other focus related activities (important for text fields)
3416        m_focusedElement->dispatchFocusEvent(oldFocusedElement, direction);
3417
3418        if (m_focusedElement != newFocusedElement) {
3419            // handler shifted focus
3420            focusChangeBlocked = true;
3421            goto SetFocusedNodeDone;
3422        }
3423
3424        m_focusedElement->dispatchFocusInEvent(eventNames().focusinEvent, oldFocusedElement); // DOM level 3 bubbling focus event.
3425
3426        if (m_focusedElement != newFocusedElement) {
3427            // handler shifted focus
3428            focusChangeBlocked = true;
3429            goto SetFocusedNodeDone;
3430        }
3431
3432        // FIXME: We should remove firing DOMFocusInEvent event when we are sure no content depends
3433        // on it, probably when <rdar://problem/8503958> is m.
3434        m_focusedElement->dispatchFocusInEvent(eventNames().DOMFocusInEvent, oldFocusedElement); // DOM level 2 for compatibility.
3435
3436        if (m_focusedElement != newFocusedElement) {
3437            // handler shifted focus
3438            focusChangeBlocked = true;
3439            goto SetFocusedNodeDone;
3440        }
3441
3442        m_focusedElement->setFocus(true);
3443
3444        if (m_focusedElement->isRootEditableElement())
3445            frame()->editor().didBeginEditing();
3446
3447        // eww, I suck. set the qt focus correctly
3448        // ### find a better place in the code for this
3449        if (view()) {
3450            Widget* focusWidget = widgetForElement(m_focusedElement.get());
3451            if (focusWidget) {
3452                // Make sure a widget has the right size before giving it focus.
3453                // Otherwise, we are testing edge cases of the Widget code.
3454                // Specifically, in WebCore this does not work well for text fields.
3455                updateLayout();
3456                // Re-get the widget in case updating the layout changed things.
3457                focusWidget = widgetForElement(m_focusedElement.get());
3458            }
3459            if (focusWidget)
3460                focusWidget->setFocus(true);
3461            else
3462                view()->setFocus(true);
3463        }
3464    }
3465
3466    if (!focusChangeBlocked && m_focusedElement) {
3467        // Create the AXObject cache in a focus change because GTK relies on it.
3468        if (AXObjectCache* cache = axObjectCache())
3469            cache->handleFocusedUIElementChanged(oldFocusedElement.get(), newFocusedElement.get());
3470    }
3471
3472    if (!focusChangeBlocked && page())
3473        page()->chrome().focusedElementChanged(m_focusedElement.get());
3474
3475SetFocusedNodeDone:
3476    updateStyleIfNeeded();
3477    return !focusChangeBlocked;
3478}
3479
3480void Document::setCSSTarget(Element* n)
3481{
3482    if (m_cssTarget)
3483        m_cssTarget->didAffectSelector(AffectedSelectorTarget);
3484    m_cssTarget = n;
3485    if (n)
3486        n->didAffectSelector(AffectedSelectorTarget);
3487}
3488
3489void Document::registerNodeListForInvalidation(LiveNodeList& list)
3490{
3491    m_nodeListAndCollectionCounts[list.invalidationType()]++;
3492    if (!list.isRootedAtDocument())
3493        return;
3494    ASSERT(!list.isRegisteredForInvalidationAtDocument());
3495    list.setRegisteredForInvalidationAtDocument(true);
3496    m_listsInvalidatedAtDocument.add(&list);
3497}
3498
3499void Document::unregisterNodeListForInvalidation(LiveNodeList& list)
3500{
3501    m_nodeListAndCollectionCounts[list.invalidationType()]--;
3502    if (!list.isRegisteredForInvalidationAtDocument())
3503        return;
3504    if (!m_listsInvalidatedAtDocument.size()) {
3505        ASSERT(m_inInvalidateNodeListAndCollectionCaches);
3506        return;
3507    }
3508    ASSERT(m_listsInvalidatedAtDocument.contains(&list));
3509    m_listsInvalidatedAtDocument.remove(&list);
3510    list.setRegisteredForInvalidationAtDocument(false);
3511}
3512
3513void Document::registerCollection(HTMLCollection& collection)
3514{
3515    m_nodeListAndCollectionCounts[collection.invalidationType()]++;
3516    if (collection.isRootedAtDocument())
3517        m_collectionsInvalidatedAtDocument.add(&collection);
3518}
3519
3520void Document::unregisterCollection(HTMLCollection& collection)
3521{
3522    ASSERT(m_nodeListAndCollectionCounts[collection.invalidationType()]);
3523    m_nodeListAndCollectionCounts[collection.invalidationType()]--;
3524    if (collection.isRootedAtDocument()) {
3525        if (!m_collectionsInvalidatedAtDocument.size()) {
3526            ASSERT(m_inInvalidateNodeListAndCollectionCaches);
3527            return;
3528        }
3529        ASSERT(m_collectionsInvalidatedAtDocument.contains(&collection));
3530        m_collectionsInvalidatedAtDocument.remove(&collection);
3531    }
3532}
3533
3534void Document::collectionCachedIdNameMap(const HTMLCollection& collection)
3535{
3536    ASSERT_UNUSED(collection, collection.hasNamedElementCache());
3537    m_nodeListAndCollectionCounts[InvalidateOnIdNameAttrChange]++;
3538}
3539
3540void Document::collectionWillClearIdNameMap(const HTMLCollection& collection)
3541{
3542    ASSERT_UNUSED(collection, collection.hasNamedElementCache());
3543    ASSERT(m_nodeListAndCollectionCounts[InvalidateOnIdNameAttrChange]);
3544    m_nodeListAndCollectionCounts[InvalidateOnIdNameAttrChange]--;
3545}
3546
3547void Document::attachNodeIterator(NodeIterator* ni)
3548{
3549    m_nodeIterators.add(ni);
3550}
3551
3552void Document::detachNodeIterator(NodeIterator* ni)
3553{
3554    // The node iterator can be detached without having been attached if its root node didn't have a document
3555    // when the iterator was created, but has it now.
3556    m_nodeIterators.remove(ni);
3557}
3558
3559void Document::moveNodeIteratorsToNewDocument(Node* node, Document* newDocument)
3560{
3561    HashSet<NodeIterator*> nodeIteratorsList = m_nodeIterators;
3562    HashSet<NodeIterator*>::const_iterator nodeIteratorsEnd = nodeIteratorsList.end();
3563    for (HashSet<NodeIterator*>::const_iterator it = nodeIteratorsList.begin(); it != nodeIteratorsEnd; ++it) {
3564        if ((*it)->root() == node) {
3565            detachNodeIterator(*it);
3566            newDocument->attachNodeIterator(*it);
3567        }
3568    }
3569}
3570
3571void Document::updateRangesAfterChildrenChanged(ContainerNode& container)
3572{
3573    if (!m_ranges.isEmpty()) {
3574        for (auto it = m_ranges.begin(), end = m_ranges.end(); it != end; ++it)
3575            (*it)->nodeChildrenChanged(container);
3576    }
3577}
3578
3579void Document::nodeChildrenWillBeRemoved(ContainerNode& container)
3580{
3581    if (!m_ranges.isEmpty()) {
3582        for (auto it = m_ranges.begin(), end = m_ranges.end(); it != end; ++it)
3583            (*it)->nodeChildrenWillBeRemoved(container);
3584    }
3585
3586    for (auto it = m_nodeIterators.begin(), end = m_nodeIterators.end(); it != end; ++it) {
3587        for (Node* n = container.firstChild(); n; n = n->nextSibling())
3588            (*it)->nodeWillBeRemoved(n);
3589    }
3590
3591    if (Frame* frame = this->frame()) {
3592        for (Node* n = container.firstChild(); n; n = n->nextSibling()) {
3593            frame->eventHandler().nodeWillBeRemoved(n);
3594            frame->selection().nodeWillBeRemoved(n);
3595            frame->page()->dragCaretController().nodeWillBeRemoved(n);
3596        }
3597    }
3598}
3599
3600void Document::nodeWillBeRemoved(Node* n)
3601{
3602    HashSet<NodeIterator*>::const_iterator nodeIteratorsEnd = m_nodeIterators.end();
3603    for (HashSet<NodeIterator*>::const_iterator it = m_nodeIterators.begin(); it != nodeIteratorsEnd; ++it)
3604        (*it)->nodeWillBeRemoved(n);
3605
3606    if (!m_ranges.isEmpty()) {
3607        HashSet<Range*>::const_iterator rangesEnd = m_ranges.end();
3608        for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != rangesEnd; ++it)
3609            (*it)->nodeWillBeRemoved(n);
3610    }
3611
3612    if (Frame* frame = this->frame()) {
3613        frame->eventHandler().nodeWillBeRemoved(n);
3614        frame->selection().nodeWillBeRemoved(n);
3615        frame->page()->dragCaretController().nodeWillBeRemoved(n);
3616    }
3617}
3618
3619void Document::textInserted(Node* text, unsigned offset, unsigned length)
3620{
3621    if (!m_ranges.isEmpty()) {
3622        for (auto& range : m_ranges)
3623            range->textInserted(text, offset, length);
3624    }
3625
3626    // Update the markers for spelling and grammar checking.
3627    m_markers->shiftMarkers(text, offset, length);
3628}
3629
3630void Document::textRemoved(Node* text, unsigned offset, unsigned length)
3631{
3632    if (!m_ranges.isEmpty()) {
3633        for (auto& range : m_ranges)
3634            range->textRemoved(text, offset, length);
3635    }
3636
3637    // Update the markers for spelling and grammar checking.
3638    m_markers->removeMarkers(text, offset, length);
3639    m_markers->shiftMarkers(text, offset + length, 0 - length);
3640}
3641
3642void Document::textNodesMerged(Text* oldNode, unsigned offset)
3643{
3644    if (!m_ranges.isEmpty()) {
3645        NodeWithIndex oldNodeWithIndex(oldNode);
3646        for (auto& range : m_ranges)
3647            range->textNodesMerged(oldNodeWithIndex, offset);
3648    }
3649
3650    // FIXME: This should update markers for spelling and grammar checking.
3651}
3652
3653void Document::textNodeSplit(Text* oldNode)
3654{
3655    if (!m_ranges.isEmpty()) {
3656        HashSet<Range*>::const_iterator end = m_ranges.end();
3657        for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it)
3658            (*it)->textNodeSplit(oldNode);
3659    }
3660
3661    // FIXME: This should update markers for spelling and grammar checking.
3662}
3663
3664void Document::createDOMWindow()
3665{
3666    ASSERT(m_frame);
3667    ASSERT(!m_domWindow);
3668
3669    m_domWindow = DOMWindow::create(this);
3670
3671    ASSERT(m_domWindow->document() == this);
3672    ASSERT(m_domWindow->frame() == m_frame);
3673}
3674
3675void Document::takeDOMWindowFrom(Document* document)
3676{
3677    ASSERT(m_frame);
3678    ASSERT(!m_domWindow);
3679    ASSERT(document->m_domWindow);
3680    // A valid DOMWindow is needed by CachedFrame for its documents.
3681    ASSERT(!document->inPageCache());
3682
3683    m_domWindow = document->m_domWindow.release();
3684    m_domWindow->didSecureTransitionTo(this);
3685
3686    ASSERT(m_domWindow->document() == this);
3687    ASSERT(m_domWindow->frame() == m_frame);
3688}
3689
3690void Document::setWindowAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener)
3691{
3692    if (!m_domWindow)
3693        return;
3694    m_domWindow->setAttributeEventListener(eventType, listener);
3695}
3696
3697void Document::setWindowAttributeEventListener(const AtomicString& eventType, const QualifiedName& attributeName, const AtomicString& attributeValue)
3698{
3699    if (!m_frame)
3700        return;
3701    setWindowAttributeEventListener(eventType, JSLazyEventListener::createForDOMWindow(*m_frame, attributeName, attributeValue));
3702}
3703
3704EventListener* Document::getWindowAttributeEventListener(const AtomicString& eventType)
3705{
3706    if (!m_domWindow)
3707        return nullptr;
3708    return m_domWindow->getAttributeEventListener(eventType);
3709}
3710
3711void Document::dispatchWindowEvent(PassRefPtr<Event> event,  PassRefPtr<EventTarget> target)
3712{
3713    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
3714    if (!m_domWindow)
3715        return;
3716    m_domWindow->dispatchEvent(event, target);
3717}
3718
3719void Document::dispatchWindowLoadEvent()
3720{
3721    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
3722    if (!m_domWindow)
3723        return;
3724    m_domWindow->dispatchLoadEvent();
3725    m_loadEventFinished = true;
3726    if (m_cachedResourceLoader)
3727        m_cachedResourceLoader->documentDidFinishLoadEvent();
3728}
3729
3730void Document::enqueueWindowEvent(PassRefPtr<Event> event)
3731{
3732    event->setTarget(m_domWindow.get());
3733    m_eventQueue.enqueueEvent(event);
3734}
3735
3736void Document::enqueueDocumentEvent(PassRefPtr<Event> event)
3737{
3738    event->setTarget(this);
3739    m_eventQueue.enqueueEvent(event);
3740}
3741
3742void Document::enqueueOverflowEvent(PassRefPtr<Event> event)
3743{
3744    m_eventQueue.enqueueEvent(event);
3745}
3746
3747PassRefPtr<Event> Document::createEvent(const String& eventType, ExceptionCode& ec)
3748{
3749    RefPtr<Event> event = EventFactory::create(eventType);
3750    if (event)
3751        return event.release();
3752
3753    ec = NOT_SUPPORTED_ERR;
3754    return nullptr;
3755}
3756
3757void Document::addListenerTypeIfNeeded(const AtomicString& eventType)
3758{
3759    if (eventType == eventNames().DOMSubtreeModifiedEvent)
3760        addListenerType(DOMSUBTREEMODIFIED_LISTENER);
3761    else if (eventType == eventNames().DOMNodeInsertedEvent)
3762        addListenerType(DOMNODEINSERTED_LISTENER);
3763    else if (eventType == eventNames().DOMNodeRemovedEvent)
3764        addListenerType(DOMNODEREMOVED_LISTENER);
3765    else if (eventType == eventNames().DOMNodeRemovedFromDocumentEvent)
3766        addListenerType(DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
3767    else if (eventType == eventNames().DOMNodeInsertedIntoDocumentEvent)
3768        addListenerType(DOMNODEINSERTEDINTODOCUMENT_LISTENER);
3769    else if (eventType == eventNames().DOMCharacterDataModifiedEvent)
3770        addListenerType(DOMCHARACTERDATAMODIFIED_LISTENER);
3771    else if (eventType == eventNames().overflowchangedEvent)
3772        addListenerType(OVERFLOWCHANGED_LISTENER);
3773    else if (eventType == eventNames().webkitAnimationStartEvent)
3774        addListenerType(ANIMATIONSTART_LISTENER);
3775    else if (eventType == eventNames().webkitAnimationEndEvent)
3776        addListenerType(ANIMATIONEND_LISTENER);
3777    else if (eventType == eventNames().webkitAnimationIterationEvent)
3778        addListenerType(ANIMATIONITERATION_LISTENER);
3779    else if (eventType == eventNames().webkitTransitionEndEvent || eventType == eventNames().transitionendEvent)
3780        addListenerType(TRANSITIONEND_LISTENER);
3781    else if (eventType == eventNames().beforeloadEvent)
3782        addListenerType(BEFORELOAD_LISTENER);
3783    else if (eventType == eventNames().scrollEvent)
3784        addListenerType(SCROLL_LISTENER);
3785}
3786
3787CSSStyleDeclaration* Document::getOverrideStyle(Element*, const String&)
3788{
3789    return nullptr;
3790}
3791
3792HTMLFrameOwnerElement* Document::ownerElement() const
3793{
3794    if (!frame())
3795        return nullptr;
3796    return frame()->ownerElement();
3797}
3798
3799String Document::cookie(ExceptionCode& ec) const
3800{
3801    if (page() && !page()->settings().cookieEnabled())
3802        return String();
3803
3804    // FIXME: The HTML5 DOM spec states that this attribute can raise an
3805    // INVALID_STATE_ERR exception on getting if the Document has no
3806    // browsing context.
3807
3808    if (!securityOrigin()->canAccessCookies()) {
3809        ec = SECURITY_ERR;
3810        return String();
3811    }
3812
3813    URL cookieURL = this->cookieURL();
3814    if (cookieURL.isEmpty())
3815        return String();
3816
3817    return cookies(this, cookieURL);
3818}
3819
3820void Document::setCookie(const String& value, ExceptionCode& ec)
3821{
3822    if (page() && !page()->settings().cookieEnabled())
3823        return;
3824
3825    // FIXME: The HTML5 DOM spec states that this attribute can raise an
3826    // INVALID_STATE_ERR exception on setting if the Document has no
3827    // browsing context.
3828
3829    if (!securityOrigin()->canAccessCookies()) {
3830        ec = SECURITY_ERR;
3831        return;
3832    }
3833
3834    URL cookieURL = this->cookieURL();
3835    if (cookieURL.isEmpty())
3836        return;
3837
3838    setCookies(this, cookieURL, value);
3839}
3840
3841String Document::referrer() const
3842{
3843    if (frame())
3844        return frame()->loader().referrer();
3845    return String();
3846}
3847
3848String Document::origin() const
3849{
3850    return securityOrigin()->databaseIdentifier();
3851}
3852
3853String Document::domain() const
3854{
3855    return securityOrigin()->domain();
3856}
3857
3858void Document::setDomain(const String& newDomain, ExceptionCode& ec)
3859{
3860    if (SchemeRegistry::isDomainRelaxationForbiddenForURLScheme(securityOrigin()->protocol())) {
3861        ec = SECURITY_ERR;
3862        return;
3863    }
3864
3865    // Both NS and IE specify that changing the domain is only allowed when
3866    // the new domain is a suffix of the old domain.
3867
3868    // FIXME: We should add logging indicating why a domain was not allowed.
3869
3870    // If the new domain is the same as the old domain, still call
3871    // securityOrigin()->setDomainForDOM. This will change the
3872    // security check behavior. For example, if a page loaded on port 8000
3873    // assigns its current domain using document.domain, the page will
3874    // allow other pages loaded on different ports in the same domain that
3875    // have also assigned to access this page.
3876    if (equalIgnoringCase(domain(), newDomain)) {
3877        securityOrigin()->setDomainFromDOM(newDomain);
3878        return;
3879    }
3880
3881    int oldLength = domain().length();
3882    int newLength = newDomain.length();
3883    // e.g. newDomain = webkit.org (10) and domain() = www.webkit.org (14)
3884    if (newLength >= oldLength) {
3885        ec = SECURITY_ERR;
3886        return;
3887    }
3888
3889    String test = domain();
3890    // Check that it's a subdomain, not e.g. "ebkit.org"
3891    if (test[oldLength - newLength - 1] != '.') {
3892        ec = SECURITY_ERR;
3893        return;
3894    }
3895
3896    // Now test is "webkit.org" from domain()
3897    // and we check that it's the same thing as newDomain
3898    test.remove(0, oldLength - newLength);
3899    if (test != newDomain) {
3900        ec = SECURITY_ERR;
3901        return;
3902    }
3903
3904    securityOrigin()->setDomainFromDOM(newDomain);
3905}
3906
3907// http://www.whatwg.org/specs/web-apps/current-work/#dom-document-lastmodified
3908String Document::lastModified() const
3909{
3910    DateComponents date;
3911    bool foundDate = false;
3912    if (m_frame) {
3913        String httpLastModified;
3914        if (DocumentLoader* documentLoader = loader())
3915            httpLastModified = documentLoader->response().httpHeaderField(HTTPHeaderName::LastModified);
3916        if (!httpLastModified.isEmpty()) {
3917            date.setMillisecondsSinceEpochForDateTime(parseDate(httpLastModified));
3918            foundDate = true;
3919        }
3920    }
3921    // FIXME: If this document came from the file system, the HTML5
3922    // specificiation tells us to read the last modification date from the file
3923    // system.
3924    if (!foundDate) {
3925        double fallbackDate = currentTimeMS();
3926#if ENABLE(WEB_REPLAY)
3927        InputCursor& cursor = inputCursor();
3928        if (cursor.isCapturing())
3929            cursor.appendInput<DocumentLastModifiedDate>(fallbackDate);
3930        else if (cursor.isReplaying()) {
3931            if (DocumentLastModifiedDate* input = cursor.fetchInput<DocumentLastModifiedDate>())
3932                fallbackDate = input->fallbackValue();
3933        }
3934#endif
3935        date.setMillisecondsSinceEpochForDateTime(fallbackDate);
3936    }
3937
3938    return String::format("%02d/%02d/%04d %02d:%02d:%02d", date.month() + 1, date.monthDay(), date.fullYear(), date.hour(), date.minute(), date.second());
3939}
3940
3941static bool isValidNameNonASCII(const LChar* characters, unsigned length)
3942{
3943    if (!isValidNameStart(characters[0]))
3944        return false;
3945
3946    for (unsigned i = 1; i < length; ++i) {
3947        if (!isValidNamePart(characters[i]))
3948            return false;
3949    }
3950
3951    return true;
3952}
3953
3954static bool isValidNameNonASCII(const UChar* characters, unsigned length)
3955{
3956    unsigned i = 0;
3957
3958    UChar32 c;
3959    U16_NEXT(characters, i, length, c)
3960    if (!isValidNameStart(c))
3961        return false;
3962
3963    while (i < length) {
3964        U16_NEXT(characters, i, length, c)
3965        if (!isValidNamePart(c))
3966            return false;
3967    }
3968
3969    return true;
3970}
3971
3972template<typename CharType>
3973static inline bool isValidNameASCII(const CharType* characters, unsigned length)
3974{
3975    CharType c = characters[0];
3976    if (!(isASCIIAlpha(c) || c == ':' || c == '_'))
3977        return false;
3978
3979    for (unsigned i = 1; i < length; ++i) {
3980        c = characters[i];
3981        if (!(isASCIIAlphanumeric(c) || c == ':' || c == '_' || c == '-' || c == '.'))
3982            return false;
3983    }
3984
3985    return true;
3986}
3987
3988bool Document::isValidName(const String& name)
3989{
3990    unsigned length = name.length();
3991    if (!length)
3992        return false;
3993
3994    if (name.is8Bit()) {
3995        const LChar* characters = name.characters8();
3996
3997        if (isValidNameASCII(characters, length))
3998            return true;
3999
4000        return isValidNameNonASCII(characters, length);
4001    }
4002
4003    const UChar* characters = name.characters16();
4004
4005    if (isValidNameASCII(characters, length))
4006        return true;
4007
4008    return isValidNameNonASCII(characters, length);
4009}
4010
4011bool Document::parseQualifiedName(const String& qualifiedName, String& prefix, String& localName, ExceptionCode& ec)
4012{
4013    unsigned length = qualifiedName.length();
4014
4015    if (!length) {
4016        ec = INVALID_CHARACTER_ERR;
4017        return false;
4018    }
4019
4020    bool nameStart = true;
4021    bool sawColon = false;
4022    int colonPos = 0;
4023
4024    for (unsigned i = 0; i < length;) {
4025        UChar32 c;
4026        U16_NEXT(qualifiedName, i, length, c)
4027        if (c == ':') {
4028            if (sawColon) {
4029                ec = NAMESPACE_ERR;
4030                return false; // multiple colons: not allowed
4031            }
4032            nameStart = true;
4033            sawColon = true;
4034            colonPos = i - 1;
4035        } else if (nameStart) {
4036            if (!isValidNameStart(c)) {
4037                ec = INVALID_CHARACTER_ERR;
4038                return false;
4039            }
4040            nameStart = false;
4041        } else {
4042            if (!isValidNamePart(c)) {
4043                ec = INVALID_CHARACTER_ERR;
4044                return false;
4045            }
4046        }
4047    }
4048
4049    if (!sawColon) {
4050        prefix = String();
4051        localName = qualifiedName;
4052    } else {
4053        prefix = qualifiedName.substring(0, colonPos);
4054        if (prefix.isEmpty()) {
4055            ec = NAMESPACE_ERR;
4056            return false;
4057        }
4058        localName = qualifiedName.substring(colonPos + 1);
4059    }
4060
4061    if (localName.isEmpty()) {
4062        ec = NAMESPACE_ERR;
4063        return false;
4064    }
4065
4066    return true;
4067}
4068
4069void Document::setDecoder(PassRefPtr<TextResourceDecoder> decoder)
4070{
4071    m_decoder = decoder;
4072}
4073
4074URL Document::completeURL(const String& url, const URL& baseURLOverride) const
4075{
4076    // Always return a null URL when passed a null string.
4077    // FIXME: Should we change the URL constructor to have this behavior?
4078    // See also [CSS]StyleSheet::completeURL(const String&)
4079    if (url.isNull())
4080        return URL();
4081    const URL& baseURL = ((baseURLOverride.isEmpty() || baseURLOverride == blankURL()) && parentDocument()) ? parentDocument()->baseURL() : baseURLOverride;
4082    if (!m_decoder)
4083        return URL(baseURL, url);
4084    return URL(baseURL, url, m_decoder->encoding());
4085}
4086
4087URL Document::completeURL(const String& url) const
4088{
4089    return completeURL(url, m_baseURL);
4090}
4091
4092void Document::setInPageCache(bool flag)
4093{
4094    if (m_inPageCache == flag)
4095        return;
4096
4097    m_inPageCache = flag;
4098
4099    FrameView* v = view();
4100    Page* page = this->page();
4101
4102    if (page)
4103        page->lockAllOverlayScrollbarsToHidden(flag);
4104
4105    if (flag) {
4106        if (v) {
4107            // FIXME: There is some scrolling related work that needs to happen whenever a page goes into the
4108            // page cache and similar work that needs to occur when it comes out. This is where we do the work
4109            // that needs to happen when we enter, and the work that needs to happen when we exit is in
4110            // HistoryController::restoreScrollPositionAndViewState(). It can't be here because this function is
4111            // called too early on in the process of a page exiting the cache for that work to be possible in this
4112            // function. It would be nice if there was more symmetry here.
4113            // https://bugs.webkit.org/show_bug.cgi?id=98698
4114            v->cacheCurrentScrollPosition();
4115            if (page && m_frame->isMainFrame()) {
4116                v->resetScrollbarsAndClearContentsSize();
4117                if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
4118                    scrollingCoordinator->clearStateTree();
4119            } else
4120                v->resetScrollbars();
4121        }
4122        m_styleRecalcTimer.stop();
4123    } else {
4124        if (childNeedsStyleRecalc())
4125            scheduleStyleRecalc();
4126    }
4127}
4128
4129void Document::documentWillBecomeInactive()
4130{
4131    if (renderView())
4132        renderView()->setIsInWindow(false);
4133}
4134
4135void Document::documentWillSuspendForPageCache()
4136{
4137    documentWillBecomeInactive();
4138
4139    HashSet<Element*>::iterator end = m_documentSuspensionCallbackElements.end();
4140    for (HashSet<Element*>::iterator i = m_documentSuspensionCallbackElements.begin(); i != end; ++i)
4141        (*i)->documentWillSuspendForPageCache();
4142
4143#ifndef NDEBUG
4144    // Clear the update flag to be able to check if the viewport arguments update
4145    // is dispatched, after the document is restored from the page cache.
4146    m_didDispatchViewportPropertiesChanged = false;
4147#endif
4148}
4149
4150void Document::documentDidResumeFromPageCache()
4151{
4152    Vector<Element*> elements;
4153    copyToVector(m_documentSuspensionCallbackElements, elements);
4154    Vector<Element*>::iterator end = elements.end();
4155    for (Vector<Element*>::iterator i = elements.begin(); i != end; ++i)
4156        (*i)->documentDidResumeFromPageCache();
4157
4158    if (renderView())
4159        renderView()->setIsInWindow(true);
4160
4161    ASSERT(page());
4162    page()->lockAllOverlayScrollbarsToHidden(false);
4163
4164    ASSERT(m_frame);
4165    m_frame->loader().client().dispatchDidBecomeFrameset(isFrameSet());
4166}
4167
4168void Document::registerForPageCacheSuspensionCallbacks(Element* e)
4169{
4170    m_documentSuspensionCallbackElements.add(e);
4171}
4172
4173void Document::unregisterForPageCacheSuspensionCallbacks(Element* e)
4174{
4175    m_documentSuspensionCallbackElements.remove(e);
4176}
4177
4178void Document::mediaVolumeDidChange()
4179{
4180    HashSet<Element*>::iterator end = m_mediaVolumeCallbackElements.end();
4181    for (HashSet<Element*>::iterator i = m_mediaVolumeCallbackElements.begin(); i != end; ++i)
4182        (*i)->mediaVolumeDidChange();
4183}
4184
4185void Document::registerForMediaVolumeCallbacks(Element* e)
4186{
4187    m_mediaVolumeCallbackElements.add(e);
4188}
4189
4190void Document::unregisterForMediaVolumeCallbacks(Element* e)
4191{
4192    m_mediaVolumeCallbackElements.remove(e);
4193}
4194
4195void Document::storageBlockingStateDidChange()
4196{
4197    if (Settings* settings = this->settings())
4198        securityOrigin()->setStorageBlockingPolicy(settings->storageBlockingPolicy());
4199}
4200
4201void Document::privateBrowsingStateDidChange()
4202{
4203    HashSet<Element*>::iterator end = m_privateBrowsingStateChangedElements.end();
4204    for (HashSet<Element*>::iterator it = m_privateBrowsingStateChangedElements.begin(); it != end; ++it)
4205        (*it)->privateBrowsingStateDidChange();
4206}
4207
4208void Document::registerForPrivateBrowsingStateChangedCallbacks(Element* e)
4209{
4210    m_privateBrowsingStateChangedElements.add(e);
4211}
4212
4213void Document::unregisterForPrivateBrowsingStateChangedCallbacks(Element* e)
4214{
4215    m_privateBrowsingStateChangedElements.remove(e);
4216}
4217
4218#if ENABLE(VIDEO_TRACK)
4219void Document::registerForCaptionPreferencesChangedCallbacks(Element* e)
4220{
4221    if (page())
4222        page()->group().captionPreferences()->setInterestedInCaptionPreferenceChanges();
4223
4224    m_captionPreferencesChangedElements.add(e);
4225}
4226
4227void Document::unregisterForCaptionPreferencesChangedCallbacks(Element* e)
4228{
4229    m_captionPreferencesChangedElements.remove(e);
4230}
4231
4232void Document::captionPreferencesChanged()
4233{
4234    HashSet<Element*>::iterator end = m_captionPreferencesChangedElements.end();
4235    for (HashSet<Element*>::iterator it = m_captionPreferencesChangedElements.begin(); it != end; ++it)
4236        (*it)->captionPreferencesChanged();
4237}
4238#endif
4239
4240#if ENABLE(MEDIA_CONTROLS_SCRIPT)
4241void Document::registerForPageScaleFactorChangedCallbacks(HTMLMediaElement* element)
4242{
4243    m_pageScaleFactorChangedElements.add(element);
4244}
4245
4246void Document::unregisterForPageScaleFactorChangedCallbacks(HTMLMediaElement* element)
4247{
4248    m_pageScaleFactorChangedElements.remove(element);
4249}
4250
4251void Document::pageScaleFactorChangedAndStable()
4252{
4253    for (HTMLMediaElement* mediaElement : m_pageScaleFactorChangedElements)
4254        mediaElement->pageScaleFactorChanged();
4255}
4256#endif
4257
4258void Document::setShouldCreateRenderers(bool f)
4259{
4260    m_createRenderers = f;
4261}
4262
4263bool Document::shouldCreateRenderers()
4264{
4265    return m_createRenderers;
4266}
4267
4268// Support for Javascript execCommand, and related methods
4269
4270static Editor::Command command(Document* document, const String& commandName, bool userInterface = false)
4271{
4272    Frame* frame = document->frame();
4273    if (!frame || frame->document() != document)
4274        return Editor::Command();
4275
4276    document->updateStyleIfNeeded();
4277
4278    return frame->editor().command(commandName,
4279        userInterface ? CommandFromDOMWithUserInterface : CommandFromDOM);
4280}
4281
4282bool Document::execCommand(const String& commandName, bool userInterface, const String& value)
4283{
4284    return command(this, commandName, userInterface).execute(value);
4285}
4286
4287bool Document::queryCommandEnabled(const String& commandName)
4288{
4289    return command(this, commandName).isEnabled();
4290}
4291
4292bool Document::queryCommandIndeterm(const String& commandName)
4293{
4294    return command(this, commandName).state() == MixedTriState;
4295}
4296
4297bool Document::queryCommandState(const String& commandName)
4298{
4299    return command(this, commandName).state() == TrueTriState;
4300}
4301
4302bool Document::queryCommandSupported(const String& commandName)
4303{
4304    return command(this, commandName).isSupported();
4305}
4306
4307String Document::queryCommandValue(const String& commandName)
4308{
4309    return command(this, commandName).value();
4310}
4311
4312void Document::pushCurrentScript(PassRefPtr<HTMLScriptElement> newCurrentScript)
4313{
4314    ASSERT(newCurrentScript);
4315    m_currentScriptStack.append(newCurrentScript);
4316}
4317
4318void Document::popCurrentScript()
4319{
4320    ASSERT(!m_currentScriptStack.isEmpty());
4321    m_currentScriptStack.removeLast();
4322}
4323
4324#if ENABLE(XSLT)
4325
4326void Document::applyXSLTransform(ProcessingInstruction* pi)
4327{
4328    RefPtr<XSLTProcessor> processor = XSLTProcessor::create();
4329    processor->setXSLStyleSheet(static_cast<XSLStyleSheet*>(pi->sheet()));
4330    String resultMIMEType;
4331    String newSource;
4332    String resultEncoding;
4333    if (!processor->transformToString(*this, resultMIMEType, newSource, resultEncoding))
4334        return;
4335    // FIXME: If the transform failed we should probably report an error (like Mozilla does).
4336    Frame* ownerFrame = frame();
4337    processor->createDocumentFromSource(newSource, resultEncoding, resultMIMEType, this, ownerFrame);
4338    InspectorInstrumentation::frameDocumentUpdated(ownerFrame);
4339}
4340
4341void Document::setTransformSource(std::unique_ptr<TransformSource> source)
4342{
4343    m_transformSource = WTF::move(source);
4344}
4345
4346#endif
4347
4348void Document::setDesignMode(InheritedBool value)
4349{
4350    m_designMode = value;
4351    for (Frame* frame = m_frame; frame && frame->document(); frame = frame->tree().traverseNext(m_frame))
4352        frame->document()->scheduleForcedStyleRecalc();
4353}
4354
4355Document::InheritedBool Document::getDesignMode() const
4356{
4357    return m_designMode;
4358}
4359
4360bool Document::inDesignMode() const
4361{
4362    for (const Document* d = this; d; d = d->parentDocument()) {
4363        if (d->m_designMode != inherit)
4364            return d->m_designMode;
4365    }
4366    return false;
4367}
4368
4369Document* Document::parentDocument() const
4370{
4371    if (!m_frame)
4372        return nullptr;
4373    Frame* parent = m_frame->tree().parent();
4374    if (!parent)
4375        return nullptr;
4376    return parent->document();
4377}
4378
4379Document& Document::topDocument() const
4380{
4381    // FIXME: This special-casing avoids incorrectly determined top documents during the process
4382    // of AXObjectCache teardown or notification posting for cached or being-destroyed documents.
4383    if (!m_inPageCache && !m_renderTreeBeingDestroyed) {
4384        if (!m_frame)
4385            return const_cast<Document&>(*this);
4386        // This should always be non-null.
4387        Document* mainFrameDocument = m_frame->mainFrame().document();
4388        return mainFrameDocument ? *mainFrameDocument : const_cast<Document&>(*this);
4389    }
4390
4391    Document* document = const_cast<Document*>(this);
4392    while (Element* element = document->ownerElement())
4393        document = &element->document();
4394    return *document;
4395}
4396
4397PassRefPtr<Attr> Document::createAttribute(const String& name, ExceptionCode& ec)
4398{
4399    return createAttributeNS(String(), name, ec, true);
4400}
4401
4402PassRefPtr<Attr> Document::createAttributeNS(const String& namespaceURI, const String& qualifiedName, ExceptionCode& ec, bool shouldIgnoreNamespaceChecks)
4403{
4404    String prefix, localName;
4405    if (!parseQualifiedName(qualifiedName, prefix, localName, ec))
4406        return nullptr;
4407
4408    QualifiedName qName(prefix, localName, namespaceURI);
4409
4410    if (!shouldIgnoreNamespaceChecks && !hasValidNamespaceForAttributes(qName)) {
4411        ec = NAMESPACE_ERR;
4412        return nullptr;
4413    }
4414
4415    return Attr::create(*this, qName, emptyString());
4416}
4417
4418const SVGDocumentExtensions* Document::svgExtensions()
4419{
4420    return m_svgExtensions.get();
4421}
4422
4423SVGDocumentExtensions* Document::accessSVGExtensions()
4424{
4425    if (!m_svgExtensions)
4426        m_svgExtensions = std::make_unique<SVGDocumentExtensions>(this);
4427    return m_svgExtensions.get();
4428}
4429
4430bool Document::hasSVGRootNode() const
4431{
4432    return documentElement() && documentElement()->hasTagName(SVGNames::svgTag);
4433}
4434
4435PassRefPtr<HTMLCollection> Document::ensureCachedCollection(CollectionType type)
4436{
4437    return ensureRareData().ensureNodeLists().addCachedCollection<HTMLCollection>(*this, type);
4438}
4439
4440PassRefPtr<HTMLCollection> Document::images()
4441{
4442    return ensureCachedCollection(DocImages);
4443}
4444
4445PassRefPtr<HTMLCollection> Document::applets()
4446{
4447    return ensureCachedCollection(DocApplets);
4448}
4449
4450PassRefPtr<HTMLCollection> Document::embeds()
4451{
4452    return ensureCachedCollection(DocEmbeds);
4453}
4454
4455PassRefPtr<HTMLCollection> Document::plugins()
4456{
4457    // This is an alias for embeds() required for the JS DOM bindings.
4458    return ensureCachedCollection(DocEmbeds);
4459}
4460
4461PassRefPtr<HTMLCollection> Document::scripts()
4462{
4463    return ensureCachedCollection(DocScripts);
4464}
4465
4466PassRefPtr<HTMLCollection> Document::links()
4467{
4468    return ensureCachedCollection(DocLinks);
4469}
4470
4471PassRefPtr<HTMLCollection> Document::forms()
4472{
4473    return ensureCachedCollection(DocForms);
4474}
4475
4476PassRefPtr<HTMLCollection> Document::anchors()
4477{
4478    return ensureCachedCollection(DocAnchors);
4479}
4480
4481PassRefPtr<HTMLCollection> Document::all()
4482{
4483    return ensureRareData().ensureNodeLists().addCachedCollection<HTMLAllCollection>(*this, DocAll);
4484}
4485
4486PassRefPtr<HTMLCollection> Document::windowNamedItems(const AtomicString& name)
4487{
4488    return ensureRareData().ensureNodeLists().addCachedCollection<WindowNameCollection>(*this, WindowNamedItems, name);
4489}
4490
4491PassRefPtr<HTMLCollection> Document::documentNamedItems(const AtomicString& name)
4492{
4493    return ensureRareData().ensureNodeLists().addCachedCollection<DocumentNameCollection>(*this, DocumentNamedItems, name);
4494}
4495
4496void Document::finishedParsing()
4497{
4498    ASSERT(!scriptableDocumentParser() || !m_parser->isParsing());
4499    ASSERT(!scriptableDocumentParser() || m_readyState != Loading);
4500    setParsing(false);
4501
4502#if ENABLE(WEB_TIMING)
4503    if (!m_documentTiming.domContentLoadedEventStart)
4504        m_documentTiming.domContentLoadedEventStart = monotonicallyIncreasingTime();
4505#endif
4506
4507    dispatchEvent(Event::create(eventNames().DOMContentLoadedEvent, true, false));
4508
4509#if ENABLE(WEB_TIMING)
4510    if (!m_documentTiming.domContentLoadedEventEnd)
4511        m_documentTiming.domContentLoadedEventEnd = monotonicallyIncreasingTime();
4512#endif
4513
4514    if (RefPtr<Frame> f = frame()) {
4515        // FrameLoader::finishedParsing() might end up calling Document::implicitClose() if all
4516        // resource loads are complete. HTMLObjectElements can start loading their resources from
4517        // post attach callbacks triggered by recalcStyle().  This means if we parse out an <object>
4518        // tag and then reach the end of the document without updating styles, we might not have yet
4519        // started the resource load and might fire the window load event too early.  To avoid this
4520        // we force the styles to be up to date before calling FrameLoader::finishedParsing().
4521        // See https://bugs.webkit.org/show_bug.cgi?id=36864 starting around comment 35.
4522        updateStyleIfNeeded();
4523
4524        f->loader().finishedParsing();
4525
4526        InspectorInstrumentation::domContentLoadedEventFired(f.get());
4527    }
4528
4529    // Schedule dropping of the DocumentSharedObjectPool. We keep it alive for a while after parsing finishes
4530    // so that dynamically inserted content can also benefit from sharing optimizations.
4531    // Note that we don't refresh the timer on pool access since that could lead to huge caches being kept
4532    // alive indefinitely by something innocuous like JS setting .innerHTML repeatedly on a timer.
4533    static const int timeToKeepSharedObjectPoolAliveAfterParsingFinishedInSeconds = 10;
4534    m_sharedObjectPoolClearTimer.startOneShot(timeToKeepSharedObjectPoolAliveAfterParsingFinishedInSeconds);
4535
4536    // Parser should have picked up all preloads by now
4537    m_cachedResourceLoader->clearPreloads();
4538}
4539
4540void Document::sharedObjectPoolClearTimerFired(Timer<Document>&)
4541{
4542    m_sharedObjectPool = nullptr;
4543}
4544
4545#if ENABLE(TELEPHONE_NUMBER_DETECTION)
4546// FIXME: Find a better place for this functionality.
4547bool Document::isTelephoneNumberParsingEnabled() const
4548{
4549    Settings* settings = this->settings();
4550    return settings && settings->telephoneNumberParsingEnabled() && m_isTelephoneNumberParsingAllowed;
4551}
4552
4553void Document::setIsTelephoneNumberParsingAllowed(bool isTelephoneNumberParsingAllowed)
4554{
4555    m_isTelephoneNumberParsingAllowed = isTelephoneNumberParsingAllowed;
4556}
4557
4558bool Document::isTelephoneNumberParsingAllowed() const
4559{
4560    return m_isTelephoneNumberParsingAllowed;
4561}
4562#endif
4563
4564PassRefPtr<XPathExpression> Document::createExpression(const String& expression,
4565                                                       XPathNSResolver* resolver,
4566                                                       ExceptionCode& ec)
4567{
4568    if (!m_xpathEvaluator)
4569        m_xpathEvaluator = XPathEvaluator::create();
4570    return m_xpathEvaluator->createExpression(expression, resolver, ec);
4571}
4572
4573PassRefPtr<XPathNSResolver> Document::createNSResolver(Node* nodeResolver)
4574{
4575    if (!m_xpathEvaluator)
4576        m_xpathEvaluator = XPathEvaluator::create();
4577    return m_xpathEvaluator->createNSResolver(nodeResolver);
4578}
4579
4580PassRefPtr<XPathResult> Document::evaluate(const String& expression,
4581                                           Node* contextNode,
4582                                           XPathNSResolver* resolver,
4583                                           unsigned short type,
4584                                           XPathResult* result,
4585                                           ExceptionCode& ec)
4586{
4587    if (!m_xpathEvaluator)
4588        m_xpathEvaluator = XPathEvaluator::create();
4589    return m_xpathEvaluator->evaluate(expression, contextNode, resolver, type, result, ec);
4590}
4591
4592const Vector<IconURL>& Document::shortcutIconURLs()
4593{
4594    // Include any icons where type = link, rel = "shortcut icon".
4595    return iconURLs(Favicon);
4596}
4597
4598const Vector<IconURL>& Document::iconURLs(int iconTypesMask)
4599{
4600    m_iconURLs.clear();
4601
4602    if (!head() || !(head()->children()))
4603        return m_iconURLs;
4604
4605    RefPtr<HTMLCollection> children = head()->children();
4606    unsigned int length = children->length();
4607    for (unsigned int i = 0; i < length; ++i) {
4608        Node* child = children->item(i);
4609        if (!child->hasTagName(linkTag))
4610            continue;
4611        HTMLLinkElement* linkElement = toHTMLLinkElement(child);
4612        if (!(linkElement->iconType() & iconTypesMask))
4613            continue;
4614        if (linkElement->href().isEmpty())
4615            continue;
4616
4617        // Put it at the front to ensure that icons seen later take precedence as required by the spec.
4618        IconURL newURL(linkElement->href(), linkElement->iconSizes(), linkElement->type(), linkElement->iconType());
4619        m_iconURLs.append(newURL);
4620    }
4621
4622    m_iconURLs.reverse();
4623    return m_iconURLs;
4624}
4625
4626void Document::addIconURL(const String& url, const String&, const String&, IconType iconType)
4627{
4628    if (url.isEmpty())
4629        return;
4630
4631    Frame* f = frame();
4632    if (!f)
4633        return;
4634
4635    f->loader().didChangeIcons(iconType);
4636}
4637
4638void Document::initSecurityContext()
4639{
4640    if (haveInitializedSecurityOrigin()) {
4641        ASSERT(securityOrigin());
4642        return;
4643    }
4644
4645    if (!m_frame) {
4646        // No source for a security context.
4647        // This can occur via document.implementation.createDocument().
4648        m_cookieURL = URL(ParsedURLString, emptyString());
4649        setSecurityOrigin(SecurityOrigin::createUnique());
4650        setContentSecurityPolicy(std::make_unique<ContentSecurityPolicy>(this));
4651        return;
4652    }
4653
4654    // In the common case, create the security context from the currently
4655    // loading URL with a fresh content security policy.
4656    m_cookieURL = m_url;
4657    enforceSandboxFlags(m_frame->loader().effectiveSandboxFlags());
4658
4659#if PLATFORM(IOS)
4660    // On iOS we display attachments inline regardless of whether the response includes
4661    // the HTTP header "Content-Disposition: attachment". So, we enforce a unique
4662    // security origin for such documents. As an optimization, we don't need to parse
4663    // the responde header (i.e. call ResourceResponse::isAttachment()) for a synthesized
4664    // document because such documents cannot be an attachment.
4665    if (!m_isSynthesized && m_frame->loader().activeDocumentLoader()->response().isAttachment())
4666        enforceSandboxFlags(SandboxOrigin);
4667#endif
4668
4669    setSecurityOrigin(isSandboxed(SandboxOrigin) ? SecurityOrigin::createUnique() : SecurityOrigin::create(m_url));
4670    setContentSecurityPolicy(std::make_unique<ContentSecurityPolicy>(this));
4671
4672    if (Settings* settings = this->settings()) {
4673        if (!settings->webSecurityEnabled()) {
4674            // Web security is turned off. We should let this document access every other document. This is used primary by testing
4675            // harnesses for web sites.
4676            securityOrigin()->grantUniversalAccess();
4677        } else if (securityOrigin()->isLocal()) {
4678            if (settings->allowUniversalAccessFromFileURLs() || m_frame->loader().client().shouldForceUniversalAccessFromLocalURL(m_url)) {
4679                // Some clients want local URLs to have universal access, but that setting is dangerous for other clients.
4680                securityOrigin()->grantUniversalAccess();
4681            } else if (!settings->allowFileAccessFromFileURLs()) {
4682                // Some clients want local URLs to have even tighter restrictions by default, and not be able to access other local files.
4683                // FIXME 81578: The naming of this is confusing. Files with restricted access to other local files
4684                // still can have other privileges that can be remembered, thereby not making them unique origins.
4685                securityOrigin()->enforceFilePathSeparation();
4686            }
4687        }
4688        securityOrigin()->setStorageBlockingPolicy(settings->storageBlockingPolicy());
4689    }
4690
4691    Document* parentDocument = ownerElement() ? &ownerElement()->document() : nullptr;
4692    if (parentDocument && m_frame->loader().shouldTreatURLAsSrcdocDocument(url())) {
4693        m_isSrcdocDocument = true;
4694        setBaseURLOverride(parentDocument->baseURL());
4695    }
4696
4697    if (!shouldInheritSecurityOriginFromOwner(m_url))
4698        return;
4699
4700    // If we do not obtain a meaningful origin from the URL, then we try to
4701    // find one via the frame hierarchy.
4702
4703    Frame* ownerFrame = m_frame->tree().parent();
4704    if (!ownerFrame)
4705        ownerFrame = m_frame->loader().opener();
4706
4707    if (!ownerFrame) {
4708        didFailToInitializeSecurityOrigin();
4709        return;
4710    }
4711
4712    if (isSandboxed(SandboxOrigin)) {
4713        // If we're supposed to inherit our security origin from our owner,
4714        // but we're also sandboxed, the only thing we inherit is the ability
4715        // to load local resources. This lets about:blank iframes in file://
4716        // URL documents load images and other resources from the file system.
4717        if (ownerFrame->document()->securityOrigin()->canLoadLocalResources())
4718            securityOrigin()->grantLoadLocalResources();
4719        return;
4720    }
4721
4722    m_cookieURL = ownerFrame->document()->cookieURL();
4723    // We alias the SecurityOrigins to match Firefox, see Bug 15313
4724    // https://bugs.webkit.org/show_bug.cgi?id=15313
4725    setSecurityOrigin(ownerFrame->document()->securityOrigin());
4726}
4727
4728void Document::initContentSecurityPolicy()
4729{
4730    if (!m_frame->tree().parent() || (!shouldInheritSecurityOriginFromOwner(m_url) && !isPluginDocument()))
4731        return;
4732
4733    contentSecurityPolicy()->copyStateFrom(m_frame->tree().parent()->document()->contentSecurityPolicy());
4734}
4735
4736bool Document::isContextThread() const
4737{
4738    return isMainThread();
4739}
4740
4741void Document::updateURLForPushOrReplaceState(const URL& url)
4742{
4743    Frame* f = frame();
4744    if (!f)
4745        return;
4746
4747    setURL(url);
4748    f->loader().setOutgoingReferrer(url);
4749
4750    if (DocumentLoader* documentLoader = loader())
4751        documentLoader->replaceRequestURLForSameDocumentNavigation(url);
4752}
4753
4754void Document::statePopped(PassRefPtr<SerializedScriptValue> stateObject)
4755{
4756    if (!frame())
4757        return;
4758
4759    // Per step 11 of section 6.5.9 (history traversal) of the HTML5 spec, we
4760    // defer firing of popstate until we're in the complete state.
4761    if (m_readyState == Complete)
4762        enqueuePopstateEvent(stateObject);
4763    else
4764        m_pendingStateObject = stateObject;
4765}
4766
4767void Document::updateFocusAppearanceSoon(bool restorePreviousSelection)
4768{
4769    m_updateFocusAppearanceRestoresSelection = restorePreviousSelection;
4770    if (!m_updateFocusAppearanceTimer.isActive())
4771        m_updateFocusAppearanceTimer.startOneShot(0);
4772}
4773
4774void Document::cancelFocusAppearanceUpdate()
4775{
4776    m_updateFocusAppearanceTimer.stop();
4777}
4778
4779void Document::updateFocusAppearanceTimerFired(Timer<Document>&)
4780{
4781    Element* element = focusedElement();
4782    if (!element)
4783        return;
4784
4785    updateLayout();
4786    if (element->isFocusable())
4787        element->updateFocusAppearance(m_updateFocusAppearanceRestoresSelection);
4788}
4789
4790void Document::attachRange(Range* range)
4791{
4792    ASSERT(!m_ranges.contains(range));
4793    m_ranges.add(range);
4794}
4795
4796void Document::detachRange(Range* range)
4797{
4798    // We don't ASSERT m_ranges.contains(range) to allow us to call this
4799    // unconditionally to fix: https://bugs.webkit.org/show_bug.cgi?id=26044
4800    m_ranges.remove(range);
4801}
4802
4803CanvasRenderingContext* Document::getCSSCanvasContext(const String& type, const String& name, int width, int height)
4804{
4805    HTMLCanvasElement* element = getCSSCanvasElement(name);
4806    if (!element)
4807        return nullptr;
4808    element->setSize(IntSize(width, height));
4809    return element->getContext(type);
4810}
4811
4812HTMLCanvasElement* Document::getCSSCanvasElement(const String& name)
4813{
4814    RefPtr<HTMLCanvasElement>& element = m_cssCanvasElements.add(name, nullptr).iterator->value;
4815    if (!element)
4816        element = HTMLCanvasElement::create(*this);
4817    return element.get();
4818}
4819
4820#if ENABLE(IOS_TEXT_AUTOSIZING)
4821void Document::addAutoSizingNode(Node* node, float candidateSize)
4822{
4823    TextAutoSizingKey key(&node->renderer()->style(), &document());
4824    TextAutoSizingMap::AddResult result = m_textAutoSizedNodes.add(key, nullptr);
4825    if (result.isNewEntry)
4826        result.iterator->value = TextAutoSizingValue::create();
4827    result.iterator->value->addNode(node, candidateSize);
4828}
4829
4830void Document::validateAutoSizingNodes()
4831{
4832    Vector<TextAutoSizingKey> nodesForRemoval;
4833    for (auto it = m_textAutoSizedNodes.begin(), end = m_textAutoSizedNodes.end(); it != end; ++it) {
4834        RefPtr<TextAutoSizingValue> value = it->value;
4835        // Update all the nodes in the collection to reflect the new
4836        // candidate size.
4837        if (!value)
4838            continue;
4839
4840        value->adjustNodeSizes();
4841        if (!value->numNodes())
4842            nodesForRemoval.append(it->key);
4843    }
4844    unsigned count = nodesForRemoval.size();
4845    for (unsigned i = 0; i < count; i++)
4846        m_textAutoSizedNodes.remove(nodesForRemoval[i]);
4847}
4848
4849void Document::resetAutoSizingNodes()
4850{
4851    for (auto it = m_textAutoSizedNodes.begin(), end = m_textAutoSizedNodes.end(); it != end; ++it) {
4852        RefPtr<TextAutoSizingValue> value = it->value;
4853        if (value)
4854            value->reset();
4855    }
4856    m_textAutoSizedNodes.clear();
4857}
4858
4859#endif // ENABLE(IOS_TEXT_AUTOSIZING)
4860
4861void Document::initDNSPrefetch()
4862{
4863    Settings* settings = this->settings();
4864
4865    m_haveExplicitlyDisabledDNSPrefetch = false;
4866    m_isDNSPrefetchEnabled = settings && settings->dnsPrefetchingEnabled() && securityOrigin()->protocol() == "http";
4867
4868    // Inherit DNS prefetch opt-out from parent frame
4869    if (Document* parent = parentDocument()) {
4870        if (!parent->isDNSPrefetchEnabled())
4871            m_isDNSPrefetchEnabled = false;
4872    }
4873}
4874
4875void Document::parseDNSPrefetchControlHeader(const String& dnsPrefetchControl)
4876{
4877    if (equalIgnoringCase(dnsPrefetchControl, "on") && !m_haveExplicitlyDisabledDNSPrefetch) {
4878        m_isDNSPrefetchEnabled = true;
4879        return;
4880    }
4881
4882    m_isDNSPrefetchEnabled = false;
4883    m_haveExplicitlyDisabledDNSPrefetch = true;
4884}
4885
4886void Document::addConsoleMessage(MessageSource source, MessageLevel level, const String& message, unsigned long requestIdentifier)
4887{
4888    if (!isContextThread()) {
4889        postTask(AddConsoleMessageTask(source, level, message.isolatedCopy()));
4890        return;
4891    }
4892
4893    if (Page* page = this->page())
4894        page->console().addMessage(source, level, message, requestIdentifier, this);
4895}
4896
4897void Document::addMessage(MessageSource source, MessageLevel level, const String& message, const String& sourceURL, unsigned lineNumber, unsigned columnNumber, PassRefPtr<Inspector::ScriptCallStack> callStack, JSC::ExecState* state, unsigned long requestIdentifier)
4898{
4899    if (!isContextThread()) {
4900        postTask(AddConsoleMessageTask(source, level, message));
4901        return;
4902    }
4903
4904    if (Page* page = this->page())
4905        page->console().addMessage(source, level, message, sourceURL, lineNumber, columnNumber, callStack, state, requestIdentifier);
4906}
4907
4908SecurityOrigin* Document::topOrigin() const
4909{
4910    return topDocument().securityOrigin();
4911}
4912
4913void Document::postTask(Task task)
4914{
4915    Task* taskPtr = std::make_unique<Task>(WTF::move(task)).release();
4916    WeakPtr<Document> documentReference(m_weakFactory.createWeakPtr());
4917
4918    callOnMainThread([=] {
4919        ASSERT(isMainThread());
4920        std::unique_ptr<Task> task(taskPtr);
4921
4922        Document* document = documentReference.get();
4923        if (!document)
4924            return;
4925
4926        Page* page = document->page();
4927        if ((page && page->defersLoading() && document->activeDOMObjectsAreSuspended()) || !document->m_pendingTasks.isEmpty())
4928            document->m_pendingTasks.append(WTF::move(*task.release()));
4929        else
4930            task->performTask(*document);
4931    });
4932}
4933
4934void Document::pendingTasksTimerFired(Timer<Document>&)
4935{
4936    Vector<Task> pendingTasks = WTF::move(m_pendingTasks);
4937    for (auto& task : pendingTasks)
4938        task.performTask(*this);
4939}
4940
4941void Document::suspendScheduledTasks(ActiveDOMObject::ReasonForSuspension reason)
4942{
4943#if PLATFORM(IOS)
4944    if (m_scheduledTasksAreSuspended) {
4945        ASSERT(reasonForSuspendingActiveDOMObjects() == ActiveDOMObject::DocumentWillBePaused);
4946        return;
4947    }
4948#endif
4949
4950    ASSERT(!m_scheduledTasksAreSuspended);
4951
4952    suspendScriptedAnimationControllerCallbacks();
4953    suspendActiveDOMObjects(reason);
4954    scriptRunner()->suspend();
4955    m_pendingTasksTimer.stop();
4956
4957    // Deferring loading and suspending parser is necessary when we need to prevent re-entrant JavaScript execution
4958    // (e.g. while displaying an alert).
4959    // It is not currently possible to suspend parser unless loading is deferred, because new data arriving from network
4960    // will trigger parsing, and leave the scheduler in an inconsistent state where it doesn't know whether it's suspended or not.
4961    if (reason == ActiveDOMObject::WillDeferLoading && m_parser)
4962        m_parser->suspendScheduledTasks();
4963
4964    m_scheduledTasksAreSuspended = true;
4965}
4966
4967void Document::resumeScheduledTasks(ActiveDOMObject::ReasonForSuspension reason)
4968{
4969    if (reasonForSuspendingActiveDOMObjects() != reason)
4970        return;
4971
4972    ASSERT(m_scheduledTasksAreSuspended);
4973
4974    if (reason == ActiveDOMObject::WillDeferLoading && m_parser)
4975        m_parser->resumeScheduledTasks();
4976    if (!m_pendingTasks.isEmpty())
4977        m_pendingTasksTimer.startOneShot(0);
4978    scriptRunner()->resume();
4979    resumeActiveDOMObjects(reason);
4980    resumeScriptedAnimationControllerCallbacks();
4981
4982    m_scheduledTasksAreSuspended = false;
4983}
4984
4985void Document::suspendScriptedAnimationControllerCallbacks()
4986{
4987#if ENABLE(REQUEST_ANIMATION_FRAME)
4988    if (m_scriptedAnimationController)
4989        m_scriptedAnimationController->suspend();
4990#endif
4991}
4992
4993void Document::resumeScriptedAnimationControllerCallbacks()
4994{
4995#if ENABLE(REQUEST_ANIMATION_FRAME)
4996    if (m_scriptedAnimationController)
4997        m_scriptedAnimationController->resume();
4998#endif
4999}
5000
5001void Document::scriptedAnimationControllerSetThrottled(bool isThrottled)
5002{
5003#if ENABLE(REQUEST_ANIMATION_FRAME)
5004    if (m_scriptedAnimationController)
5005        m_scriptedAnimationController->setThrottled(isThrottled);
5006#else
5007    UNUSED_PARAM(isThrottled);
5008#endif
5009}
5010
5011void Document::windowScreenDidChange(PlatformDisplayID displayID)
5012{
5013    UNUSED_PARAM(displayID);
5014
5015#if ENABLE(REQUEST_ANIMATION_FRAME)
5016    if (m_scriptedAnimationController)
5017        m_scriptedAnimationController->windowScreenDidChange(displayID);
5018#endif
5019
5020    if (RenderView* view = renderView()) {
5021        if (view->usesCompositing())
5022            view->compositor().windowScreenDidChange(displayID);
5023    }
5024}
5025
5026String Document::displayStringModifiedByEncoding(const String& str) const
5027{
5028    if (m_decoder)
5029        return m_decoder->encoding().displayString(str.impl());
5030    return str;
5031}
5032
5033PassRefPtr<StringImpl> Document::displayStringModifiedByEncoding(PassRefPtr<StringImpl> str) const
5034{
5035    if (m_decoder)
5036        return m_decoder->encoding().displayString(str);
5037    return str;
5038}
5039
5040template <typename CharacterType>
5041void Document::displayBufferModifiedByEncodingInternal(CharacterType* buffer, unsigned len) const
5042{
5043    if (m_decoder)
5044        m_decoder->encoding().displayBuffer(buffer, len);
5045}
5046
5047// Generate definitions for both character types
5048template void Document::displayBufferModifiedByEncodingInternal<LChar>(LChar*, unsigned) const;
5049template void Document::displayBufferModifiedByEncodingInternal<UChar>(UChar*, unsigned) const;
5050
5051void Document::enqueuePageshowEvent(PageshowEventPersistence persisted)
5052{
5053    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36334 Pageshow event needs to fire asynchronously.
5054    dispatchWindowEvent(PageTransitionEvent::create(eventNames().pageshowEvent, persisted), this);
5055}
5056
5057void Document::enqueueHashchangeEvent(const String& oldURL, const String& newURL)
5058{
5059    enqueueWindowEvent(HashChangeEvent::create(oldURL, newURL));
5060}
5061
5062void Document::enqueuePopstateEvent(PassRefPtr<SerializedScriptValue> stateObject)
5063{
5064    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36202 Popstate event needs to fire asynchronously
5065    dispatchWindowEvent(PopStateEvent::create(stateObject, m_domWindow ? m_domWindow->history() : nullptr));
5066}
5067
5068void Document::addMediaCanStartListener(MediaCanStartListener* listener)
5069{
5070    ASSERT(!m_mediaCanStartListeners.contains(listener));
5071    m_mediaCanStartListeners.add(listener);
5072}
5073
5074void Document::removeMediaCanStartListener(MediaCanStartListener* listener)
5075{
5076    ASSERT(m_mediaCanStartListeners.contains(listener));
5077    m_mediaCanStartListeners.remove(listener);
5078}
5079
5080MediaCanStartListener* Document::takeAnyMediaCanStartListener()
5081{
5082    return m_mediaCanStartListeners.takeAny();
5083}
5084
5085#if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS)
5086DeviceMotionController* Document::deviceMotionController() const
5087{
5088    return m_deviceMotionController.get();
5089}
5090
5091DeviceOrientationController* Document::deviceOrientationController() const
5092{
5093    return m_deviceOrientationController.get();
5094}
5095#endif
5096
5097#if ENABLE(FULLSCREEN_API)
5098bool Document::fullScreenIsAllowedForElement(Element* element) const
5099{
5100    ASSERT(element);
5101    return isAttributeOnAllOwners(allowfullscreenAttr, webkitallowfullscreenAttr, element->document().ownerElement());
5102}
5103
5104void Document::requestFullScreenForElement(Element* element, unsigned short flags, FullScreenCheckType checkType)
5105{
5106    // The Mozilla Full Screen API <https://wiki.mozilla.org/Gecko:FullScreenAPI> has different requirements
5107    // for full screen mode, and do not have the concept of a full screen element stack.
5108    bool inLegacyMozillaMode = (flags & Element::LEGACY_MOZILLA_REQUEST);
5109
5110    do {
5111        if (!element)
5112            element = documentElement();
5113
5114        // 1. If any of the following conditions are true, terminate these steps and queue a task to fire
5115        // an event named fullscreenerror with its bubbles attribute set to true on the context object's
5116        // node document:
5117
5118        // The context object is not in a document.
5119        if (!element->inDocument())
5120            break;
5121
5122        // The context object's node document, or an ancestor browsing context's document does not have
5123        // the fullscreen enabled flag set.
5124        if (checkType == EnforceIFrameAllowFullScreenRequirement && !fullScreenIsAllowedForElement(element))
5125            break;
5126
5127        // The context object's node document fullscreen element stack is not empty and its top element
5128        // is not an ancestor of the context object. (NOTE: Ignore this requirement if the request was
5129        // made via the legacy Mozilla-style API.)
5130        if (!m_fullScreenElementStack.isEmpty() && !m_fullScreenElementStack.last()->contains(element) && !inLegacyMozillaMode)
5131            break;
5132
5133        // A descendant browsing context's document has a non-empty fullscreen element stack.
5134        bool descendentHasNonEmptyStack = false;
5135        for (Frame* descendant = frame() ? frame()->tree().traverseNext() : nullptr; descendant; descendant = descendant->tree().traverseNext()) {
5136            if (descendant->document()->webkitFullscreenElement()) {
5137                descendentHasNonEmptyStack = true;
5138                break;
5139            }
5140        }
5141        if (descendentHasNonEmptyStack && !inLegacyMozillaMode)
5142            break;
5143
5144        // This algorithm is not allowed to show a pop-up:
5145        //   An algorithm is allowed to show a pop-up if, in the task in which the algorithm is running, either:
5146        //   - an activation behavior is currently being processed whose click event was trusted, or
5147        //   - the event listener for a trusted click event is being handled.
5148        if (!ScriptController::processingUserGesture())
5149            break;
5150
5151        // There is a previously-established user preference, security risk, or platform limitation.
5152        if (!page() || !page()->settings().fullScreenEnabled())
5153            break;
5154
5155        if (!page()->chrome().client().supportsFullScreenForElement(element, flags & Element::ALLOW_KEYBOARD_INPUT)) {
5156            // The new full screen API does not accept a "flags" parameter, so fall back to disallowing
5157            // keyboard input if the chrome client refuses to allow keyboard input.
5158            if (!inLegacyMozillaMode && flags & Element::ALLOW_KEYBOARD_INPUT) {
5159                flags &= ~Element::ALLOW_KEYBOARD_INPUT;
5160                if (!page()->chrome().client().supportsFullScreenForElement(element, false))
5161                    break;
5162            } else
5163                break;
5164        }
5165
5166        // 2. Let doc be element's node document. (i.e. "this")
5167        Document* currentDoc = this;
5168
5169        // 3. Let docs be all doc's ancestor browsing context's documents (if any) and doc.
5170        Deque<Document*> docs;
5171
5172        do {
5173            docs.prepend(currentDoc);
5174            currentDoc = currentDoc->ownerElement() ? &currentDoc->ownerElement()->document() : nullptr;
5175        } while (currentDoc);
5176
5177        // 4. For each document in docs, run these substeps:
5178        Deque<Document*>::iterator current = docs.begin(), following = docs.begin();
5179
5180        do {
5181            ++following;
5182
5183            // 1. Let following document be the document after document in docs, or null if there is no
5184            // such document.
5185            Document* currentDoc = *current;
5186            Document* followingDoc = following != docs.end() ? *following : nullptr;
5187
5188            // 2. If following document is null, push context object on document's fullscreen element
5189            // stack, and queue a task to fire an event named fullscreenchange with its bubbles attribute
5190            // set to true on the document.
5191            if (!followingDoc) {
5192                currentDoc->pushFullscreenElementStack(element);
5193                addDocumentToFullScreenChangeEventQueue(currentDoc);
5194                continue;
5195            }
5196
5197            // 3. Otherwise, if document's fullscreen element stack is either empty or its top element
5198            // is not following document's browsing context container,
5199            Element* topElement = currentDoc->webkitFullscreenElement();
5200            if (!topElement || topElement != followingDoc->ownerElement()) {
5201                // ...push following document's browsing context container on document's fullscreen element
5202                // stack, and queue a task to fire an event named fullscreenchange with its bubbles attribute
5203                // set to true on document.
5204                currentDoc->pushFullscreenElementStack(followingDoc->ownerElement());
5205                addDocumentToFullScreenChangeEventQueue(currentDoc);
5206                continue;
5207            }
5208
5209            // 4. Otherwise, do nothing for this document. It stays the same.
5210        } while (++current != docs.end());
5211
5212        // 5. Return, and run the remaining steps asynchronously.
5213        // 6. Optionally, perform some animation.
5214        m_areKeysEnabledInFullScreen = flags & Element::ALLOW_KEYBOARD_INPUT;
5215        page()->chrome().client().enterFullScreenForElement(element);
5216
5217        // 7. Optionally, display a message indicating how the user can exit displaying the context object fullscreen.
5218        return;
5219    } while (0);
5220
5221    m_fullScreenErrorEventTargetQueue.append(element ? element : documentElement());
5222    m_fullScreenChangeDelayTimer.startOneShot(0);
5223}
5224
5225void Document::webkitCancelFullScreen()
5226{
5227    // The Mozilla "cancelFullScreen()" API behaves like the W3C "fully exit fullscreen" behavior, which
5228    // is defined as:
5229    // "To fully exit fullscreen act as if the exitFullscreen() method was invoked on the top-level browsing
5230    // context's document and subsequently empty that document's fullscreen element stack."
5231    Document& topDocument = this->topDocument();
5232    if (!topDocument.webkitFullscreenElement())
5233        return;
5234
5235    // To achieve that aim, remove all the elements from the top document's stack except for the first before
5236    // calling webkitExitFullscreen():
5237    Vector<RefPtr<Element>> replacementFullscreenElementStack;
5238    replacementFullscreenElementStack.append(topDocument.webkitFullscreenElement());
5239    topDocument.m_fullScreenElementStack.swap(replacementFullscreenElementStack);
5240
5241    topDocument.webkitExitFullscreen();
5242}
5243
5244void Document::webkitExitFullscreen()
5245{
5246    // The exitFullscreen() method must run these steps:
5247
5248    // 1. Let doc be the context object. (i.e. "this")
5249    Document* currentDoc = this;
5250
5251    // 2. If doc's fullscreen element stack is empty, terminate these steps.
5252    if (m_fullScreenElementStack.isEmpty())
5253        return;
5254
5255    // 3. Let descendants be all the doc's descendant browsing context's documents with a non-empty fullscreen
5256    // element stack (if any), ordered so that the child of the doc is last and the document furthest
5257    // away from the doc is first.
5258    Deque<RefPtr<Document>> descendants;
5259    for (Frame* descendant = frame() ? frame()->tree().traverseNext() : nullptr; descendant; descendant = descendant->tree().traverseNext()) {
5260        if (descendant->document()->webkitFullscreenElement())
5261            descendants.prepend(descendant->document());
5262    }
5263
5264    // 4. For each descendant in descendants, empty descendant's fullscreen element stack, and queue a
5265    // task to fire an event named fullscreenchange with its bubbles attribute set to true on descendant.
5266    for (Deque<RefPtr<Document>>::iterator i = descendants.begin(); i != descendants.end(); ++i) {
5267        (*i)->clearFullscreenElementStack();
5268        addDocumentToFullScreenChangeEventQueue(i->get());
5269    }
5270
5271    // 5. While doc is not null, run these substeps:
5272    Element* newTop = nullptr;
5273    while (currentDoc) {
5274        // 1. Pop the top element of doc's fullscreen element stack.
5275        currentDoc->popFullscreenElementStack();
5276
5277        //    If doc's fullscreen element stack is non-empty and the element now at the top is either
5278        //    not in a document or its node document is not doc, repeat this substep.
5279        newTop = currentDoc->webkitFullscreenElement();
5280        if (newTop && (!newTop->inDocument() || &newTop->document() != currentDoc))
5281            continue;
5282
5283        // 2. Queue a task to fire an event named fullscreenchange with its bubbles attribute set to true
5284        // on doc.
5285        addDocumentToFullScreenChangeEventQueue(currentDoc);
5286
5287        // 3. If doc's fullscreen element stack is empty and doc's browsing context has a browsing context
5288        // container, set doc to that browsing context container's node document.
5289        if (!newTop && currentDoc->ownerElement()) {
5290            currentDoc = &currentDoc->ownerElement()->document();
5291            continue;
5292        }
5293
5294        // 4. Otherwise, set doc to null.
5295        currentDoc = nullptr;
5296    }
5297
5298    // 6. Return, and run the remaining steps asynchronously.
5299    // 7. Optionally, perform some animation.
5300
5301    if (!page())
5302        return;
5303
5304    // Only exit out of full screen window mode if there are no remaining elements in the
5305    // full screen stack.
5306    if (!newTop) {
5307        page()->chrome().client().exitFullScreenForElement(m_fullScreenElement.get());
5308        return;
5309    }
5310
5311    // Otherwise, notify the chrome of the new full screen element.
5312    page()->chrome().client().enterFullScreenForElement(newTop);
5313}
5314
5315bool Document::webkitFullscreenEnabled() const
5316{
5317    // 4. The fullscreenEnabled attribute must return true if the context object and all ancestor
5318    // browsing context's documents have their fullscreen enabled flag set, or false otherwise.
5319
5320    // Top-level browsing contexts are implied to have their allowFullScreen attribute set.
5321    return isAttributeOnAllOwners(allowfullscreenAttr, webkitallowfullscreenAttr, ownerElement());
5322}
5323
5324static void unwrapFullScreenRenderer(RenderFullScreen* fullScreenRenderer, Element* fullScreenElement)
5325{
5326    if (!fullScreenRenderer)
5327        return;
5328    bool requiresRenderTreeRebuild;
5329    fullScreenRenderer->unwrapRenderer(requiresRenderTreeRebuild);
5330
5331    if (requiresRenderTreeRebuild && fullScreenElement && fullScreenElement->parentNode())
5332        fullScreenElement->parentNode()->setNeedsStyleRecalc(ReconstructRenderTree);
5333}
5334
5335static bool hostIsYouTube(const String& host)
5336{
5337    // Match .youtube.com, youtube.com, youtube.co.uk, and all two-letter country codes.
5338    static NeverDestroyed<JSC::Yarr::RegularExpression> youtubePattern("(^|\\.)youtube.(com|co.uk|[a-z]{2})$", TextCaseInsensitive);
5339    ASSERT(youtubePattern.get().isValid());
5340
5341    return youtubePattern.get().match(host);
5342}
5343
5344void Document::webkitWillEnterFullScreenForElement(Element* element)
5345{
5346    if (!hasLivingRenderTree() || inPageCache())
5347        return;
5348
5349    ASSERT(element);
5350
5351    // Protect against being called after the document has been removed from the page.
5352    if (!page())
5353        return;
5354
5355    ASSERT(page()->settings().fullScreenEnabled());
5356
5357    unwrapFullScreenRenderer(m_fullScreenRenderer, m_fullScreenElement.get());
5358
5359    m_fullScreenElement = element;
5360
5361#if USE(NATIVE_FULLSCREEN_VIDEO)
5362    if (element && element->isMediaElement())
5363        return;
5364#endif
5365
5366    // Create a placeholder block for a the full-screen element, to keep the page from reflowing
5367    // when the element is removed from the normal flow.  Only do this for a RenderBox, as only
5368    // a box will have a frameRect.  The placeholder will be created in setFullScreenRenderer()
5369    // during layout.
5370    auto renderer = m_fullScreenElement->renderer();
5371    bool shouldCreatePlaceholder = renderer && renderer->isBox();
5372    if (shouldCreatePlaceholder) {
5373        m_savedPlaceholderFrameRect = toRenderBox(renderer)->frameRect();
5374        m_savedPlaceholderRenderStyle = RenderStyle::clone(&renderer->style());
5375    }
5376
5377    if (m_fullScreenElement != documentElement())
5378        RenderFullScreen::wrapRenderer(renderer, renderer ? renderer->parent() : nullptr, *this);
5379
5380    m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(true);
5381
5382    recalcStyle(Style::Force);
5383
5384    if (settings() && settings()->needsSiteSpecificQuirks() && hostIsYouTube(url().host()))
5385        fullScreenChangeDelayTimerFired(m_fullScreenChangeDelayTimer);
5386}
5387
5388void Document::webkitDidEnterFullScreenForElement(Element*)
5389{
5390    if (!m_fullScreenElement)
5391        return;
5392
5393    if (!hasLivingRenderTree() || inPageCache())
5394        return;
5395
5396    m_fullScreenElement->didBecomeFullscreenElement();
5397
5398    if (!settings() || !settings()->needsSiteSpecificQuirks() || !hostIsYouTube(url().host()))
5399        m_fullScreenChangeDelayTimer.startOneShot(0);
5400}
5401
5402void Document::webkitWillExitFullScreenForElement(Element*)
5403{
5404    if (!m_fullScreenElement)
5405        return;
5406
5407    if (!hasLivingRenderTree() || inPageCache())
5408        return;
5409
5410    m_fullScreenElement->willStopBeingFullscreenElement();
5411}
5412
5413void Document::webkitDidExitFullScreenForElement(Element*)
5414{
5415    if (!m_fullScreenElement)
5416        return;
5417
5418    if (!hasLivingRenderTree() || inPageCache())
5419        return;
5420
5421    m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);
5422
5423    m_areKeysEnabledInFullScreen = false;
5424
5425    unwrapFullScreenRenderer(m_fullScreenRenderer, m_fullScreenElement.get());
5426
5427    m_fullScreenElement = nullptr;
5428    scheduleForcedStyleRecalc();
5429
5430    // When webkitCancelFullScreen is called, we call webkitExitFullScreen on the topDocument(). That
5431    // means that the events will be queued there. So if we have no events here, start the timer on
5432    // the exiting document.
5433    bool eventTargetQueuesEmpty = m_fullScreenChangeEventTargetQueue.isEmpty() && m_fullScreenErrorEventTargetQueue.isEmpty();
5434    Document& exitingDocument = eventTargetQueuesEmpty ? topDocument() : *this;
5435
5436    // FIXME(136605): Remove this quirk once YouTube moves to relative widths and heights for
5437    // fullscreen mode.
5438    if (settings() && settings()->needsSiteSpecificQuirks() && hostIsYouTube(url().host()))
5439        exitingDocument.fullScreenChangeDelayTimerFired(exitingDocument.m_fullScreenChangeDelayTimer);
5440    else
5441        exitingDocument.m_fullScreenChangeDelayTimer.startOneShot(0);
5442
5443}
5444
5445void Document::setFullScreenRenderer(RenderFullScreen* renderer)
5446{
5447    if (renderer == m_fullScreenRenderer)
5448        return;
5449
5450    if (renderer && m_savedPlaceholderRenderStyle)
5451        renderer->createPlaceholder(m_savedPlaceholderRenderStyle.releaseNonNull(), m_savedPlaceholderFrameRect);
5452    else if (renderer && m_fullScreenRenderer && m_fullScreenRenderer->placeholder()) {
5453        RenderBlock* placeholder = m_fullScreenRenderer->placeholder();
5454        renderer->createPlaceholder(RenderStyle::clone(&placeholder->style()), placeholder->frameRect());
5455    }
5456
5457    if (m_fullScreenRenderer)
5458        m_fullScreenRenderer->destroy();
5459    ASSERT(!m_fullScreenRenderer);
5460
5461    m_fullScreenRenderer = renderer;
5462}
5463
5464void Document::fullScreenRendererDestroyed()
5465{
5466    m_fullScreenRenderer = nullptr;
5467}
5468
5469void Document::fullScreenChangeDelayTimerFired(Timer<Document>&)
5470{
5471    // Since we dispatch events in this function, it's possible that the
5472    // document will be detached and GC'd. We protect it here to make sure we
5473    // can finish the function successfully.
5474    Ref<Document> protect(*this);
5475    Deque<RefPtr<Node>> changeQueue;
5476    m_fullScreenChangeEventTargetQueue.swap(changeQueue);
5477    Deque<RefPtr<Node>> errorQueue;
5478    m_fullScreenErrorEventTargetQueue.swap(errorQueue);
5479    dispatchFullScreenChangeOrErrorEvent(changeQueue, eventNames().webkitfullscreenchangeEvent, /* shouldNotifyMediaElement */ true);
5480    dispatchFullScreenChangeOrErrorEvent(errorQueue, eventNames().webkitfullscreenerrorEvent, /* shouldNotifyMediaElement */ false);
5481}
5482
5483void Document::dispatchFullScreenChangeOrErrorEvent(Deque<RefPtr<Node>>& queue, const AtomicString& eventName, bool shouldNotifyMediaElement)
5484{
5485    while (!queue.isEmpty()) {
5486        RefPtr<Node> node = queue.takeFirst();
5487        if (!node)
5488            node = documentElement();
5489        // The dispatchEvent below may have blown away our documentElement.
5490        if (!node)
5491            continue;
5492
5493        // If the element was removed from our tree, also message the documentElement. Since we may
5494        // have a document hierarchy, check that node isn't in another document.
5495        if (!node->inDocument())
5496            queue.append(documentElement());
5497
5498#if ENABLE(VIDEO)
5499        if (shouldNotifyMediaElement && isHTMLMediaElement(*node))
5500            toHTMLMediaElement(*node).enteredOrExitedFullscreen();
5501#endif
5502        node->dispatchEvent(Event::create(eventName, true, false));
5503    }
5504}
5505
5506void Document::fullScreenElementRemoved()
5507{
5508    m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);
5509    webkitCancelFullScreen();
5510}
5511
5512void Document::removeFullScreenElementOfSubtree(Node* node, bool amongChildrenOnly)
5513{
5514    if (!m_fullScreenElement)
5515        return;
5516
5517    bool elementInSubtree = false;
5518    if (amongChildrenOnly)
5519        elementInSubtree = m_fullScreenElement->isDescendantOf(node);
5520    else
5521        elementInSubtree = (m_fullScreenElement == node) || m_fullScreenElement->isDescendantOf(node);
5522
5523    if (elementInSubtree)
5524        fullScreenElementRemoved();
5525}
5526
5527bool Document::isAnimatingFullScreen() const
5528{
5529    return m_isAnimatingFullScreen;
5530}
5531
5532void Document::setAnimatingFullScreen(bool flag)
5533{
5534    if (m_isAnimatingFullScreen == flag)
5535        return;
5536    m_isAnimatingFullScreen = flag;
5537
5538    if (m_fullScreenElement && m_fullScreenElement->isDescendantOf(this)) {
5539        m_fullScreenElement->setNeedsStyleRecalc();
5540        scheduleForcedStyleRecalc();
5541    }
5542}
5543
5544void Document::clearFullscreenElementStack()
5545{
5546    m_fullScreenElementStack.clear();
5547}
5548
5549void Document::popFullscreenElementStack()
5550{
5551    if (m_fullScreenElementStack.isEmpty())
5552        return;
5553
5554    m_fullScreenElementStack.removeLast();
5555}
5556
5557void Document::pushFullscreenElementStack(Element* element)
5558{
5559    m_fullScreenElementStack.append(element);
5560}
5561
5562void Document::addDocumentToFullScreenChangeEventQueue(Document* doc)
5563{
5564    ASSERT(doc);
5565    Node* target = doc->webkitFullscreenElement();
5566    if (!target)
5567        target = doc->webkitCurrentFullScreenElement();
5568    if (!target)
5569        target = doc;
5570    m_fullScreenChangeEventTargetQueue.append(target);
5571}
5572#endif
5573
5574#if ENABLE(POINTER_LOCK)
5575void Document::exitPointerLock()
5576{
5577    if (!page())
5578        return;
5579    if (Element* target = page()->pointerLockController().element()) {
5580        if (&target->document() != this)
5581            return;
5582    }
5583    page()->pointerLockController().requestPointerUnlock();
5584}
5585
5586Element* Document::pointerLockElement() const
5587{
5588    if (!page() || page()->pointerLockController().lockPending())
5589        return nullptr;
5590    if (Element* element = page()->pointerLockController().element()) {
5591        if (&element->document() == this)
5592            return element;
5593    }
5594    return nullptr;
5595}
5596#endif
5597
5598void Document::decrementLoadEventDelayCount()
5599{
5600    ASSERT(m_loadEventDelayCount);
5601    --m_loadEventDelayCount;
5602
5603    if (frame() && !m_loadEventDelayCount && !m_loadEventDelayTimer.isActive())
5604        m_loadEventDelayTimer.startOneShot(0);
5605}
5606
5607void Document::loadEventDelayTimerFired(Timer<Document>&)
5608{
5609    if (frame())
5610        frame()->loader().checkCompleted();
5611}
5612
5613#if ENABLE(REQUEST_ANIMATION_FRAME)
5614int Document::requestAnimationFrame(PassRefPtr<RequestAnimationFrameCallback> callback)
5615{
5616    if (!m_scriptedAnimationController) {
5617#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
5618        m_scriptedAnimationController = ScriptedAnimationController::create(this, page() ? page()->chrome().displayID() : 0);
5619#else
5620        m_scriptedAnimationController = ScriptedAnimationController::create(this, 0);
5621#endif
5622        // It's possible that the Page may have suspended scripted animations before
5623        // we were created. We need to make sure that we don't start up the animation
5624        // controller on a background tab, for example.
5625        if (!page() || page()->scriptedAnimationsSuspended())
5626            m_scriptedAnimationController->suspend();
5627    }
5628
5629    return m_scriptedAnimationController->registerCallback(callback);
5630}
5631
5632void Document::cancelAnimationFrame(int id)
5633{
5634    if (!m_scriptedAnimationController)
5635        return;
5636    m_scriptedAnimationController->cancelCallback(id);
5637}
5638
5639void Document::serviceScriptedAnimations(double monotonicAnimationStartTime)
5640{
5641    if (!m_scriptedAnimationController)
5642        return;
5643    m_scriptedAnimationController->serviceScriptedAnimations(monotonicAnimationStartTime);
5644}
5645
5646void Document::clearScriptedAnimationController()
5647{
5648    // FIXME: consider using ActiveDOMObject.
5649    if (m_scriptedAnimationController)
5650        m_scriptedAnimationController->clearDocumentPointer();
5651    m_scriptedAnimationController.clear();
5652}
5653#endif
5654
5655void Document::sendWillRevealEdgeEventsIfNeeded(const IntPoint& oldPosition, const IntPoint& newPosition, const IntRect& visibleRect, const IntSize& contentsSize, Element* target)
5656{
5657    // For each edge (top, bottom, left and right), send the will reveal edge event for that direction
5658    // if newPosition is at or beyond the notification point, if the scroll direction is heading in the
5659    // direction of that edge point, and if oldPosition is before the notification point (which indicates
5660    // that this is the first moment that we know we crossed the magic line).
5661
5662#if ENABLE(WILL_REVEAL_EDGE_EVENTS)
5663
5664    int willRevealBottomNotificationPoint = std::max(0, contentsSize.height() - 2 *  visibleRect.height());
5665    int willRevealTopNotificationPoint = visibleRect.height();
5666
5667    // Bottom edge.
5668    if (newPosition.y() >= willRevealBottomNotificationPoint && newPosition.y() > oldPosition.y()
5669        && willRevealBottomNotificationPoint >= oldPosition.y()) {
5670        RefPtr<Event> willRevealEvent = Event::create(eventNames().webkitwillrevealbottomEvent, false, false);
5671        if (!target)
5672            enqueueWindowEvent(willRevealEvent.release());
5673        else {
5674            willRevealEvent->setTarget(target);
5675            m_eventQueue.enqueueEvent(willRevealEvent.release());
5676        }
5677    }
5678
5679    // Top edge.
5680    if (newPosition.y() <= willRevealTopNotificationPoint && newPosition.y() < oldPosition.y()
5681        && willRevealTopNotificationPoint <= oldPosition.y()) {
5682        RefPtr<Event> willRevealEvent = Event::create(eventNames().webkitwillrevealtopEvent, false, false);
5683        if (!target)
5684            enqueueWindowEvent(willRevealEvent.release());
5685        else {
5686            willRevealEvent->setTarget(target);
5687            m_eventQueue.enqueueEvent(willRevealEvent.release());
5688        }
5689    }
5690
5691    int willRevealRightNotificationPoint = std::max(0, contentsSize.width() - 2 * visibleRect.width());
5692    int willRevealLeftNotificationPoint = visibleRect.width();
5693
5694    // Right edge.
5695    if (newPosition.x() >= willRevealRightNotificationPoint && newPosition.x() > oldPosition.x()
5696        && willRevealRightNotificationPoint >= oldPosition.x()) {
5697        RefPtr<Event> willRevealEvent = Event::create(eventNames().webkitwillrevealrightEvent, false, false);
5698        if (!target)
5699            enqueueWindowEvent(willRevealEvent.release());
5700        else {
5701            willRevealEvent->setTarget(target);
5702            m_eventQueue.enqueueEvent(willRevealEvent.release());
5703        }
5704    }
5705
5706    // Left edge.
5707    if (newPosition.x() <= willRevealLeftNotificationPoint && newPosition.x() < oldPosition.x()
5708        && willRevealLeftNotificationPoint <= oldPosition.x()) {
5709        RefPtr<Event> willRevealEvent = Event::create(eventNames().webkitwillrevealleftEvent, false, false);
5710        if (!target)
5711            enqueueWindowEvent(willRevealEvent.release());
5712        else {
5713            willRevealEvent->setTarget(target);
5714            m_eventQueue.enqueueEvent(willRevealEvent.release());
5715        }
5716    }
5717#else
5718    UNUSED_PARAM(oldPosition);
5719    UNUSED_PARAM(newPosition);
5720    UNUSED_PARAM(visibleRect);
5721    UNUSED_PARAM(contentsSize);
5722    UNUSED_PARAM(target);
5723#endif
5724}
5725
5726#if !PLATFORM(IOS)
5727#if ENABLE(TOUCH_EVENTS)
5728PassRefPtr<Touch> Document::createTouch(DOMWindow* window, EventTarget* target, int identifier, int pageX, int pageY, int screenX, int screenY, int radiusX, int radiusY, float rotationAngle, float force, ExceptionCode&) const
5729{
5730    // FIXME: It's not clear from the documentation at
5731    // http://developer.apple.com/library/safari/#documentation/UserExperience/Reference/DocumentAdditionsReference/DocumentAdditions/DocumentAdditions.html
5732    // when this method should throw and nor is it by inspection of iOS behavior. It would be nice to verify any cases where it throws under iOS
5733    // and implement them here. See https://bugs.webkit.org/show_bug.cgi?id=47819
5734    Frame* frame = window ? window->frame() : this->frame();
5735    return Touch::create(frame, target, identifier, screenX, screenY, pageX, pageY, radiusX, radiusY, rotationAngle, force);
5736}
5737#endif
5738#endif // !PLATFORM(IOS)
5739
5740static void wheelEventHandlerCountChanged(Document* document)
5741{
5742    Page* page = document->page();
5743    if (!page)
5744        return;
5745
5746    pageWheelEventHandlerCountChanged(*page);
5747
5748    ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator();
5749    if (!scrollingCoordinator)
5750        return;
5751
5752    FrameView* frameView = document->view();
5753    if (!frameView)
5754        return;
5755
5756    // FIXME: Why doesn't this need to be called in didBecomeCurrentDocumentInFrame?
5757    scrollingCoordinator->frameViewWheelEventHandlerCountChanged(frameView);
5758}
5759
5760void Document::didAddWheelEventHandler()
5761{
5762    ++m_wheelEventHandlerCount;
5763    wheelEventHandlerCountChanged(this);
5764}
5765
5766void Document::didRemoveWheelEventHandler()
5767{
5768    ASSERT(m_wheelEventHandlerCount > 0);
5769    --m_wheelEventHandlerCount;
5770    wheelEventHandlerCountChanged(this);
5771}
5772
5773void Document::didAddTouchEventHandler(Node* handler)
5774{
5775#if ENABLE(TOUCH_EVENTS)
5776    if (!m_touchEventTargets.get())
5777        m_touchEventTargets = std::make_unique<TouchEventTargetSet>();
5778    m_touchEventTargets->add(handler);
5779    if (Document* parent = parentDocument()) {
5780        parent->didAddTouchEventHandler(this);
5781        return;
5782    }
5783    if (Page* page = this->page()) {
5784        if (m_touchEventTargets->size() == 1)
5785            page->chrome().client().needTouchEvents(true);
5786    }
5787#else
5788    UNUSED_PARAM(handler);
5789#endif
5790}
5791
5792void Document::didRemoveTouchEventHandler(Node* handler)
5793{
5794#if ENABLE(TOUCH_EVENTS)
5795    if (!m_touchEventTargets.get())
5796        return;
5797    ASSERT(m_touchEventTargets->contains(handler));
5798    m_touchEventTargets->remove(handler);
5799    if (Document* parent = parentDocument()) {
5800        parent->didRemoveTouchEventHandler(this);
5801        return;
5802    }
5803
5804    Page* page = this->page();
5805    if (!page)
5806        return;
5807    if (m_touchEventTargets->size())
5808        return;
5809    for (const Frame* frame = &page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
5810        if (frame->document() && frame->document()->hasTouchEventHandlers())
5811            return;
5812    }
5813    page->chrome().client().needTouchEvents(false);
5814#else
5815    UNUSED_PARAM(handler);
5816#endif
5817}
5818
5819#if ENABLE(TOUCH_EVENTS)
5820void Document::didRemoveEventTargetNode(Node* handler)
5821{
5822    if (m_touchEventTargets) {
5823        m_touchEventTargets->removeAll(handler);
5824        if ((handler == this || m_touchEventTargets->isEmpty()) && parentDocument())
5825            parentDocument()->didRemoveEventTargetNode(this);
5826    }
5827}
5828#endif
5829
5830void Document::resetLastHandledUserGestureTimestamp()
5831{
5832    m_lastHandledUserGestureTimestamp = monotonicallyIncreasingTime();
5833}
5834
5835DocumentLoader* Document::loader() const
5836{
5837    if (!m_frame)
5838        return nullptr;
5839
5840    DocumentLoader* loader = m_frame->loader().documentLoader();
5841    if (!loader)
5842        return nullptr;
5843
5844    if (m_frame->document() != this)
5845        return nullptr;
5846
5847    return loader;
5848}
5849
5850#if ENABLE(CSS_DEVICE_ADAPTATION)
5851IntSize Document::initialViewportSize() const
5852{
5853    if (!view())
5854        return IntSize();
5855    return view()->initialViewportSize();
5856}
5857#endif
5858
5859Element* eventTargetElementForDocument(Document* doc)
5860{
5861    if (!doc)
5862        return nullptr;
5863    Element* element = doc->focusedElement();
5864    if (!element && doc->isPluginDocument()) {
5865        PluginDocument* pluginDocument = toPluginDocument(doc);
5866        element = pluginDocument->pluginElement();
5867    }
5868    if (!element && doc->isHTMLDocument())
5869        element = doc->body();
5870    if (!element)
5871        element = doc->documentElement();
5872    return element;
5873}
5874
5875void Document::adjustFloatQuadsForScrollAndAbsoluteZoomAndFrameScale(Vector<FloatQuad>& quads, const RenderStyle& style)
5876{
5877    if (!view())
5878        return;
5879
5880    float zoom = style.effectiveZoom();
5881    float inverseFrameScale = 1;
5882    if (frame())
5883        inverseFrameScale = 1 / frame()->frameScaleFactor();
5884
5885    LayoutRect visibleContentRect = view()->visibleContentRect();
5886    for (size_t i = 0; i < quads.size(); ++i) {
5887        quads[i].move(-visibleContentRect.x(), -visibleContentRect.y());
5888        if (zoom != 1)
5889            quads[i].scale(1 / zoom, 1 / zoom);
5890        if (inverseFrameScale != 1)
5891            quads[i].scale(inverseFrameScale, inverseFrameScale);
5892    }
5893}
5894
5895void Document::adjustFloatRectForScrollAndAbsoluteZoomAndFrameScale(FloatRect& rect, const RenderStyle& style)
5896{
5897    if (!view())
5898        return;
5899
5900    float zoom = style.effectiveZoom();
5901    float inverseFrameScale = 1;
5902    if (frame())
5903        inverseFrameScale = 1 / frame()->frameScaleFactor();
5904
5905    LayoutRect visibleContentRect = view()->visibleContentRect();
5906    rect.move(-visibleContentRect.x(), -visibleContentRect.y());
5907    if (zoom != 1)
5908        rect.scale(1 / zoom);
5909    if (inverseFrameScale != 1)
5910        rect.scale(inverseFrameScale);
5911}
5912
5913bool Document::hasActiveParser()
5914{
5915    return m_activeParserCount || (m_parser && m_parser->processingData());
5916}
5917
5918void Document::decrementActiveParserCount()
5919{
5920    --m_activeParserCount;
5921    if (!frame())
5922        return;
5923
5924    // FIXME: We should call loader()->checkLoadComplete() as well here,
5925    // but it seems to cause http/tests/security/feed-urls-from-remote.html
5926    // to timeout on Mac WK1; see http://webkit.org/b/110554 and http://webkit.org/b/110401.
5927    frame()->loader().checkLoadComplete();
5928}
5929
5930static RenderElement* nearestCommonHoverAncestor(RenderElement* obj1, RenderElement* obj2)
5931{
5932    if (!obj1 || !obj2)
5933        return nullptr;
5934
5935    for (RenderElement* currObj1 = obj1; currObj1; currObj1 = currObj1->hoverAncestor()) {
5936        for (RenderElement* currObj2 = obj2; currObj2; currObj2 = currObj2->hoverAncestor()) {
5937            if (currObj1 == currObj2)
5938                return currObj1;
5939        }
5940    }
5941
5942    return nullptr;
5943}
5944
5945void Document::updateHoverActiveState(const HitTestRequest& request, Element* innerElement, StyleResolverUpdateFlag updateFlag)
5946{
5947    ASSERT(!request.readOnly());
5948
5949    Element* innerElementInDocument = innerElement;
5950    while (innerElementInDocument && &innerElementInDocument->document() != this) {
5951        innerElementInDocument->document().updateHoverActiveState(request, innerElementInDocument);
5952        innerElementInDocument = innerElementInDocument->document().ownerElement();
5953    }
5954
5955    Element* oldActiveElement = m_activeElement.get();
5956    if (oldActiveElement && !request.active()) {
5957        // We are clearing the :active chain because the mouse has been released.
5958        for (Element* curr = oldActiveElement; curr; curr = curr->parentOrShadowHostElement()) {
5959            curr->setActive(false);
5960            m_userActionElements.setInActiveChain(curr, false);
5961        }
5962        m_activeElement.clear();
5963    } else {
5964        Element* newActiveElement = innerElementInDocument;
5965        if (!oldActiveElement && newActiveElement && request.active() && !request.touchMove()) {
5966            // We are setting the :active chain and freezing it. If future moves happen, they
5967            // will need to reference this chain.
5968            for (RenderElement* curr = newActiveElement->renderer(); curr; curr = curr->parent()) {
5969                Element* element = curr->element();
5970                if (!element || curr->isTextOrLineBreak())
5971                    continue;
5972                m_userActionElements.setInActiveChain(element, true);
5973            }
5974
5975            m_activeElement = newActiveElement;
5976        }
5977    }
5978    // If the mouse has just been pressed, set :active on the chain. Those (and only those)
5979    // nodes should remain :active until the mouse is released.
5980    bool allowActiveChanges = !oldActiveElement && m_activeElement;
5981
5982    // If the mouse is down and if this is a mouse move event, we want to restrict changes in
5983    // :hover/:active to only apply to elements that are in the :active chain that we froze
5984    // at the time the mouse went down.
5985    bool mustBeInActiveChain = request.active() && request.move();
5986
5987    RefPtr<Element> oldHoveredElement = m_hoveredElement.release();
5988
5989    // A touch release does not set a new hover target; clearing the element we're working with
5990    // will clear the chain of hovered elements all the way to the top of the tree.
5991    if (request.touchRelease())
5992        innerElementInDocument = nullptr;
5993
5994    // Check to see if the hovered Element has changed.
5995    // If it hasn't, we do not need to do anything.
5996    Element* newHoveredElement = innerElementInDocument;
5997    while (newHoveredElement && !newHoveredElement->renderer())
5998        newHoveredElement = newHoveredElement->parentOrShadowHostElement();
5999
6000    m_hoveredElement = newHoveredElement;
6001
6002    // We have two different objects. Fetch their renderers.
6003    RenderElement* oldHoverObj = oldHoveredElement ? oldHoveredElement->renderer() : nullptr;
6004    RenderElement* newHoverObj = newHoveredElement ? newHoveredElement->renderer() : nullptr;
6005
6006    // Locate the common ancestor render object for the two renderers.
6007    RenderElement* ancestor = nearestCommonHoverAncestor(oldHoverObj, newHoverObj);
6008
6009    Vector<RefPtr<Element>, 32> elementsToRemoveFromChain;
6010    Vector<RefPtr<Element>, 32> elementsToAddToChain;
6011
6012    if (oldHoverObj != newHoverObj) {
6013        // If the old hovered element is not nil but it's renderer is, it was probably detached as part of the :hover style
6014        // (for instance by setting display:none in the :hover pseudo-class). In this case, the old hovered element (and its ancestors)
6015        // must be updated, to ensure it's normal style is re-applied.
6016        if (oldHoveredElement && !oldHoverObj) {
6017            for (Element* element = oldHoveredElement.get(); element; element = element->parentElement()) {
6018                if (!mustBeInActiveChain || element->inActiveChain())
6019                    elementsToRemoveFromChain.append(element);
6020            }
6021        }
6022
6023        // The old hover path only needs to be cleared up to (and not including) the common ancestor;
6024        for (RenderElement* curr = oldHoverObj; curr && curr != ancestor; curr = curr->hoverAncestor()) {
6025            Element* element = curr->element();
6026            if (!element)
6027                continue;
6028            if (!mustBeInActiveChain || element->inActiveChain())
6029                elementsToRemoveFromChain.append(element);
6030        }
6031        // Unset hovered nodes in sub frame documents if the old hovered node was a frame owner.
6032        if (oldHoveredElement && oldHoveredElement->isFrameOwnerElement()) {
6033            if (Document* contentDocument = toHTMLFrameOwnerElement(*oldHoveredElement).contentDocument())
6034                contentDocument->updateHoverActiveState(request, nullptr);
6035        }
6036    }
6037
6038    // Now set the hover state for our new object up to the root.
6039    for (RenderElement* curr = newHoverObj; curr; curr = curr->hoverAncestor()) {
6040        Element* element = curr->element();
6041        if (!element)
6042            continue;
6043        if (!mustBeInActiveChain || element->inActiveChain())
6044            elementsToAddToChain.append(element);
6045    }
6046
6047    size_t removeCount = elementsToRemoveFromChain.size();
6048    for (size_t i = 0; i < removeCount; ++i)
6049        elementsToRemoveFromChain[i]->setHovered(false);
6050
6051    bool sawCommonAncestor = false;
6052    for (size_t i = 0, size = elementsToAddToChain.size(); i < size; ++i) {
6053        if (allowActiveChanges)
6054            elementsToAddToChain[i]->setActive(true);
6055        if (ancestor && elementsToAddToChain[i] == ancestor->element())
6056            sawCommonAncestor = true;
6057        if (!sawCommonAncestor) {
6058            // Elements after the common hover ancestor does not change hover state, but are iterated over because they may change active state.
6059            elementsToAddToChain[i]->setHovered(true);
6060        }
6061    }
6062
6063    ASSERT(updateFlag == RecalcStyleIfNeeded || updateFlag == DeferRecalcStyleIfNeeded);
6064    if (updateFlag == RecalcStyleIfNeeded)
6065        updateStyleIfNeeded();
6066}
6067
6068bool Document::haveStylesheetsLoaded() const
6069{
6070    return !m_styleSheetCollection.hasPendingSheets() || m_ignorePendingStylesheets;
6071}
6072
6073Locale& Document::getCachedLocale(const AtomicString& locale)
6074{
6075    AtomicString localeKey = locale;
6076    if (locale.isEmpty() || !RuntimeEnabledFeatures::sharedFeatures().langAttributeAwareFormControlUIEnabled())
6077        localeKey = defaultLanguage();
6078    LocaleIdentifierToLocaleMap::AddResult result = m_localeCache.add(localeKey, nullptr);
6079    if (result.isNewEntry)
6080        result.iterator->value = Locale::create(localeKey);
6081    return *(result.iterator->value);
6082}
6083
6084#if ENABLE(TEMPLATE_ELEMENT)
6085Document* Document::ensureTemplateDocument()
6086{
6087    if (const Document* document = templateDocument())
6088        return const_cast<Document*>(document);
6089
6090    if (isHTMLDocument())
6091        m_templateDocument = HTMLDocument::create(nullptr, blankURL());
6092    else
6093        m_templateDocument = Document::create(nullptr, blankURL());
6094
6095    m_templateDocument->setTemplateDocumentHost(this); // balanced in dtor.
6096
6097    return m_templateDocument.get();
6098}
6099#endif
6100
6101#if ENABLE(FONT_LOAD_EVENTS)
6102PassRefPtr<FontLoader> Document::fontloader()
6103{
6104    if (!m_fontloader)
6105        m_fontloader = FontLoader::create(this);
6106    return m_fontloader;
6107}
6108#endif
6109
6110float Document::deviceScaleFactor() const
6111{
6112    float deviceScaleFactor = 1.0;
6113    if (Page* documentPage = page())
6114        deviceScaleFactor = documentPage->deviceScaleFactor();
6115    return deviceScaleFactor;
6116}
6117void Document::didAssociateFormControl(Element* element)
6118{
6119    if (!frame() || !frame()->page() || !frame()->page()->chrome().client().shouldNotifyOnFormChanges())
6120        return;
6121    m_associatedFormControls.add(element);
6122    if (!m_didAssociateFormControlsTimer.isActive())
6123        m_didAssociateFormControlsTimer.startOneShot(0);
6124}
6125
6126void Document::didAssociateFormControlsTimerFired(Timer<Document>& timer)
6127{
6128    ASSERT_UNUSED(timer, &timer == &m_didAssociateFormControlsTimer);
6129
6130    if (!frame() || !frame()->page())
6131        return;
6132
6133    Vector<RefPtr<Element>> associatedFormControls;
6134    copyToVector(m_associatedFormControls, associatedFormControls);
6135
6136    frame()->page()->chrome().client().didAssociateFormControls(associatedFormControls);
6137    m_associatedFormControls.clear();
6138}
6139
6140void Document::ensurePlugInsInjectedScript(DOMWrapperWorld& world)
6141{
6142    if (m_hasInjectedPlugInsScript)
6143        return;
6144
6145    // Use the JS file provided by the Chrome client, or fallback to the default one.
6146    String jsString = page()->chrome().client().plugInExtraScript();
6147    if (!jsString)
6148        jsString = plugInsJavaScript;
6149
6150    m_frame->mainFrame().script().evaluateInWorld(ScriptSourceCode(jsString), world);
6151
6152    m_hasInjectedPlugInsScript = true;
6153}
6154
6155#if ENABLE(SUBTLE_CRYPTO)
6156bool Document::wrapCryptoKey(const Vector<uint8_t>& key, Vector<uint8_t>& wrappedKey)
6157{
6158    Page* page = this->page();
6159    if (!page)
6160        return false;
6161    return page->chrome().client().wrapCryptoKey(key, wrappedKey);
6162}
6163
6164bool Document::unwrapCryptoKey(const Vector<uint8_t>& wrappedKey, Vector<uint8_t>& key)
6165{
6166    Page* page = this->page();
6167    if (!page)
6168        return false;
6169    return page->chrome().client().unwrapCryptoKey(wrappedKey, key);
6170}
6171#endif // ENABLE(SUBTLE_CRYPTO)
6172
6173static inline bool nodeOrItsAncestorNeedsStyleRecalc(const Node& node)
6174{
6175    for (const Node* n = &node; n; n = n->parentOrShadowHostNode()) {
6176        if (n->needsStyleRecalc())
6177            return true;
6178    }
6179    return false;
6180}
6181
6182bool Document::updateStyleIfNeededForNode(const Node& node)
6183{
6184    if (!hasPendingForcedStyleRecalc() && !(childNeedsStyleRecalc() && nodeOrItsAncestorNeedsStyleRecalc(node)))
6185        return false;
6186    updateStyleIfNeeded();
6187    return true;
6188}
6189
6190Element* Document::activeElement()
6191{
6192    updateStyleIfNeeded();
6193    if (Element* element = treeScope().focusedElement())
6194        return element;
6195    return body();
6196}
6197
6198bool Document::hasFocus() const
6199{
6200    Page* page = this->page();
6201    if (!page || !page->focusController().isActive())
6202        return false;
6203    if (Frame* focusedFrame = page->focusController().focusedFrame()) {
6204        if (focusedFrame->tree().isDescendantOf(frame()))
6205            return true;
6206    }
6207    return false;
6208}
6209
6210#if ENABLE(WEB_REPLAY)
6211void Document::setInputCursor(PassRefPtr<InputCursor> cursor)
6212{
6213    m_inputCursor = cursor;
6214}
6215#endif
6216
6217} // namespace WebCore
6218