/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All
 * rights reserved.
 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
 * (http://www.torchmobile.com/)
 * Copyright (C) 2008, 2009, 2011, 2012 Google Inc. All rights reserved.
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
 * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "core/dom/Document.h"

#include "bindings/core/v8/DOMDataStore.h"
#include "bindings/core/v8/ExceptionMessages.h"
#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/HTMLScriptElementOrSVGScriptElement.h"
#include "bindings/core/v8/Microtask.h"
#include "bindings/core/v8/ScriptController.h"
#include "bindings/core/v8/SourceLocation.h"
#include "bindings/core/v8/StringOrDictionary.h"
#include "bindings/core/v8/V0CustomElementConstructorBuilder.h"
#include "bindings/core/v8/V8DOMWrapper.h"
#include "bindings/core/v8/V8ElementCreationOptions.h"
#include "bindings/core/v8/V8PerIsolateData.h"
#include "bindings/core/v8/WindowProxy.h"
#include "core/HTMLElementFactory.h"
#include "core/HTMLElementTypeHelpers.h"
#include "core/HTMLNames.h"
#include "core/SVGElementFactory.h"
#include "core/SVGNames.h"
#include "core/XMLNSNames.h"
#include "core/XMLNames.h"
#include "core/animation/CompositorPendingAnimations.h"
#include "core/animation/DocumentAnimations.h"
#include "core/animation/DocumentTimeline.h"
#include "core/css/CSSFontSelector.h"
#include "core/css/CSSStyleDeclaration.h"
#include "core/css/CSSStyleSheet.h"
#include "core/css/CSSTiming.h"
#include "core/css/FontFaceSet.h"
#include "core/css/MediaQueryMatcher.h"
#include "core/css/PropertyRegistry.h"
#include "core/css/StylePropertySet.h"
#include "core/css/StyleSheetContents.h"
#include "core/css/StyleSheetList.h"
#include "core/css/invalidation/StyleInvalidator.h"
#include "core/css/parser/CSSParser.h"
#include "core/css/resolver/FontBuilder.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/css/resolver/StyleResolverStats.h"
#include "core/dom/AXObjectCache.h"
#include "core/dom/Attr.h"
#include "core/dom/CDATASection.h"
#include "core/dom/ClientRect.h"
#include "core/dom/Comment.h"
#include "core/dom/ContextFeatures.h"
#include "core/dom/DOMImplementation.h"
#include "core/dom/DocumentFragment.h"
#include "core/dom/DocumentParserTiming.h"
#include "core/dom/DocumentType.h"
#include "core/dom/Element.h"
#include "core/dom/ElementCreationOptions.h"
#include "core/dom/ElementDataCache.h"
#include "core/dom/ElementRegistrationOptions.h"
#include "core/dom/ElementTraversal.h"
#include "core/dom/ExceptionCode.h"
#include "core/dom/ExecutionContextTask.h"
#include "core/dom/FrameRequestCallback.h"
#include "core/dom/IntersectionObserverController.h"
#include "core/dom/LayoutTreeBuilderTraversal.h"
#include "core/dom/LiveNodeList.h"
#include "core/dom/MutationObserver.h"
#include "core/dom/NodeChildRemovalTracker.h"
#include "core/dom/NodeComputedStyle.h"
#include "core/dom/NodeFilter.h"
#include "core/dom/NodeIterator.h"
#include "core/dom/NodeRareData.h"
#include "core/dom/NodeTraversal.h"
#include "core/dom/NodeWithIndex.h"
#include "core/dom/NthIndexCache.h"
#include "core/dom/ProcessingInstruction.h"
#include "core/dom/ScriptRunner.h"
#include "core/dom/ScriptedAnimationController.h"
#include "core/dom/ScriptedIdleTaskController.h"
#include "core/dom/SelectorQuery.h"
#include "core/dom/StaticNodeList.h"
#include "core/dom/StyleChangeReason.h"
#include "core/dom/StyleEngine.h"
#include "core/dom/TaskRunnerHelper.h"
#include "core/dom/TouchList.h"
#include "core/dom/TransformSource.h"
#include "core/dom/TreeWalker.h"
#include "core/dom/VisitedLinkState.h"
#include "core/dom/XMLDocument.h"
#include "core/dom/custom/CustomElement.h"
#include "core/dom/custom/CustomElementDefinition.h"
#include "core/dom/custom/CustomElementDescriptor.h"
#include "core/dom/custom/CustomElementRegistry.h"
#include "core/dom/custom/V0CustomElementMicrotaskRunQueue.h"
#include "core/dom/custom/V0CustomElementRegistrationContext.h"
#include "core/dom/shadow/ElementShadow.h"
#include "core/dom/shadow/FlatTreeTraversal.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/editing/EditingUtilities.h"
#include "core/editing/Editor.h"
#include "core/editing/FrameSelection.h"
#include "core/editing/markers/DocumentMarkerController.h"
#include "core/editing/serializers/Serialization.h"
#include "core/editing/spellcheck/SpellChecker.h"
#include "core/events/BeforeUnloadEvent.h"
#include "core/events/Event.h"
#include "core/events/EventFactory.h"
#include "core/events/EventListener.h"
#include "core/events/HashChangeEvent.h"
#include "core/events/PageTransitionEvent.h"
#include "core/events/ScopedEventQueue.h"
#include "core/events/VisualViewportResizeEvent.h"
#include "core/events/VisualViewportScrollEvent.h"
#include "core/fetch/ResourceFetcher.h"
#include "core/frame/DOMTimer.h"
#include "core/frame/DOMVisualViewport.h"
#include "core/frame/EventHandlerRegistry.h"
#include "core/frame/FrameConsole.h"
#include "core/frame/FrameHost.h"
#include "core/frame/FrameView.h"
#include "core/frame/History.h"
#include "core/frame/HostsUsingFeatures.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/PerformanceMonitor.h"
#include "core/frame/Settings.h"
#include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/html/DocumentNameCollection.h"
#include "core/html/HTMLAllCollection.h"
#include "core/html/HTMLAnchorElement.h"
#include "core/html/HTMLBaseElement.h"
#include "core/html/HTMLBodyElement.h"
#include "core/html/HTMLCanvasElement.h"
#include "core/html/HTMLCollection.h"
#include "core/html/HTMLDialogElement.h"
#include "core/html/HTMLDocument.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/html/HTMLHeadElement.h"
#include "core/html/HTMLHtmlElement.h"
#include "core/html/HTMLIFrameElement.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/HTMLLinkElement.h"
#include "core/html/HTMLMetaElement.h"
#include "core/html/HTMLScriptElement.h"
#include "core/html/HTMLTemplateElement.h"
#include "core/html/HTMLTitleElement.h"
#include "core/html/PluginDocument.h"
#include "core/html/WindowNameCollection.h"
#include "core/html/canvas/CanvasContextCreationAttributes.h"
#include "core/html/canvas/CanvasFontCache.h"
#include "core/html/canvas/CanvasRenderingContext.h"
#include "core/html/forms/FormController.h"
#include "core/html/imports/HTMLImportLoader.h"
#include "core/html/imports/HTMLImportsController.h"
#include "core/html/parser/HTMLDocumentParser.h"
#include "core/html/parser/HTMLParserIdioms.h"
#include "core/html/parser/NestingLevelIncrementer.h"
#include "core/html/parser/TextResourceDecoder.h"
#include "core/input/EventHandler.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/inspector/InspectorTraceEvents.h"
#include "core/inspector/MainThreadDebugger.h"
#include "core/layout/HitTestCanvasResult.h"
#include "core/layout/HitTestResult.h"
#include "core/layout/LayoutPart.h"
#include "core/layout/LayoutView.h"
#include "core/layout/TextAutosizer.h"
#include "core/layout/api/LayoutPartItem.h"
#include "core/layout/api/LayoutViewItem.h"
#include "core/layout/compositing/PaintLayerCompositor.h"
#include "core/loader/CookieJar.h"
#include "core/loader/DocumentLoader.h"
#include "core/loader/FrameFetchContext.h"
#include "core/loader/FrameLoader.h"
#include "core/loader/FrameLoaderClient.h"
#include "core/loader/ImageLoader.h"
#include "core/loader/NavigationScheduler.h"
#include "core/loader/PrerendererClient.h"
#include "core/loader/appcache/ApplicationCacheHost.h"
#include "core/observer/ResizeObserverController.h"
#include "core/page/ChromeClient.h"
#include "core/page/EventWithHitTestResults.h"
#include "core/page/FocusController.h"
#include "core/page/FrameTree.h"
#include "core/page/Page.h"
#include "core/page/PointerLockController.h"
#include "core/page/scrolling/RootScrollerController.h"
#include "core/page/scrolling/ScrollStateCallback.h"
#include "core/page/scrolling/ScrollingCoordinator.h"
#include "core/page/scrolling/SnapCoordinator.h"
#include "core/page/scrolling/TopDocumentRootScrollerController.h"
#include "core/svg/SVGDocumentExtensions.h"
#include "core/svg/SVGScriptElement.h"
#include "core/svg/SVGTitleElement.h"
#include "core/svg/SVGUseElement.h"
#include "core/timing/DOMWindowPerformance.h"
#include "core/timing/Performance.h"
#include "core/workers/SharedWorkerRepositoryClient.h"
#include "core/xml/parser/XMLDocumentParser.h"
#include "platform/DateComponents.h"
#include "platform/EventDispatchForbiddenScope.h"
#include "platform/Histogram.h"
#include "platform/InstanceCounters.h"
#include "platform/Language.h"
#include "platform/LengthFunctions.h"
#include "platform/PluginScriptForbiddenScope.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/ScriptForbiddenScope.h"
#include "platform/WebFrameScheduler.h"
#include "platform/instrumentation/tracing/TraceEvent.h"
#include "platform/network/ContentSecurityPolicyParsers.h"
#include "platform/network/HTTPParsers.h"
#include "platform/scroll/Scrollbar.h"
#include "platform/scroll/ScrollbarTheme.h"
#include "platform/text/PlatformLocale.h"
#include "platform/text/SegmentedString.h"
#include "platform/weborigin/OriginAccessEntry.h"
#include "platform/weborigin/SchemeRegistry.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "public/platform/InterfaceProvider.h"
#include "public/platform/Platform.h"
#include "public/platform/WebAddressSpace.h"
#include "public/platform/WebPrerenderingSupport.h"
#include "public/platform/WebScheduler.h"
#include "public/platform/modules/sensitive_input_visibility/sensitive_input_visibility_service.mojom-blink.h"
#include "wtf/AutoReset.h"
#include "wtf/CurrentTime.h"
#include "wtf/DateMath.h"
#include "wtf/Functional.h"
#include "wtf/HashFunctions.h"
#include "wtf/PtrUtil.h"
#include "wtf/StdLibExtras.h"
#include "wtf/text/CharacterNames.h"
#include "wtf/text/StringBuffer.h"
#include "wtf/text/TextEncodingRegistry.h"
#include <memory>

using namespace WTF;
using namespace Unicode;

#ifndef NDEBUG
using WeakDocumentSet =
    blink::PersistentHeapHashSet<blink::WeakMember<blink::Document>>;
static WeakDocumentSet& liveDocumentSet();
#endif

namespace blink {

using namespace HTMLNames;

static const unsigned cMaxWriteRecursionDepth = 21;

// This amount of time must have elapsed before we will even consider scheduling
// a layout without a delay.
// FIXME: For faster machines this value can really be lowered to 200.  250 is
// adequate, but a little high for dual G5s. :)
static const int cLayoutScheduleThreshold = 250;

// DOM Level 2 says (letters added):
//
// a) Name start characters must have one of the categories Ll, Lu, Lo, Lt, Nl.
// b) Name characters other than Name-start characters must have one of the
//    categories Mc, Me, Mn, Lm, or Nd.
// c) Characters in the compatibility area (i.e. with character code greater
//    than #xF900 and less than #xFFFE) are not allowed in XML names.
// 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.
// 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.
// f) Characters #x20DD-#x20E0 are excluded (in accordance with Unicode, section
//    5.14).
// g) Character #x00B7 is classified as an extender, because the property list
//    so identifies it.
// h) Character #x0387 is added as a name character, because #x00B7 is its
//    canonical equivalent.
// i) Characters ':' and '_' are allowed as name-start characters.
// j) Characters '-' and '.' are allowed as name characters.
//
// It also contains complete tables. If we decide it's better, we could include
// those instead of the following code.

static inline bool isValidNameStart(UChar32 c) {
  // rule (e) above
  if ((c >= 0x02BB && c <= 0x02C1) || c == 0x559 || c == 0x6E5 || c == 0x6E6)
    return true;

  // rule (i) above
  if (c == ':' || c == '_')
    return true;

  // rules (a) and (f) above
  const uint32_t nameStartMask = Letter_Lowercase | Letter_Uppercase |
                                 Letter_Other | Letter_Titlecase |
                                 Number_Letter;
  if (!(Unicode::category(c) & nameStartMask))
    return false;

  // rule (c) above
  if (c >= 0xF900 && c < 0xFFFE)
    return false;

  // rule (d) above
  CharDecompositionType decompType = decompositionType(c);
  if (decompType == DecompositionFont || decompType == DecompositionCompat)
    return false;

  return true;
}

static inline bool isValidNamePart(UChar32 c) {
  // rules (a), (e), and (i) above
  if (isValidNameStart(c))
    return true;

  // rules (g) and (h) above
  if (c == 0x00B7 || c == 0x0387)
    return true;

  // rule (j) above
  if (c == '-' || c == '.')
    return true;

  // rules (b) and (f) above
  const uint32_t otherNamePartMask = Mark_NonSpacing | Mark_Enclosing |
                                     Mark_SpacingCombining | Letter_Modifier |
                                     Number_DecimalDigit;
  if (!(Unicode::category(c) & otherNamePartMask))
    return false;

  // rule (c) above
  if (c >= 0xF900 && c < 0xFFFE)
    return false;

  // rule (d) above
  CharDecompositionType decompType = decompositionType(c);
  if (decompType == DecompositionFont || decompType == DecompositionCompat)
    return false;

  return true;
}

static Widget* widgetForElement(const Element& focusedElement) {
  LayoutObject* layoutObject = focusedElement.layoutObject();
  if (!layoutObject || !layoutObject->isLayoutPart())
    return 0;
  return toLayoutPart(layoutObject)->widget();
}

static bool acceptsEditingFocus(const Element& element) {
  DCHECK(hasEditableStyle(element));

  return element.document().frame() && rootEditableElement(element);
}

uint64_t Document::s_globalTreeVersion = 0;

static bool s_threadedParsingEnabledForTesting = true;

// This doesn't work with non-Document ExecutionContext.
static void runAutofocusTask(ExecutionContext* context) {
  Document* document = toDocument(context);
  if (Element* element = document->autofocusElement()) {
    document->setAutofocusElement(0);
    element->focus();
  }
}

static void recordLoadReasonToHistogram(WouldLoadReason reason) {
  DEFINE_STATIC_LOCAL(
      EnumerationHistogram, unseenFrameHistogram,
      ("Navigation.DeferredDocumentLoading.StatesV3", WouldLoadReasonEnd));
  unseenFrameHistogram.count(reason);
}

Document::Document(const DocumentInit& initializer,
                   DocumentClassFlags documentClasses)
    : ContainerNode(0, CreateDocument),
      TreeScope(*this),
      m_hasNodesWithPlaceholderStyle(false),
      m_evaluateMediaQueriesOnStyleRecalc(false),
      m_pendingSheetLayout(NoLayoutWithPendingSheets),
      m_frame(initializer.frame()),
      // TODO(dcheng): Why does this need both a LocalFrame and LocalDOMWindow
      // pointer?
      m_domWindow(m_frame ? m_frame->domWindow() : nullptr),
      m_importsController(this, initializer.importsController()),
      m_contextFeatures(ContextFeatures::defaultSwitch()),
      m_wellFormed(false),
      m_implementation(this, nullptr),
      m_printing(NotPrinting),
      m_paginatedForScreen(false),
      m_compatibilityMode(NoQuirksMode),
      m_compatibilityModeLocked(false),
      m_hasAutofocused(false),
      m_clearFocusedElementTimer(
          TaskRunnerHelper::get(TaskType::UnspecedTimer, this),
          this,
          &Document::clearFocusedElementTimerFired),
      m_domTreeVersion(++s_globalTreeVersion),
      m_styleVersion(0),
      m_listenerTypes(0),
      m_mutationObserverTypes(0),
      m_styleEngine(this, nullptr),
      m_styleSheetList(this, nullptr),
      m_visitedLinkState(VisitedLinkState::create(*this)),
      m_visuallyOrdered(false),
      m_readyState(Complete),
      m_parsingState(FinishedParsing),
      m_gotoAnchorNeededAfterStylesheetsLoad(false),
      m_containsValidityStyleRules(false),
      m_containsPlugins(false),
      m_updateFocusAppearanceSelectionBahavior(SelectionBehaviorOnFocus::Reset),
      m_ignoreDestructiveWriteCount(0),
      m_throwOnDynamicMarkupInsertionCount(0),
      m_markers(new DocumentMarkerController(*this)),
      m_updateFocusAppearanceTimer(
          TaskRunnerHelper::get(TaskType::UnspecedTimer, this),
          this,
          &Document::updateFocusAppearanceTimerFired),
      m_cssTarget(nullptr),
      m_loadEventProgress(LoadEventNotRun),
      m_startTime(currentTime()),
      m_scriptRunner(ScriptRunner::create(this)),
      m_xmlVersion("1.0"),
      m_xmlStandalone(StandaloneUnspecified),
      m_hasXMLDeclaration(0),
      m_designMode(false),
      m_isRunningExecCommand(false),
      m_hasReceivedUserGesture(false),
      m_hasAnnotatedRegions(false),
      m_annotatedRegionsDirty(false),
      m_documentClasses(documentClasses),
      m_isViewSource(false),
      m_sawElementsInKnownNamespaces(false),
      m_isSrcdocDocument(false),
      m_isMobileDocument(false),
      m_layoutView(0),
      m_contextDocument(initializer.contextDocument()),
      m_hasFullscreenSupplement(false),
      m_loadEventDelayCount(0),
      m_loadEventDelayTimer(TaskRunnerHelper::get(TaskType::Networking, this),
                            this,
                            &Document::loadEventDelayTimerFired),
      m_pluginLoadingTimer(
          TaskRunnerHelper::get(TaskType::UnspecedLoading, this),
          this,
          &Document::pluginLoadingTimerFired),
      m_documentTiming(*this),
      m_writeRecursionIsTooDeep(false),
      m_writeRecursionDepth(0),
      m_registrationContext(initializer.registrationContext(this)),
      m_elementDataCacheClearTimer(
          TaskRunnerHelper::get(TaskType::UnspecedTimer, this),
          this,
          &Document::elementDataCacheClearTimerFired),
      m_timeline(DocumentTimeline::create(this)),
      m_compositorPendingAnimations(new CompositorPendingAnimations(*this)),
      m_templateDocumentHost(nullptr),
      m_didAssociateFormControlsTimer(
          TaskRunnerHelper::get(TaskType::UnspecedLoading, this),
          this,
          &Document::didAssociateFormControlsTimerFired),
      m_timers(TaskRunnerHelper::get(TaskType::Timer, this)->clone()),
      m_hasViewportUnits(false),
      m_parserSyncPolicy(AllowAsynchronousParsing),
      m_nodeCount(0),
      m_wouldLoadReason(Created),
      m_passwordCount(0),
      m_engagementLevel(mojom::blink::EngagementLevel::NONE) {
  if (m_frame) {
    DCHECK(m_frame->page());
    provideContextFeaturesToDocumentFrom(*this, *m_frame->page());

    m_fetcher = m_frame->loader().documentLoader()->fetcher();
    FrameFetchContext::provideDocumentToContext(m_fetcher->context(), this);

    // TODO(dcheng): Why does this need to check that DOMWindow is non-null?
    CustomElementRegistry* registry =
        m_frame->domWindow() ? m_frame->domWindow()->maybeCustomElements()
                             : nullptr;
    if (registry && m_registrationContext)
      registry->entangle(m_registrationContext);
  } else if (m_importsController) {
    m_fetcher = FrameFetchContext::createFetcherFromDocument(this);
  } else {
    m_fetcher = ResourceFetcher::create(nullptr);
  }
  DCHECK(m_fetcher);

  m_rootScrollerController = RootScrollerController::create(*this);

  // We depend on the url getting immediately set in subframes, but we
  // also depend on the url NOT getting immediately set in opened windows.
  // See fast/dom/early-frame-url.html
  // and fast/dom/location-new-window-no-crash.html, respectively.
  // FIXME: Can/should we unify this behavior?
  if (initializer.shouldSetURL())
    setURL(initializer.url());

  initSecurityContext(initializer);

  initDNSPrefetch();

  InstanceCounters::incrementCounter(InstanceCounters::DocumentCounter);

  m_lifecycle.advanceTo(DocumentLifecycle::Inactive);

  // Since CSSFontSelector requires Document::m_fetcher and StyleEngine owns
  // CSSFontSelector, need to initialize m_styleEngine after initializing
  // m_fetcher.
  m_styleEngine = StyleEngine::create(*this);

  // The parent's parser should be suspended together with all the other
  // objects, else this new Document would have a new ExecutionContext which
  // suspended state would not match the one from the parent, and could start
  // loading resources ignoring the defersLoading flag.
  DCHECK(!parentDocument() || !parentDocument()->isContextSuspended());

#ifndef NDEBUG
  liveDocumentSet().add(this);
#endif
}

Document::~Document() {
  DCHECK(layoutViewItem().isNull());
  DCHECK(!parentTreeScope());
  // If a top document with a cache, verify that it was comprehensively
  // cleared during detach.
  DCHECK(!m_axObjectCache);
  InstanceCounters::decrementCounter(InstanceCounters::DocumentCounter);
}

SelectorQueryCache& Document::selectorQueryCache() {
  if (!m_selectorQueryCache)
    m_selectorQueryCache = WTF::makeUnique<SelectorQueryCache>();
  return *m_selectorQueryCache;
}

MediaQueryMatcher& Document::mediaQueryMatcher() {
  if (!m_mediaQueryMatcher)
    m_mediaQueryMatcher = MediaQueryMatcher::create(*this);
  return *m_mediaQueryMatcher;
}

void Document::mediaQueryAffectingValueChanged() {
  styleEngine().mediaQueryAffectingValueChanged();
  if (needsLayoutTreeUpdate())
    m_evaluateMediaQueriesOnStyleRecalc = true;
  else
    evaluateMediaQueryList();
  InspectorInstrumentation::mediaQueryResultChanged(this);
}

void Document::setCompatibilityMode(CompatibilityMode mode) {
  if (m_compatibilityModeLocked || mode == m_compatibilityMode)
    return;
  m_compatibilityMode = mode;
  selectorQueryCache().invalidate();
}

String Document::compatMode() const {
  return inQuirksMode() ? "BackCompat" : "CSS1Compat";
}

void Document::setDoctype(DocumentType* docType) {
  // This should never be called more than once.
  DCHECK(!m_docType || !docType);
  m_docType = docType;
  if (m_docType) {
    this->adoptIfNeeded(*m_docType);
    if (m_docType->publicId().startsWith("-//wapforum//dtd xhtml mobile 1.",
                                         TextCaseASCIIInsensitive)) {
      m_isMobileDocument = true;
      m_styleEngine->viewportRulesChanged();
    }
  }
}

DOMImplementation& Document::implementation() {
  if (!m_implementation)
    m_implementation = DOMImplementation::create(*this);
  return *m_implementation;
}

bool Document::hasAppCacheManifest() const {
  return isHTMLHtmlElement(documentElement()) &&
         documentElement()->hasAttribute(manifestAttr);
}

Location* Document::location() const {
  if (!frame())
    return 0;

  return domWindow()->location();
}

void Document::childrenChanged(const ChildrenChange& change) {
  ContainerNode::childrenChanged(change);
  m_documentElement = ElementTraversal::firstWithin(*this);

  // For non-HTML documents the willInsertBody notification won't happen
  // so we resume as soon as we have a document element. Even for XHTML
  // documents there may never be a <body> (since the parser won't always
  // insert one), so we resume here too. That does mean XHTML documents make
  // frames when there's only a <head>, but such documents are pretty rare.
  if (m_documentElement && !isHTMLDocument())
    beginLifecycleUpdatesIfRenderingReady();
}

void Document::setRootScroller(Element* newScroller,
                               ExceptionState& exceptionState) {
  m_rootScrollerController->set(newScroller);
}

Element* Document::rootScroller() const {
  return m_rootScrollerController->get();
}

bool Document::isInMainFrame() const {
  return frame() && frame()->isMainFrame();
}

AtomicString Document::convertLocalName(const AtomicString& name) {
  return isHTMLDocument() ? name.lower() : name;
}

// https://dom.spec.whatwg.org/#dom-document-createelement
Element* Document::createElement(const AtomicString& name,
                                 ExceptionState& exceptionState) {
  if (!isValidName(name)) {
    exceptionState.throwDOMException(
        InvalidCharacterError,
        "The tag name provided ('" + name + "') is not a valid name.");
    return nullptr;
  }

  if (isXHTMLDocument() || isHTMLDocument()) {
    // 2. If the context object is an HTML document, let localName be
    // converted to ASCII lowercase.
    AtomicString localName = convertLocalName(name);
    if (CustomElement::shouldCreateCustomElement(localName)) {
      return CustomElement::createCustomElementSync(
          *this,
          QualifiedName(nullAtom, localName, HTMLNames::xhtmlNamespaceURI));
    }
    return HTMLElementFactory::createHTMLElement(localName, *this,
                                                 CreatedByCreateElement);
  }
  return Element::create(QualifiedName(nullAtom, name, nullAtom), this);
}

String getTypeExtension(Document* document,
                        const StringOrDictionary& stringOrOptions,
                        ExceptionState& exceptionState) {
  if (stringOrOptions.isNull())
    return emptyString();

  if (stringOrOptions.isString()) {
    UseCounter::count(document,
                      UseCounter::DocumentCreateElement2ndArgStringHandling);
    return stringOrOptions.getAsString();
  }

  if (stringOrOptions.isDictionary()) {
    Dictionary dict = stringOrOptions.getAsDictionary();
    ElementCreationOptions impl;
    V8ElementCreationOptions::toImpl(dict.isolate(), dict.v8Value(), impl,
                                     exceptionState);
    if (impl.hasIs())
      return impl.is();

    return toCoreString(dict.v8Value()->ToString());
  }

  return emptyString();
}

// https://dom.spec.whatwg.org/#dom-document-createelement
Element* Document::createElement(const AtomicString& localName,
                                 const StringOrDictionary& stringOrOptions,
                                 ExceptionState& exceptionState) {
  // 1. If localName does not match Name production, throw InvalidCharacterError
  if (!isValidName(localName)) {
    exceptionState.throwDOMException(
        InvalidCharacterError,
        "The tag name provided ('" + localName + "') is not a valid name.");
    return nullptr;
  }

  // 2. localName converted to ASCII lowercase
  const AtomicString& convertedLocalName = convertLocalName(localName);

  bool isV1 = stringOrOptions.isDictionary() || !registrationContext();
  bool createV1Builtin = stringOrOptions.isDictionary() &&
                         RuntimeEnabledFeatures::customElementsBuiltinEnabled();
  bool shouldCreateBuiltin = createV1Builtin || stringOrOptions.isString();

  // 3.
  const AtomicString& is =
      AtomicString(getTypeExtension(this, stringOrOptions, exceptionState));
  const AtomicString& name = shouldCreateBuiltin ? is : convertedLocalName;

  // 4. Let definition be result of lookup up custom element definition
  CustomElementDefinition* definition = nullptr;
  if (isV1) {
    // Is the runtime flag enabled for customized builtin elements?
    const CustomElementDescriptor desc =
        RuntimeEnabledFeatures::customElementsBuiltinEnabled()
            ? CustomElementDescriptor(name, convertedLocalName)
            : CustomElementDescriptor(convertedLocalName, convertedLocalName);
    if (CustomElementRegistry* registry = CustomElement::registry(*this))
      definition = registry->definitionFor(desc);

    // 5. If 'is' is non-null and definition is null, throw NotFoundError
    // TODO(yurak): update when https://github.com/w3c/webcomponents/issues/608
    //              is resolved
    if (!definition && createV1Builtin) {
      exceptionState.throwDOMException(NotFoundError,
                                       "Custom element definition not found.");
      return nullptr;
    }
  }

  // 7. Let element be the result of creating an element
  Element* element;

  if (definition) {
    element = CustomElement::createCustomElementSync(*this, convertedLocalName,
                                                     definition);
  } else if (V0CustomElement::isValidName(localName) && registrationContext()) {
    element = registrationContext()->createCustomTagElement(
        *this, QualifiedName(nullAtom, convertedLocalName, xhtmlNamespaceURI));
  } else {
    element = createElement(localName, exceptionState);
    if (exceptionState.hadException())
      return nullptr;
  }

  // 8. If 'is' is non-null, set 'is' attribute
  if (!is.isEmpty()) {
    if (stringOrOptions.isString()) {
      V0CustomElementRegistrationContext::setIsAttributeAndTypeExtension(
          element, is);
    } else if (stringOrOptions.isDictionary()) {
      element->setAttribute(HTMLNames::isAttr, is);
    }
  }

  return element;
}

static inline QualifiedName createQualifiedName(
    const AtomicString& namespaceURI,
    const AtomicString& qualifiedName,
    ExceptionState& exceptionState) {
  AtomicString prefix, localName;
  if (!Document::parseQualifiedName(qualifiedName, prefix, localName,
                                    exceptionState))
    return QualifiedName::null();

  QualifiedName qName(prefix, localName, namespaceURI);
  if (!Document::hasValidNamespaceForElements(qName)) {
    exceptionState.throwDOMException(
        NamespaceError,
        "The namespace URI provided ('" + namespaceURI +
            "') is not valid for the qualified name provided ('" +
            qualifiedName + "').");
    return QualifiedName::null();
  }

  return qName;
}

Element* Document::createElementNS(const AtomicString& namespaceURI,
                                   const AtomicString& qualifiedName,
                                   ExceptionState& exceptionState) {
  QualifiedName qName(
      createQualifiedName(namespaceURI, qualifiedName, exceptionState));
  if (qName == QualifiedName::null())
    return nullptr;

  if (CustomElement::shouldCreateCustomElement(qName))
    return CustomElement::createCustomElementSync(*this, qName);
  return createElement(qName, CreatedByCreateElement);
}

// https://dom.spec.whatwg.org/#internal-createelementns-steps
Element* Document::createElementNS(const AtomicString& namespaceURI,
                                   const AtomicString& qualifiedName,
                                   const StringOrDictionary& stringOrOptions,
                                   ExceptionState& exceptionState) {
  // 1. Validate and extract
  QualifiedName qName(
      createQualifiedName(namespaceURI, qualifiedName, exceptionState));
  if (qName == QualifiedName::null())
    return nullptr;

  bool isV1 = stringOrOptions.isDictionary() || !registrationContext();
  bool createV1Builtin = stringOrOptions.isDictionary() &&
                         RuntimeEnabledFeatures::customElementsBuiltinEnabled();
  bool shouldCreateBuiltin = createV1Builtin || stringOrOptions.isString();

  // 2.
  const AtomicString& is =
      AtomicString(getTypeExtension(this, stringOrOptions, exceptionState));
  const AtomicString& name = shouldCreateBuiltin ? is : qualifiedName;

  if (!isValidName(qualifiedName)) {
    exceptionState.throwDOMException(
        InvalidCharacterError,
        "The tag name provided ('" + qualifiedName + "') is not a valid name.");
    return nullptr;
  }

  // 3. Let definition be result of lookup up custom element definition
  CustomElementDefinition* definition = nullptr;
  if (isV1) {
    const CustomElementDescriptor desc =
        RuntimeEnabledFeatures::customElementsBuiltinEnabled()
            ? CustomElementDescriptor(name, qualifiedName)
            : CustomElementDescriptor(qualifiedName, qualifiedName);
    if (CustomElementRegistry* registry = CustomElement::registry(*this))
      definition = registry->definitionFor(desc);

    // 4. If 'is' is non-null and definition is null, throw NotFoundError
    if (!definition && createV1Builtin) {
      exceptionState.throwDOMException(NotFoundError,
                                       "Custom element definition not found.");
      return nullptr;
    }
  }

  // 5. Let element be the result of creating an element
  Element* element;

  if (CustomElement::shouldCreateCustomElement(qName) || createV1Builtin) {
    element = CustomElement::createCustomElementSync(*this, qName, definition);
  } else if (V0CustomElement::isValidName(qName.localName()) &&
             registrationContext()) {
    element = registrationContext()->createCustomTagElement(*this, qName);
  } else {
    element = createElement(qName, CreatedByCreateElement);
  }

  // 6. If 'is' is non-null, set 'is' attribute
  if (!is.isEmpty()) {
    if (element->getCustomElementState() != CustomElementState::Custom) {
      V0CustomElementRegistrationContext::setIsAttributeAndTypeExtension(
          element, is);
    } else if (stringOrOptions.isDictionary()) {
      element->setAttribute(HTMLNames::isAttr, is);
    }
  }

  return element;
}

ScriptValue Document::registerElement(ScriptState* scriptState,
                                      const AtomicString& name,
                                      const ElementRegistrationOptions& options,
                                      ExceptionState& exceptionState,
                                      V0CustomElement::NameSet validNames) {
  HostsUsingFeatures::countMainWorldOnly(
      scriptState, *this, HostsUsingFeatures::Feature::DocumentRegisterElement);

  if (!registrationContext()) {
    exceptionState.throwDOMException(
        NotSupportedError, "No element registration context is available.");
    return ScriptValue();
  }

  V0CustomElementConstructorBuilder constructorBuilder(scriptState, options);
  registrationContext()->registerElement(this, &constructorBuilder, name,
                                         validNames, exceptionState);
  return constructorBuilder.bindingsReturnValue();
}

V0CustomElementMicrotaskRunQueue* Document::customElementMicrotaskRunQueue() {
  if (!m_customElementMicrotaskRunQueue)
    m_customElementMicrotaskRunQueue =
        V0CustomElementMicrotaskRunQueue::create();
  return m_customElementMicrotaskRunQueue.get();
}

void Document::clearImportsController() {
  m_importsController = nullptr;
  if (!loader())
    m_fetcher->clearContext();
}

void Document::createImportsController() {
  DCHECK(!m_importsController);
  m_importsController = HTMLImportsController::create(*this);
}

HTMLImportLoader* Document::importLoader() const {
  if (!m_importsController)
    return 0;
  return m_importsController->loaderFor(*this);
}

bool Document::haveImportsLoaded() const {
  if (!m_importsController)
    return true;
  return !m_importsController->shouldBlockScriptExecution(*this);
}

LocalDOMWindow* Document::executingWindow() const {
  if (LocalDOMWindow* owningWindow = domWindow())
    return owningWindow;
  if (HTMLImportsController* import = this->importsController())
    return import->master()->domWindow();
  return 0;
}

LocalFrame* Document::executingFrame() {
  LocalDOMWindow* window = executingWindow();
  if (!window)
    return 0;
  return window->frame();
}

DocumentFragment* Document::createDocumentFragment() {
  return DocumentFragment::create(*this);
}

Text* Document::createTextNode(const String& data) {
  return Text::create(*this, data);
}

Comment* Document::createComment(const String& data) {
  return Comment::create(*this, data);
}

CDATASection* Document::createCDATASection(const String& data,
                                           ExceptionState& exceptionState) {
  if (isHTMLDocument()) {
    exceptionState.throwDOMException(
        NotSupportedError,
        "This operation is not supported for HTML documents.");
    return nullptr;
  }
  if (data.contains("]]>")) {
    exceptionState.throwDOMException(InvalidCharacterError,
                                     "String cannot contain ']]>' since that "
                                     "is the end delimiter of a CData "
                                     "section.");
    return nullptr;
  }
  return CDATASection::create(*this, data);
}

ProcessingInstruction* Document::createProcessingInstruction(
    const String& target,
    const String& data,
    ExceptionState& exceptionState) {
  if (!isValidName(target)) {
    exceptionState.throwDOMException(
        InvalidCharacterError,
        "The target provided ('" + target + "') is not a valid name.");
    return nullptr;
  }
  if (data.contains("?>")) {
    exceptionState.throwDOMException(
        InvalidCharacterError,
        "The data provided ('" + data + "') contains '?>'.");
    return nullptr;
  }
  return ProcessingInstruction::create(*this, target, data);
}

Text* Document::createEditingTextNode(const String& text) {
  return Text::createEditingText(*this, text);
}

bool Document::importContainerNodeChildren(ContainerNode* oldContainerNode,
                                           ContainerNode* newContainerNode,
                                           ExceptionState& exceptionState) {
  for (Node& oldChild : NodeTraversal::childrenOf(*oldContainerNode)) {
    Node* newChild = importNode(&oldChild, true, exceptionState);
    if (exceptionState.hadException())
      return false;
    newContainerNode->appendChild(newChild, exceptionState);
    if (exceptionState.hadException())
      return false;
  }

  return true;
}

Node* Document::importNode(Node* importedNode,
                           bool deep,
                           ExceptionState& exceptionState) {
  switch (importedNode->getNodeType()) {
    case kTextNode:
      return createTextNode(importedNode->nodeValue());
    case kCdataSectionNode:
      return CDATASection::create(*this, importedNode->nodeValue());
    case kProcessingInstructionNode:
      return createProcessingInstruction(
          importedNode->nodeName(), importedNode->nodeValue(), exceptionState);
    case kCommentNode:
      return createComment(importedNode->nodeValue());
    case kDocumentTypeNode: {
      DocumentType* doctype = toDocumentType(importedNode);
      return DocumentType::create(this, doctype->name(), doctype->publicId(),
                                  doctype->systemId());
    }
    case kElementNode: {
      Element* oldElement = toElement(importedNode);
      // FIXME: The following check might be unnecessary. Is it possible that
      // oldElement has mismatched prefix/namespace?
      if (!hasValidNamespaceForElements(oldElement->tagQName())) {
        exceptionState.throwDOMException(
            NamespaceError, "The imported node has an invalid namespace.");
        return nullptr;
      }
      Element* newElement =
          createElement(oldElement->tagQName(), CreatedByImportNode);

      newElement->cloneDataFromElement(*oldElement);

      if (deep) {
        if (!importContainerNodeChildren(oldElement, newElement,
                                         exceptionState))
          return nullptr;
        if (isHTMLTemplateElement(*oldElement) &&
            !ensureTemplateDocument().importContainerNodeChildren(
                toHTMLTemplateElement(oldElement)->content(),
                toHTMLTemplateElement(newElement)->content(), exceptionState))
          return nullptr;
      }

      return newElement;
    }
    case kAttributeNode:
      return Attr::create(
          *this,
          QualifiedName(nullAtom, AtomicString(toAttr(importedNode)->name()),
                        nullAtom),
          toAttr(importedNode)->value());
    case kDocumentFragmentNode: {
      if (importedNode->isShadowRoot()) {
        // ShadowRoot nodes should not be explicitly importable.
        // Either they are imported along with their host node, or created
        // implicitly.
        exceptionState.throwDOMException(
            NotSupportedError,
            "The node provided is a shadow root, which may not be imported.");
        return nullptr;
      }
      DocumentFragment* oldFragment = toDocumentFragment(importedNode);
      DocumentFragment* newFragment = createDocumentFragment();
      if (deep &&
          !importContainerNodeChildren(oldFragment, newFragment,
                                       exceptionState))
        return nullptr;

      return newFragment;
    }
    case kDocumentNode:
      exceptionState.throwDOMException(
          NotSupportedError,
          "The node provided is a document, which may not be imported.");
      return nullptr;
  }

  NOTREACHED();
  return nullptr;
}

Node* Document::adoptNode(Node* source, ExceptionState& exceptionState) {
  EventQueueScope scope;

  switch (source->getNodeType()) {
    case kDocumentNode:
      exceptionState.throwDOMException(NotSupportedError,
                                       "The node provided is of type '" +
                                           source->nodeName() +
                                           "', which may not be adopted.");
      return nullptr;
    case kAttributeNode: {
      Attr* attr = toAttr(source);
      if (Element* ownerElement = attr->ownerElement())
        ownerElement->removeAttributeNode(attr, exceptionState);
      break;
    }
    default:
      if (source->isShadowRoot()) {
        // ShadowRoot cannot disconnect itself from the host node.
        exceptionState.throwDOMException(
            HierarchyRequestError,
            "The node provided is a shadow root, which may not be adopted.");
        return nullptr;
      }

      if (source->isFrameOwnerElement()) {
        HTMLFrameOwnerElement* frameOwnerElement =
            toHTMLFrameOwnerElement(source);
        if (frame() &&
            frame()->tree().isDescendantOf(frameOwnerElement->contentFrame())) {
          exceptionState.throwDOMException(
              HierarchyRequestError,
              "The node provided is a frame which contains this document.");
          return nullptr;
        }
      }
      if (source->parentNode()) {
        source->parentNode()->removeChild(source, exceptionState);
        if (exceptionState.hadException())
          return nullptr;
        RELEASE_ASSERT(!source->parentNode());
      }
  }

  this->adoptIfNeeded(*source);

  return source;
}

bool Document::hasValidNamespaceForElements(const QualifiedName& qName) {
  // These checks are from DOM Core Level 2, createElementNS
  // http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-DocCrElNS
  // createElementNS(null, "html:div")
  if (!qName.prefix().isEmpty() && qName.namespaceURI().isNull())
    return false;
  // createElementNS("http://www.example.com", "xml:lang")
  if (qName.prefix() == xmlAtom &&
      qName.namespaceURI() != XMLNames::xmlNamespaceURI)
    return false;

  // Required by DOM Level 3 Core and unspecified by DOM Level 2 Core:
  // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-DocCrElNS
  // createElementNS("http://www.w3.org/2000/xmlns/", "foo:bar"),
  // createElementNS(null, "xmlns:bar"), createElementNS(null, "xmlns")
  if (qName.prefix() == xmlnsAtom ||
      (qName.prefix().isEmpty() && qName.localName() == xmlnsAtom))
    return qName.namespaceURI() == XMLNSNames::xmlnsNamespaceURI;
  return qName.namespaceURI() != XMLNSNames::xmlnsNamespaceURI;
}

bool Document::hasValidNamespaceForAttributes(const QualifiedName& qName) {
  return hasValidNamespaceForElements(qName);
}

// FIXME: This should really be in a possible ElementFactory class
Element* Document::createElement(const QualifiedName& qName,
                                 CreateElementFlags flags) {
  Element* e = nullptr;

  // FIXME: Use registered namespaces and look up in a hash to find the right
  // factory.
  if (qName.namespaceURI() == xhtmlNamespaceURI)
    e = HTMLElementFactory::createHTMLElement(qName.localName(), *this, flags);
  else if (qName.namespaceURI() == SVGNames::svgNamespaceURI)
    e = SVGElementFactory::createSVGElement(qName.localName(), *this, flags);

  if (e)
    m_sawElementsInKnownNamespaces = true;
  else
    e = Element::create(qName, this);

  if (e->prefix() != qName.prefix())
    e->setTagNameForCreateElementNS(qName);

  DCHECK(qName == e->tagQName());

  return e;
}

String Document::readyState() const {
  DEFINE_STATIC_LOCAL(const String, loading, ("loading"));
  DEFINE_STATIC_LOCAL(const String, interactive, ("interactive"));
  DEFINE_STATIC_LOCAL(const String, complete, ("complete"));

  switch (m_readyState) {
    case Loading:
      return loading;
    case Interactive:
      return interactive;
    case Complete:
      return complete;
  }

  NOTREACHED();
  return String();
}

void Document::setReadyState(DocumentReadyState readyState) {
  if (readyState == m_readyState)
    return;

  switch (readyState) {
    case Loading:
      if (!m_documentTiming.domLoading()) {
        m_documentTiming.markDomLoading();
      }
      break;
    case Interactive:
      if (!m_documentTiming.domInteractive())
        m_documentTiming.markDomInteractive();
      break;
    case Complete:
      if (!m_documentTiming.domComplete())
        m_documentTiming.markDomComplete();
      break;
  }

  m_readyState = readyState;
  dispatchEvent(Event::create(EventTypeNames::readystatechange));
}

bool Document::isLoadCompleted() {
  return m_readyState == Complete;
}

AtomicString Document::encodingName() const {
  // TextEncoding::name() returns a char*, no need to allocate a new
  // String for it each time.
  // FIXME: We should fix TextEncoding to speak AtomicString anyway.
  return AtomicString(encoding().name());
}

void Document::setContentLanguage(const AtomicString& language) {
  if (m_contentLanguage == language)
    return;
  m_contentLanguage = language;

  // Document's style depends on the content language.
  setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(
                                              StyleChangeReason::Language));
}

void Document::setXMLVersion(const String& version,
                             ExceptionState& exceptionState) {
  if (!XMLDocumentParser::supportsXMLVersion(version)) {
    exceptionState.throwDOMException(
        NotSupportedError,
        "This document does not support the XML version '" + version + "'.");
    return;
  }

  m_xmlVersion = version;
}

void Document::setXMLStandalone(bool standalone,
                                ExceptionState& exceptionState) {
  m_xmlStandalone = standalone ? Standalone : NotStandalone;
}

void Document::setContent(const String& content) {
  open();
  m_parser->append(content);
  close();
}

String Document::suggestedMIMEType() const {
  if (isXMLDocument()) {
    if (isXHTMLDocument())
      return "application/xhtml+xml";
    if (isSVGDocument())
      return "image/svg+xml";
    return "application/xml";
  }
  if (xmlStandalone())
    return "text/xml";
  if (isHTMLDocument())
    return "text/html";

  if (DocumentLoader* documentLoader = loader())
    return documentLoader->responseMIMEType();
  return String();
}

void Document::setMimeType(const AtomicString& mimeType) {
  m_mimeType = mimeType;
}

AtomicString Document::contentType() const {
  if (!m_mimeType.isEmpty())
    return m_mimeType;

  if (DocumentLoader* documentLoader = loader())
    return documentLoader->mimeType();

  String mimeType = suggestedMIMEType();
  if (!mimeType.isEmpty())
    return AtomicString(mimeType);

  return AtomicString("application/xml");
}

Element* Document::elementFromPoint(int x, int y) const {
  if (layoutViewItem().isNull())
    return 0;

  return TreeScope::elementFromPoint(x, y);
}

HeapVector<Member<Element>> Document::elementsFromPoint(int x, int y) const {
  if (layoutViewItem().isNull())
    return HeapVector<Member<Element>>();
  return TreeScope::elementsFromPoint(x, y);
}

Range* Document::caretRangeFromPoint(int x, int y) {
  if (layoutViewItem().isNull())
    return nullptr;

  HitTestResult result = hitTestInDocument(this, x, y);
  PositionWithAffinity positionWithAffinity = result.position();
  if (positionWithAffinity.isNull())
    return nullptr;

  Position rangeCompliantPosition =
      positionWithAffinity.position().parentAnchoredEquivalent();
  return Range::createAdjustedToTreeScope(*this, rangeCompliantPosition);
}

Element* Document::scrollingElement() {
  if (RuntimeEnabledFeatures::scrollTopLeftInteropEnabled()) {
    if (inQuirksMode()) {
      updateStyleAndLayoutTree();
      HTMLBodyElement* body = firstBodyElement();
      if (body && body->layoutObject() &&
          body->layoutObject()->hasOverflowClip())
        return nullptr;

      return body;
    }

    return documentElement();
  }

  return body();
}

// We use HashMap::set over HashMap::add here as we want to
// replace the ComputedStyle but not the Node if the Node is
// already present.
void Document::addStyleReattachData(Node& node,
                                    StyleReattachData& styleReattachData) {
  DCHECK(node.isElementNode() || node.isTextNode());
  m_styleReattachDataMap.set(&node, styleReattachData);
}

StyleReattachData Document::getStyleReattachData(Node& node) {
  return m_styleReattachDataMap.get(&node);
}

/*
 * Performs three operations:
 *  1. Convert control characters to spaces
 *  2. Trim leading and trailing spaces
 *  3. Collapse internal whitespace.
 */
template <typename CharacterType>
static inline String canonicalizedTitle(Document* document,
                                        const String& title) {
  unsigned length = title.length();
  unsigned builderIndex = 0;
  const CharacterType* characters = title.getCharacters<CharacterType>();

  StringBuffer<CharacterType> buffer(length);

  // Replace control characters with spaces and collapse whitespace.
  bool pendingWhitespace = false;
  for (unsigned i = 0; i < length; ++i) {
    UChar32 c = characters[i];
    if ((c <= spaceCharacter && c != lineTabulationCharacter) ||
        c == deleteCharacter) {
      if (builderIndex != 0)
        pendingWhitespace = true;
    } else {
      if (pendingWhitespace) {
        buffer[builderIndex++] = ' ';
        pendingWhitespace = false;
      }
      buffer[builderIndex++] = c;
    }
  }
  buffer.shrink(builderIndex);

  return String::adopt(buffer);
}

void Document::updateTitle(const String& title) {
  if (m_rawTitle == title)
    return;

  m_rawTitle = title;

  String oldTitle = m_title;
  if (m_rawTitle.isEmpty())
    m_title = String();
  else if (m_rawTitle.is8Bit())
    m_title = canonicalizedTitle<LChar>(this, m_rawTitle);
  else
    m_title = canonicalizedTitle<UChar>(this, m_rawTitle);

  if (!m_frame || oldTitle == m_title)
    return;
  m_frame->loader().client()->dispatchDidReceiveTitle(m_title);
}

void Document::setTitle(const String& title) {
  // Title set by JavaScript -- overrides any title elements.
  if (!m_titleElement) {
    if (isHTMLDocument() || isXHTMLDocument()) {
      HTMLElement* headElement = head();
      if (!headElement)
        return;
      m_titleElement = HTMLTitleElement::create(*this);
      headElement->appendChild(m_titleElement.get());
    } else if (isSVGDocument()) {
      Element* element = documentElement();
      if (!isSVGSVGElement(element))
        return;
      m_titleElement = SVGTitleElement::create(*this);
      element->insertBefore(m_titleElement.get(), element->firstChild());
    }
  } else {
    if (!isHTMLDocument() && !isXHTMLDocument() && !isSVGDocument())
      m_titleElement = nullptr;
  }

  if (isHTMLTitleElement(m_titleElement))
    toHTMLTitleElement(m_titleElement)->setText(title);
  else if (isSVGTitleElement(m_titleElement))
    toSVGTitleElement(m_titleElement)->setText(title);
  else
    updateTitle(title);
}

void Document::setTitleElement(Element* titleElement) {
  // If the root element is an svg element in the SVG namespace, then let value
  // be the child text content of the first title element in the SVG namespace
  // that is a child of the root element.
  if (isSVGSVGElement(documentElement())) {
    m_titleElement = Traversal<SVGTitleElement>::firstChild(*documentElement());
  } else {
    if (m_titleElement && m_titleElement != titleElement)
      m_titleElement = Traversal<HTMLTitleElement>::firstWithin(*this);
    else
      m_titleElement = titleElement;

    // If the root element isn't an svg element in the SVG namespace and the
    // title element is in the SVG namespace, it is ignored.
    if (isSVGTitleElement(m_titleElement)) {
      m_titleElement = nullptr;
      return;
    }
  }

  if (isHTMLTitleElement(m_titleElement))
    updateTitle(toHTMLTitleElement(m_titleElement)->text());
  else if (isSVGTitleElement(m_titleElement))
    updateTitle(toSVGTitleElement(m_titleElement)->textContent());
}

void Document::removeTitle(Element* titleElement) {
  if (m_titleElement != titleElement)
    return;

  m_titleElement = nullptr;

  // Update title based on first title element in the document, if one exists.
  if (isHTMLDocument() || isXHTMLDocument()) {
    if (HTMLTitleElement* title =
            Traversal<HTMLTitleElement>::firstWithin(*this))
      setTitleElement(title);
  } else if (isSVGDocument()) {
    if (SVGTitleElement* title = Traversal<SVGTitleElement>::firstWithin(*this))
      setTitleElement(title);
  }

  if (!m_titleElement)
    updateTitle(String());
}

const AtomicString& Document::dir() {
  Element* rootElement = documentElement();
  if (isHTMLHtmlElement(rootElement))
    return toHTMLHtmlElement(rootElement)->dir();
  return nullAtom;
}

void Document::setDir(const AtomicString& value) {
  Element* rootElement = documentElement();
  if (isHTMLHtmlElement(rootElement))
    toHTMLHtmlElement(rootElement)->setDir(value);
}

PageVisibilityState Document::pageVisibilityState() const {
  // The visibility of the document is inherited from the visibility of the
  // page. If there is no page associated with the document, we will assume
  // that the page is hidden, as specified by the spec:
  // https://w3c.github.io/page-visibility/#hidden-attribute
  if (!m_frame || !m_frame->page())
    return PageVisibilityStateHidden;
  // While visibilitychange is being dispatched during unloading it is
  // expected that the visibility is hidden regardless of the page's
  // visibility.
  if (m_loadEventProgress >= UnloadVisibilityChangeInProgress)
    return PageVisibilityStateHidden;
  return m_frame->page()->visibilityState();
}

bool Document::isPrefetchOnly() const {
  if (!m_frame || !m_frame->page())
    return false;

  PrerendererClient* prerendererClient =
      PrerendererClient::from(m_frame->page());
  return prerendererClient && prerendererClient->isPrefetchOnly();
}

String Document::visibilityState() const {
  return pageVisibilityStateString(pageVisibilityState());
}

bool Document::hidden() const {
  return pageVisibilityState() != PageVisibilityStateVisible;
}

void Document::didChangeVisibilityState() {
  dispatchEvent(Event::createBubble(EventTypeNames::visibilitychange));
  // Also send out the deprecated version until it can be removed.
  dispatchEvent(Event::createBubble(EventTypeNames::webkitvisibilitychange));

  if (pageVisibilityState() == PageVisibilityStateVisible)
    timeline().setAllCompositorPending();

  if (hidden() && m_canvasFontCache)
    m_canvasFontCache->pruneAll();
}

String Document::nodeName() const {
  return "#document";
}

Node::NodeType Document::getNodeType() const {
  return kDocumentNode;
}

FormController& Document::formController() {
  if (!m_formController) {
    m_formController = FormController::create();
    if (m_frame && m_frame->loader().currentItem() &&
        m_frame->loader().currentItem()->isCurrentDocument(this))
      m_frame->loader().currentItem()->setDocumentState(
          m_formController->formElementsState());
  }
  return *m_formController;
}

DocumentState* Document::formElementsState() const {
  if (!m_formController)
    return 0;
  return m_formController->formElementsState();
}

void Document::setStateForNewFormElements(const Vector<String>& stateVector) {
  if (!stateVector.size() && !m_formController)
    return;
  formController().setStateForNewFormElements(stateVector);
}

FrameView* Document::view() const {
  return m_frame ? m_frame->view() : nullptr;
}

Page* Document::page() const {
  return m_frame ? m_frame->page() : nullptr;
}

FrameHost* Document::frameHost() const {
  return m_frame ? m_frame->host() : nullptr;
}

Settings* Document::settings() const {
  return m_frame ? m_frame->settings() : nullptr;
}

Range* Document::createRange() {
  return Range::create(*this);
}

NodeIterator* Document::createNodeIterator(Node* root,
                                           unsigned whatToShow,
                                           NodeFilter* filter) {
  DCHECK(root);
  return NodeIterator::create(root, whatToShow, filter);
}

TreeWalker* Document::createTreeWalker(Node* root,
                                       unsigned whatToShow,
                                       NodeFilter* filter) {
  DCHECK(root);
  return TreeWalker::create(root, whatToShow, filter);
}

bool Document::needsLayoutTreeUpdate() const {
  if (!isActive() || !view())
    return false;
  if (needsFullLayoutTreeUpdate())
    return true;
  if (childNeedsStyleRecalc())
    return true;
  if (childNeedsStyleInvalidation())
    return true;
  if (layoutViewItem().wasNotifiedOfSubtreeChange())
    return true;
  return false;
}

bool Document::needsFullLayoutTreeUpdate() const {
  if (!isActive() || !view())
    return false;
  if (m_styleEngine->needsActiveStyleUpdate())
    return true;
  if (!m_useElementsNeedingUpdate.isEmpty())
    return true;
  if (needsStyleRecalc())
    return true;
  if (needsStyleInvalidation())
    return true;
  // FIXME: The childNeedsDistributionRecalc bit means either self or children,
  // we should fix that.
  if (childNeedsDistributionRecalc())
    return true;
  if (DocumentAnimations::needsAnimationTimingUpdate(*this))
    return true;
  return false;
}

bool Document::shouldScheduleLayoutTreeUpdate() const {
  if (!isActive())
    return false;
  if (inStyleRecalc())
    return false;
  // InPreLayout will recalc style itself. There's no reason to schedule another
  // recalc.
  if (m_lifecycle.state() == DocumentLifecycle::InPreLayout)
    return false;
  if (!shouldScheduleLayout())
    return false;
  return true;
}

void Document::scheduleLayoutTreeUpdate() {
  DCHECK(!hasPendingVisualUpdate());
  DCHECK(shouldScheduleLayoutTreeUpdate());
  DCHECK(needsLayoutTreeUpdate());

  if (!view()->canThrottleRendering())
    page()->animator().scheduleVisualUpdate(frame());
  m_lifecycle.ensureStateAtMost(DocumentLifecycle::VisualUpdatePending);

  TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
                       "ScheduleStyleRecalculation", TRACE_EVENT_SCOPE_THREAD,
                       "data", InspectorRecalculateStylesEvent::data(frame()));
  InspectorInstrumentation::didScheduleStyleRecalculation(this);

  ++m_styleVersion;
}

bool Document::hasPendingForcedStyleRecalc() const {
  return hasPendingVisualUpdate() && !inStyleRecalc() &&
         getStyleChangeType() >= SubtreeStyleChange;
}

void Document::updateStyleInvalidationIfNeeded() {
  DCHECK(isActive());
  ScriptForbiddenScope forbidScript;

  if (!childNeedsStyleInvalidation())
    return;
  TRACE_EVENT0("blink", "Document::updateStyleInvalidationIfNeeded");
  styleEngine().styleInvalidator().invalidate(*this);
}

void Document::setupFontBuilder(ComputedStyle& documentStyle) {
  FontBuilder fontBuilder(*this);
  CSSFontSelector* selector = styleEngine().fontSelector();
  fontBuilder.createFontForDocument(selector, documentStyle);
}

void Document::inheritHtmlAndBodyElementStyles(StyleRecalcChange change) {
  DCHECK(inStyleRecalc());
  DCHECK(documentElement());

  bool didRecalcDocumentElement = false;
  RefPtr<ComputedStyle> documentElementStyle =
      documentElement()->mutableComputedStyle();
  if (change == Force)
    documentElement()->clearAnimationStyleChange();
  if (!documentElementStyle || documentElement()->needsStyleRecalc() ||
      change == Force) {
    documentElementStyle =
        ensureStyleResolver().styleForElement(documentElement());
    didRecalcDocumentElement = true;
  }

  WritingMode rootWritingMode = documentElementStyle->getWritingMode();
  TextDirection rootDirection = documentElementStyle->direction();

  HTMLElement* body = this->body();
  RefPtr<ComputedStyle> bodyStyle;

  if (body) {
    bodyStyle = body->mutableComputedStyle();
    if (didRecalcDocumentElement)
      body->clearAnimationStyleChange();
    if (!bodyStyle || body->needsStyleRecalc() || didRecalcDocumentElement)
      bodyStyle = ensureStyleResolver().styleForElement(
          body, documentElementStyle.get());
    rootWritingMode = bodyStyle->getWritingMode();
    rootDirection = bodyStyle->direction();
  }

  const ComputedStyle* backgroundStyle = documentElementStyle.get();
  // http://www.w3.org/TR/css3-background/#body-background
  // <html> root element with no background steals background from its first
  // <body> child.
  // Also see LayoutBoxModelObject::backgroundStolenForBeingBody()
  if (isHTMLHtmlElement(documentElement()) && isHTMLBodyElement(body) &&
      !backgroundStyle->hasBackground())
    backgroundStyle = bodyStyle.get();
  Color backgroundColor =
      backgroundStyle->visitedDependentColor(CSSPropertyBackgroundColor);
  FillLayer backgroundLayers = backgroundStyle->backgroundLayers();
  for (auto currentLayer = &backgroundLayers; currentLayer;
       currentLayer = currentLayer->next()) {
    // http://www.w3.org/TR/css3-background/#root-background
    // The root element background always have painting area of the whole
    // canvas.
    currentLayer->setClip(BorderFillBox);

    // The root element doesn't scroll. It always propagates its layout overflow
    // to the viewport. Positioning background against either box is equivalent
    // to positioning against the scrolled box of the viewport.
    if (currentLayer->attachment() == ScrollBackgroundAttachment)
      currentLayer->setAttachment(LocalBackgroundAttachment);
  }
  EImageRendering imageRendering = backgroundStyle->imageRendering();

  const ComputedStyle* overflowStyle = nullptr;
  if (Element* element = viewportDefiningElement(documentElementStyle.get())) {
    if (element == body) {
      overflowStyle = bodyStyle.get();
    } else {
      DCHECK_EQ(element, documentElement());
      overflowStyle = documentElementStyle.get();

      // The body element has its own scrolling box, independent from the
      // viewport.  This is a bit of a weird edge case in the CSS spec that we
      // might want to try to eliminate some day (eg. for ScrollTopLeftInterop -
      // see http://crbug.com/157855).
      if (bodyStyle && !bodyStyle->isOverflowVisible())
        UseCounter::count(*this, UseCounter::BodyScrollsInAdditionToViewport);
    }
  }

  // Resolved rem units are stored in the matched properties cache so we need to
  // make sure to invalidate the cache if the documentElement needed to reattach
  // or the font size changed and then trigger a full document recalc. We also
  // need to clear it here since the call to styleForElement on the body above
  // can cache bad values for rem units if the documentElement's style was
  // dirty. We could keep track of which elements depend on rem units like we do
  // for viewport styles, but we assume root font size changes are rare and just
  // invalidate the cache for now.
  if (styleEngine().usesRemUnits() &&
      (documentElement()->needsAttach() ||
       !documentElement()->computedStyle() ||
       documentElement()->computedStyle()->fontSize() !=
           documentElementStyle->fontSize())) {
    ensureStyleResolver().invalidateMatchedPropertiesCache();
    documentElement()->setNeedsStyleRecalc(
        SubtreeStyleChange,
        StyleChangeReasonForTracing::create(StyleChangeReason::FontSizeChange));
  }

  EOverflowAnchor overflowAnchor = EOverflowAnchor::Auto;
  EOverflow overflowX = EOverflow::Auto;
  EOverflow overflowY = EOverflow::Auto;
  float columnGap = 0;
  if (overflowStyle) {
    overflowAnchor = overflowStyle->overflowAnchor();
    overflowX = overflowStyle->overflowX();
    overflowY = overflowStyle->overflowY();
    // Visible overflow on the viewport is meaningless, and the spec says to
    // treat it as 'auto':
    if (overflowX == EOverflow::Visible)
      overflowX = EOverflow::Auto;
    if (overflowY == EOverflow::Visible)
      overflowY = EOverflow::Auto;
    if (overflowAnchor == EOverflowAnchor::Visible)
      overflowAnchor = EOverflowAnchor::Auto;
    // Column-gap is (ab)used by the current paged overflow implementation (in
    // lack of other ways to specify gaps between pages), so we have to
    // propagate it too.
    columnGap = overflowStyle->columnGap();
  }

  ScrollSnapType snapType = overflowStyle->getScrollSnapType();
  const LengthPoint& snapDestination = overflowStyle->scrollSnapDestination();

  RefPtr<ComputedStyle> documentStyle = layoutViewItem().mutableStyle();
  if (documentStyle->getWritingMode() != rootWritingMode ||
      documentStyle->direction() != rootDirection ||
      documentStyle->visitedDependentColor(CSSPropertyBackgroundColor) !=
          backgroundColor ||
      documentStyle->backgroundLayers() != backgroundLayers ||
      documentStyle->imageRendering() != imageRendering ||
      documentStyle->overflowAnchor() != overflowAnchor ||
      documentStyle->overflowX() != overflowX ||
      documentStyle->overflowY() != overflowY ||
      documentStyle->columnGap() != columnGap ||
      documentStyle->getScrollSnapType() != snapType ||
      documentStyle->scrollSnapDestination() != snapDestination) {
    RefPtr<ComputedStyle> newStyle = ComputedStyle::clone(*documentStyle);
    newStyle->setWritingMode(rootWritingMode);
    newStyle->setDirection(rootDirection);
    newStyle->setBackgroundColor(backgroundColor);
    newStyle->accessBackgroundLayers() = backgroundLayers;
    newStyle->setImageRendering(imageRendering);
    newStyle->setOverflowAnchor(overflowAnchor);
    newStyle->setOverflowX(overflowX);
    newStyle->setOverflowY(overflowY);
    newStyle->setColumnGap(columnGap);
    newStyle->setScrollSnapType(snapType);
    newStyle->setScrollSnapDestination(snapDestination);
    layoutViewItem().setStyle(newStyle);
    setupFontBuilder(*newStyle);
  }

  if (body) {
    if (const ComputedStyle* style = body->computedStyle()) {
      if (style->direction() != rootDirection ||
          style->getWritingMode() != rootWritingMode)
        body->setNeedsStyleRecalc(SubtreeStyleChange,
                                  StyleChangeReasonForTracing::create(
                                      StyleChangeReason::WritingModeChange));
    }
  }

  if (const ComputedStyle* style = documentElement()->computedStyle()) {
    if (style->direction() != rootDirection ||
        style->getWritingMode() != rootWritingMode)
      documentElement()->setNeedsStyleRecalc(
          SubtreeStyleChange, StyleChangeReasonForTracing::create(
                                  StyleChangeReason::WritingModeChange));
  }
}

#if DCHECK_IS_ON()
static void assertLayoutTreeUpdated(Node& root) {
  for (Node& node : NodeTraversal::inclusiveDescendantsOf(root)) {
    // We leave some nodes with dirty bits in the tree because they don't
    // matter like Comment and ProcessingInstruction nodes.
    // TODO(esprehn): Don't even mark those nodes as needing recalcs in the
    // first place.
    if (!node.isElementNode() && !node.isTextNode() && !node.isShadowRoot() &&
        !node.isDocumentNode())
      continue;
    DCHECK(!node.needsStyleRecalc());
    DCHECK(!node.childNeedsStyleRecalc());
    DCHECK(!node.needsReattachLayoutTree());
    DCHECK(!node.childNeedsReattachLayoutTree());
    DCHECK(!node.childNeedsDistributionRecalc());
    DCHECK(!node.needsStyleInvalidation());
    DCHECK(!node.childNeedsStyleInvalidation());
    for (ShadowRoot* shadowRoot = node.youngestShadowRoot(); shadowRoot;
         shadowRoot = shadowRoot->olderShadowRoot())
      assertLayoutTreeUpdated(*shadowRoot);
  }
}
#endif

void Document::updateStyleAndLayoutTree() {
  DCHECK(isMainThread());

  ScriptForbiddenScope forbidScript;
  // We should forbid script execution for plugins here because update while
  // layout is changing, HTMLPlugin element can be reattached and plugin can be
  // destroyed. Plugin can execute scripts on destroy. It produces crash without
  // PluginScriptForbiddenScope: crbug.com/550427.
  PluginScriptForbiddenScope pluginForbidScript;

  if (!view() || !isActive())
    return;

  if (view()->shouldThrottleRendering())
    return;

  if (!needsLayoutTreeUpdate()) {
    if (lifecycle().state() < DocumentLifecycle::StyleClean) {
      // needsLayoutTreeUpdate may change to false without any actual layout
      // tree update.  For example, needsAnimationTimingUpdate may change to
      // false when time elapses.  Advance lifecycle to StyleClean because style
      // is actually clean now.
      lifecycle().advanceTo(DocumentLifecycle::InStyleRecalc);
      lifecycle().advanceTo(DocumentLifecycle::StyleClean);
    }
    return;
  }

  if (inStyleRecalc())
    return;

  // Entering here from inside layout, paint etc. would be catastrophic since
  // recalcStyle can tear down the layout tree or (unfortunately) run
  // script. Kill the whole layoutObject if someone managed to get into here in
  // states not allowing tree mutations.
  RELEASE_ASSERT(lifecycle().stateAllowsTreeMutations());

  TRACE_EVENT_BEGIN1("blink,devtools.timeline", "UpdateLayoutTree", "beginData",
                     InspectorRecalculateStylesEvent::data(frame()));

  unsigned startElementCount = styleEngine().styleForElementCount();

  InspectorInstrumentation::willRecalculateStyle(this);
  PerformanceMonitor::willRecalculateStyle(this);

  DocumentAnimations::updateAnimationTimingIfNeeded(*this);
  evaluateMediaQueryListIfNeeded();
  updateUseShadowTreesIfNeeded();
  updateDistribution();
  updateActiveStyle();
  updateStyleInvalidationIfNeeded();

  // FIXME: We should update style on our ancestor chain before proceeding
  // however doing so currently causes several tests to crash, as
  // LocalFrame::setDocument calls Document::attach before setting the
  // LocalDOMWindow on the LocalFrame, or the SecurityOrigin on the
  // document. The attach, in turn resolves style (here) and then when we
  // resolve style on the parent chain, we may end up re-attaching our
  // containing iframe, which when asked HTMLFrameElementBase::isURLAllowed hits
  // a null-dereference due to security code always assuming the document has a
  // SecurityOrigin.

  updateStyle();

  notifyLayoutTreeOfSubtreeChanges();

  // As a result of the style recalculation, the currently hovered element might
  // have been detached (for example, by setting display:none in the :hover
  // style), schedule another mouseMove event to check if any other elements
  // ended up under the mouse pointer due to re-layout.
  if (hoverNode() && !hoverNode()->layoutObject() && frame())
    frame()->eventHandler().dispatchFakeMouseMoveEventSoon();

  if (m_focusedElement && !m_focusedElement->isFocusable())
    clearFocusedElementSoon();
  layoutViewItem().clearHitTestCache();

  DCHECK(!DocumentAnimations::needsAnimationTimingUpdate(*this));

  unsigned elementCount =
      styleEngine().styleForElementCount() - startElementCount;

  TRACE_EVENT_END1("blink,devtools.timeline", "UpdateLayoutTree",
                   "elementCount", elementCount);

#if DCHECK_IS_ON()
  assertLayoutTreeUpdated(*this);
#endif
  InspectorInstrumentation::didRecalculateStyle(this);
  PerformanceMonitor::didRecalculateStyle(this);
}

void Document::updateActiveStyle() {
  DCHECK(isActive());
  DCHECK(isMainThread());
  TRACE_EVENT0("blink", "Document::updateActiveStyle");
  styleEngine().updateActiveStyle();
}

void Document::updateStyle() {
  DCHECK(!view()->shouldThrottleRendering());
  TRACE_EVENT_BEGIN0("blink,blink_style", "Document::updateStyle");
  double startTime = monotonicallyIncreasingTime();

  unsigned initialElementCount = styleEngine().styleForElementCount();

  HTMLFrameOwnerElement::UpdateSuspendScope suspendWidgetHierarchyUpdates;
  m_lifecycle.advanceTo(DocumentLifecycle::InStyleRecalc);

  StyleRecalcChange change = NoChange;
  if (getStyleChangeType() >= SubtreeStyleChange)
    change = Force;

  NthIndexCache nthIndexCache(*this);

  // FIXME: Cannot access the ensureStyleResolver() before calling
  // styleForDocument below because apparently the StyleResolver's constructor
  // has side effects. We should fix it.  See printing/setPrinting.html,
  // printing/width-overflow.html though they only fail on mac when accessing
  // the resolver by what appears to be a viewport size difference.

  if (change == Force) {
    m_hasNodesWithPlaceholderStyle = false;
    RefPtr<ComputedStyle> documentStyle =
        StyleResolver::styleForDocument(*this);
    StyleRecalcChange localChange = ComputedStyle::stylePropagationDiff(
        documentStyle.get(), layoutViewItem().style());
    if (localChange != NoChange)
      layoutViewItem().setStyle(documentStyle.release());
  }

  clearNeedsStyleRecalc();
  clearNeedsReattachLayoutTree();

  StyleResolver& resolver = ensureStyleResolver();

  bool shouldRecordStats;
  TRACE_EVENT_CATEGORY_GROUP_ENABLED("blink,blink_style", &shouldRecordStats);
  styleEngine().setStatsEnabled(shouldRecordStats);

  if (Element* documentElement = this->documentElement()) {
    inheritHtmlAndBodyElementStyles(change);
    if (documentElement->shouldCallRecalcStyle(change))
      documentElement->recalcStyle(change);
  }

  view()->recalcOverflowAfterStyleChange();

  // Only retain the HashMap for the duration of StyleRecalc and
  // LayoutTreeConstruction.
  m_styleReattachDataMap.clear();
  clearChildNeedsStyleRecalc();
  clearChildNeedsReattachLayoutTree();

  resolver.clearStyleSharingList();

  DCHECK(!needsStyleRecalc());
  DCHECK(!childNeedsStyleRecalc());
  DCHECK(!needsReattachLayoutTree());
  DCHECK(!childNeedsReattachLayoutTree());
  DCHECK(inStyleRecalc());
  DCHECK_EQ(styleResolver(), &resolver);
  DCHECK(m_styleReattachDataMap.isEmpty());
  m_lifecycle.advanceTo(DocumentLifecycle::StyleClean);
  if (shouldRecordStats) {
    TRACE_EVENT_END2("blink,blink_style", "Document::updateStyle",
                     "resolverAccessCount",
                     styleEngine().styleForElementCount() - initialElementCount,
                     "counters", styleEngine().stats()->toTracedValue());
  } else {
    TRACE_EVENT_END1(
        "blink,blink_style", "Document::updateStyle", "resolverAccessCount",
        styleEngine().styleForElementCount() - initialElementCount);
  }

  double updateDurationSeconds = monotonicallyIncreasingTime() - startTime;
  DEFINE_STATIC_LOCAL(CustomCountHistogram, updateHistogram,
                      ("Style.UpdateTime", 0, 10000000, 50));
  updateHistogram.count(updateDurationSeconds * 1000 * 1000);
  CSSTiming::from(*this).recordUpdateDuration(updateDurationSeconds);
}

void Document::notifyLayoutTreeOfSubtreeChanges() {
  if (!layoutViewItem().wasNotifiedOfSubtreeChange())
    return;

  m_lifecycle.advanceTo(DocumentLifecycle::InLayoutSubtreeChange);

  layoutViewItem().handleSubtreeModifications();
  DCHECK(!layoutViewItem().wasNotifiedOfSubtreeChange());

  m_lifecycle.advanceTo(DocumentLifecycle::LayoutSubtreeChangeClean);
}

bool Document::needsLayoutTreeUpdateForNode(const Node& node) const {
  if (!node.canParticipateInFlatTree())
    return false;
  if (!needsLayoutTreeUpdate())
    return false;
  if (!node.isConnected())
    return false;

  if (needsFullLayoutTreeUpdate() || node.needsStyleRecalc() ||
      node.needsStyleInvalidation())
    return true;
  for (const ContainerNode* ancestor = LayoutTreeBuilderTraversal::parent(node);
       ancestor; ancestor = LayoutTreeBuilderTraversal::parent(*ancestor)) {
    if (ancestor->needsStyleRecalc() || ancestor->needsStyleInvalidation() ||
        ancestor->needsAdjacentStyleRecalc())
      return true;
  }
  return false;
}

void Document::updateStyleAndLayoutTreeForNode(const Node* node) {
  DCHECK(node);
  if (!needsLayoutTreeUpdateForNode(*node))
    return;
  updateStyleAndLayoutTree();
}

void Document::updateStyleAndLayoutIgnorePendingStylesheetsForNode(Node* node) {
  DCHECK(node);
  if (!node->inActiveDocument())
    return;
  updateStyleAndLayoutIgnorePendingStylesheets();
}

void Document::updateStyleAndLayout() {
  DCHECK(isMainThread());

  ScriptForbiddenScope forbidScript;

  FrameView* frameView = view();
  if (frameView && frameView->isInPerformLayout()) {
    // View layout should not be re-entrant.
    NOTREACHED();
    return;
  }

  if (HTMLFrameOwnerElement* owner = localOwner())
    owner->document().updateStyleAndLayout();

  updateStyleAndLayoutTree();

  if (!isActive())
    return;

  if (frameView->needsLayout())
    frameView->layout();

  if (lifecycle().state() < DocumentLifecycle::LayoutClean)
    lifecycle().advanceTo(DocumentLifecycle::LayoutClean);

  if (FrameView* frameView = view())
    frameView->performScrollAnchoringAdjustments();
}

void Document::layoutUpdated() {
  // Plugins can run script inside layout which can detach the page.
  // TODO(esprehn): Can this still happen now that all plugins are out of
  // process?
  if (frame() && frame()->page())
    frame()->page()->chromeClient().layoutUpdated(frame());

  markers().invalidateRectsForAllMarkers();

  // The layout system may perform layouts with pending stylesheets. When
  // recording first layout time, we ignore these layouts, since painting is
  // suppressed for them. We're interested in tracking the time of the
  // first real or 'paintable' layout.
  // TODO(esprehn): This doesn't really make sense, why not track the first
  // beginFrame? This will catch the first layout in a page that does lots
  // of layout thrashing even though that layout might not be followed by
  // a paint for many seconds.
  if (isRenderingReady() && body() &&
      !styleEngine().hasPendingScriptBlockingSheets()) {
    if (!m_documentTiming.firstLayout())
      m_documentTiming.markFirstLayout();
  }

  m_rootScrollerController->didUpdateLayout();
}

void Document::clearFocusedElementSoon() {
  if (!m_clearFocusedElementTimer.isActive())
    m_clearFocusedElementTimer.startOneShot(0, BLINK_FROM_HERE);
}

void Document::clearFocusedElementTimerFired(TimerBase*) {
  updateStyleAndLayoutTree();

  if (m_focusedElement && !m_focusedElement->isFocusable())
    m_focusedElement->blur();
}

// FIXME: This is a bad idea and needs to be removed eventually.
// Other browsers load stylesheets before they continue parsing the web page.
// Since we don't, we can run JavaScript code that needs answers before the
// stylesheets are loaded. Doing a layout ignoring the pending stylesheets
// lets us get reasonable answers. The long term solution to this problem is
// to instead suspend JavaScript execution.
void Document::updateStyleAndLayoutTreeIgnorePendingStylesheets() {
  StyleEngine::IgnoringPendingStylesheet ignoring(styleEngine());

  if (styleEngine().hasPendingScriptBlockingSheets()) {
    // FIXME: We are willing to attempt to suppress painting with outdated style
    // info only once.  Our assumption is that it would be dangerous to try to
    // stop it a second time, after page content has already been loaded and
    // displayed with accurate style information. (Our suppression involves
    // blanking the whole page at the moment. If it were more refined, we might
    // be able to do something better.) It's worth noting though that this
    // entire method is a hack, since what we really want to do is suspend JS
    // instead of doing a layout with inaccurate information.
    HTMLElement* bodyElement = body();
    if (bodyElement && !bodyElement->layoutObject() &&
        m_pendingSheetLayout == NoLayoutWithPendingSheets) {
      m_pendingSheetLayout = DidLayoutWithPendingSheets;
      styleEngine().markAllTreeScopesDirty();
    }
    if (m_hasNodesWithPlaceholderStyle) {
      // If new nodes have been added or style recalc has been done with style
      // sheets still pending, some nodes may not have had their real style
      // calculated yet.  Normally this gets cleaned when style sheets arrive
      // but here we need up-to-date style immediately.
      setNeedsStyleRecalc(SubtreeStyleChange,
                          StyleChangeReasonForTracing::create(
                              StyleChangeReason::CleanupPlaceholderStyles));
    }
  }
  updateStyleAndLayoutTree();
}

void Document::updateStyleAndLayoutIgnorePendingStylesheets(
    Document::RunPostLayoutTasks runPostLayoutTasks) {
  updateStyleAndLayoutTreeIgnorePendingStylesheets();
  updateStyleAndLayout();

  if (runPostLayoutTasks == RunPostLayoutTasksSynchronously && view())
    view()->flushAnyPendingPostLayoutTasks();
}

PassRefPtr<ComputedStyle> Document::styleForElementIgnoringPendingStylesheets(
    Element* element) {
  DCHECK_EQ(element->document(), this);
  StyleEngine::IgnoringPendingStylesheet ignoring(styleEngine());
  if (!element->canParticipateInFlatTree())
    return ensureStyleResolver().styleForElement(element, nullptr);
  ContainerNode* parent = LayoutTreeBuilderTraversal::parent(*element);
  return ensureStyleResolver().styleForElement(
      element, parent ? parent->ensureComputedStyle() : nullptr);
}

PassRefPtr<ComputedStyle> Document::styleForPage(int pageIndex) {
  updateDistribution();
  return ensureStyleResolver().styleForPage(pageIndex);
}

bool Document::isPageBoxVisible(int pageIndex) {
  return styleForPage(pageIndex)->visibility() !=
         EVisibility::kHidden;  // display property doesn't apply to @page.
}

void Document::pageSizeAndMarginsInPixels(int pageIndex,
                                          DoubleSize& pageSize,
                                          int& marginTop,
                                          int& marginRight,
                                          int& marginBottom,
                                          int& marginLeft) {
  RefPtr<ComputedStyle> style = styleForPage(pageIndex);

  double width = pageSize.width();
  double height = pageSize.height();
  switch (style->getPageSizeType()) {
    case PAGE_SIZE_AUTO:
      break;
    case PAGE_SIZE_AUTO_LANDSCAPE:
      if (width < height)
        std::swap(width, height);
      break;
    case PAGE_SIZE_AUTO_PORTRAIT:
      if (width > height)
        std::swap(width, height);
      break;
    case PAGE_SIZE_RESOLVED: {
      FloatSize size = style->pageSize();
      width = size.width();
      height = size.height();
      break;
    }
    default:
      NOTREACHED();
  }
  pageSize = DoubleSize(width, height);

  // The percentage is calculated with respect to the width even for margin top
  // and bottom.
  // http://www.w3.org/TR/CSS2/box.html#margin-properties
  marginTop = style->marginTop().isAuto()
                  ? marginTop
                  : intValueForLength(style->marginTop(), width);
  marginRight = style->marginRight().isAuto()
                    ? marginRight
                    : intValueForLength(style->marginRight(), width);
  marginBottom = style->marginBottom().isAuto()
                     ? marginBottom
                     : intValueForLength(style->marginBottom(), width);
  marginLeft = style->marginLeft().isAuto()
                   ? marginLeft
                   : intValueForLength(style->marginLeft(), width);
}

void Document::setIsViewSource(bool isViewSource) {
  m_isViewSource = isViewSource;
  if (!m_isViewSource)
    return;

  setSecurityOrigin(SecurityOrigin::createUnique());
  didUpdateSecurityOrigin();
}

void Document::scheduleUseShadowTreeUpdate(SVGUseElement& element) {
  m_useElementsNeedingUpdate.add(&element);
  scheduleLayoutTreeUpdateIfNeeded();
}

void Document::unscheduleUseShadowTreeUpdate(SVGUseElement& element) {
  m_useElementsNeedingUpdate.remove(&element);
}

void Document::updateUseShadowTreesIfNeeded() {
  ScriptForbiddenScope forbidScript;

  if (m_useElementsNeedingUpdate.isEmpty())
    return;

  HeapHashSet<Member<SVGUseElement>> elements;
  m_useElementsNeedingUpdate.swap(elements);
  for (SVGUseElement* element : elements)
    element->buildPendingResource();
}

StyleResolver* Document::styleResolver() const {
  return m_styleEngine->resolver();
}

StyleResolver& Document::ensureStyleResolver() const {
  return m_styleEngine->ensureResolver();
}

void Document::initialize() {
  DCHECK_EQ(m_lifecycle.state(), DocumentLifecycle::Inactive);
  DCHECK(!m_axObjectCache || this != &axObjectCacheOwner());

  m_layoutView = new LayoutView(this);
  setLayoutObject(m_layoutView);

  m_layoutView->setIsInWindow(true);
  m_layoutView->setStyle(StyleResolver::styleForDocument(*this));
  m_layoutView->compositor()->setNeedsCompositingUpdate(
      CompositingUpdateAfterCompositingInputChange);

  ContainerNode::attachLayoutTree();

  // The TextAutosizer can't update layout view info while the Document is
  // detached, so update now in case anything changed.
  if (TextAutosizer* autosizer = textAutosizer())
    autosizer->updatePageInfo();

  m_frame->documentAttached();
  m_lifecycle.advanceTo(DocumentLifecycle::StyleClean);

  if (view())
    view()->didAttachDocument();
}

void Document::shutdown() {
  TRACE_EVENT0("blink", "Document::shutdown");
  RELEASE_ASSERT(!m_frame || m_frame->tree().childCount() == 0);
  if (!isActive())
    return;

  // Frame navigation can cause a new Document to be attached. Don't allow that,
  // since that will cause a situation where LocalFrame still has a Document
  // attached after this finishes!  Normally, it shouldn't actually be possible
  // to trigger navigation here.  However, plugins (see below) can cause lots of
  // crazy things to happen, since plugin detach involves nested message loops.
  FrameNavigationDisabler navigationDisabler(*m_frame);
  // Defer widget updates to avoid plugins trying to run script inside
  // ScriptForbiddenScope, which will crash the renderer after
  // https://crrev.com/200984
  HTMLFrameOwnerElement::UpdateSuspendScope suspendWidgetHierarchyUpdates;
  // Don't allow script to run in the middle of detachLayoutTree() because a
  // detaching Document is not in a consistent state.
  ScriptForbiddenScope forbidScript;

  view()->dispose();

  // If the widget of the document's frame owner doesn't match view() then
  // FrameView::dispose() didn't clear the owner's widget. If we don't clear it
  // here, it may be clobbered later in LocalFrame::createView(). See also
  // https://crbug.com/673170 and the comment in FrameView::dispose().
  HTMLFrameOwnerElement* ownerElement = m_frame->deprecatedLocalOwner();
  if (ownerElement)
    ownerElement->setWidget(nullptr);

  m_markers->prepareForDestruction();

  m_lifecycle.advanceTo(DocumentLifecycle::Stopping);

  if (page())
    page()->documentDetached(this);
  InspectorInstrumentation::documentDetached(this);

  if (m_frame->loader().client()->sharedWorkerRepositoryClient())
    m_frame->loader()
        .client()
        ->sharedWorkerRepositoryClient()
        ->documentDetached(this);

  // FIXME: consider using SuspendableObject.
  if (m_scriptedAnimationController)
    m_scriptedAnimationController->clearDocumentPointer();
  m_scriptedAnimationController.clear();

  m_scriptedIdleTaskController.clear();

  if (svgExtensions())
    accessSVGExtensions().pauseAnimations();

  // FIXME: This shouldn't be needed once LocalDOMWindow becomes
  // ExecutionContext.
  if (m_domWindow)
    m_domWindow->clearEventQueue();

  if (m_layoutView)
    m_layoutView->setIsInWindow(false);

  if (registrationContext())
    registrationContext()->documentWasDetached();

  m_hoverNode = nullptr;
  m_activeHoverElement = nullptr;
  m_autofocusElement = nullptr;

  if (m_focusedElement.get()) {
    Element* oldFocusedElement = m_focusedElement;
    m_focusedElement = nullptr;
    if (frameHost())
      frameHost()->chromeClient().focusedNodeChanged(oldFocusedElement,
                                                     nullptr);
  }
  m_sequentialFocusNavigationStartingPoint = nullptr;

  if (this == &axObjectCacheOwner())
    clearAXObjectCache();

  m_layoutView = nullptr;
  ContainerNode::detachLayoutTree();

  if (this != &axObjectCacheOwner()) {
    if (AXObjectCache* cache = existingAXObjectCache()) {
      // Documents that are not a root document use the AXObjectCache in
      // their root document. Node::removedFrom is called after the
      // document has been detached so it can't find the root document.
      // We do the removals here instead.
      for (Node& node : NodeTraversal::descendantsOf(*this)) {
        cache->remove(&node);
      }
    }
  }

  styleEngine().didDetach();

  frameHost()->eventHandlerRegistry().documentDetached(*this);

  // Since |Document| class has multiple |LifecycleNotifier| as base class,
  // we need to have |static_cast<SynchronousMutationNotifier>| here.
  static_cast<SynchronousMutationNotifier*>(this)->notifyContextDestroyed();
  m_frame->selection().documentDetached(*this);

  // If this Document is associated with a live DocumentLoader, the
  // DocumentLoader will take care of clearing the FetchContext. Deferring
  // to the DocumentLoader when possible also prevents prematurely clearing
  // the context in the case where multiple Documents end up associated with
  // a single DocumentLoader (e.g., navigating to a javascript: url).
  if (!loader())
    m_fetcher->clearContext();
  // If this document is the master for an HTMLImportsController, sever that
  // relationship. This ensures that we don't leave import loads in flight,
  // thinking they should have access to a valid frame when they don't.
  if (m_importsController) {
    m_importsController->dispose();
    clearImportsController();
  }

  m_timers.setTimerTaskRunner(Platform::current()
                                  ->currentThread()
                                  ->scheduler()
                                  ->timerTaskRunner()
                                  ->clone());

  if (m_mediaQueryMatcher)
    m_mediaQueryMatcher->documentDetached();

  m_lifecycle.advanceTo(DocumentLifecycle::Stopped);

  // TODO(haraken): Call contextDestroyed() before we start any disruptive
  // operations.
  // TODO(haraken): Currently we call notifyContextDestroyed() only in
  // Document::detachLayoutTree(), which means that we don't call
  // notifyContextDestroyed() for a document that doesn't get detached.
  // If such a document has any observer, the observer won't get
  // a contextDestroyed() notification. This can happen for a document
  // created by DOMImplementation::createDocument().
  ExecutionContext::notifyContextDestroyed();

  // This is required, as our LocalFrame might delete itself as soon as it
  // detaches us. However, this violates Node::detachLayoutTree() semantics, as
  // it's never possible to re-attach. Eventually Document::detachLayoutTree()
  // should be renamed, or this setting of the frame to 0 could be made
  // explicit in each of the callers of Document::detachLayoutTree().
  m_frame = nullptr;
}

void Document::removeAllEventListeners() {
  ContainerNode::removeAllEventListeners();

  if (LocalDOMWindow* domWindow = this->domWindow())
    domWindow->removeAllEventListeners();
}

Document& Document::axObjectCacheOwner() const {
  // Every document has its own axObjectCache if accessibility is enabled,
  // except for page popups, which share the axObjectCache of their owner.
  Document* doc = const_cast<Document*>(this);
  if (doc->frame() && doc->frame()->pagePopupOwner()) {
    DCHECK(!doc->m_axObjectCache);
    return doc->frame()->pagePopupOwner()->document().axObjectCacheOwner();
  }
  return *doc;
}

void Document::clearAXObjectCache() {
  DCHECK_EQ(&axObjectCacheOwner(), this);
  // Clear the cache member variable before calling delete because attempts
  // are made to access it during destruction.
  if (m_axObjectCache)
    m_axObjectCache->dispose();
  m_axObjectCache.clear();
}

AXObjectCache* Document::existingAXObjectCache() const {
  // If the layoutObject is gone then we are in the process of destruction.
  // This method will be called before m_frame = nullptr.
  if (!axObjectCacheOwner().layoutView())
    return 0;

  return axObjectCacheOwner().m_axObjectCache.get();
}

AXObjectCache* Document::axObjectCache() const {
  Settings* settings = this->settings();
  if (!settings || !settings->getAccessibilityEnabled())
    return 0;

  // The only document that actually has a AXObjectCache is the top-level
  // document.  This is because we need to be able to get from any
  // WebCoreAXObject to any other WebCoreAXObject on the same page.  Using a
  // single cache allows lookups across nested webareas (i.e. multiple
  // documents).
  Document& cacheOwner = this->axObjectCacheOwner();

  // If the document has already been detached, do not make a new axObjectCache.
  if (!cacheOwner.layoutView())
    return 0;

  DCHECK(&cacheOwner == this || !m_axObjectCache);
  if (!cacheOwner.m_axObjectCache)
    cacheOwner.m_axObjectCache = AXObjectCache::create(cacheOwner);
  return cacheOwner.m_axObjectCache.get();
}

CanvasFontCache* Document::canvasFontCache() {
  if (!m_canvasFontCache)
    m_canvasFontCache = CanvasFontCache::create(*this);

  return m_canvasFontCache.get();
}

DocumentParser* Document::createParser() {
  if (isHTMLDocument())
    return HTMLDocumentParser::create(toHTMLDocument(*this),
                                      m_parserSyncPolicy);
  // FIXME: this should probably pass the frame instead
  return XMLDocumentParser::create(*this, view());
}

bool Document::isFrameSet() const {
  if (!isHTMLDocument())
    return false;
  return isHTMLFrameSetElement(body());
}

ScriptableDocumentParser* Document::scriptableDocumentParser() const {
  return parser() ? parser()->asScriptableDocumentParser() : nullptr;
}

void Document::open(Document* enteredDocument, ExceptionState& exceptionState) {
  if (importLoader()) {
    exceptionState.throwDOMException(
        InvalidStateError, "Imported document doesn't support open().");
    return;
  }

  if (!isHTMLDocument()) {
    exceptionState.throwDOMException(InvalidStateError,
                                     "Only HTML documents support open().");
    return;
  }

  if (m_throwOnDynamicMarkupInsertionCount) {
    exceptionState.throwDOMException(
        InvalidStateError, "Custom Element constructor should not use open().");
    return;
  }

  if (enteredDocument) {
    if (!getSecurityOrigin()->canAccess(enteredDocument->getSecurityOrigin())) {
      exceptionState.throwSecurityError(
          "Can only call open() on same-origin documents.");
      return;
    }
    setSecurityOrigin(enteredDocument->getSecurityOrigin());
    setURL(enteredDocument->url());
    m_cookieURL = enteredDocument->cookieURL();
  }

  open();
}

void Document::open() {
  DCHECK(!importLoader());

  if (m_frame) {
    if (ScriptableDocumentParser* parser = scriptableDocumentParser()) {
      if (parser->isParsing()) {
        // FIXME: HTML5 doesn't tell us to check this, it might not be correct.
        if (parser->isExecutingScript())
          return;

        if (!parser->wasCreatedByScript() && parser->hasInsertionPoint())
          return;
      }
    }

    if (m_frame->loader().provisionalDocumentLoader())
      m_frame->loader().stopAllLoaders();
  }

  removeAllEventListenersRecursively();
  implicitOpen(ForceSynchronousParsing);
  if (ScriptableDocumentParser* parser = scriptableDocumentParser())
    parser->setWasCreatedByScript(true);

  if (m_frame)
    m_frame->loader().didExplicitOpen();
  if (m_loadEventProgress != LoadEventInProgress &&
      pageDismissalEventBeingDispatched() == NoDismissal)
    m_loadEventProgress = LoadEventNotRun;
}

void Document::detachParser() {
  if (!m_parser)
    return;
  m_parser->detach();
  m_parser.clear();
  DocumentParserTiming::from(*this).markParserDetached();
}

void Document::cancelParsing() {
  detachParser();
  setParsingState(FinishedParsing);
  setReadyState(Complete);
}

DocumentParser* Document::implicitOpen(
    ParserSynchronizationPolicy parserSyncPolicy) {
  detachParser();

  removeChildren();
  DCHECK(!m_focusedElement);

  setCompatibilityMode(NoQuirksMode);

  if (!threadedParsingEnabledForTesting()) {
    parserSyncPolicy = ForceSynchronousParsing;
  } else if (parserSyncPolicy == AllowAsynchronousParsing && isPrefetchOnly()) {
    // Prefetch must be synchronous.
    parserSyncPolicy = ForceSynchronousParsing;
  }

  m_parserSyncPolicy = parserSyncPolicy;
  m_parser = createParser();
  DocumentParserTiming::from(*this).markParserStart();
  setParsingState(Parsing);
  setReadyState(Loading);

  return m_parser;
}

HTMLElement* Document::body() const {
  if (!documentElement() || !isHTMLHtmlElement(documentElement()))
    return 0;

  for (HTMLElement* child =
           Traversal<HTMLElement>::firstChild(*documentElement());
       child; child = Traversal<HTMLElement>::nextSibling(*child)) {
    if (isHTMLFrameSetElement(*child) || isHTMLBodyElement(*child))
      return child;
  }

  return 0;
}

HTMLBodyElement* Document::firstBodyElement() const {
  if (!documentElement())
    return 0;

  for (HTMLElement* child =
           Traversal<HTMLElement>::firstChild(*documentElement());
       child; child = Traversal<HTMLElement>::nextSibling(*child)) {
    if (isHTMLBodyElement(*child))
      return toHTMLBodyElement(child);
  }

  return 0;
}

void Document::setBody(HTMLElement* prpNewBody,
                       ExceptionState& exceptionState) {
  HTMLElement* newBody = prpNewBody;

  if (!newBody) {
    exceptionState.throwDOMException(
        HierarchyRequestError,
        ExceptionMessages::argumentNullOrIncorrectType(1, "HTMLElement"));
    return;
  }
  if (!documentElement()) {
    exceptionState.throwDOMException(HierarchyRequestError,
                                     "No document element exists.");
    return;
  }

  if (!isHTMLBodyElement(*newBody) && !isHTMLFrameSetElement(*newBody)) {
    exceptionState.throwDOMException(
        HierarchyRequestError,
        "The new body element is of type '" + newBody->tagName() +
            "'. It must be either a 'BODY' or 'FRAMESET' element.");
    return;
  }

  HTMLElement* oldBody = body();
  if (oldBody == newBody)
    return;

  if (oldBody)
    documentElement()->replaceChild(newBody, oldBody, exceptionState);
  else
    documentElement()->appendChild(newBody, exceptionState);
}

void Document::willInsertBody() {
  if (frame())
    frame()->loader().client()->dispatchWillInsertBody();
  // If we get to the <body> try to resume commits since we should have content
  // to paint now.
  // TODO(esprehn): Is this really optimal? We might start producing frames
  // for very little content, should we wait for some heuristic like
  // isVisuallyNonEmpty() ?
  beginLifecycleUpdatesIfRenderingReady();
}

HTMLHeadElement* Document::head() const {
  Node* de = documentElement();
  if (!de)
    return 0;

  return Traversal<HTMLHeadElement>::firstChild(*de);
}

Element* Document::viewportDefiningElement(
    const ComputedStyle* rootStyle) const {
  // If a BODY element sets non-visible overflow, it is to be propagated to the
  // viewport, as long as the following conditions are all met:
  // (1) The root element is HTML.
  // (2) It is the primary BODY element (we only assert for this, expecting
  //     callers to behave).
  // (3) The root element has visible overflow.
  // Otherwise it's the root element's properties that are to be propagated.
  Element* rootElement = documentElement();
  Element* bodyElement = body();
  if (!rootElement)
    return 0;
  if (!rootStyle) {
    rootStyle = rootElement->computedStyle();
    if (!rootStyle)
      return 0;
  }
  if (bodyElement && rootStyle->isOverflowVisible() &&
      isHTMLHtmlElement(*rootElement))
    return bodyElement;
  return rootElement;
}

void Document::close(ExceptionState& exceptionState) {
  // FIXME: We should follow the specification more closely:
  //        http://www.whatwg.org/specs/web-apps/current-work/#dom-document-close

  if (importLoader()) {
    exceptionState.throwDOMException(
        InvalidStateError, "Imported document doesn't support close().");
    return;
  }

  if (!isHTMLDocument()) {
    exceptionState.throwDOMException(InvalidStateError,
                                     "Only HTML documents support close().");
    return;
  }

  if (m_throwOnDynamicMarkupInsertionCount) {
    exceptionState.throwDOMException(
        InvalidStateError,
        "Custom Element constructor should not use close().");
    return;
  }

  close();
}

void Document::close() {
  if (!scriptableDocumentParser() ||
      !scriptableDocumentParser()->wasCreatedByScript() ||
      !scriptableDocumentParser()->isParsing())
    return;

  if (DocumentParser* parser = m_parser)
    parser->finish();

  if (!m_frame) {
    // Because we have no frame, we don't know if all loading has completed,
    // so we just call implicitClose() immediately. FIXME: This might fire
    // the load event prematurely
    // <http://bugs.webkit.org/show_bug.cgi?id=14568>.
    implicitClose();
    return;
  }

  m_frame->loader().checkCompleted();
}

void Document::implicitClose() {
  DCHECK(!inStyleRecalc());
  if (processingLoadEvent() || !m_parser)
    return;
  if (frame() && frame()->navigationScheduler().locationChangePending()) {
    suppressLoadEvent();
    return;
  }

  m_loadEventProgress = LoadEventInProgress;

  ScriptableDocumentParser* parser = scriptableDocumentParser();
  m_wellFormed = parser && parser->wellFormed();

  // We have to clear the parser, in case someone document.write()s from the
  // onLoad event handler, as in Radar 3206524.
  detachParser();

  if (frame() && frame()->script().canExecuteScripts(NotAboutToExecuteScript)) {
    ImageLoader::dispatchPendingLoadEvents();
    ImageLoader::dispatchPendingErrorEvents();
  }

  // JS running below could remove the frame or destroy the LayoutView so we
  // call those two functions repeatedly and don't save them on the stack.

  // To align the HTML load event and the SVGLoad event for the outermost <svg>
  // element, fire it from here, instead of doing it from
  // SVGElement::finishedParsingChildren.
  if (svgExtensions())
    accessSVGExtensions().dispatchSVGLoadEventToOutermostSVGElements();

  if (this->domWindow())
    this->domWindow()->documentWasClosed();

  if (frame()) {
    frame()->loader().client()->dispatchDidHandleOnloadEvents();
    loader()->applicationCacheHost()->stopDeferringEvents();
  }

  if (!frame()) {
    m_loadEventProgress = LoadEventCompleted;
    return;
  }

  // Make sure both the initial layout and reflow happen after the onload
  // fires. This will improve onload scores, and other browsers do it.
  // If they wanna cheat, we can too. -dwh

  if (frame()->navigationScheduler().locationChangePending() &&
      elapsedTime() < cLayoutScheduleThreshold) {
    // Just bail out. Before or during the onload we were shifted to another
    // page.  The old i-Bench suite does this. When this happens don't bother
    // painting or laying out.
    m_loadEventProgress = LoadEventCompleted;
    return;
  }

  // We used to force a synchronous display and flush here.  This really isn't
  // necessary and can in fact be actively harmful if pages are loading at a
  // rate of > 60fps
  // (if your platform is syncing flushes and limiting them to 60fps).
  if (!localOwner() || (localOwner()->layoutObject() &&
                        !localOwner()->layoutObject()->needsLayout())) {
    updateStyleAndLayoutTree();

    // Always do a layout after loading if needed.
    if (view() && !layoutViewItem().isNull() &&
        (!layoutViewItem().firstChild() || layoutViewItem().needsLayout()))
      view()->layout();
  }

  m_loadEventProgress = LoadEventCompleted;

  if (frame() && !layoutViewItem().isNull() &&
      settings()->getAccessibilityEnabled()) {
    if (AXObjectCache* cache = axObjectCache()) {
      if (this == &axObjectCacheOwner())
        cache->handleLoadComplete(this);
      else
        cache->handleLayoutComplete(this);
    }
  }

  if (svgExtensions())
    accessSVGExtensions().startAnimations();
}

bool Document::dispatchBeforeUnloadEvent(ChromeClient& chromeClient,
                                         bool isReload,
                                         bool& didAllowNavigation) {
  if (!m_domWindow)
    return true;

  if (!body())
    return true;

  if (processingBeforeUnload())
    return false;

  BeforeUnloadEvent* beforeUnloadEvent = BeforeUnloadEvent::create();
  m_loadEventProgress = BeforeUnloadEventInProgress;
  m_domWindow->dispatchEvent(beforeUnloadEvent, this);
  m_loadEventProgress = BeforeUnloadEventCompleted;
  if (!beforeUnloadEvent->defaultPrevented())
    defaultEventHandler(beforeUnloadEvent);
  if (!frame() || beforeUnloadEvent->returnValue().isNull())
    return true;

  if (didAllowNavigation) {
    addConsoleMessage(ConsoleMessage::create(
        JSMessageSource, ErrorMessageLevel,
        "Blocked attempt to show multiple 'beforeunload' confirmation panels "
        "for a single navigation."));
    return true;
  }

  String text = beforeUnloadEvent->returnValue();
  if (chromeClient.openBeforeUnloadConfirmPanel(text, m_frame, isReload)) {
    didAllowNavigation = true;
    return true;
  }
  return false;
}

void Document::dispatchUnloadEvents() {
  PluginScriptForbiddenScope forbidPluginDestructorScripting;
  if (m_parser)
    m_parser->stopParsing();

  if (m_loadEventProgress == LoadEventNotRun)
    return;

  if (m_loadEventProgress <= UnloadEventInProgress) {
    Element* currentFocusedElement = focusedElement();
    if (isHTMLInputElement(currentFocusedElement))
      toHTMLInputElement(*currentFocusedElement).endEditing();
    if (m_loadEventProgress < PageHideInProgress) {
      m_loadEventProgress = PageHideInProgress;
      if (LocalDOMWindow* window = domWindow())
        window->dispatchEvent(
            PageTransitionEvent::create(EventTypeNames::pagehide, false), this);
      if (!m_frame)
        return;

      PageVisibilityState visibilityState = pageVisibilityState();
      m_loadEventProgress = UnloadVisibilityChangeInProgress;
      if (visibilityState != PageVisibilityStateHidden &&
          RuntimeEnabledFeatures::visibilityChangeOnUnloadEnabled()) {
        // Dispatch visibilitychange event, but don't bother doing
        // other notifications as we're about to be unloaded.
        dispatchEvent(Event::createBubble(EventTypeNames::visibilitychange));
        dispatchEvent(
            Event::createBubble(EventTypeNames::webkitvisibilitychange));
      }
      if (!m_frame)
        return;

      DocumentLoader* documentLoader =
          m_frame->loader().provisionalDocumentLoader();
      m_loadEventProgress = UnloadEventInProgress;
      Event* unloadEvent(Event::create(EventTypeNames::unload));
      if (documentLoader && !documentLoader->timing().unloadEventStart() &&
          !documentLoader->timing().unloadEventEnd()) {
        DocumentLoadTiming& timing = documentLoader->timing();
        DCHECK(timing.navigationStart());
        timing.markUnloadEventStart();
        m_frame->domWindow()->dispatchEvent(unloadEvent, this);
        timing.markUnloadEventEnd();
      } else {
        m_frame->domWindow()->dispatchEvent(unloadEvent, m_frame->document());
      }
    }
    m_loadEventProgress = UnloadEventHandled;
  }

  if (!m_frame)
    return;

  // Don't remove event listeners from a transitional empty document (see
  // https://bugs.webkit.org/show_bug.cgi?id=28716 for more information).
  bool keepEventListeners =
      m_frame->loader().provisionalDocumentLoader() &&
      m_frame->shouldReuseDefaultView(
          m_frame->loader().provisionalDocumentLoader()->url());
  if (!keepEventListeners)
    removeAllEventListenersRecursively();
}

Document::PageDismissalType Document::pageDismissalEventBeingDispatched()
    const {
  switch (m_loadEventProgress) {
    case BeforeUnloadEventInProgress:
      return BeforeUnloadDismissal;
    case PageHideInProgress:
      return PageHideDismissal;
    case UnloadVisibilityChangeInProgress:
      return UnloadVisibilityChangeDismissal;
    case UnloadEventInProgress:
      return UnloadDismissal;

    case LoadEventNotRun:
    case LoadEventInProgress:
    case LoadEventCompleted:
    case BeforeUnloadEventCompleted:
    case UnloadEventHandled:
      return NoDismissal;
  }
  NOTREACHED();
  return NoDismissal;
}

void Document::setParsingState(ParsingState parsingState) {
  m_parsingState = parsingState;

  if (parsing() && !m_elementDataCache)
    m_elementDataCache = ElementDataCache::create();
}

bool Document::shouldScheduleLayout() const {
  // This function will only be called when FrameView thinks a layout is needed.
  // This enforces a couple extra rules.
  //
  //    (a) Only schedule a layout once the stylesheets are loaded.
  //    (b) Only schedule layout once we have a body element.
  if (!isActive())
    return false;

  if (isRenderingReady() && body())
    return true;

  if (documentElement() && !isHTMLHtmlElement(*documentElement()))
    return true;

  return false;
}

int Document::elapsedTime() const {
  return static_cast<int>((currentTime() - m_startTime) * 1000);
}

void Document::write(const SegmentedString& text,
                     Document* enteredDocument,
                     ExceptionState& exceptionState) {
  if (importLoader()) {
    exceptionState.throwDOMException(
        InvalidStateError, "Imported document doesn't support write().");
    return;
  }

  if (!isHTMLDocument()) {
    exceptionState.throwDOMException(InvalidStateError,
                                     "Only HTML documents support write().");
    return;
  }

  if (m_throwOnDynamicMarkupInsertionCount) {
    exceptionState.throwDOMException(
        InvalidStateError,
        "Custom Element constructor should not use write().");
    return;
  }

  if (enteredDocument &&
      !getSecurityOrigin()->canAccess(enteredDocument->getSecurityOrigin())) {
    exceptionState.throwSecurityError(
        "Can only call write() on same-origin documents.");
    return;
  }

  NestingLevelIncrementer nestingLevelIncrementer(m_writeRecursionDepth);

  m_writeRecursionIsTooDeep =
      (m_writeRecursionDepth > 1) && m_writeRecursionIsTooDeep;
  m_writeRecursionIsTooDeep =
      (m_writeRecursionDepth > cMaxWriteRecursionDepth) ||
      m_writeRecursionIsTooDeep;

  if (m_writeRecursionIsTooDeep)
    return;

  bool hasInsertionPoint = m_parser && m_parser->hasInsertionPoint();

  if (!hasInsertionPoint && m_ignoreDestructiveWriteCount) {
    addConsoleMessage(
        ConsoleMessage::create(JSMessageSource, WarningMessageLevel,
                               ExceptionMessages::failedToExecute(
                                   "write", "Document",
                                   "It isn't possible to write into a document "
                                   "from an asynchronously-loaded external "
                                   "script unless it is explicitly opened.")));
    return;
  }

  if (!hasInsertionPoint)
    open(enteredDocument, ASSERT_NO_EXCEPTION);

  DCHECK(m_parser);
  InspectorInstrumentation::NativeBreakpoint nativeBreakpoint(
      this, "document.write", true);
  m_parser->insert(text);
}

void Document::write(const String& text,
                     Document* enteredDocument,
                     ExceptionState& exceptionState) {
  write(SegmentedString(text), enteredDocument, exceptionState);
}

void Document::writeln(const String& text,
                       Document* enteredDocument,
                       ExceptionState& exceptionState) {
  write(text, enteredDocument, exceptionState);
  if (exceptionState.hadException())
    return;
  write("\n", enteredDocument);
}

void Document::write(LocalDOMWindow* callingWindow,
                     const Vector<String>& text,
                     ExceptionState& exceptionState) {
  DCHECK(callingWindow);
  StringBuilder builder;
  for (const String& string : text)
    builder.append(string);
  write(builder.toString(), callingWindow->document(), exceptionState);
}

void Document::writeln(LocalDOMWindow* callingWindow,
                       const Vector<String>& text,
                       ExceptionState& exceptionState) {
  DCHECK(callingWindow);
  StringBuilder builder;
  for (const String& string : text)
    builder.append(string);
  writeln(builder.toString(), callingWindow->document(), exceptionState);
}

const KURL& Document::virtualURL() const {
  return m_url;
}

KURL Document::virtualCompleteURL(const String& url) const {
  return completeURL(url);
}

DOMTimerCoordinator* Document::timers() {
  return &m_timers;
}

EventTarget* Document::errorEventTarget() {
  return domWindow();
}

void Document::exceptionThrown(ErrorEvent* event) {
  MainThreadDebugger::instance()->exceptionThrown(this, event);
}

void Document::setURL(const KURL& url) {
  const KURL& newURL = url.isEmpty() ? blankURL() : url;
  if (newURL == m_url)
    return;

  m_url = newURL;
  m_accessEntryFromURL = nullptr;
  updateBaseURL();
  contextFeatures().urlDidChange(this);
}

KURL Document::validBaseElementURL() const {
  if (m_baseElementURL.isValid())
    return m_baseElementURL;

  return KURL();
}

void Document::updateBaseURL() {
  KURL oldBaseURL = m_baseURL;
  // DOM 3 Core: When the Document supports the feature "HTML" [DOM Level 2
  // HTML], the base URI is computed using first the value of the href attribute
  // of the HTML BASE element if any, and the value of the documentURI attribute
  // from the Document interface otherwise (which we store, preparsed, in
  // m_url).
  if (!m_baseElementURL.isEmpty())
    m_baseURL = m_baseElementURL;
  else if (!m_baseURLOverride.isEmpty())
    m_baseURL = m_baseURLOverride;
  else
    m_baseURL = m_url;

  selectorQueryCache().invalidate();

  if (!m_baseURL.isValid())
    m_baseURL = KURL();

  if (m_elemSheet) {
    // Element sheet is silly. It never contains anything.
    DCHECK(!m_elemSheet->contents()->ruleCount());
    m_elemSheet = CSSStyleSheet::createInline(*this, m_baseURL);
  }

  if (!equalIgnoringFragmentIdentifier(oldBaseURL, m_baseURL)) {
    // Base URL change changes any relative visited links.
    // 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.
    for (HTMLAnchorElement& anchor :
         Traversal<HTMLAnchorElement>::startsAfter(*this))
      anchor.invalidateCachedVisitedLinkHash();
  }
}

void Document::setBaseURLOverride(const KURL& url) {
  m_baseURLOverride = url;
  updateBaseURL();
}

void Document::processBaseElement() {
  // Find the first href attribute in a base element and the first target
  // attribute in a base element.
  const AtomicString* href = 0;
  const AtomicString* target = 0;
  for (HTMLBaseElement* base = Traversal<HTMLBaseElement>::firstWithin(*this);
       base && (!href || !target);
       base = Traversal<HTMLBaseElement>::next(*base)) {
    if (!href) {
      const AtomicString& value = base->fastGetAttribute(hrefAttr);
      if (!value.isNull())
        href = &value;
    }
    if (!target) {
      const AtomicString& value = base->fastGetAttribute(targetAttr);
      if (!value.isNull())
        target = &value;
    }
    if (contentSecurityPolicy()->isActive())
      UseCounter::count(*this,
                        UseCounter::ContentSecurityPolicyWithBaseElement);
  }

  // FIXME: Since this doesn't share code with completeURL it may not handle
  // encodings correctly.
  KURL baseElementURL;
  if (href) {
    String strippedHref = stripLeadingAndTrailingHTMLSpaces(*href);
    if (!strippedHref.isEmpty())
      baseElementURL = KURL(url(), strippedHref);
  }
  if (m_baseElementURL != baseElementURL &&
      contentSecurityPolicy()->allowBaseURI(baseElementURL)) {
    m_baseElementURL = baseElementURL;
    updateBaseURL();
  }

  m_baseTarget = target ? *target : nullAtom;
}

String Document::userAgent() const {
  return frame() ? frame()->loader().userAgent() : String();
}

void Document::disableEval(const String& errorMessage) {
  if (!frame())
    return;

  frame()->script().disableEval(errorMessage);
}

void Document::didLoadAllImports() {
  if (!haveScriptBlockingStylesheetsLoaded())
    return;
  if (!importLoader())
    styleResolverMayHaveChanged();
  didLoadAllScriptBlockingResources();
}

void Document::didRemoveAllPendingStylesheet() {
  styleResolverMayHaveChanged();

  // Only imports on master documents can trigger rendering.
  if (HTMLImportLoader* import = importLoader())
    import->didRemoveAllPendingStylesheet();
  if (!haveImportsLoaded())
    return;
  didLoadAllScriptBlockingResources();
}

void Document::didLoadAllScriptBlockingResources() {
  // Use wrapWeakPersistent because the task should not keep this Document alive
  // just for executing scripts.
  m_executeScriptsWaitingForResourcesTaskHandle =
      TaskRunnerHelper::get(TaskType::Networking, this)
          ->postCancellableTask(
              BLINK_FROM_HERE,
              WTF::bind(&Document::executeScriptsWaitingForResources,
                        wrapWeakPersistent(this)));

  if (isHTMLDocument() && body()) {
    // For HTML if we have no more stylesheets to load and we're past the body
    // tag, we should have something to paint so resume.
    beginLifecycleUpdatesIfRenderingReady();
  } else if (!isHTMLDocument() && documentElement()) {
    // For non-HTML there is no body so resume as soon as the sheets are loaded.
    beginLifecycleUpdatesIfRenderingReady();
  }

  if (m_gotoAnchorNeededAfterStylesheetsLoad && view())
    view()->processUrlFragment(m_url);
}

void Document::executeScriptsWaitingForResources() {
  if (!isScriptExecutionReady())
    return;
  if (ScriptableDocumentParser* parser = scriptableDocumentParser())
    parser->executeScriptsWaitingForResources();
}

CSSStyleSheet& Document::elementSheet() {
  if (!m_elemSheet)
    m_elemSheet = CSSStyleSheet::createInline(*this, m_baseURL);
  return *m_elemSheet;
}

void Document::maybeHandleHttpRefresh(const String& content,
                                      HttpRefreshType httpRefreshType) {
  if (m_isViewSource || !m_frame)
    return;

  double delay;
  String refreshURL;
  if (!parseHTTPRefresh(content, httpRefreshType == HttpRefreshFromMetaTag
                                     ? isHTMLSpace<UChar>
                                     : nullptr,
                        delay, refreshURL))
    return;
  if (refreshURL.isEmpty())
    refreshURL = url().getString();
  else
    refreshURL = completeURL(refreshURL).getString();

  if (protocolIsJavaScript(refreshURL)) {
    String message =
        "Refused to refresh " + m_url.elidedString() + " to a javascript: URL";
    addConsoleMessage(ConsoleMessage::create(SecurityMessageSource,
                                             ErrorMessageLevel, message));
    return;
  }

  if (httpRefreshType == HttpRefreshFromMetaTag &&
      isSandboxed(SandboxAutomaticFeatures)) {
    String message =
        "Refused to execute the redirect specified via '<meta "
        "http-equiv='refresh' content='...'>'. The document is sandboxed, and "
        "the 'allow-scripts' keyword is not set.";
    addConsoleMessage(ConsoleMessage::create(SecurityMessageSource,
                                             ErrorMessageLevel, message));
    return;
  }
  m_frame->navigationScheduler().scheduleRedirect(delay, refreshURL);
}

bool Document::shouldMergeWithLegacyDescription(
    ViewportDescription::Type origin) const {
  return settings() && settings()->getViewportMetaMergeContentQuirk() &&
         m_legacyViewportDescription.isMetaViewportType() &&
         m_legacyViewportDescription.type == origin;
}

void Document::setViewportDescription(
    const ViewportDescription& viewportDescription) {
  if (viewportDescription.isLegacyViewportType()) {
    if (viewportDescription == m_legacyViewportDescription)
      return;
    m_legacyViewportDescription = viewportDescription;
  } else {
    if (viewportDescription == m_viewportDescription)
      return;
    m_viewportDescription = viewportDescription;

    // The UA-defined min-width is considered specifically by Android WebView
    // quirks mode.
    if (!viewportDescription.isSpecifiedByAuthor())
      m_viewportDefaultMinWidth = viewportDescription.minWidth;
  }

  updateViewportDescription();
}

ViewportDescription Document::viewportDescription() const {
  ViewportDescription appliedViewportDescription = m_viewportDescription;
  bool viewportMetaEnabled = settings() && settings()->getViewportMetaEnabled();
  if (m_legacyViewportDescription.type !=
          ViewportDescription::UserAgentStyleSheet &&
      viewportMetaEnabled)
    appliedViewportDescription = m_legacyViewportDescription;
  if (shouldOverrideLegacyDescription(m_viewportDescription.type))
    appliedViewportDescription = m_viewportDescription;

  return appliedViewportDescription;
}

void Document::updateViewportDescription() {
  if (frame() && frame()->isMainFrame()) {
    frameHost()->chromeClient().dispatchViewportPropertiesDidChange(
        viewportDescription());
  }
}

String Document::outgoingReferrer() const {
  if (getSecurityOrigin()->isUnique()) {
    // Return |no-referrer|.
    return String();
  }

  // See http://www.whatwg.org/specs/web-apps/current-work/#fetching-resources
  // for why we walk the parent chain for srcdoc documents.
  const Document* referrerDocument = this;
  if (LocalFrame* frame = m_frame) {
    while (frame->document()->isSrcdocDocument()) {
      // Srcdoc documents must be local within the containing frame.
      frame = toLocalFrame(frame->tree().parent());
      // Srcdoc documents cannot be top-level documents, by definition,
      // because they need to be contained in iframes with the srcdoc.
      DCHECK(frame);
    }
    referrerDocument = frame->document();
  }
  return referrerDocument->m_url.strippedForUseAsReferrer();
}

ReferrerPolicy Document::getReferrerPolicy() const {
  ReferrerPolicy policy = ExecutionContext::getReferrerPolicy();
  // For srcdoc documents without their own policy, walk up the frame
  // tree to find the document that is either not a srcdoc or doesn't
  // have its own policy. This algorithm is defined in
  // https://html.spec.whatwg.org/multipage/browsers.html#set-up-a-browsing-context-environment-settings-object.
  if (!m_frame || policy != ReferrerPolicyDefault || !isSrcdocDocument()) {
    return policy;
  }
  LocalFrame* frame = toLocalFrame(m_frame->tree().parent());
  DCHECK(frame);
  return frame->document()->getReferrerPolicy();
}

MouseEventWithHitTestResults Document::performMouseEventHitTest(
    const HitTestRequest& request,
    const LayoutPoint& documentPoint,
    const PlatformMouseEvent& event) {
  DCHECK(layoutViewItem().isNull() || layoutViewItem().isLayoutView());

  // LayoutView::hitTest causes a layout, and we don't want to hit that until
  // the first layout because until then, there is nothing shown on the screen -
  // the user can't have intentionally clicked on something belonging to this
  // page.  Furthermore, mousemove events before the first layout should not
  // lead to a premature layout() happening, which could show a flash of white.
  // See also the similar code in EventHandler::hitTestResultAtPoint.
  if (layoutViewItem().isNull() || !view() || !view()->didFirstLayout())
    return MouseEventWithHitTestResults(event,
                                        HitTestResult(request, LayoutPoint()));

  HitTestResult result(request, documentPoint);
  layoutViewItem().hitTest(result);

  if (!request.readOnly())
    updateHoverActiveState(request, result.innerElement(), result.scrollbar());

  if (isHTMLCanvasElement(result.innerNode())) {
    PlatformMouseEvent eventWithRegion = event;
    HitTestCanvasResult* hitTestCanvasResult =
        toHTMLCanvasElement(result.innerNode())
            ->getControlAndIdIfHitRegionExists(result.pointInInnerNodeFrame());
    if (hitTestCanvasResult->getControl()) {
      result.setInnerNode(hitTestCanvasResult->getControl());
    }
    eventWithRegion.setRegion(hitTestCanvasResult->getId());
    return MouseEventWithHitTestResults(eventWithRegion, result);
  }

  return MouseEventWithHitTestResults(event, result);
}

// DOM Section 1.1.1
bool Document::childTypeAllowed(NodeType type) const {
  switch (type) {
    case kAttributeNode:
    case kCdataSectionNode:
    case kDocumentFragmentNode:
    case kDocumentNode:
    case kTextNode:
      return false;
    case kCommentNode:
    case kProcessingInstructionNode:
      return true;
    case kDocumentTypeNode:
    case kElementNode:
      // Documents may contain no more than one of each of these.
      // (One Element and one DocumentType.)
      for (Node& c : NodeTraversal::childrenOf(*this)) {
        if (c.getNodeType() == type)
          return false;
      }
      return true;
  }
  return false;
}

bool Document::canAcceptChild(const Node& newChild,
                              const Node* oldChild,
                              ExceptionState& exceptionState) const {
  if (oldChild && oldChild->getNodeType() == newChild.getNodeType())
    return true;

  int numDoctypes = 0;
  int numElements = 0;

  // First, check how many doctypes and elements we have, not counting
  // the child we're about to remove.
  for (Node& child : NodeTraversal::childrenOf(*this)) {
    if (oldChild && *oldChild == child)
      continue;

    switch (child.getNodeType()) {
      case kDocumentTypeNode:
        numDoctypes++;
        break;
      case kElementNode:
        numElements++;
        break;
      default:
        break;
    }
  }

  // Then, see how many doctypes and elements might be added by the new child.
  if (newChild.isDocumentFragment()) {
    for (Node& child :
         NodeTraversal::childrenOf(toDocumentFragment(newChild))) {
      switch (child.getNodeType()) {
        case kAttributeNode:
        case kCdataSectionNode:
        case kDocumentFragmentNode:
        case kDocumentNode:
        case kTextNode:
          exceptionState.throwDOMException(
              HierarchyRequestError,
              "Nodes of type '" + newChild.nodeName() +
                  "' may not be inserted inside nodes of type '#document'.");
          return false;
        case kCommentNode:
        case kProcessingInstructionNode:
          break;
        case kDocumentTypeNode:
          numDoctypes++;
          break;
        case kElementNode:
          numElements++;
          break;
      }
    }
  } else {
    switch (newChild.getNodeType()) {
      case kAttributeNode:
      case kCdataSectionNode:
      case kDocumentFragmentNode:
      case kDocumentNode:
      case kTextNode:
        exceptionState.throwDOMException(
            HierarchyRequestError,
            "Nodes of type '" + newChild.nodeName() +
                "' may not be inserted inside nodes of type '#document'.");
        return false;
      case kCommentNode:
      case kProcessingInstructionNode:
        return true;
      case kDocumentTypeNode:
        numDoctypes++;
        break;
      case kElementNode:
        numElements++;
        break;
    }
  }

  if (numElements > 1 || numDoctypes > 1) {
    exceptionState.throwDOMException(
        HierarchyRequestError,
        String::format("Only one %s on document allowed.",
                       numElements > 1 ? "element" : "doctype"));
    return false;
  }

  return true;
}

Node* Document::cloneNode(bool deep) {
  Document* clone = cloneDocumentWithoutChildren();
  clone->cloneDataFromDocument(*this);
  if (deep)
    cloneChildNodes(clone);
  return clone;
}

Document* Document::cloneDocumentWithoutChildren() {
  DocumentInit init(url());
  if (isXMLDocument()) {
    if (isXHTMLDocument())
      return XMLDocument::createXHTML(
          init.withRegistrationContext(registrationContext()));
    return XMLDocument::create(init);
  }
  return create(init);
}

void Document::cloneDataFromDocument(const Document& other) {
  setCompatibilityMode(other.getCompatibilityMode());
  setEncodingData(other.m_encodingData);
  setContextFeatures(other.contextFeatures());
  setSecurityOrigin(other.getSecurityOrigin()->isolatedCopy());
  setMimeType(other.contentType());
}

bool Document::isSecureContextImpl(
    const SecureContextCheck privilegeContextCheck) const {
  // There may be exceptions for the secure context check defined for certain
  // schemes. The exceptions are applied only to the special scheme and to
  // sandboxed URLs from those origins, but *not* to any children.
  //
  // For example:
  //   <iframe src="http://host">
  //     <iframe src="scheme-has-exception://host"></iframe>
  //     <iframe sandbox src="scheme-has-exception://host"></iframe>
  //   </iframe>
  // both inner iframes pass this check, assuming that the scheme
  // "scheme-has-exception:" is granted an exception.
  //
  // However,
  //   <iframe src="http://host">
  //     <iframe sandbox src="http://host"></iframe>
  //   </iframe>
  // would fail the check (that is, sandbox does not grant an exception itself).
  //
  // Additionally, with
  //   <iframe src="scheme-has-exception://host">
  //     <iframe src="http://host"></iframe>
  //     <iframe sandbox src="http://host"></iframe>
  //   </iframe>
  // both inner iframes would fail the check, even though the outermost iframe
  // passes.
  //
  // In all cases, a frame must be potentially trustworthy in addition to
  // having an exception listed in order for the exception to be granted.
  if (!getSecurityOrigin()->isPotentiallyTrustworthy())
    return false;

  if (SchemeRegistry::schemeShouldBypassSecureContextCheck(
          getSecurityOrigin()->protocol()))
    return true;

  if (privilegeContextCheck == StandardSecureContextCheck) {
    if (!m_frame)
      return true;
    Frame* parent = m_frame->tree().parent();
    while (parent) {
      if (!parent->securityContext()
               ->getSecurityOrigin()
               ->isPotentiallyTrustworthy())
        return false;
      parent = parent->tree().parent();
    }
  }
  return true;
}

StyleSheetList& Document::styleSheets() {
  if (!m_styleSheetList)
    m_styleSheetList = StyleSheetList::create(this);
  return *m_styleSheetList;
}

String Document::preferredStylesheetSet() const {
  return m_styleEngine->preferredStylesheetSetName();
}

String Document::selectedStylesheetSet() const {
  return m_styleEngine->selectedStylesheetSetName();
}

void Document::setSelectedStylesheetSet(const String& aString) {
  styleEngine().setSelectedStylesheetSetName(aString);
}

void Document::evaluateMediaQueryListIfNeeded() {
  if (!m_evaluateMediaQueriesOnStyleRecalc)
    return;
  evaluateMediaQueryList();
  m_evaluateMediaQueriesOnStyleRecalc = false;
}

void Document::evaluateMediaQueryList() {
  if (m_mediaQueryMatcher)
    m_mediaQueryMatcher->mediaFeaturesChanged();
}

void Document::setResizedForViewportUnits() {
  if (m_mediaQueryMatcher)
    m_mediaQueryMatcher->viewportChanged();
  if (!hasViewportUnits())
    return;
  ensureStyleResolver().setResizedForViewportUnits();
  setNeedsStyleRecalcForViewportUnits();
}

void Document::clearResizedForViewportUnits() {
  ensureStyleResolver().clearResizedForViewportUnits();
}

void Document::styleResolverMayHaveChanged() {
  if (hasNodesWithPlaceholderStyle()) {
    setNeedsStyleRecalc(SubtreeStyleChange,
                        StyleChangeReasonForTracing::create(
                            StyleChangeReason::CleanupPlaceholderStyles));
  }

  if (didLayoutWithPendingStylesheets() &&
      !styleEngine().hasPendingScriptBlockingSheets()) {
    // We need to manually repaint because we avoid doing all repaints in layout
    // or style recalc while sheets are still loading to avoid FOUC.
    m_pendingSheetLayout = IgnoreLayoutWithPendingSheets;

    DCHECK(!layoutViewItem().isNull() || importsController());
    if (!layoutViewItem().isNull())
      layoutViewItem().invalidatePaintForViewAndCompositedLayers();
  }
}

void Document::setHoverNode(Node* newHoverNode) {
  m_hoverNode = newHoverNode;
}

void Document::setActiveHoverElement(Element* newActiveElement) {
  if (!newActiveElement) {
    m_activeHoverElement.clear();
    return;
  }

  m_activeHoverElement = newActiveElement;
}

void Document::removeFocusedElementOfSubtree(Node* node,
                                             bool amongChildrenOnly) {
  if (!m_focusedElement)
    return;

  // We can't be focused if we're not in the document.
  if (!node->isConnected())
    return;
  bool contains =
      node->isShadowIncludingInclusiveAncestorOf(m_focusedElement.get());
  if (contains && (m_focusedElement != node || !amongChildrenOnly))
    clearFocusedElement();
}

void Document::hoveredNodeDetached(Element& element) {
  if (!m_hoverNode)
    return;

  m_hoverNode->updateDistribution();
  if (element != m_hoverNode &&
      (!m_hoverNode->isTextNode() ||
       element != FlatTreeTraversal::parent(*m_hoverNode)))
    return;

  m_hoverNode = FlatTreeTraversal::parent(element);
  while (m_hoverNode && !m_hoverNode->layoutObject())
    m_hoverNode = FlatTreeTraversal::parent(*m_hoverNode);

  // If the mouse cursor is not visible, do not clear existing
  // hover effects on the ancestors of |element| and do not invoke
  // new hover effects on any other element.
  if (!page()->isCursorVisible())
    return;

  if (frame())
    frame()->eventHandler().scheduleHoverStateUpdate();
}

void Document::activeChainNodeDetached(Element& element) {
  if (!m_activeHoverElement)
    return;

  if (element != m_activeHoverElement)
    return;

  Node* activeNode = FlatTreeTraversal::parent(element);
  while (activeNode && activeNode->isElementNode() &&
         !activeNode->layoutObject())
    activeNode = FlatTreeTraversal::parent(*activeNode);

  m_activeHoverElement = activeNode && activeNode->isElementNode()
                             ? toElement(activeNode)
                             : nullptr;
}

const Vector<AnnotatedRegionValue>& Document::annotatedRegions() const {
  return m_annotatedRegions;
}

void Document::setAnnotatedRegions(
    const Vector<AnnotatedRegionValue>& regions) {
  m_annotatedRegions = regions;
  setAnnotatedRegionsDirty(false);
}

bool Document::setFocusedElement(Element* prpNewFocusedElement,
                                 const FocusParams& params) {
  DCHECK(!m_lifecycle.inDetach());

  m_clearFocusedElementTimer.stop();

  Element* newFocusedElement = prpNewFocusedElement;

  // Make sure newFocusedNode is actually in this document
  if (newFocusedElement && (newFocusedElement->document() != this))
    return true;

  if (NodeChildRemovalTracker::isBeingRemoved(newFocusedElement))
    return true;

  if (m_focusedElement == newFocusedElement)
    return true;

  bool focusChangeBlocked = false;
  Element* oldFocusedElement = m_focusedElement;
  m_focusedElement = nullptr;

  // Remove focus from the existing focus node (if any)
  if (oldFocusedElement) {
    oldFocusedElement->setFocused(false);

    // Dispatch the blur event and let the node do any other blur related
    // activities (important for text fields)
    // If page lost focus, blur event will have already been dispatched
    if (page() && (page()->focusController().isFocused())) {
      oldFocusedElement->dispatchBlurEvent(newFocusedElement, params.type,
                                           params.sourceCapabilities);

      if (m_focusedElement) {
        // handler shifted focus
        focusChangeBlocked = true;
        newFocusedElement = nullptr;
      }

      // 'focusout' is a DOM level 3 name for the bubbling blur event.
      oldFocusedElement->dispatchFocusOutEvent(EventTypeNames::focusout,
                                               newFocusedElement,
                                               params.sourceCapabilities);
      // 'DOMFocusOut' is a DOM level 2 name for compatibility.
      // FIXME: We should remove firing DOMFocusOutEvent event when we are sure
      // no content depends on it, probably when <rdar://problem/8503958> is
      // resolved.
      oldFocusedElement->dispatchFocusOutEvent(EventTypeNames::DOMFocusOut,
                                               newFocusedElement,
                                               params.sourceCapabilities);

      if (m_focusedElement) {
        // handler shifted focus
        focusChangeBlocked = true;
        newFocusedElement = nullptr;
      }
    }

    if (view()) {
      Widget* oldWidget = widgetForElement(*oldFocusedElement);
      if (oldWidget)
        oldWidget->setFocused(false, params.type);
      else
        view()->setFocused(false, params.type);
    }
  }

  if (newFocusedElement)
    updateStyleAndLayoutTreeForNode(newFocusedElement);
  if (newFocusedElement && newFocusedElement->isFocusable()) {
    if (isRootEditableElement(*newFocusedElement) &&
        !acceptsEditingFocus(*newFocusedElement)) {
      // delegate blocks focus change
      focusChangeBlocked = true;
      goto SetFocusedElementDone;
    }
    // Set focus on the new node
    m_focusedElement = newFocusedElement;
    setSequentialFocusNavigationStartingPoint(m_focusedElement.get());

    m_focusedElement->setFocused(true);
    // Element::setFocused for frames can dispatch events.
    if (m_focusedElement != newFocusedElement) {
      focusChangeBlocked = true;
      goto SetFocusedElementDone;
    }
    cancelFocusAppearanceUpdate();
    m_focusedElement->updateFocusAppearance(params.selectionBehavior);

    // Dispatch the focus event and let the node do any other focus related
    // activities (important for text fields)
    // If page lost focus, event will be dispatched on page focus, don't
    // duplicate
    if (page() && (page()->focusController().isFocused())) {
      m_focusedElement->dispatchFocusEvent(oldFocusedElement, params.type,
                                           params.sourceCapabilities);

      if (m_focusedElement != newFocusedElement) {
        // handler shifted focus
        focusChangeBlocked = true;
        goto SetFocusedElementDone;
      }
      // DOM level 3 bubbling focus event.
      m_focusedElement->dispatchFocusInEvent(EventTypeNames::focusin,
                                             oldFocusedElement, params.type,
                                             params.sourceCapabilities);

      if (m_focusedElement != newFocusedElement) {
        // handler shifted focus
        focusChangeBlocked = true;
        goto SetFocusedElementDone;
      }

      // For DOM level 2 compatibility.
      // FIXME: We should remove firing DOMFocusInEvent event when we are sure
      // no content depends on it, probably when <rdar://problem/8503958> is m.
      m_focusedElement->dispatchFocusInEvent(EventTypeNames::DOMFocusIn,
                                             oldFocusedElement, params.type,
                                             params.sourceCapabilities);

      if (m_focusedElement != newFocusedElement) {
        // handler shifted focus
        focusChangeBlocked = true;
        goto SetFocusedElementDone;
      }
    }

    if (isRootEditableElement(*m_focusedElement))
      frame()->spellChecker().didBeginEditing(m_focusedElement.get());

    // eww, I suck. set the qt focus correctly
    // ### find a better place in the code for this
    if (view()) {
      Widget* focusWidget = widgetForElement(*m_focusedElement);
      if (focusWidget) {
        // Make sure a widget has the right size before giving it focus.
        // Otherwise, we are testing edge cases of the Widget code.
        // Specifically, in WebCore this does not work well for text fields.
        updateStyleAndLayout();
        // Re-get the widget in case updating the layout changed things.
        focusWidget = widgetForElement(*m_focusedElement);
      }
      if (focusWidget)
        focusWidget->setFocused(true, params.type);
      else
        view()->setFocused(true, params.type);
    }
  }

  if (!focusChangeBlocked && m_focusedElement) {
    // Create the AXObject cache in a focus change because Chromium relies on
    // it.
    if (AXObjectCache* cache = axObjectCache())
      cache->handleFocusedUIElementChanged(oldFocusedElement,
                                           newFocusedElement);
  }

  if (!focusChangeBlocked && frameHost())
    frameHost()->chromeClient().focusedNodeChanged(oldFocusedElement,
                                                   m_focusedElement.get());

SetFocusedElementDone:
  updateStyleAndLayoutTree();
  if (LocalFrame* frame = this->frame())
    frame->selection().didChangeFocus();
  return !focusChangeBlocked;
}

void Document::clearFocusedElement() {
  setFocusedElement(nullptr, FocusParams(SelectionBehaviorOnFocus::None,
                                         WebFocusTypeNone, nullptr));
}

void Document::setSequentialFocusNavigationStartingPoint(Node* node) {
  if (!m_frame)
    return;
  if (!node) {
    m_sequentialFocusNavigationStartingPoint = nullptr;
    return;
  }
  DCHECK_EQ(node->document(), this);
  if (!m_sequentialFocusNavigationStartingPoint)
    m_sequentialFocusNavigationStartingPoint = Range::create(*this);
  m_sequentialFocusNavigationStartingPoint->selectNodeContents(
      node, ASSERT_NO_EXCEPTION);
}

Element* Document::sequentialFocusNavigationStartingPoint(
    WebFocusType type) const {
  if (m_focusedElement)
    return m_focusedElement.get();
  if (!m_sequentialFocusNavigationStartingPoint)
    return nullptr;
  if (!m_sequentialFocusNavigationStartingPoint->collapsed()) {
    Node* node = m_sequentialFocusNavigationStartingPoint->startContainer();
    DCHECK_EQ(node, m_sequentialFocusNavigationStartingPoint->endContainer());
    if (node->isElementNode())
      return toElement(node);
    if (Element* neighborElement = type == WebFocusTypeForward
                                       ? ElementTraversal::previous(*node)
                                       : ElementTraversal::next(*node))
      return neighborElement;
    return node->parentOrShadowHostElement();
  }

  // Range::selectNodeContents didn't select contents because the element had
  // no children.
  if (m_sequentialFocusNavigationStartingPoint->startContainer()
          ->isElementNode() &&
      !m_sequentialFocusNavigationStartingPoint->startContainer()
           ->hasChildren() &&
      m_sequentialFocusNavigationStartingPoint->startOffset() == 0)
    return toElement(
        m_sequentialFocusNavigationStartingPoint->startContainer());

  // A node selected by Range::selectNodeContents was removed from the
  // document tree.
  if (Node* nextNode = m_sequentialFocusNavigationStartingPoint->firstNode()) {
    if (type == WebFocusTypeForward)
      return ElementTraversal::previous(*nextNode);
    if (nextNode->isElementNode())
      return toElement(nextNode);
    return ElementTraversal::next(*nextNode);
  }
  return nullptr;
}

void Document::setCSSTarget(Element* newTarget) {
  if (m_cssTarget)
    m_cssTarget->pseudoStateChanged(CSSSelector::PseudoTarget);
  m_cssTarget = newTarget;
  if (m_cssTarget)
    m_cssTarget->pseudoStateChanged(CSSSelector::PseudoTarget);
}

static void liveNodeListBaseWriteBarrier(void* parent,
                                         const LiveNodeListBase* list) {
  if (isHTMLCollectionType(list->type())) {
    ScriptWrappableVisitor::writeBarrier(
        parent, static_cast<const HTMLCollection*>(list));
  } else {
    ScriptWrappableVisitor::writeBarrier(
        parent, static_cast<const LiveNodeList*>(list));
  }
}

void Document::registerNodeList(const LiveNodeListBase* list) {
  DCHECK(!m_nodeLists[list->invalidationType()].contains(list));
  m_nodeLists[list->invalidationType()].add(list);
  liveNodeListBaseWriteBarrier(this, list);
  if (list->isRootedAtTreeScope())
    m_listsInvalidatedAtDocument.add(list);
}

void Document::unregisterNodeList(const LiveNodeListBase* list) {
  DCHECK(m_nodeLists[list->invalidationType()].contains(list));
  m_nodeLists[list->invalidationType()].remove(list);
  if (list->isRootedAtTreeScope()) {
    DCHECK(m_listsInvalidatedAtDocument.contains(list));
    m_listsInvalidatedAtDocument.remove(list);
  }
}

void Document::registerNodeListWithIdNameCache(const LiveNodeListBase* list) {
  DCHECK(!m_nodeLists[InvalidateOnIdNameAttrChange].contains(list));
  m_nodeLists[InvalidateOnIdNameAttrChange].add(list);
  liveNodeListBaseWriteBarrier(this, list);
}

void Document::unregisterNodeListWithIdNameCache(const LiveNodeListBase* list) {
  DCHECK(m_nodeLists[InvalidateOnIdNameAttrChange].contains(list));
  m_nodeLists[InvalidateOnIdNameAttrChange].remove(list);
}

void Document::attachNodeIterator(NodeIterator* ni) {
  m_nodeIterators.add(ni);
}

void Document::detachNodeIterator(NodeIterator* ni) {
  // The node iterator can be detached without having been attached if its root
  // node didn't have a document when the iterator was created, but has it now.
  m_nodeIterators.remove(ni);
}

void Document::moveNodeIteratorsToNewDocument(Node& node,
                                              Document& newDocument) {
  HeapHashSet<WeakMember<NodeIterator>> nodeIteratorsList = m_nodeIterators;
  for (NodeIterator* ni : nodeIteratorsList) {
    if (ni->root() == node) {
      detachNodeIterator(ni);
      newDocument.attachNodeIterator(ni);
    }
  }
}

void Document::didMoveTreeToNewDocument(const Node& root) {
  DCHECK_NE(root.document(), this);
  if (m_ranges.isEmpty())
    return;

  AttachedRangeSet ranges = m_ranges;
  for (Range* range : ranges)
    range->updateOwnerDocumentIfNeeded();
}

void Document::nodeChildrenWillBeRemoved(ContainerNode& container) {
  EventDispatchForbiddenScope assertNoEventDispatch;
  for (Range* range : m_ranges)
    range->nodeChildrenWillBeRemoved(container);

  for (NodeIterator* ni : m_nodeIterators) {
    for (Node& n : NodeTraversal::childrenOf(container))
      ni->nodeWillBeRemoved(n);
  }

  notifyNodeChildrenWillBeRemoved(container);
  if (LocalFrame* frame = this->frame())
    frame->selection().nodeChildrenWillBeRemoved(container);

  if (containsV1ShadowTree()) {
    for (Node& n : NodeTraversal::childrenOf(container))
      n.checkSlotChangeBeforeRemoved();
  }
}

void Document::nodeWillBeRemoved(Node& n) {
  for (NodeIterator* ni : m_nodeIterators)
    ni->nodeWillBeRemoved(n);

  for (Range* range : m_ranges)
    range->nodeWillBeRemoved(n);

  notifyNodeWillBeRemoved(n);

  if (LocalFrame* frame = this->frame()) {
    frame->selection().nodeWillBeRemoved(n);
  }

  if (containsV1ShadowTree())
    n.checkSlotChangeBeforeRemoved();

  if (n.inActiveDocument() && n.isElementNode())
    styleEngine().elementWillBeRemoved(toElement(n));
}

void Document::dataWillChange(const CharacterData& characterData) {
  if (LocalFrame* frame = this->frame())
    frame->selection().dataWillChange(characterData);
}

void Document::didInsertText(Node* text, unsigned offset, unsigned length) {
  for (Range* range : m_ranges)
    range->didInsertText(text, offset, length);

  m_markers->shiftMarkers(text, offset, length);
}

void Document::didRemoveText(Node* text, unsigned offset, unsigned length) {
  for (Range* range : m_ranges)
    range->didRemoveText(text, offset, length);

  m_markers->removeMarkers(text, offset, length);
  m_markers->shiftMarkers(text, offset + length, 0 - length);
}

void Document::didMergeTextNodes(Text& oldNode, unsigned offset) {
  if (!m_ranges.isEmpty()) {
    NodeWithIndex oldNodeWithIndex(oldNode);
    for (Range* range : m_ranges)
      range->didMergeTextNodes(oldNodeWithIndex, offset);
  }

  notifyMergeTextNodes(oldNode, offset);
  if (m_frame)
    m_frame->selection().didMergeTextNodes(oldNode, offset);

  // FIXME: This should update markers for spelling and grammar checking.
}

void Document::didSplitTextNode(const Text& oldNode) {
  for (Range* range : m_ranges)
    range->didSplitTextNode(oldNode);

  notifySplitTextNode(oldNode);
  if (m_frame)
    m_frame->selection().didSplitTextNode(oldNode);

  // FIXME: This should update markers for spelling and grammar checking.
}

void Document::setWindowAttributeEventListener(const AtomicString& eventType,
                                               EventListener* listener) {
  LocalDOMWindow* domWindow = this->domWindow();
  if (!domWindow)
    return;
  domWindow->setAttributeEventListener(eventType, listener);
}

EventListener* Document::getWindowAttributeEventListener(
    const AtomicString& eventType) {
  LocalDOMWindow* domWindow = this->domWindow();
  if (!domWindow)
    return 0;
  return domWindow->getAttributeEventListener(eventType);
}

EventQueue* Document::getEventQueue() const {
  if (!m_domWindow)
    return 0;
  return m_domWindow->getEventQueue();
}

void Document::enqueueAnimationFrameTask(std::unique_ptr<WTF::Closure> task) {
  ensureScriptedAnimationController().enqueueTask(std::move(task));
}

void Document::enqueueAnimationFrameEvent(Event* event) {
  ensureScriptedAnimationController().enqueueEvent(event);
}

void Document::enqueueUniqueAnimationFrameEvent(Event* event) {
  ensureScriptedAnimationController().enqueuePerFrameEvent(event);
}

void Document::enqueueScrollEventForNode(Node* target) {
  // Per the W3C CSSOM View Module only scroll events fired at the document
  // should bubble.
  Event* scrollEvent = target->isDocumentNode()
                           ? Event::createBubble(EventTypeNames::scroll)
                           : Event::create(EventTypeNames::scroll);
  scrollEvent->setTarget(target);
  ensureScriptedAnimationController().enqueuePerFrameEvent(scrollEvent);
}

void Document::enqueueResizeEvent() {
  Event* event = Event::create(EventTypeNames::resize);
  event->setTarget(domWindow());
  ensureScriptedAnimationController().enqueuePerFrameEvent(event);
}

void Document::enqueueMediaQueryChangeListeners(
    HeapVector<Member<MediaQueryListListener>>& listeners) {
  ensureScriptedAnimationController().enqueueMediaQueryChangeListeners(
      listeners);
}

void Document::enqueueVisualViewportScrollEvent() {
  VisualViewportScrollEvent* event = VisualViewportScrollEvent::create();
  event->setTarget(domWindow()->visualViewport());
  ensureScriptedAnimationController().enqueuePerFrameEvent(event);
}

void Document::enqueueVisualViewportResizeEvent() {
  VisualViewportResizeEvent* event = VisualViewportResizeEvent::create();
  event->setTarget(domWindow()->visualViewport());
  ensureScriptedAnimationController().enqueuePerFrameEvent(event);
}

void Document::dispatchEventsForPrinting() {
  if (!m_scriptedAnimationController)
    return;
  m_scriptedAnimationController->dispatchEventsAndCallbacksForPrinting();
}

Document::EventFactorySet& Document::eventFactories() {
  DEFINE_STATIC_LOCAL(EventFactorySet, s_eventFactory, ());
  return s_eventFactory;
}

const OriginAccessEntry& Document::accessEntryFromURL() {
  if (!m_accessEntryFromURL) {
    m_accessEntryFromURL = WTF::wrapUnique(
        new OriginAccessEntry(url().protocol(), url().host(),
                              OriginAccessEntry::AllowRegisterableDomains));
  }
  return *m_accessEntryFromURL;
}

void Document::sendSensitiveInputVisibility() {
  if (m_sensitiveInputVisibilityTask.isActive())
    return;

  m_sensitiveInputVisibilityTask =
      TaskRunnerHelper::get(TaskType::UnspecedLoading, this)
          ->postCancellableTask(
              BLINK_FROM_HERE,
              WTF::bind(&Document::sendSensitiveInputVisibilityInternal,
                        wrapWeakPersistent(this)));
}

void Document::sendSensitiveInputVisibilityInternal() {
  if (!frame())
    return;

  mojom::blink::SensitiveInputVisibilityServicePtr sensitiveInputServicePtr;
  frame()->interfaceProvider()->getInterface(
      mojo::MakeRequest(&sensitiveInputServicePtr));
  if (m_passwordCount > 0) {
    sensitiveInputServicePtr->PasswordFieldVisibleInInsecureContext();
    return;
  }
  sensitiveInputServicePtr->AllPasswordFieldsInInsecureContextInvisible();
}

void Document::runExecutionContextTask(
    std::unique_ptr<ExecutionContextTask> task,
    bool isInstrumented) {
  InspectorInstrumentation::AsyncTask asyncTask(this, task.get(),
                                                isInstrumented);
  task->performTask(this);
}

void Document::registerEventFactory(
    std::unique_ptr<EventFactoryBase> eventFactory) {
  DCHECK(!eventFactories().contains(eventFactory.get()));
  eventFactories().add(std::move(eventFactory));
}

Event* Document::createEvent(ExecutionContext* executionContext,
                             const String& eventType,
                             ExceptionState& exceptionState) {
  Event* event = nullptr;
  for (const auto& factory : eventFactories()) {
    event = factory->create(executionContext, eventType);
    if (event)
      return event;
  }
  exceptionState.throwDOMException(
      NotSupportedError,
      "The provided event type ('" + eventType + "') is invalid.");
  return nullptr;
}

void Document::addMutationEventListenerTypeIfEnabled(
    ListenerType listenerType) {
  if (ContextFeatures::mutationEventsEnabled(this))
    addListenerType(listenerType);
}

void Document::addListenerTypeIfNeeded(const AtomicString& eventType) {
  if (eventType == EventTypeNames::DOMSubtreeModified) {
    UseCounter::count(*this, UseCounter::DOMSubtreeModifiedEvent);
    addMutationEventListenerTypeIfEnabled(DOMSUBTREEMODIFIED_LISTENER);
  } else if (eventType == EventTypeNames::DOMNodeInserted) {
    UseCounter::count(*this, UseCounter::DOMNodeInsertedEvent);
    addMutationEventListenerTypeIfEnabled(DOMNODEINSERTED_LISTENER);
  } else if (eventType == EventTypeNames::DOMNodeRemoved) {
    UseCounter::count(*this, UseCounter::DOMNodeRemovedEvent);
    addMutationEventListenerTypeIfEnabled(DOMNODEREMOVED_LISTENER);
  } else if (eventType == EventTypeNames::DOMNodeRemovedFromDocument) {
    UseCounter::count(*this, UseCounter::DOMNodeRemovedFromDocumentEvent);
    addMutationEventListenerTypeIfEnabled(DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
  } else if (eventType == EventTypeNames::DOMNodeInsertedIntoDocument) {
    UseCounter::count(*this, UseCounter::DOMNodeInsertedIntoDocumentEvent);
    addMutationEventListenerTypeIfEnabled(DOMNODEINSERTEDINTODOCUMENT_LISTENER);
  } else if (eventType == EventTypeNames::DOMCharacterDataModified) {
    UseCounter::count(*this, UseCounter::DOMCharacterDataModifiedEvent);
    addMutationEventListenerTypeIfEnabled(DOMCHARACTERDATAMODIFIED_LISTENER);
  } else if (eventType == EventTypeNames::webkitAnimationStart ||
             eventType == EventTypeNames::animationstart) {
    addListenerType(ANIMATIONSTART_LISTENER);
  } else if (eventType == EventTypeNames::webkitAnimationEnd ||
             eventType == EventTypeNames::animationend) {
    addListenerType(ANIMATIONEND_LISTENER);
  } else if (eventType == EventTypeNames::webkitAnimationIteration ||
             eventType == EventTypeNames::animationiteration) {
    addListenerType(ANIMATIONITERATION_LISTENER);
    if (view()) {
      // Need to re-evaluate time-to-effect-change for any running animations.
      view()->scheduleAnimation();
    }
  } else if (eventType == EventTypeNames::webkitTransitionEnd ||
             eventType == EventTypeNames::transitionend) {
    addListenerType(TRANSITIONEND_LISTENER);
  } else if (eventType == EventTypeNames::scroll) {
    addListenerType(SCROLL_LISTENER);
  }
}

HTMLFrameOwnerElement* Document::localOwner() const {
  if (!frame())
    return 0;
  // FIXME: This probably breaks the attempts to layout after a load is finished
  // in implicitClose(), and probably tons of other things...
  return frame()->deprecatedLocalOwner();
}

void Document::willChangeFrameOwnerProperties(int marginWidth,
                                              int marginHeight,
                                              ScrollbarMode scrollingMode) {
  if (!body())
    return;

  DCHECK(frame() && frame()->owner());
  FrameOwner* owner = frame()->owner();

  if (marginWidth != owner->marginWidth())
    body()->setIntegralAttribute(marginwidthAttr, marginWidth);
  if (marginHeight != owner->marginHeight())
    body()->setIntegralAttribute(marginheightAttr, marginHeight);
  if (scrollingMode != owner->scrollingMode() && view())
    view()->setNeedsLayout();
}

bool Document::isInInvisibleSubframe() const {
  if (!localOwner())
    return false;  // this is a local root element

  // TODO(bokan): This looks like it doesn't work in OOPIF.
  DCHECK(frame());
  return frame()->ownerLayoutItem().isNull();
}

String Document::cookie(ExceptionState& exceptionState) const {
  if (settings() && !settings()->getCookieEnabled())
    return String();

  // FIXME: The HTML5 DOM spec states that this attribute can raise an
  // InvalidStateError exception on getting if the Document has no
  // browsing context.

  if (!getSecurityOrigin()->canAccessCookies()) {
    if (isSandboxed(SandboxOrigin))
      exceptionState.throwSecurityError(
          "The document is sandboxed and lacks the 'allow-same-origin' flag.");
    else if (url().protocolIs("data"))
      exceptionState.throwSecurityError(
          "Cookies are disabled inside 'data:' URLs.");
    else
      exceptionState.throwSecurityError("Access is denied for this document.");
    return String();
  }

  // Suborigins are cookie-averse and thus should always return the empty
  // string, unless the 'unsafe-cookies' option is provided.
  if (getSecurityOrigin()->hasSuborigin() &&
      !getSecurityOrigin()->suborigin()->policyContains(
          Suborigin::SuboriginPolicyOptions::UnsafeCookies))
    return String();

  KURL cookieURL = this->cookieURL();
  if (cookieURL.isEmpty())
    return String();

  return cookies(this, cookieURL);
}

void Document::setCookie(const String& value, ExceptionState& exceptionState) {
  if (settings() && !settings()->getCookieEnabled())
    return;

  // FIXME: The HTML5 DOM spec states that this attribute can raise an
  // InvalidStateError exception on setting if the Document has no
  // browsing context.

  if (!getSecurityOrigin()->canAccessCookies()) {
    if (isSandboxed(SandboxOrigin))
      exceptionState.throwSecurityError(
          "The document is sandboxed and lacks the 'allow-same-origin' flag.");
    else if (url().protocolIs("data"))
      exceptionState.throwSecurityError(
          "Cookies are disabled inside 'data:' URLs.");
    else
      exceptionState.throwSecurityError("Access is denied for this document.");
    return;
  }

  // Suborigins are cookie-averse and thus setting should be a no-op, unless
  // the 'unsafe-cookies' option is provided.
  if (getSecurityOrigin()->hasSuborigin() &&
      !getSecurityOrigin()->suborigin()->policyContains(
          Suborigin::SuboriginPolicyOptions::UnsafeCookies))
    return;

  KURL cookieURL = this->cookieURL();
  if (cookieURL.isEmpty())
    return;

  setCookies(this, cookieURL, value);
}

const AtomicString& Document::referrer() const {
  if (loader())
    return loader()->getRequest().httpReferrer();
  return nullAtom;
}

String Document::domain() const {
  return getSecurityOrigin()->domain();
}

void Document::setDomain(const String& rawDomain,
                         ExceptionState& exceptionState) {
  UseCounter::count(*this, UseCounter::DocumentSetDomain);

  if (isSandboxed(SandboxDocumentDomain)) {
    exceptionState.throwSecurityError(
        "Assignment is forbidden for sandboxed iframes.");
    return;
  }

  if (SchemeRegistry::isDomainRelaxationForbiddenForURLScheme(
          getSecurityOrigin()->protocol())) {
    exceptionState.throwSecurityError("Assignment is forbidden for the '" +
                                      getSecurityOrigin()->protocol() +
                                      "' scheme.");
    return;
  }

  bool success = false;
  String newDomain = SecurityOrigin::canonicalizeHost(rawDomain, &success);
  if (!success) {
    exceptionState.throwSecurityError("'" + rawDomain +
                                      "' could not be parsed properly.");
    return;
  }

  if (newDomain.isEmpty()) {
    exceptionState.throwSecurityError("'" + newDomain +
                                      "' is an empty domain.");
    return;
  }

  OriginAccessEntry accessEntry(getSecurityOrigin()->protocol(), newDomain,
                                OriginAccessEntry::AllowSubdomains);
  OriginAccessEntry::MatchResult result =
      accessEntry.matchesOrigin(*getSecurityOrigin());
  if (result == OriginAccessEntry::DoesNotMatchOrigin) {
    exceptionState.throwSecurityError(
        "'" + newDomain + "' is not a suffix of '" + domain() + "'.");
    return;
  }

  if (result == OriginAccessEntry::MatchesOriginButIsPublicSuffix) {
    exceptionState.throwSecurityError("'" + newDomain +
                                      "' is a top-level domain.");
    return;
  }

  getSecurityOrigin()->setDomainFromDOM(newDomain);
  if (m_frame)
    m_frame->script().updateSecurityOrigin(getSecurityOrigin());
}

// http://www.whatwg.org/specs/web-apps/current-work/#dom-document-lastmodified
String Document::lastModified() const {
  DateComponents date;
  bool foundDate = false;
  if (m_frame) {
    if (DocumentLoader* documentLoader = loader()) {
      const AtomicString& httpLastModified =
          documentLoader->response().httpHeaderField(HTTPNames::Last_Modified);
      if (!httpLastModified.isEmpty()) {
        date.setMillisecondsSinceEpochForDateTime(
            convertToLocalTime(parseDate(httpLastModified)));
        foundDate = true;
      }
    }
  }
  // FIXME: If this document came from the file system, the HTML5
  // specificiation tells us to read the last modification date from the file
  // system.
  if (!foundDate)
    date.setMillisecondsSinceEpochForDateTime(
        convertToLocalTime(currentTimeMS()));
  return String::format("%02d/%02d/%04d %02d:%02d:%02d", date.month() + 1,
                        date.monthDay(), date.fullYear(), date.hour(),
                        date.minute(), date.second());
}

const KURL Document::firstPartyForCookies() const {
  // TODO(mkwst): This doesn't properly handle HTML Import documents.

  // If this is an imported document, grab its master document's first-party:
  if (importsController() && importsController()->master() &&
      importsController()->master() != this)
    return importsController()->master()->firstPartyForCookies();

  if (!frame())
    return SecurityOrigin::urlWithUniqueSecurityOrigin();

  // TODO(mkwst): This doesn't correctly handle sandboxed documents; we want to
  // look at their URL, but we can't because we don't know what it is.
  Frame* top = frame()->tree().top();
  KURL topDocumentURL =
      top->isLocalFrame()
          ? toLocalFrame(top)->document()->url()
          : KURL(KURL(),
                 top->securityContext()->getSecurityOrigin()->toString());
  if (SchemeRegistry::shouldTreatURLSchemeAsFirstPartyWhenTopLevel(
          topDocumentURL.protocol()))
    return topDocumentURL;

  // We're intentionally using the URL of each document rather than the
  // document's SecurityOrigin.  Sandboxing a document into a unique origin
  // shouldn't effect first-/third-party status for cookies and site data.
  const OriginAccessEntry& accessEntry =
      top->isLocalFrame()
          ? toLocalFrame(top)->document()->accessEntryFromURL()
          : OriginAccessEntry(topDocumentURL.protocol(), topDocumentURL.host(),
                              OriginAccessEntry::AllowRegisterableDomains);
  const Frame* currentFrame = frame();
  while (currentFrame) {
    // Skip over srcdoc documents, as they are always same-origin with their
    // closest non-srcdoc parent.
    while (currentFrame->isLocalFrame() &&
           toLocalFrame(currentFrame)->document()->isSrcdocDocument())
      currentFrame = currentFrame->tree().parent();
    DCHECK(currentFrame);

    // We use 'matchesDomain' here, as it turns out that some folks embed HTTPS
    // login forms
    // into HTTP pages; we should allow this kind of upgrade.
    if (accessEntry.matchesDomain(
            *currentFrame->securityContext()->getSecurityOrigin()) ==
        OriginAccessEntry::DoesNotMatchOrigin)
      return SecurityOrigin::urlWithUniqueSecurityOrigin();

    currentFrame = currentFrame->tree().parent();
  }

  return topDocumentURL;
}

static bool isValidNameNonASCII(const LChar* characters, unsigned length) {
  if (!isValidNameStart(characters[0]))
    return false;

  for (unsigned i = 1; i < length; ++i) {
    if (!isValidNamePart(characters[i]))
      return false;
  }

  return true;
}

static bool isValidNameNonASCII(const UChar* characters, unsigned length) {
  for (unsigned i = 0; i < length;) {
    bool first = i == 0;
    UChar32 c;
    U16_NEXT(characters, i, length, c);  // Increments i.
    if (first ? !isValidNameStart(c) : !isValidNamePart(c))
      return false;
  }

  return true;
}

template <typename CharType>
static inline bool isValidNameASCII(const CharType* characters,
                                    unsigned length) {
  CharType c = characters[0];
  if (!(isASCIIAlpha(c) || c == ':' || c == '_'))
    return false;

  for (unsigned i = 1; i < length; ++i) {
    c = characters[i];
    if (!(isASCIIAlphanumeric(c) || c == ':' || c == '_' || c == '-' ||
          c == '.'))
      return false;
  }

  return true;
}

bool Document::isValidName(const String& name) {
  unsigned length = name.length();
  if (!length)
    return false;

  if (name.is8Bit()) {
    const LChar* characters = name.characters8();

    if (isValidNameASCII(characters, length))
      return true;

    return isValidNameNonASCII(characters, length);
  }

  const UChar* characters = name.characters16();

  if (isValidNameASCII(characters, length))
    return true;

  return isValidNameNonASCII(characters, length);
}

enum QualifiedNameStatus {
  QNValid,
  QNMultipleColons,
  QNInvalidStartChar,
  QNInvalidChar,
  QNEmptyPrefix,
  QNEmptyLocalName
};

struct ParseQualifiedNameResult {
  QualifiedNameStatus status;
  UChar32 character;
  ParseQualifiedNameResult() {}
  explicit ParseQualifiedNameResult(QualifiedNameStatus status)
      : status(status) {}
  ParseQualifiedNameResult(QualifiedNameStatus status, UChar32 character)
      : status(status), character(character) {}
};

template <typename CharType>
static ParseQualifiedNameResult parseQualifiedNameInternal(
    const AtomicString& qualifiedName,
    const CharType* characters,
    unsigned length,
    AtomicString& prefix,
    AtomicString& localName) {
  bool nameStart = true;
  bool sawColon = false;
  int colonPos = 0;

  for (unsigned i = 0; i < length;) {
    UChar32 c;
    U16_NEXT(characters, i, length, c)
    if (c == ':') {
      if (sawColon)
        return ParseQualifiedNameResult(QNMultipleColons);
      nameStart = true;
      sawColon = true;
      colonPos = i - 1;
    } else if (nameStart) {
      if (!isValidNameStart(c))
        return ParseQualifiedNameResult(QNInvalidStartChar, c);
      nameStart = false;
    } else {
      if (!isValidNamePart(c))
        return ParseQualifiedNameResult(QNInvalidChar, c);
    }
  }

  if (!sawColon) {
    prefix = nullAtom;
    localName = qualifiedName;
  } else {
    prefix = AtomicString(characters, colonPos);
    if (prefix.isEmpty())
      return ParseQualifiedNameResult(QNEmptyPrefix);
    int prefixStart = colonPos + 1;
    localName = AtomicString(characters + prefixStart, length - prefixStart);
  }

  if (localName.isEmpty())
    return ParseQualifiedNameResult(QNEmptyLocalName);

  return ParseQualifiedNameResult(QNValid);
}

bool Document::parseQualifiedName(const AtomicString& qualifiedName,
                                  AtomicString& prefix,
                                  AtomicString& localName,
                                  ExceptionState& exceptionState) {
  unsigned length = qualifiedName.length();

  if (!length) {
    exceptionState.throwDOMException(InvalidCharacterError,
                                     "The qualified name provided is empty.");
    return false;
  }

  ParseQualifiedNameResult returnValue;
  if (qualifiedName.is8Bit())
    returnValue = parseQualifiedNameInternal(
        qualifiedName, qualifiedName.characters8(), length, prefix, localName);
  else
    returnValue = parseQualifiedNameInternal(
        qualifiedName, qualifiedName.characters16(), length, prefix, localName);
  if (returnValue.status == QNValid)
    return true;

  StringBuilder message;
  message.append("The qualified name provided ('");
  message.append(qualifiedName);
  message.append("') ");

  if (returnValue.status == QNMultipleColons) {
    message.append("contains multiple colons.");
  } else if (returnValue.status == QNInvalidStartChar) {
    message.append("contains the invalid name-start character '");
    message.append(returnValue.character);
    message.append("'.");
  } else if (returnValue.status == QNInvalidChar) {
    message.append("contains the invalid character '");
    message.append(returnValue.character);
    message.append("'.");
  } else if (returnValue.status == QNEmptyPrefix) {
    message.append("has an empty namespace prefix.");
  } else {
    DCHECK_EQ(returnValue.status, QNEmptyLocalName);
    message.append("has an empty local name.");
  }

  if (returnValue.status == QNInvalidStartChar ||
      returnValue.status == QNInvalidChar)
    exceptionState.throwDOMException(InvalidCharacterError, message.toString());
  else
    exceptionState.throwDOMException(NamespaceError, message.toString());
  return false;
}

void Document::setEncodingData(const DocumentEncodingData& newData) {
  // It's possible for the encoding of the document to change while we're
  // decoding data. That can only occur while we're processing the <head>
  // portion of the document. There isn't much user-visible content in the
  // <head>, but there is the <title> element. This function detects that
  // situation and re-decodes the document's title so that the user doesn't see
  // an incorrectly decoded title in the title bar.
  if (m_titleElement && encoding() != newData.encoding() &&
      !ElementTraversal::firstWithin(*m_titleElement) &&
      encoding() == Latin1Encoding() &&
      m_titleElement->textContent().containsOnlyLatin1()) {
    CString originalBytes = m_titleElement->textContent().latin1();
    std::unique_ptr<TextCodec> codec = newTextCodec(newData.encoding());
    String correctlyDecodedTitle =
        codec->decode(originalBytes.data(), originalBytes.length(), DataEOF);
    m_titleElement->setTextContent(correctlyDecodedTitle);
  }

  DCHECK(newData.encoding().isValid());
  m_encodingData = newData;

  // FIXME: Should be removed as part of
  // https://code.google.com/p/chromium/issues/detail?id=319643
  bool shouldUseVisualOrdering = m_encodingData.encoding().usesVisualOrdering();
  if (shouldUseVisualOrdering != m_visuallyOrdered) {
    m_visuallyOrdered = shouldUseVisualOrdering;
    // FIXME: How is possible to not have a layoutObject here?
    if (!layoutViewItem().isNull()) {
      layoutViewItem().mutableStyleRef().setRtlOrdering(
          m_visuallyOrdered ? EOrder::kVisual : EOrder::kLogical);
    }
    setNeedsStyleRecalc(SubtreeStyleChange,
                        StyleChangeReasonForTracing::create(
                            StyleChangeReason::VisuallyOrdered));
  }
}

KURL Document::completeURL(const String& url) const {
  return completeURLWithOverride(url, m_baseURL);
}

KURL Document::completeURLWithOverride(const String& url,
                                       const KURL& baseURLOverride) const {
  DCHECK(baseURLOverride.isEmpty() || baseURLOverride.isValid());

  // Always return a null URL when passed a null string.
  // FIXME: Should we change the KURL constructor to have this behavior?
  // See also [CSS]StyleSheet::completeURL(const String&)
  if (url.isNull())
    return KURL();
  // This logic is deliberately spread over many statements in an attempt to
  // track down http://crbug.com/312410.
  const KURL& baseURL = baseURLForOverride(baseURLOverride);
  if (!encoding().isValid())
    return KURL(baseURL, url);
  return KURL(baseURL, url, encoding());
}

const KURL& Document::baseURLForOverride(const KURL& baseURLOverride) const {
  // This logic is deliberately spread over many statements in an attempt to
  // track down http://crbug.com/312410.
  const KURL* baseURLFromParent = 0;
  bool shouldUseParentBaseURL = baseURLOverride.isEmpty();
  if (!shouldUseParentBaseURL) {
    const KURL& aboutBlankURL = blankURL();
    shouldUseParentBaseURL = (baseURLOverride == aboutBlankURL);
  }
  if (shouldUseParentBaseURL) {
    if (Document* parent = parentDocument())
      baseURLFromParent = &parent->baseURL();
  }
  return baseURLFromParent ? *baseURLFromParent : baseURLOverride;
}

// Support for Javascript execCommand, and related methods

static Editor::Command command(Document* document, const String& commandName) {
  LocalFrame* frame = document->frame();
  if (!frame || frame->document() != document)
    return Editor::Command();

  document->updateStyleAndLayoutTree();
  return frame->editor().createCommandFromDOM(commandName);
}

bool Document::execCommand(const String& commandName,
                           bool,
                           const String& value,
                           ExceptionState& exceptionState) {
  if (!isHTMLDocument() && !isXHTMLDocument()) {
    exceptionState.throwDOMException(
        InvalidStateError, "execCommand is only supported on HTML documents.");
    return false;
  }
  if (focusedElement() && isTextControlElement(*focusedElement()))
    UseCounter::count(*this, UseCounter::ExecCommandOnInputOrTextarea);

  // We don't allow recursive |execCommand()| to protect against attack code.
  // Recursive call of |execCommand()| could be happened by moving iframe
  // with script triggered by insertion, e.g. <iframe src="javascript:...">
  // <iframe onload="...">. This usage is valid as of the specification
  // although, it isn't common use case, rather it is used as attack code.
  if (m_isRunningExecCommand) {
    String message =
        "We don't execute document.execCommand() this time, because it is "
        "called recursively.";
    addConsoleMessage(
        ConsoleMessage::create(JSMessageSource, WarningMessageLevel, message));
    return false;
  }
  AutoReset<bool> executeScope(&m_isRunningExecCommand, true);

  // Postpone DOM mutation events, which can execute scripts and change
  // DOM tree against implementation assumption.
  EventQueueScope eventQueueScope;
  Editor::tidyUpHTMLStructure(*this);
  Editor::Command editorCommand = command(this, commandName);

  DEFINE_STATIC_LOCAL(SparseHistogram, editorCommandHistogram,
                      ("WebCore.Document.execCommand"));
  editorCommandHistogram.sample(editorCommand.idForHistogram());
  return editorCommand.execute(value);
}

bool Document::queryCommandEnabled(const String& commandName,
                                   ExceptionState& exceptionState) {
  if (!isHTMLDocument() && !isXHTMLDocument()) {
    exceptionState.throwDOMException(
        InvalidStateError,
        "queryCommandEnabled is only supported on HTML documents.");
    return false;
  }

  return command(this, commandName).isEnabled();
}

bool Document::queryCommandIndeterm(const String& commandName,
                                    ExceptionState& exceptionState) {
  if (!isHTMLDocument() && !isXHTMLDocument()) {
    exceptionState.throwDOMException(
        InvalidStateError,
        "queryCommandIndeterm is only supported on HTML documents.");
    return false;
  }

  return command(this, commandName).state() == MixedTriState;
}

bool Document::queryCommandState(const String& commandName,
                                 ExceptionState& exceptionState) {
  if (!isHTMLDocument() && !isXHTMLDocument()) {
    exceptionState.throwDOMException(
        InvalidStateError,
        "queryCommandState is only supported on HTML documents.");
    return false;
  }

  return command(this, commandName).state() == TrueTriState;
}

bool Document::queryCommandSupported(const String& commandName,
                                     ExceptionState& exceptionState) {
  if (!isHTMLDocument() && !isXHTMLDocument()) {
    exceptionState.throwDOMException(
        InvalidStateError,
        "queryCommandSupported is only supported on HTML documents.");
    return false;
  }

  return command(this, commandName).isSupported();
}

String Document::queryCommandValue(const String& commandName,
                                   ExceptionState& exceptionState) {
  if (!isHTMLDocument() && !isXHTMLDocument()) {
    exceptionState.throwDOMException(
        InvalidStateError,
        "queryCommandValue is only supported on HTML documents.");
    return "";
  }

  return command(this, commandName).value();
}

KURL Document::openSearchDescriptionURL() {
  static const char openSearchMIMEType[] =
      "application/opensearchdescription+xml";
  static const char openSearchRelation[] = "search";

  // FIXME: Why do only top-level frames have openSearchDescriptionURLs?
  if (!frame() || frame()->tree().parent())
    return KURL();

  // FIXME: Why do we need to wait for load completion?
  if (!loadEventFinished())
    return KURL();

  if (!head())
    return KURL();

  for (HTMLLinkElement* linkElement =
           Traversal<HTMLLinkElement>::firstChild(*head());
       linkElement;
       linkElement = Traversal<HTMLLinkElement>::nextSibling(*linkElement)) {
    if (!equalIgnoringCase(linkElement->type(), openSearchMIMEType) ||
        !equalIgnoringCase(linkElement->rel(), openSearchRelation))
      continue;
    if (linkElement->href().isEmpty())
      continue;

    // Count usage; perhaps we can lock this to secure contexts.
    UseCounter::Feature osdDisposition;
    RefPtr<SecurityOrigin> target = SecurityOrigin::create(linkElement->href());
    if (isSecureContext()) {
      osdDisposition = target->isPotentiallyTrustworthy()
                           ? UseCounter::OpenSearchSecureOriginSecureTarget
                           : UseCounter::OpenSearchSecureOriginInsecureTarget;
    } else {
      osdDisposition = target->isPotentiallyTrustworthy()
                           ? UseCounter::OpenSearchInsecureOriginSecureTarget
                           : UseCounter::OpenSearchInsecureOriginInsecureTarget;
    }
    UseCounter::count(*this, osdDisposition);

    return linkElement->href();
  }

  return KURL();
}

void Document::currentScriptForBinding(
    HTMLScriptElementOrSVGScriptElement& scriptElement) const {
  if (Element* script = currentScript()) {
    if (script->isInV1ShadowTree())
      return;
    if (isHTMLScriptElement(script))
      scriptElement.setHTMLScriptElement(toHTMLScriptElement(script));
    else if (isSVGScriptElement(script))
      scriptElement.setSVGScriptElement(toSVGScriptElement(script));
  }
}

void Document::pushCurrentScript(Element* newCurrentScript) {
  DCHECK(isHTMLScriptElement(newCurrentScript) ||
         isSVGScriptElement(newCurrentScript));
  m_currentScriptStack.push_back(newCurrentScript);
}

void Document::popCurrentScript() {
  DCHECK(!m_currentScriptStack.isEmpty());
  m_currentScriptStack.pop_back();
}

void Document::setTransformSource(std::unique_ptr<TransformSource> source) {
  m_transformSource = std::move(source);
}

String Document::designMode() const {
  return inDesignMode() ? "on" : "off";
}

void Document::setDesignMode(const String& value) {
  bool newValue = m_designMode;
  if (equalIgnoringCase(value, "on")) {
    newValue = true;
    UseCounter::count(*this, UseCounter::DocumentDesignModeEnabeld);
  } else if (equalIgnoringCase(value, "off")) {
    newValue = false;
  }
  if (newValue == m_designMode)
    return;
  m_designMode = newValue;
  setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(
                                              StyleChangeReason::DesignMode));
}

Document* Document::parentDocument() const {
  if (!m_frame)
    return 0;
  Frame* parent = m_frame->tree().parent();
  if (!parent || !parent->isLocalFrame())
    return 0;
  return toLocalFrame(parent)->document();
}

Document& Document::topDocument() const {
  // FIXME: Not clear what topDocument() should do in the OOPI case--should it
  // return the topmost available Document, or something else?
  Document* doc = const_cast<Document*>(this);
  for (HTMLFrameOwnerElement* element = doc->localOwner(); element;
       element = doc->localOwner())
    doc = &element->document();

  DCHECK(doc);
  return *doc;
}

Document* Document::contextDocument() {
  if (m_contextDocument)
    return m_contextDocument;
  if (m_frame)
    return this;
  return nullptr;
}

Attr* Document::createAttribute(const AtomicString& name,
                                ExceptionState& exceptionState) {
  return createAttributeNS(nullAtom, convertLocalName(name), exceptionState,
                           true);
}

Attr* Document::createAttributeNS(const AtomicString& namespaceURI,
                                  const AtomicString& qualifiedName,
                                  ExceptionState& exceptionState,
                                  bool shouldIgnoreNamespaceChecks) {
  AtomicString prefix, localName;
  if (!parseQualifiedName(qualifiedName, prefix, localName, exceptionState))
    return nullptr;

  QualifiedName qName(prefix, localName, namespaceURI);

  if (!shouldIgnoreNamespaceChecks && !hasValidNamespaceForAttributes(qName)) {
    exceptionState.throwDOMException(
        NamespaceError,
        "The namespace URI provided ('" + namespaceURI +
            "') is not valid for the qualified name provided ('" +
            qualifiedName + "').");
    return nullptr;
  }

  return Attr::create(*this, qName, emptyAtom);
}

const SVGDocumentExtensions* Document::svgExtensions() {
  return m_svgExtensions.get();
}

SVGDocumentExtensions& Document::accessSVGExtensions() {
  if (!m_svgExtensions)
    m_svgExtensions = new SVGDocumentExtensions(this);
  return *m_svgExtensions;
}

bool Document::hasSVGRootNode() const {
  return isSVGSVGElement(documentElement());
}

HTMLCollection* Document::images() {
  return ensureCachedCollection<HTMLCollection>(DocImages);
}

HTMLCollection* Document::applets() {
  return ensureCachedCollection<HTMLCollection>(DocApplets);
}

HTMLCollection* Document::embeds() {
  return ensureCachedCollection<HTMLCollection>(DocEmbeds);
}

HTMLCollection* Document::scripts() {
  return ensureCachedCollection<HTMLCollection>(DocScripts);
}

HTMLCollection* Document::links() {
  return ensureCachedCollection<HTMLCollection>(DocLinks);
}

HTMLCollection* Document::forms() {
  return ensureCachedCollection<HTMLCollection>(DocForms);
}

HTMLCollection* Document::anchors() {
  return ensureCachedCollection<HTMLCollection>(DocAnchors);
}

HTMLAllCollection* Document::all() {
  return ensureCachedCollection<HTMLAllCollection>(DocAll);
}

HTMLCollection* Document::windowNamedItems(const AtomicString& name) {
  return ensureCachedCollection<WindowNameCollection>(WindowNamedItems, name);
}

DocumentNameCollection* Document::documentNamedItems(const AtomicString& name) {
  return ensureCachedCollection<DocumentNameCollection>(DocumentNamedItems,
                                                        name);
}

void Document::finishedParsing() {
  DCHECK(!scriptableDocumentParser() || !m_parser->isParsing());
  DCHECK(!scriptableDocumentParser() || m_readyState != Loading);
  setParsingState(InDOMContentLoaded);
  DocumentParserTiming::from(*this).markParserStop();

  // FIXME: DOMContentLoaded is dispatched synchronously, but this should be
  // dispatched in a queued task, see https://crbug.com/425790
  if (!m_documentTiming.domContentLoadedEventStart())
    m_documentTiming.markDomContentLoadedEventStart();
  dispatchEvent(Event::createBubble(EventTypeNames::DOMContentLoaded));
  if (!m_documentTiming.domContentLoadedEventEnd())
    m_documentTiming.markDomContentLoadedEventEnd();
  setParsingState(FinishedParsing);

  // Ensure Custom Element callbacks are drained before DOMContentLoaded.
  // FIXME: Remove this ad-hoc checkpoint when DOMContentLoaded is dispatched in
  // a queued task, which will do a checkpoint anyway. https://crbug.com/425790
  Microtask::performCheckpoint(V8PerIsolateData::mainThreadIsolate());

  if (LocalFrame* frame = this->frame()) {
    // Don't update the layout tree if we haven't requested the main resource
    // yet to avoid adding extra latency. Note that the first layout tree update
    // can be expensive since it triggers the parsing of the default stylesheets
    // which are compiled-in.
    const bool mainResourceWasAlreadyRequested =
        frame->loader().stateMachine()->committedFirstRealDocumentLoad();

    // FrameLoader::finishedParsing() might end up calling
    // Document::implicitClose() if all resource loads are
    // complete. HTMLObjectElements can start loading their resources from post
    // attach callbacks triggered by recalcStyle().  This means if we parse out
    // an <object> tag and then reach the end of the document without updating
    // styles, we might not have yet started the resource load and might fire
    // the window load event too early.  To avoid this we force the styles to be
    // up to date before calling FrameLoader::finishedParsing().  See
    // https://bugs.webkit.org/show_bug.cgi?id=36864 starting around comment 35.
    if (mainResourceWasAlreadyRequested)
      updateStyleAndLayoutTree();

    beginLifecycleUpdatesIfRenderingReady();

    frame->loader().finishedParsing();

    TRACE_EVENT_INSTANT1("devtools.timeline", "MarkDOMContent",
                         TRACE_EVENT_SCOPE_THREAD, "data",
                         InspectorMarkLoadEvent::data(frame));
    InspectorInstrumentation::domContentLoadedEventFired(frame);
  }

  // Schedule dropping of the ElementDataCache. We keep it alive for a while
  // after parsing finishes so that dynamically inserted content can also
  // benefit from sharing optimizations.  Note that we don't refresh the timer
  // on cache access since that could lead to huge caches being kept alive
  // indefinitely by something innocuous like JS setting .innerHTML repeatedly
  // on a timer.
  m_elementDataCacheClearTimer.startOneShot(10, BLINK_FROM_HERE);

  // Parser should have picked up all preloads by now
  m_fetcher->clearPreloads(ResourceFetcher::ClearSpeculativeMarkupPreloads);

  if (isPrefetchOnly())
    WebPrerenderingSupport::current()->prefetchFinished();
}

void Document::elementDataCacheClearTimerFired(TimerBase*) {
  m_elementDataCache.clear();
}

void Document::beginLifecycleUpdatesIfRenderingReady() {
  if (!isActive())
    return;
  if (!isRenderingReady())
    return;
  view()->beginLifecycleUpdates();
}

Vector<IconURL> Document::iconURLs(int iconTypesMask) {
  IconURL firstFavicon;
  IconURL firstTouchIcon;
  IconURL firstTouchPrecomposedIcon;
  Vector<IconURL> secondaryIcons;

  // Start from the last child node so that icons seen later take precedence as
  // required by the spec.
  for (HTMLLinkElement* linkElement =
           head() ? Traversal<HTMLLinkElement>::firstChild(*head()) : 0;
       linkElement;
       linkElement = Traversal<HTMLLinkElement>::nextSibling(*linkElement)) {
    if (!(linkElement->getIconType() & iconTypesMask))
      continue;
    if (linkElement->href().isEmpty())
      continue;

    IconURL newURL(linkElement->href(), linkElement->iconSizes(),
                   linkElement->type(), linkElement->getIconType());
    if (linkElement->getIconType() == Favicon) {
      if (firstFavicon.m_iconType != InvalidIcon)
        secondaryIcons.push_back(firstFavicon);
      firstFavicon = newURL;
    } else if (linkElement->getIconType() == TouchIcon) {
      if (firstTouchIcon.m_iconType != InvalidIcon)
        secondaryIcons.push_back(firstTouchIcon);
      firstTouchIcon = newURL;
    } else if (linkElement->getIconType() == TouchPrecomposedIcon) {
      if (firstTouchPrecomposedIcon.m_iconType != InvalidIcon)
        secondaryIcons.push_back(firstTouchPrecomposedIcon);
      firstTouchPrecomposedIcon = newURL;
    } else {
      NOTREACHED();
    }
  }

  Vector<IconURL> iconURLs;
  if (firstFavicon.m_iconType != InvalidIcon)
    iconURLs.push_back(firstFavicon);
  else if (m_url.protocolIsInHTTPFamily() && iconTypesMask & Favicon)
    iconURLs.push_back(IconURL::defaultFavicon(m_url));

  if (firstTouchIcon.m_iconType != InvalidIcon)
    iconURLs.push_back(firstTouchIcon);
  if (firstTouchPrecomposedIcon.m_iconType != InvalidIcon)
    iconURLs.push_back(firstTouchPrecomposedIcon);
  for (int i = secondaryIcons.size() - 1; i >= 0; --i)
    iconURLs.push_back(secondaryIcons[i]);
  return iconURLs;
}

Color Document::themeColor() const {
  auto rootElement = documentElement();
  if (!rootElement)
    return Color();
  for (HTMLMetaElement& metaElement :
       Traversal<HTMLMetaElement>::descendantsOf(*rootElement)) {
    Color color = Color::transparent;
    if (equalIgnoringCase(metaElement.name(), "theme-color") &&
        CSSParser::parseColor(
            color, metaElement.content().getString().stripWhiteSpace(), true))
      return color;
  }
  return Color();
}

HTMLLinkElement* Document::linkManifest() const {
  HTMLHeadElement* head = this->head();
  if (!head)
    return 0;

  // The first link element with a manifest rel must be used. Others are
  // ignored.
  for (HTMLLinkElement* linkElement =
           Traversal<HTMLLinkElement>::firstChild(*head);
       linkElement;
       linkElement = Traversal<HTMLLinkElement>::nextSibling(*linkElement)) {
    if (!linkElement->relAttribute().isManifest())
      continue;
    return linkElement;
  }

  return 0;
}

void Document::initSecurityContext(const DocumentInit& initializer) {
  DCHECK(!getSecurityOrigin());

  if (!initializer.hasSecurityContext()) {
    // No source for a security context.
    // This can occur via document.implementation.createDocument().
    m_cookieURL = KURL(ParsedURLString, emptyString());
    setSecurityOrigin(SecurityOrigin::createUnique());
    initContentSecurityPolicy();
    // Unique security origins cannot have a suborigin
    return;
  }

  // In the common case, create the security context from the currently
  // loading URL with a fresh content security policy.
  enforceSandboxFlags(initializer.getSandboxFlags());
  setInsecureRequestPolicy(initializer.getInsecureRequestPolicy());
  if (initializer.insecureNavigationsToUpgrade()) {
    for (auto toUpgrade : *initializer.insecureNavigationsToUpgrade())
      addInsecureNavigationUpgrade(toUpgrade);
  }

  if (isSandboxed(SandboxOrigin)) {
    m_cookieURL = m_url;
    setSecurityOrigin(SecurityOrigin::createUnique());
    // If we're supposed to inherit our security origin from our
    // owner, but we're also sandboxed, the only things we inherit are
    // the origin's potential trustworthiness and the ability to
    // load local resources. The latter lets about:blank iframes in
    // file:// URL documents load images and other resources from
    // the file system.
    if (initializer.owner() &&
        initializer.owner()->getSecurityOrigin()->isPotentiallyTrustworthy())
      getSecurityOrigin()->setUniqueOriginIsPotentiallyTrustworthy(true);
    if (initializer.owner() &&
        initializer.owner()->getSecurityOrigin()->canLoadLocalResources())
      getSecurityOrigin()->grantLoadLocalResources();
  } else if (initializer.owner()) {
    m_cookieURL = initializer.owner()->cookieURL();
    // We alias the SecurityOrigins to match Firefox, see Bug 15313
    // https://bugs.webkit.org/show_bug.cgi?id=15313
    setSecurityOrigin(initializer.owner()->getSecurityOrigin());
  } else {
    m_cookieURL = m_url;
    setSecurityOrigin(SecurityOrigin::create(m_url));
  }

  // Set the address space before setting up CSP, as the latter may override
  // the former via the 'treat-as-public-address' directive (see
  // https://mikewest.github.io/cors-rfc1918/#csp).
  if (initializer.isHostedInReservedIPRange()) {
    setAddressSpace(getSecurityOrigin()->isLocalhost()
                        ? WebAddressSpaceLocal
                        : WebAddressSpacePrivate);
  } else if (getSecurityOrigin()->isLocal()) {
    // "Local" security origins (like 'file://...') are treated as having
    // a local address space.
    //
    // TODO(mkwst): It's not entirely clear that this is a good idea.
    setAddressSpace(WebAddressSpaceLocal);
  } else {
    setAddressSpace(WebAddressSpacePublic);
  }

  if (importsController()) {
    // If this document is an HTML import, grab a reference to it's master
    // document's Content Security Policy. We don't call
    // 'initContentSecurityPolicy' in this case, as we can't rebind the master
    // document's policy object: its ExecutionContext needs to remain tied to
    // the master document.
    setContentSecurityPolicy(
        importsController()->master()->contentSecurityPolicy());
  } else {
    initContentSecurityPolicy();
  }

  if (getSecurityOrigin()->hasSuborigin())
    enforceSuborigin(*getSecurityOrigin()->suborigin());

  if (Settings* settings = initializer.settings()) {
    if (!settings->getWebSecurityEnabled()) {
      // Web security is turned off. We should let this document access every
      // other document. This is used primary by testing harnesses for web
      // sites.
      getSecurityOrigin()->grantUniversalAccess();
    } else if (getSecurityOrigin()->isLocal()) {
      if (settings->getAllowUniversalAccessFromFileURLs()) {
        // Some clients want local URLs to have universal access, but that
        // setting is dangerous for other clients.
        getSecurityOrigin()->grantUniversalAccess();
      } else if (!settings->getAllowFileAccessFromFileURLs()) {
        // Some clients do not want local URLs to have access to other local
        // URLs.
        getSecurityOrigin()->blockLocalAccessFromLocalOrigin();
      }
    }
  }

  if (initializer.shouldTreatURLAsSrcdocDocument()) {
    m_isSrcdocDocument = true;
    setBaseURLOverride(initializer.parentBaseURL());
  }

  if (getSecurityOrigin()->isUnique() &&
      SecurityOrigin::create(m_url)->isPotentiallyTrustworthy())
    getSecurityOrigin()->setUniqueOriginIsPotentiallyTrustworthy(true);

  if (getSecurityOrigin()->hasSuborigin())
    enforceSuborigin(*getSecurityOrigin()->suborigin());
}

void Document::initContentSecurityPolicy(ContentSecurityPolicy* csp) {
  setContentSecurityPolicy(csp ? csp : ContentSecurityPolicy::create());

  // We inherit the parent/opener's CSP for documents with "local" schemes:
  // 'about', 'blob', 'data', and 'filesystem'. We also inherit CSP for
  // documents with empty/invalid URLs because we treat those URLs as
  // 'about:blank' in Blink.
  //
  // https://w3c.github.io/webappsec-csp/#initialize-document-csp
  //
  // TODO(dcheng): This is similar enough to work we're doing in
  // 'DocumentLoader::ensureWriter' that it might make sense to combine them.
  if (m_frame) {
    Frame* inheritFrom = m_frame->tree().parent() ? m_frame->tree().parent()
                                                  : m_frame->client()->opener();
    if (inheritFrom && m_frame != inheritFrom) {
      DCHECK(inheritFrom->securityContext() &&
             inheritFrom->securityContext()->contentSecurityPolicy());
      ContentSecurityPolicy* policyToInherit =
          inheritFrom->securityContext()->contentSecurityPolicy();
      if (m_url.isEmpty() || m_url.protocolIsAbout() ||
          m_url.protocolIsData() || m_url.protocolIs("blob") ||
          m_url.protocolIs("filesystem")) {
        contentSecurityPolicy()->copyStateFrom(policyToInherit);
      }
      // Plugin documents inherit their parent/opener's 'plugin-types' directive
      // regardless of URL.
      if (isPluginDocument())
        contentSecurityPolicy()->copyPluginTypesFrom(policyToInherit);
    }
  }
  contentSecurityPolicy()->bindToExecutionContext(this);
}

bool Document::isSecureTransitionTo(const KURL& url) const {
  RefPtr<SecurityOrigin> other = SecurityOrigin::create(url);
  return getSecurityOrigin()->canAccess(other.get());
}

bool Document::allowInlineEventHandler(Node* node,
                                       EventListener* listener,
                                       const String& contextURL,
                                       const WTF::OrdinalNumber& contextLine) {
  Element* element = node && node->isElementNode() ? toElement(node) : nullptr;
  if (!ContentSecurityPolicy::shouldBypassMainWorld(this) &&
      !contentSecurityPolicy()->allowInlineEventHandler(
          element, listener->code(), contextURL, contextLine))
    return false;

  // HTML says that inline script needs browsing context to create its execution
  // environment.
  // http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#event-handler-attributes
  // Also, if the listening node came from other document, which happens on
  // context-less event dispatching, we also need to ask the owner document of
  // the node.
  LocalFrame* frame = executingFrame();
  if (!frame)
    return false;
  if (!frame->script().canExecuteScripts(NotAboutToExecuteScript))
    return false;
  if (node && node->document() != this &&
      !node->document().allowInlineEventHandler(node, listener, contextURL,
                                                contextLine))
    return false;

  return true;
}

bool Document::allowExecutingScripts(Node* node) {
  // FIXME: Eventually we'd like to evaluate scripts which are inserted into a
  // viewless document but this'll do for now.
  // See http://bugs.webkit.org/show_bug.cgi?id=5727
  LocalFrame* frame = executingFrame();
  if (!frame)
    return false;
  if (!node->document().executingFrame())
    return false;
  if (!frame->script().canExecuteScripts(AboutToExecuteScript))
    return false;
  return true;
}

void Document::enforceSandboxFlags(SandboxFlags mask) {
  RefPtr<SecurityOrigin> standInOrigin = getSecurityOrigin();
  applySandboxFlags(mask);
  // Send a notification if the origin has been updated.
  if (standInOrigin && !standInOrigin->isUnique() &&
      getSecurityOrigin()->isUnique()) {
    getSecurityOrigin()->setUniqueOriginIsPotentiallyTrustworthy(
        standInOrigin->isPotentiallyTrustworthy());
    if (frame())
      frame()->loader().client()->didUpdateToUniqueOrigin();
  }
}

void Document::updateSecurityOrigin(PassRefPtr<SecurityOrigin> origin) {
  setSecurityOrigin(std::move(origin));
  didUpdateSecurityOrigin();
}

void Document::didUpdateSecurityOrigin() {
  if (!m_frame)
    return;
  m_frame->script().updateSecurityOrigin(getSecurityOrigin());
}

bool Document::isContextThread() const {
  return isMainThread();
}

void Document::updateFocusAppearanceSoon(
    SelectionBehaviorOnFocus selectionbehavioronfocus) {
  m_updateFocusAppearanceSelectionBahavior = selectionbehavioronfocus;
  if (!m_updateFocusAppearanceTimer.isActive())
    m_updateFocusAppearanceTimer.startOneShot(0, BLINK_FROM_HERE);
}

void Document::cancelFocusAppearanceUpdate() {
  m_updateFocusAppearanceTimer.stop();
}

void Document::updateFocusAppearanceTimerFired(TimerBase*) {
  Element* element = focusedElement();
  if (!element)
    return;
  updateStyleAndLayout();
  if (element->isFocusable())
    element->updateFocusAppearance(m_updateFocusAppearanceSelectionBahavior);
}

void Document::attachRange(Range* range) {
  DCHECK(!m_ranges.contains(range));
  m_ranges.add(range);
}

void Document::detachRange(Range* range) {
  // We don't ASSERT m_ranges.contains(range) to allow us to call this
  // unconditionally to fix: https://bugs.webkit.org/show_bug.cgi?id=26044
  m_ranges.remove(range);
}

void Document::initDNSPrefetch() {
  Settings* settings = this->settings();

  m_haveExplicitlyDisabledDNSPrefetch = false;
  m_isDNSPrefetchEnabled = settings && settings->getDNSPrefetchingEnabled() &&
                           getSecurityOrigin()->protocol() == "http";

  // Inherit DNS prefetch opt-out from parent frame
  if (Document* parent = parentDocument()) {
    if (!parent->isDNSPrefetchEnabled())
      m_isDNSPrefetchEnabled = false;
  }
}

void Document::parseDNSPrefetchControlHeader(const String& dnsPrefetchControl) {
  if (equalIgnoringCase(dnsPrefetchControl, "on") &&
      !m_haveExplicitlyDisabledDNSPrefetch) {
    m_isDNSPrefetchEnabled = true;
    return;
  }

  m_isDNSPrefetchEnabled = false;
  m_haveExplicitlyDisabledDNSPrefetch = true;
}

IntersectionObserverController* Document::intersectionObserverController() {
  return m_intersectionObserverController;
}

IntersectionObserverController&
Document::ensureIntersectionObserverController() {
  if (!m_intersectionObserverController)
    m_intersectionObserverController =
        IntersectionObserverController::create(this);
  return *m_intersectionObserverController;
}

ResizeObserverController& Document::ensureResizeObserverController() {
  if (!m_resizeObserverController)
    m_resizeObserverController = new ResizeObserverController();
  return *m_resizeObserverController;
}

static void runAddConsoleMessageTask(MessageSource source,
                                     MessageLevel level,
                                     const String& message,
                                     ExecutionContext* context) {
  context->addConsoleMessage(ConsoleMessage::create(source, level, message));
}

void Document::addConsoleMessage(ConsoleMessage* consoleMessage) {
  if (!isContextThread()) {
    postTask(TaskType::Unthrottled, BLINK_FROM_HERE,
             createCrossThreadTask(
                 &runAddConsoleMessageTask, consoleMessage->source(),
                 consoleMessage->level(), consoleMessage->message()));
    return;
  }

  if (!m_frame)
    return;

  if (consoleMessage->location()->isUnknown()) {
    // TODO(dgozman): capture correct location at call places instead.
    unsigned lineNumber = 0;
    if (!isInDocumentWrite() && scriptableDocumentParser()) {
      ScriptableDocumentParser* parser = scriptableDocumentParser();
      if (parser->isParsingAtLineNumber())
        lineNumber = parser->lineNumber().oneBasedInt();
    }
    consoleMessage = ConsoleMessage::create(
        consoleMessage->source(), consoleMessage->level(),
        consoleMessage->message(),
        SourceLocation::create(url().getString(), lineNumber, 0, nullptr));
  }
  m_frame->console().addMessage(consoleMessage);
}

void Document::postTask(TaskType taskType,
                        const WebTraceLocation& location,
                        std::unique_ptr<ExecutionContextTask> task,
                        const String& taskNameForInstrumentation) {
  if (!taskNameForInstrumentation.isEmpty()) {
    InspectorInstrumentation::asyncTaskScheduled(
        this, taskNameForInstrumentation, task.get());
  }

  TaskRunnerHelper::get(taskType, this)
      ->postTask(location,
                 crossThreadBind(&Document::runExecutionContextTask,
                                 wrapCrossThreadWeakPersistent(this),
                                 WTF::passed(std::move(task)),
                                 !taskNameForInstrumentation.isEmpty()));
}

void Document::tasksWereSuspended() {
  scriptRunner()->suspend();

  if (m_parser)
    m_parser->suspendScheduledTasks();
  if (m_scriptedAnimationController)
    m_scriptedAnimationController->suspend();
}

void Document::tasksWereResumed() {
  scriptRunner()->resume();

  if (m_parser)
    m_parser->resumeScheduledTasks();
  if (m_scriptedAnimationController)
    m_scriptedAnimationController->resume();

  MutationObserver::resumeSuspendedObservers();
  if (m_domWindow)
    DOMWindowPerformance::performance(*m_domWindow)->resumeSuspendedObservers();
}

bool Document::tasksNeedSuspension() {
  Page* page = this->page();
  return page && page->suspended();
}

void Document::addToTopLayer(Element* element, const Element* before) {
  if (element->isInTopLayer())
    return;

  DCHECK(!m_topLayerElements.contains(element));
  DCHECK(!before || m_topLayerElements.contains(before));
  if (before) {
    size_t beforePosition = m_topLayerElements.find(before);
    m_topLayerElements.insert(beforePosition, element);
  } else {
    m_topLayerElements.push_back(element);
  }
  element->setIsInTopLayer(true);
}

void Document::removeFromTopLayer(Element* element) {
  if (!element->isInTopLayer())
    return;
  size_t position = m_topLayerElements.find(element);
  DCHECK_NE(position, kNotFound);
  m_topLayerElements.remove(position);
  element->setIsInTopLayer(false);
}

HTMLDialogElement* Document::activeModalDialog() const {
  if (m_topLayerElements.isEmpty())
    return 0;
  return toHTMLDialogElement(m_topLayerElements.back().get());
}

void Document::exitPointerLock() {
  if (!page())
    return;
  if (Element* target = page()->pointerLockController().element()) {
    if (target->document() != this)
      return;
    page()->pointerLockController().requestPointerUnlock();
  }
}

Element* Document::pointerLockElement() const {
  if (!page() || page()->pointerLockController().lockPending())
    return 0;
  if (Element* element = page()->pointerLockController().element()) {
    if (element->document() == this)
      return element;
  }
  return 0;
}

void Document::suppressLoadEvent() {
  if (!loadEventFinished())
    m_loadEventProgress = LoadEventCompleted;
}

void Document::decrementLoadEventDelayCount() {
  DCHECK(m_loadEventDelayCount);
  --m_loadEventDelayCount;

  if (!m_loadEventDelayCount)
    checkLoadEventSoon();
}

void Document::checkLoadEventSoon() {
  if (frame() && !m_loadEventDelayTimer.isActive())
    m_loadEventDelayTimer.startOneShot(0, BLINK_FROM_HERE);
}

bool Document::isDelayingLoadEvent() {
  // Always delay load events until after garbage collection.
  // This way we don't have to explicitly delay load events via
  // incrementLoadEventDelayCount and decrementLoadEventDelayCount in
  // Node destructors.
  if (ThreadState::current()->sweepForbidden()) {
    if (!m_loadEventDelayCount)
      checkLoadEventSoon();
    return true;
  }
  return m_loadEventDelayCount;
}

void Document::loadEventDelayTimerFired(TimerBase*) {
  if (frame())
    frame()->loader().checkCompleted();
}

void Document::loadPluginsSoon() {
  // FIXME: Remove this timer once we don't need to compute layout to load
  // plugins.
  if (!m_pluginLoadingTimer.isActive())
    m_pluginLoadingTimer.startOneShot(0, BLINK_FROM_HERE);
}

void Document::pluginLoadingTimerFired(TimerBase*) {
  updateStyleAndLayout();
}

ScriptedAnimationController& Document::ensureScriptedAnimationController() {
  if (!m_scriptedAnimationController) {
    m_scriptedAnimationController = ScriptedAnimationController::create(this);
    // We need to make sure that we don't start up the animation controller on a
    // background tab, for example.
    if (!page())
      m_scriptedAnimationController->suspend();
  }
  return *m_scriptedAnimationController;
}

int Document::requestAnimationFrame(FrameRequestCallback* callback) {
  return ensureScriptedAnimationController().registerCallback(callback);
}

void Document::cancelAnimationFrame(int id) {
  if (!m_scriptedAnimationController)
    return;
  m_scriptedAnimationController->cancelCallback(id);
}

void Document::serviceScriptedAnimations(double monotonicAnimationStartTime) {
  if (!m_scriptedAnimationController)
    return;
  m_scriptedAnimationController->serviceScriptedAnimations(
      monotonicAnimationStartTime);
}

ScriptedIdleTaskController& Document::ensureScriptedIdleTaskController() {
  if (!m_scriptedIdleTaskController)
    m_scriptedIdleTaskController = ScriptedIdleTaskController::create(this);
  return *m_scriptedIdleTaskController;
}

int Document::requestIdleCallback(IdleRequestCallback* callback,
                                  const IdleRequestOptions& options) {
  return ensureScriptedIdleTaskController().registerCallback(callback, options);
}

void Document::cancelIdleCallback(int id) {
  if (!m_scriptedIdleTaskController)
    return;
  m_scriptedIdleTaskController->cancelCallback(id);
}

Touch* Document::createTouch(DOMWindow* window,
                             EventTarget* target,
                             int identifier,
                             double pageX,
                             double pageY,
                             double screenX,
                             double screenY,
                             double radiusX,
                             double radiusY,
                             float rotationAngle,
                             float force) const {
  // Match behavior from when these types were integers, and avoid surprises
  // from someone explicitly
  // passing Infinity/NaN.
  if (!std::isfinite(pageX))
    pageX = 0;
  if (!std::isfinite(pageY))
    pageY = 0;
  if (!std::isfinite(screenX))
    screenX = 0;
  if (!std::isfinite(screenY))
    screenY = 0;
  if (!std::isfinite(radiusX))
    radiusX = 0;
  if (!std::isfinite(radiusY))
    radiusY = 0;
  if (!std::isfinite(rotationAngle))
    rotationAngle = 0;
  if (!std::isfinite(force))
    force = 0;

  if (radiusX || radiusY || rotationAngle || force)
    UseCounter::count(*this,
                      UseCounter::DocumentCreateTouchMoreThanSevenArguments);

  // FIXME: It's not clear from the documentation at
  // http://developer.apple.com/library/safari/#documentation/UserExperience/Reference/DocumentAdditionsReference/DocumentAdditions/DocumentAdditions.html
  // 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 and
  // implement them here. See https://bugs.webkit.org/show_bug.cgi?id=47819
  LocalFrame* frame = window && window->isLocalDOMWindow()
                          ? blink::toLocalDOMWindow(window)->frame()
                          : this->frame();
  return Touch::create(frame, target, identifier, FloatPoint(screenX, screenY),
                       FloatPoint(pageX, pageY), FloatSize(radiusX, radiusY),
                       rotationAngle, force, String());
}

TouchList* Document::createTouchList(HeapVector<Member<Touch>>& touches) const {
  return TouchList::adopt(touches);
}

DocumentLoader* Document::loader() const {
  if (!m_frame)
    return 0;

  DocumentLoader* loader = m_frame->loader().documentLoader();
  if (!loader)
    return 0;

  if (m_frame->document() != this)
    return 0;

  return loader;
}

Node* eventTargetNodeForDocument(Document* doc) {
  if (!doc)
    return 0;
  Node* node = doc->focusedElement();
  if (!node && doc->isPluginDocument()) {
    PluginDocument* pluginDocument = toPluginDocument(doc);
    node = pluginDocument->pluginNode();
  }
  if (!node && doc->isHTMLDocument())
    node = doc->body();
  if (!node)
    node = doc->documentElement();
  return node;
}

void Document::adjustFloatQuadsForScrollAndAbsoluteZoom(
    Vector<FloatQuad>& quads,
    LayoutObject& layoutObject) {
  if (!view())
    return;

  LayoutRect visibleContentRect(view()->visibleContentRect());
  for (size_t i = 0; i < quads.size(); ++i) {
    quads[i].move(-FloatSize(visibleContentRect.x().toFloat(),
                             visibleContentRect.y().toFloat()));
    adjustFloatQuadForAbsoluteZoom(quads[i], layoutObject);
  }
}

void Document::adjustFloatRectForScrollAndAbsoluteZoom(
    FloatRect& rect,
    LayoutObject& layoutObject) {
  if (!view())
    return;

  LayoutRect visibleContentRect(view()->visibleContentRect());
  rect.move(-FloatSize(visibleContentRect.x().toFloat(),
                       visibleContentRect.y().toFloat()));
  adjustFloatRectForAbsoluteZoom(rect, layoutObject);
}

void Document::setThreadedParsingEnabledForTesting(bool enabled) {
  s_threadedParsingEnabledForTesting = enabled;
}

bool Document::threadedParsingEnabledForTesting() {
  return s_threadedParsingEnabledForTesting;
}

SnapCoordinator* Document::snapCoordinator() {
  if (RuntimeEnabledFeatures::cssScrollSnapPointsEnabled() &&
      !m_snapCoordinator)
    m_snapCoordinator = SnapCoordinator::create();

  return m_snapCoordinator.get();
}

void Document::setContextFeatures(ContextFeatures& features) {
  m_contextFeatures = &features;
}

static LayoutObject* nearestCommonHoverAncestor(LayoutObject* obj1,
                                                LayoutObject* obj2) {
  if (!obj1 || !obj2)
    return 0;

  for (LayoutObject* currObj1 = obj1; currObj1;
       currObj1 = currObj1->hoverAncestor()) {
    for (LayoutObject* currObj2 = obj2; currObj2;
         currObj2 = currObj2->hoverAncestor()) {
      if (currObj1 == currObj2)
        return currObj1;
    }
  }

  return 0;
}

void Document::updateHoverActiveState(const HitTestRequest& request,
                                      Element* innerElement,
                                      Scrollbar* hitScrollbar) {
  DCHECK(!request.readOnly());

  // Only cancel hover state when hitting native scrollbar because custom
  // scrollbar's style depends on the owner element's hover state.
  bool hitNativeScrollbar = hitScrollbar && !hitScrollbar->isCustomScrollbar();

  if (request.active() && m_frame && !hitNativeScrollbar)
    m_frame->eventHandler().notifyElementActivated();

  Element* innerElementInDocument = hitNativeScrollbar ? nullptr : innerElement;
  while (innerElementInDocument && innerElementInDocument->document() != this) {
    innerElementInDocument->document().updateHoverActiveState(
        request, innerElementInDocument, hitScrollbar);
    innerElementInDocument = innerElementInDocument->document().localOwner();
  }

  updateDistribution();
  Element* oldActiveElement = activeHoverElement();
  if (oldActiveElement && (!request.active() || hitNativeScrollbar)) {
    // The oldActiveElement layoutObject is null, dropped on :active by setting
    // display: none, for instance. We still need to clear the ActiveChain as
    // the mouse is released.
    for (Node* node = oldActiveElement; node;
         node = FlatTreeTraversal::parent(*node)) {
      DCHECK(!node->isTextNode());
      node->setActive(false);
      m_userActionElements.setInActiveChain(node, false);
    }
    setActiveHoverElement(nullptr);
  } else {
    Element* newActiveElement = innerElementInDocument;
    if (!oldActiveElement && newActiveElement &&
        !newActiveElement->isDisabledFormControl() && request.active() &&
        !request.touchMove()) {
      // We are setting the :active chain and freezing it. If future moves
      // happen, they will need to reference this chain.
      for (Node* node = newActiveElement; node;
           node = FlatTreeTraversal::parent(*node)) {
        DCHECK(!node->isTextNode());
        m_userActionElements.setInActiveChain(node, true);
      }
      setActiveHoverElement(newActiveElement);
    }
  }
  // If the mouse has just been pressed, set :active on the chain. Those (and
  // only those) nodes should remain :active until the mouse is released.
  bool allowActiveChanges = !oldActiveElement && activeHoverElement();

  // If the mouse is down and if this is a mouse move event, we want to restrict
  // changes in :hover/:active to only apply to elements that are in the :active
  // chain that we froze at the time the mouse went down.
  bool mustBeInActiveChain = request.active() && request.move();

  Node* oldHoverNode = hoverNode();

  // Check to see if the hovered node has changed.
  // If it hasn't, we do not need to do anything.
  Node* newHoverNode = innerElementInDocument;
  while (newHoverNode && !newHoverNode->layoutObject())
    newHoverNode = newHoverNode->parentOrShadowHostNode();

  // Update our current hover node.
  setHoverNode(newHoverNode);

  // We have two different objects. Fetch their layoutObjects.
  LayoutObject* oldHoverObj =
      oldHoverNode ? oldHoverNode->layoutObject() : nullptr;
  LayoutObject* newHoverObj =
      newHoverNode ? newHoverNode->layoutObject() : nullptr;

  // Locate the common ancestor layout object for the two layoutObjects.
  LayoutObject* ancestor = nearestCommonHoverAncestor(oldHoverObj, newHoverObj);
  Node* ancestorNode(ancestor ? ancestor->node() : nullptr);

  HeapVector<Member<Node>, 32> nodesToRemoveFromChain;
  HeapVector<Member<Node>, 32> nodesToAddToChain;

  if (oldHoverObj != newHoverObj) {
    // If the old hovered node is not nil but it's layoutObject is, it was
    // probably detached as part of the :hover style (for instance by setting
    // display:none in the :hover pseudo-class). In this case, the old hovered
    // element (and its ancestors) must be updated, to ensure it's normal style
    // is re-applied.
    if (oldHoverNode && !oldHoverObj) {
      for (Node& node : NodeTraversal::inclusiveAncestorsOf(*oldHoverNode)) {
        if (!mustBeInActiveChain ||
            (node.isElementNode() && toElement(node).inActiveChain()))
          nodesToRemoveFromChain.push_back(node);
      }
    }

    // The old hover path only needs to be cleared up to (and not including) the
    // common ancestor;
    for (LayoutObject* curr = oldHoverObj; curr && curr != ancestor;
         curr = curr->hoverAncestor()) {
      if (curr->node() && !curr->isText() &&
          (!mustBeInActiveChain || curr->node()->inActiveChain()))
        nodesToRemoveFromChain.push_back(curr->node());
    }

    // TODO(mustaq): The two loops above may push a single node twice into
    // nodesToRemoveFromChain. There must be a better way.
  }

  // Now set the hover state for our new object up to the root.
  for (LayoutObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) {
    if (curr->node() && !curr->isText() &&
        (!mustBeInActiveChain || curr->node()->inActiveChain()))
      nodesToAddToChain.push_back(curr->node());
  }

  size_t removeCount = nodesToRemoveFromChain.size();
  for (size_t i = 0; i < removeCount; ++i) {
    nodesToRemoveFromChain[i]->setHovered(false);
  }

  bool sawCommonAncestor = false;
  size_t addCount = nodesToAddToChain.size();
  for (size_t i = 0; i < addCount; ++i) {
    // Elements past the common ancestor do not change hover state, but might
    // change active state.
    if (ancestorNode && nodesToAddToChain[i] == ancestorNode)
      sawCommonAncestor = true;
    if (allowActiveChanges)
      nodesToAddToChain[i]->setActive(true);
    if (!sawCommonAncestor || nodesToAddToChain[i] == m_hoverNode) {
      nodesToAddToChain[i]->setHovered(true);
    }
  }
}

bool Document::haveScriptBlockingStylesheetsLoaded() const {
  return m_styleEngine->haveScriptBlockingStylesheetsLoaded();
}

bool Document::haveRenderBlockingStylesheetsLoaded() const {
  if (RuntimeEnabledFeatures::cssInBodyDoesNotBlockPaintEnabled())
    return m_styleEngine->haveRenderBlockingStylesheetsLoaded();
  return m_styleEngine->haveScriptBlockingStylesheetsLoaded();
}

Locale& Document::getCachedLocale(const AtomicString& locale) {
  AtomicString localeKey = locale;
  if (locale.isEmpty() ||
      !RuntimeEnabledFeatures::langAttributeAwareFormControlUIEnabled())
    return Locale::defaultLocale();
  LocaleIdentifierToLocaleMap::AddResult result =
      m_localeCache.add(localeKey, nullptr);
  if (result.isNewEntry)
    result.storedValue->value = Locale::create(localeKey);
  return *(result.storedValue->value);
}

AnimationClock& Document::animationClock() {
  DCHECK(page());
  return page()->animator().clock();
}

Document& Document::ensureTemplateDocument() {
  if (isTemplateDocument())
    return *this;

  if (m_templateDocument)
    return *m_templateDocument;

  if (isHTMLDocument()) {
    DocumentInit init = DocumentInit::fromContext(contextDocument(), blankURL())
                            .withNewRegistrationContext();
    m_templateDocument = HTMLDocument::create(init);
  } else {
    m_templateDocument = Document::create(DocumentInit(blankURL()));
  }

  m_templateDocument->m_templateDocumentHost = this;  // balanced in dtor.

  return *m_templateDocument.get();
}

void Document::didAssociateFormControl(Element* element) {
  if (!frame() || !frame()->page() || !loadEventFinished())
    return;

  // We add a slight delay because this could be called rapidly.
  if (!m_didAssociateFormControlsTimer.isActive())
    m_didAssociateFormControlsTimer.startOneShot(0.3, BLINK_FROM_HERE);
}

void Document::didAssociateFormControlsTimerFired(TimerBase* timer) {
  DCHECK_EQ(timer, &m_didAssociateFormControlsTimer);
  if (!frame() || !frame()->page())
    return;

  frame()->page()->chromeClient().didAssociateFormControlsAfterLoad(frame());
}

float Document::devicePixelRatio() const {
  return m_frame ? m_frame->devicePixelRatio() : 1.0;
}

TextAutosizer* Document::textAutosizer() {
  if (!m_textAutosizer)
    m_textAutosizer = TextAutosizer::create(this);
  return m_textAutosizer.get();
}

void Document::setAutofocusElement(Element* element) {
  if (!element) {
    m_autofocusElement = nullptr;
    return;
  }
  if (m_hasAutofocused)
    return;
  m_hasAutofocused = true;
  DCHECK(!m_autofocusElement);
  m_autofocusElement = element;
  postTask(TaskType::UserInteraction, BLINK_FROM_HERE,
           createSameThreadTask(&runAutofocusTask));
}

Element* Document::activeElement() const {
  if (Element* element = adjustedFocusedElement())
    return element;
  return body();
}

bool Document::hasFocus() const {
  return page() && page()->focusController().isDocumentFocused(*this);
}

template <unsigned type>
bool shouldInvalidateNodeListCachesForAttr(
    const HeapHashSet<WeakMember<const LiveNodeListBase>> nodeLists[],
    const QualifiedName& attrName) {
  if (!nodeLists[type].isEmpty() &&
      LiveNodeListBase::shouldInvalidateTypeOnAttributeChange(
          static_cast<NodeListInvalidationType>(type), attrName))
    return true;
  return shouldInvalidateNodeListCachesForAttr<type + 1>(nodeLists, attrName);
}

template <>
bool shouldInvalidateNodeListCachesForAttr<numNodeListInvalidationTypes>(
    const HeapHashSet<WeakMember<const LiveNodeListBase>>[],
    const QualifiedName&) {
  return false;
}

bool Document::shouldInvalidateNodeListCaches(
    const QualifiedName* attrName) const {
  if (attrName) {
    return shouldInvalidateNodeListCachesForAttr<
        DoNotInvalidateOnAttributeChanges + 1>(m_nodeLists, *attrName);
  }

  for (int type = 0; type < numNodeListInvalidationTypes; ++type) {
    if (!m_nodeLists[type].isEmpty())
      return true;
  }

  return false;
}

void Document::invalidateNodeListCaches(const QualifiedName* attrName) {
  for (const LiveNodeListBase* list : m_listsInvalidatedAtDocument)
    list->invalidateCacheForAttribute(attrName);
}

void Document::platformColorsChanged() {
  if (!isActive())
    return;

  styleEngine().platformColorsChanged();
}

bool Document::isSecureContext(
    String& errorMessage,
    const SecureContextCheck privilegeContextCheck) const {
  if (!isSecureContext(privilegeContextCheck)) {
    errorMessage = SecurityOrigin::isPotentiallyTrustworthyErrorMessage();
    return false;
  }
  return true;
}

bool Document::isSecureContext(
    const SecureContextCheck privilegeContextCheck) const {
  bool isSecure = isSecureContextImpl(privilegeContextCheck);
  if (getSandboxFlags() != SandboxNone) {
    UseCounter::count(
        *this, isSecure
                   ? UseCounter::SecureContextCheckForSandboxedOriginPassed
                   : UseCounter::SecureContextCheckForSandboxedOriginFailed);
  }
  UseCounter::count(*this, isSecure ? UseCounter::SecureContextCheckPassed
                                    : UseCounter::SecureContextCheckFailed);
  return isSecure;
}

void Document::enforceInsecureRequestPolicy(WebInsecureRequestPolicy policy) {
  // Combine the new policy with the existing policy, as a base policy may be
  // inherited from a remote parent before this page's policy is set. In other
  // words, insecure requests should be upgraded or blocked if _either_ the
  // existing policy or the newly enforced policy triggers upgrades or
  // blockage.
  setInsecureRequestPolicy(getInsecureRequestPolicy() | policy);
  if (frame())
    frame()->loader().client()->didEnforceInsecureRequestPolicy(
        getInsecureRequestPolicy());
}

void Document::setShadowCascadeOrder(ShadowCascadeOrder order) {
  DCHECK_NE(order, ShadowCascadeOrder::ShadowCascadeNone);

  if (order == m_shadowCascadeOrder)
    return;

  if (order == ShadowCascadeOrder::ShadowCascadeV0) {
    m_mayContainV0Shadow = true;
    if (m_shadowCascadeOrder == ShadowCascadeOrder::ShadowCascadeV1)
      UseCounter::count(*this, UseCounter::MixedShadowRootV0AndV1);
  }

  // For V0 -> V1 upgrade, we need style recalculation for the whole document.
  if (m_shadowCascadeOrder == ShadowCascadeOrder::ShadowCascadeV0 &&
      order == ShadowCascadeOrder::ShadowCascadeV1) {
    this->setNeedsStyleRecalc(
        SubtreeStyleChange,
        StyleChangeReasonForTracing::create(StyleChangeReason::Shadow));
    UseCounter::count(*this, UseCounter::MixedShadowRootV0AndV1);
  }

  if (order > m_shadowCascadeOrder)
    m_shadowCascadeOrder = order;
}

LayoutViewItem Document::layoutViewItem() const {
  return LayoutViewItem(m_layoutView);
}

PropertyRegistry* Document::propertyRegistry() {
  // TODO(timloh): When the flag is removed, return a reference instead.
  if (!m_propertyRegistry && RuntimeEnabledFeatures::cssVariables2Enabled())
    m_propertyRegistry = PropertyRegistry::create();
  return m_propertyRegistry;
}

const PropertyRegistry* Document::propertyRegistry() const {
  return const_cast<Document*>(this)->propertyRegistry();
}

void Document::incrementPasswordCount() {
  ++m_passwordCount;
  if (isSecureContext() || m_passwordCount != 1) {
    // The browser process only cares about passwords on pages where the
    // top-level URL is not secure. Secure contexts must have a top-level
    // URL that is secure, so there is no need to send notifications for
    // password fields in secure contexts.
    //
    // Also, only send a message on the first visible password field; the
    // browser process doesn't care about the presence of additional
    // password fields beyond that.
    return;
  }
  sendSensitiveInputVisibility();
}

void Document::decrementPasswordCount() {
  DCHECK_GT(m_passwordCount, 0u);
  --m_passwordCount;
  if (isSecureContext() || m_passwordCount > 0)
    return;
  sendSensitiveInputVisibility();
}

DEFINE_TRACE(Document) {
  visitor->trace(m_importsController);
  visitor->trace(m_docType);
  visitor->trace(m_implementation);
  visitor->trace(m_autofocusElement);
  visitor->trace(m_focusedElement);
  visitor->trace(m_sequentialFocusNavigationStartingPoint);
  visitor->trace(m_hoverNode);
  visitor->trace(m_activeHoverElement);
  visitor->trace(m_documentElement);
  visitor->trace(m_rootScrollerController);
  visitor->trace(m_titleElement);
  visitor->trace(m_axObjectCache);
  visitor->trace(m_markers);
  visitor->trace(m_cssTarget);
  visitor->trace(m_currentScriptStack);
  visitor->trace(m_scriptRunner);
  visitor->trace(m_listsInvalidatedAtDocument);
  for (int i = 0; i < numNodeListInvalidationTypes; ++i)
    visitor->trace(m_nodeLists[i]);
  visitor->trace(m_topLayerElements);
  visitor->trace(m_elemSheet);
  visitor->trace(m_nodeIterators);
  visitor->trace(m_ranges);
  visitor->trace(m_styleEngine);
  visitor->trace(m_formController);
  visitor->trace(m_visitedLinkState);
  visitor->trace(m_frame);
  visitor->trace(m_domWindow);
  visitor->trace(m_fetcher);
  visitor->trace(m_parser);
  visitor->trace(m_contextFeatures);
  visitor->trace(m_styleSheetList);
  visitor->trace(m_documentTiming);
  visitor->trace(m_mediaQueryMatcher);
  visitor->trace(m_scriptedAnimationController);
  visitor->trace(m_scriptedIdleTaskController);
  visitor->trace(m_textAutosizer);
  visitor->trace(m_registrationContext);
  visitor->trace(m_customElementMicrotaskRunQueue);
  visitor->trace(m_elementDataCache);
  visitor->trace(m_useElementsNeedingUpdate);
  visitor->trace(m_timers);
  visitor->trace(m_templateDocument);
  visitor->trace(m_templateDocumentHost);
  visitor->trace(m_userActionElements);
  visitor->trace(m_svgExtensions);
  visitor->trace(m_timeline);
  visitor->trace(m_compositorPendingAnimations);
  visitor->trace(m_contextDocument);
  visitor->trace(m_canvasFontCache);
  visitor->trace(m_intersectionObserverController);
  visitor->trace(m_snapCoordinator);
  visitor->trace(m_resizeObserverController);
  visitor->trace(m_propertyRegistry);
  visitor->trace(m_styleReattachDataMap);
  Supplementable<Document>::trace(visitor);
  TreeScope::trace(visitor);
  ContainerNode::trace(visitor);
  ExecutionContext::trace(visitor);
  SecurityContext::trace(visitor);
  SynchronousMutationNotifier::trace(visitor);
}

void Document::maybeRecordLoadReason(WouldLoadReason reason) {
  DCHECK(m_wouldLoadReason == Created || reason != Created);
  DCHECK(frame());
  if (m_wouldLoadReason == Created && frame()->isCrossOriginSubframe() &&
      frame()->loader().stateMachine()->committedFirstRealDocumentLoad()) {
    recordLoadReasonToHistogram(reason);
  }
  m_wouldLoadReason = reason;
}

DEFINE_TRACE_WRAPPERS(Document) {
  visitor->traceWrappers(m_importsController);
  visitor->traceWrappers(m_implementation);
  visitor->traceWrappers(m_styleSheetList);
  visitor->traceWrappers(m_styleEngine);
  for (int i = 0; i < numNodeListInvalidationTypes; ++i) {
    for (auto list : m_nodeLists[i]) {
      if (isHTMLCollectionType(list->type())) {
        visitor->traceWrappersWithManualWriteBarrier(
            static_cast<const HTMLCollection*>(list.get()));
      } else {
        visitor->traceWrappersWithManualWriteBarrier(
            static_cast<const LiveNodeList*>(list.get()));
      }
    }
  }
  // Cannot trace in Supplementable<Document> as it is part of platform/ and
  // thus cannot refer to ScriptWrappableVisitor.
  visitor->traceWrappers(
      static_cast<FontFaceSet*>(Supplementable<Document>::m_supplements.get(
          FontFaceSet::supplementName())));
  ContainerNode::traceWrappers(visitor);
}

template class CORE_TEMPLATE_EXPORT Supplement<Document>;

}  // namespace blink

#ifndef NDEBUG
using namespace blink;

static WeakDocumentSet& liveDocumentSet() {
  DEFINE_STATIC_LOCAL(WeakDocumentSet, set, ());
  return set;
}

void showLiveDocumentInstances() {
  WeakDocumentSet& set = liveDocumentSet();
  fprintf(stderr, "There are %u documents currently alive:\n", set.size());
  for (Document* document : set)
    fprintf(stderr, "- Document %p URL: %s\n", document,
            document->url().getString().utf8().data());
}
#endif
