/*
 * 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/ExceptionStatePlaceholder.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/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/tracing/TraceEvent.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::Internal, 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::Internal, 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::Internal, this),
                           this,
                           &Document::pluginLoadingTimerFired),
      m_documentTiming(*this),
      m_writeRecursionIsTooDeep(false),
      m_writeRecursionDepth(0),
      m_registrationContext(initializer.registrationContext(this)),
      m_elementDataCacheClearTimer(
          TaskRunnerHelper::get(TaskType::Internal, this),
          this,
          &Document::elementDataCacheClearTimerFired),
      m_timeline(DocumentTimeline::create(this)),
      m_compositorPendingAnimations(new CompositorPendingAnimations()),
      m_templateDocumentHost(nullptr),
      m_didAssociateFormControlsTimer(
          TaskRunnerHelper::get(TaskType::Internal, 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) {
  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()->activeDOMObjectsAreSuspended());

#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::setNeedsFocusedElementCheck() {
  setNeedsStyleRecalc(
      LocalStyleChange,
      StyleChangeReasonForTracing::createWithExtraData(
          StyleChangeReason::PseudoClass, StyleChangeExtraData::Focus));
}

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::Hidden;  // 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->accessibilityEnabled())
    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()->accessibilityEnabled()) {
    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()->viewportMetaMergeContentQuirk() &&
         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()->viewportMetaEnabled();
  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::notifyResizeForViewportUnits() {
  if (m_mediaQueryMatcher)
    m_mediaQueryMatcher->viewportChanged();
  if (!hasViewportUnits())
    return;
  ensureStyleResolver().notifyResizeForViewportUnits();
  setNeedsStyleRecalcForViewportUnits();
}

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();
}

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::Internal, 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::GetProxy(&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()->cookieEnabled())
    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()->cookieEnabled())
    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()->request().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::Visual : EOrder::Logical);
    }
    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::allForBinding() {
  UseCounter::count(*this, UseCounter::DocumentAll);
  return all();
}

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->webSecurityEnabled()) {
      // 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->allowUniversalAccessFromFileURLs()) {
        // Some clients want local URLs to have universal access, but that
        // setting is dangerous for other clients.
        getSecurityOrigin()->grantUniversalAccess();
      } else if (!settings->allowFileAccessFromFileURLs()) {
        // 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->dnsPrefetchingEnabled() &&
                           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(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(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;
}

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
