/*
 * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "core/frame/LocalDOMWindow.h"

#include "bindings/core/v8/ScriptController.h"
#include "bindings/core/v8/SourceLocation.h"
#include "bindings/core/v8/WindowProxy.h"
#include "core/css/CSSComputedStyleDeclaration.h"
#include "core/css/CSSRuleList.h"
#include "core/css/DOMWindowCSS.h"
#include "core/css/MediaQueryList.h"
#include "core/css/MediaQueryMatcher.h"
#include "core/css/StyleMedia.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/dom/DOMImplementation.h"
#include "core/dom/DocumentUserGestureToken.h"
#include "core/dom/ExecutionContextTask.h"
#include "core/dom/FrameRequestCallback.h"
#include "core/dom/SandboxFlags.h"
#include "core/dom/TaskRunnerHelper.h"
#include "core/dom/custom/CustomElementRegistry.h"
#include "core/editing/Editor.h"
#include "core/events/DOMWindowEventQueue.h"
#include "core/events/HashChangeEvent.h"
#include "core/events/MessageEvent.h"
#include "core/events/PageTransitionEvent.h"
#include "core/events/PopStateEvent.h"
#include "core/events/ScopedEventQueue.h"
#include "core/frame/BarProp.h"
#include "core/frame/DOMVisualViewport.h"
#include "core/frame/EventHandlerRegistry.h"
#include "core/frame/FrameConsole.h"
#include "core/frame/FrameView.h"
#include "core/frame/History.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Navigator.h"
#include "core/frame/Screen.h"
#include "core/frame/ScrollToOptions.h"
#include "core/frame/Settings.h"
#include "core/frame/SuspendableTimer.h"
#include "core/frame/VisualViewport.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/input/EventHandler.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/inspector/InspectorTraceEvents.h"
#include "core/loader/DocumentLoader.h"
#include "core/loader/FrameLoaderClient.h"
#include "core/loader/SinkDocument.h"
#include "core/loader/appcache/ApplicationCache.h"
#include "core/page/ChromeClient.h"
#include "core/page/CreateWindow.h"
#include "core/page/Page.h"
#include "core/page/WindowFeatures.h"
#include "core/page/scrolling/ScrollingCoordinator.h"
#include "core/timing/DOMWindowPerformance.h"
#include "core/timing/Performance.h"
#include "platform/EventDispatchForbiddenScope.h"
#include "platform/WebFrameScheduler.h"
#include "platform/loader/fetch/ResourceFetcher.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "platform/weborigin/Suborigin.h"
#include "public/platform/Platform.h"
#include "public/platform/WebScreenInfo.h"
#include <memory>

namespace blink {

// Timeout for link preloads to be used after window.onload
static const int unusedPreloadTimeoutInSeconds = 3;

class PostMessageTimer final
    : public GarbageCollectedFinalized<PostMessageTimer>,
      public SuspendableTimer {
  USING_GARBAGE_COLLECTED_MIXIN(PostMessageTimer);

 public:
  PostMessageTimer(LocalDOMWindow& window,
                   MessageEvent* event,
                   PassRefPtr<SecurityOrigin> targetOrigin,
                   std::unique_ptr<SourceLocation> location,
                   UserGestureToken* userGestureToken)
      : SuspendableTimer(window.document(), TaskType::Timer),
        m_event(event),
        m_window(&window),
        m_targetOrigin(targetOrigin),
        m_location(std::move(location)),
        m_userGestureToken(userGestureToken),
        m_disposalAllowed(true) {
    InspectorInstrumentation::asyncTaskScheduled(window.document(),
                                                 "postMessage", this);
  }

  MessageEvent* event() const { return m_event; }
  SecurityOrigin* targetOrigin() const { return m_targetOrigin.get(); }
  std::unique_ptr<SourceLocation> takeLocation() {
    return std::move(m_location);
  }
  UserGestureToken* userGestureToken() const {
    return m_userGestureToken.get();
  }
  void contextDestroyed(ExecutionContext* destroyedContext) override {
    SuspendableTimer::contextDestroyed(destroyedContext);

    if (m_disposalAllowed)
      dispose();
  }

  // Eager finalization is needed to promptly stop this timer object.
  // (see DOMTimer comment for more.)
  EAGERLY_FINALIZE();
  DEFINE_INLINE_VIRTUAL_TRACE() {
    visitor->trace(m_event);
    visitor->trace(m_window);
    SuspendableTimer::trace(visitor);
  }

  // TODO(alexclarke): Override timerTaskRunner() to pass in a document specific
  // default task runner.

 private:
  void fired() override {
    InspectorInstrumentation::AsyncTask asyncTask(m_window->document(), this);
    m_disposalAllowed = false;
    m_window->postMessageTimerFired(this);
    dispose();
    // Oilpan optimization: unregister as an observer right away.
    clearContext();
  }

  void dispose() { m_window->removePostMessageTimer(this); }

  Member<MessageEvent> m_event;
  Member<LocalDOMWindow> m_window;
  RefPtr<SecurityOrigin> m_targetOrigin;
  std::unique_ptr<SourceLocation> m_location;
  RefPtr<UserGestureToken> m_userGestureToken;
  bool m_disposalAllowed;
};

static void updateSuddenTerminationStatus(
    LocalDOMWindow* domWindow,
    bool addedListener,
    FrameLoaderClient::SuddenTerminationDisablerType disablerType) {
  Platform::current()->suddenTerminationChanged(!addedListener);
  if (domWindow->frame() && domWindow->frame()->loader().client())
    domWindow->frame()->loader().client()->suddenTerminationDisablerChanged(
        addedListener, disablerType);
}

using DOMWindowSet = PersistentHeapHashCountedSet<WeakMember<LocalDOMWindow>>;

static DOMWindowSet& windowsWithUnloadEventListeners() {
  DEFINE_STATIC_LOCAL(DOMWindowSet, windowsWithUnloadEventListeners, ());
  return windowsWithUnloadEventListeners;
}

static DOMWindowSet& windowsWithBeforeUnloadEventListeners() {
  DEFINE_STATIC_LOCAL(DOMWindowSet, windowsWithBeforeUnloadEventListeners, ());
  return windowsWithBeforeUnloadEventListeners;
}

static void addUnloadEventListener(LocalDOMWindow* domWindow) {
  DOMWindowSet& set = windowsWithUnloadEventListeners();
  if (set.isEmpty())
    updateSuddenTerminationStatus(domWindow, true,
                                  FrameLoaderClient::UnloadHandler);

  set.add(domWindow);
}

static void removeUnloadEventListener(LocalDOMWindow* domWindow) {
  DOMWindowSet& set = windowsWithUnloadEventListeners();
  DOMWindowSet::iterator it = set.find(domWindow);
  if (it == set.end())
    return;
  set.remove(it);
  if (set.isEmpty())
    updateSuddenTerminationStatus(domWindow, false,
                                  FrameLoaderClient::UnloadHandler);
}

static void removeAllUnloadEventListeners(LocalDOMWindow* domWindow) {
  DOMWindowSet& set = windowsWithUnloadEventListeners();
  DOMWindowSet::iterator it = set.find(domWindow);
  if (it == set.end())
    return;
  set.removeAll(it);
  if (set.isEmpty())
    updateSuddenTerminationStatus(domWindow, false,
                                  FrameLoaderClient::UnloadHandler);
}

static void addBeforeUnloadEventListener(LocalDOMWindow* domWindow) {
  DOMWindowSet& set = windowsWithBeforeUnloadEventListeners();
  if (set.isEmpty())
    updateSuddenTerminationStatus(domWindow, true,
                                  FrameLoaderClient::BeforeUnloadHandler);

  set.add(domWindow);
}

static void removeBeforeUnloadEventListener(LocalDOMWindow* domWindow) {
  DOMWindowSet& set = windowsWithBeforeUnloadEventListeners();
  DOMWindowSet::iterator it = set.find(domWindow);
  if (it == set.end())
    return;
  set.remove(it);
  if (set.isEmpty())
    updateSuddenTerminationStatus(domWindow, false,
                                  FrameLoaderClient::BeforeUnloadHandler);
}

static void removeAllBeforeUnloadEventListeners(LocalDOMWindow* domWindow) {
  DOMWindowSet& set = windowsWithBeforeUnloadEventListeners();
  DOMWindowSet::iterator it = set.find(domWindow);
  if (it == set.end())
    return;
  set.removeAll(it);
  if (set.isEmpty())
    updateSuddenTerminationStatus(domWindow, false,
                                  FrameLoaderClient::BeforeUnloadHandler);
}

static bool allowsBeforeUnloadListeners(LocalDOMWindow* window) {
  DCHECK(window);
  LocalFrame* frame = window->frame();
  if (!frame)
    return false;
  return frame->isMainFrame();
}

unsigned LocalDOMWindow::pendingUnloadEventListeners() const {
  return windowsWithUnloadEventListeners().count(
      const_cast<LocalDOMWindow*>(this));
}

bool LocalDOMWindow::allowPopUp(LocalFrame& firstFrame) {
  if (UserGestureIndicator::utilizeUserGesture())
    return true;

  Settings* settings = firstFrame.settings();
  return settings && settings->getJavaScriptCanOpenWindowsAutomatically();
}

bool LocalDOMWindow::allowPopUp() {
  return frame() && allowPopUp(*frame());
}

LocalDOMWindow::LocalDOMWindow(LocalFrame& frame)
    : DOMWindow(frame),
      m_visualViewport(DOMVisualViewport::create(this)),
      m_unusedPreloadsTimer(
          TaskRunnerHelper::get(TaskType::UnspecedTimer, &frame),
          this,
          &LocalDOMWindow::warnUnusedPreloads),
      m_shouldPrintWhenFinishedLoading(false),
      m_customElements(this, nullptr) {}

void LocalDOMWindow::clearDocument() {
  if (!m_document)
    return;

  ASSERT(!m_document->isActive());

  // FIXME: This should be part of SuspendableObject shutdown
  clearEventQueue();

  m_unusedPreloadsTimer.stop();
  m_document->clearDOMWindow();
  m_document = nullptr;
}

void LocalDOMWindow::clearEventQueue() {
  if (!m_eventQueue)
    return;
  m_eventQueue->close();
  m_eventQueue.clear();
}

void LocalDOMWindow::acceptLanguagesChanged() {
  if (m_navigator)
    m_navigator->setLanguagesChanged();

  dispatchEvent(Event::create(EventTypeNames::languagechange));
}

Document* LocalDOMWindow::createDocument(const String& mimeType,
                                         const DocumentInit& init,
                                         bool forceXHTML) {
  Document* document = nullptr;
  if (forceXHTML) {
    // This is a hack for XSLTProcessor. See
    // XSLTProcessor::createDocumentFromSource().
    document = Document::create(init);
  } else {
    document = DOMImplementation::createDocument(
        mimeType, init,
        init.frame() ? init.frame()->inViewSourceMode() : false);
    if (document->isPluginDocument() && document->isSandboxed(SandboxPlugins))
      document = SinkDocument::create(init);
  }

  return document;
}

Document* LocalDOMWindow::installNewDocument(const String& mimeType,
                                             const DocumentInit& init,
                                             bool forceXHTML) {
  ASSERT(init.frame() == frame());

  clearDocument();

  m_document = createDocument(mimeType, init, forceXHTML);
  m_eventQueue = DOMWindowEventQueue::create(m_document.get());
  m_document->initialize();

  if (!frame())
    return m_document;

  frame()->script().updateDocument();
  m_document->updateViewportDescription();

  if (frame()->page() && frame()->view()) {
    if (ScrollingCoordinator* scrollingCoordinator =
            frame()->page()->scrollingCoordinator()) {
      scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(
          frame()->view(), HorizontalScrollbar);
      scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(
          frame()->view(), VerticalScrollbar);
      scrollingCoordinator->scrollableAreaScrollLayerDidChange(frame()->view());
    }
  }

  frame()->selection().updateSecureKeyboardEntryIfActive();

  m_document->maybeRecordLoadReason(Created);

  return m_document;
}

EventQueue* LocalDOMWindow::getEventQueue() const {
  return m_eventQueue.get();
}

void LocalDOMWindow::enqueueWindowEvent(Event* event) {
  if (!m_eventQueue)
    return;
  event->setTarget(this);
  m_eventQueue->enqueueEvent(event);
}

void LocalDOMWindow::enqueueDocumentEvent(Event* event) {
  if (!m_eventQueue)
    return;
  event->setTarget(m_document.get());
  m_eventQueue->enqueueEvent(event);
}

void LocalDOMWindow::dispatchWindowLoadEvent() {
#if DCHECK_IS_ON()
  DCHECK(!EventDispatchForbiddenScope::isEventDispatchForbidden());
#endif
  // Delay 'load' event if we are in EventQueueScope.  This is a short-term
  // workaround to avoid Editing code crashes.  We should always dispatch
  // 'load' event asynchronously.  crbug.com/569511.
  if (ScopedEventQueue::instance()->shouldQueueEvents() && m_document) {
    m_document->postTask(
        TaskType::Networking, BLINK_FROM_HERE,
        createSameThreadTask(&LocalDOMWindow::dispatchLoadEvent,
                             wrapPersistent(this)));
    return;
  }
  dispatchLoadEvent();
}

void LocalDOMWindow::documentWasClosed() {
  dispatchWindowLoadEvent();
  enqueuePageshowEvent(PageshowEventNotPersisted);
  if (m_pendingStateObject)
    enqueuePopstateEvent(std::move(m_pendingStateObject));
}

void LocalDOMWindow::enqueuePageshowEvent(PageshowEventPersistence persisted) {
  // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36334 Pageshow event needs
  // to fire asynchronously.  As per spec pageshow must be triggered
  // asynchronously.  However to be compatible with other browsers blink fires
  // pageshow synchronously.
  dispatchEvent(
      PageTransitionEvent::create(EventTypeNames::pageshow, persisted),
      m_document.get());
}

void LocalDOMWindow::enqueueHashchangeEvent(const String& oldURL,
                                            const String& newURL) {
  enqueueWindowEvent(HashChangeEvent::create(oldURL, newURL));
}

void LocalDOMWindow::enqueuePopstateEvent(
    PassRefPtr<SerializedScriptValue> stateObject) {
  // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36202 Popstate event needs
  // to fire asynchronously
  dispatchEvent(PopStateEvent::create(std::move(stateObject), history()));
}

void LocalDOMWindow::statePopped(
    PassRefPtr<SerializedScriptValue> stateObject) {
  if (!frame())
    return;

  // Per step 11 of section 6.5.9 (history traversal) of the HTML5 spec, we
  // defer firing of popstate until we're in the complete state.
  if (document()->isLoadCompleted())
    enqueuePopstateEvent(std::move(stateObject));
  else
    m_pendingStateObject = stateObject;
}

LocalDOMWindow::~LocalDOMWindow() {
  // Cleared when detaching document.
  ASSERT(!m_eventQueue);
}

void LocalDOMWindow::dispose() {
  // Oilpan: should the LocalDOMWindow be GCed along with its LocalFrame without
  // the frame having first notified its observers of imminent destruction, the
  // LocalDOMWindow will not have had an opportunity to remove event listeners.
  //
  // Arrange for that removal to happen using a prefinalizer action. Making
  // LocalDOMWindow eager finalizable is problematic as other eagerly finalized
  // objects may well want to access their associated LocalDOMWindow from their
  // destructors.
  if (!frame())
    return;

  removeAllEventListeners();
}

ExecutionContext* LocalDOMWindow::getExecutionContext() const {
  return m_document.get();
}

const LocalDOMWindow* LocalDOMWindow::toLocalDOMWindow() const {
  return this;
}

LocalDOMWindow* LocalDOMWindow::toLocalDOMWindow() {
  return this;
}

MediaQueryList* LocalDOMWindow::matchMedia(const String& media) {
  return document() ? document()->mediaQueryMatcher().matchMedia(media)
                    : nullptr;
}

void LocalDOMWindow::frameDestroyed() {
  resetLocation();
  removeAllEventListeners();
  disconnectFromFrame();
}

void LocalDOMWindow::registerEventListenerObserver(
    EventListenerObserver* eventListenerObserver) {
  m_eventListenerObservers.add(eventListenerObserver);
}

void LocalDOMWindow::reset() {
  DCHECK(document());
  DCHECK(document()->isContextDestroyed());
  frameDestroyed();

  m_screen = nullptr;
  m_history = nullptr;
  m_locationbar = nullptr;
  m_menubar = nullptr;
  m_personalbar = nullptr;
  m_scrollbars = nullptr;
  m_statusbar = nullptr;
  m_toolbar = nullptr;
  m_navigator = nullptr;
  m_media = nullptr;
  m_customElements = nullptr;
  m_applicationCache = nullptr;
}

void LocalDOMWindow::sendOrientationChangeEvent() {
  ASSERT(RuntimeEnabledFeatures::orientationEventEnabled());
  ASSERT(frame()->isMainFrame());

  // Before dispatching the event, build a list of all frames in the page
  // to send the event to, to mitigate side effects from event handlers
  // potentially interfering with others.
  HeapVector<Member<Frame>> frames;
  for (Frame* f = frame(); f; f = f->tree().traverseNext())
    frames.push_back(f);

  for (size_t i = 0; i < frames.size(); ++i) {
    if (!frames[i]->isLocalFrame())
      continue;
    toLocalFrame(frames[i].get())
        ->domWindow()
        ->dispatchEvent(Event::create(EventTypeNames::orientationchange));
  }
}

int LocalDOMWindow::orientation() const {
  ASSERT(RuntimeEnabledFeatures::orientationEventEnabled());

  if (!frame() || !frame()->host())
    return 0;

  int orientation =
      frame()->host()->chromeClient().screenInfo().orientationAngle;
  // For backward compatibility, we want to return a value in the range of
  // [-90; 180] instead of [0; 360[ because window.orientation used to behave
  // like that in WebKit (this is a WebKit proprietary API).
  if (orientation == 270)
    return -90;
  return orientation;
}

Screen* LocalDOMWindow::screen() const {
  if (!m_screen)
    m_screen = Screen::create(frame());
  return m_screen.get();
}

History* LocalDOMWindow::history() const {
  if (!m_history)
    m_history = History::create(frame());
  return m_history.get();
}

BarProp* LocalDOMWindow::locationbar() const {
  if (!m_locationbar)
    m_locationbar = BarProp::create(frame(), BarProp::Locationbar);
  return m_locationbar.get();
}

BarProp* LocalDOMWindow::menubar() const {
  if (!m_menubar)
    m_menubar = BarProp::create(frame(), BarProp::Menubar);
  return m_menubar.get();
}

BarProp* LocalDOMWindow::personalbar() const {
  if (!m_personalbar)
    m_personalbar = BarProp::create(frame(), BarProp::Personalbar);
  return m_personalbar.get();
}

BarProp* LocalDOMWindow::scrollbars() const {
  if (!m_scrollbars)
    m_scrollbars = BarProp::create(frame(), BarProp::Scrollbars);
  return m_scrollbars.get();
}

BarProp* LocalDOMWindow::statusbar() const {
  if (!m_statusbar)
    m_statusbar = BarProp::create(frame(), BarProp::Statusbar);
  return m_statusbar.get();
}

BarProp* LocalDOMWindow::toolbar() const {
  if (!m_toolbar)
    m_toolbar = BarProp::create(frame(), BarProp::Toolbar);
  return m_toolbar.get();
}

FrameConsole* LocalDOMWindow::frameConsole() const {
  if (!isCurrentlyDisplayedInFrame())
    return nullptr;
  return &frame()->console();
}

ApplicationCache* LocalDOMWindow::applicationCache() const {
  if (!isCurrentlyDisplayedInFrame())
    return nullptr;
  if (!m_applicationCache)
    m_applicationCache = ApplicationCache::create(frame());
  return m_applicationCache.get();
}

Navigator* LocalDOMWindow::navigator() const {
  if (!m_navigator)
    m_navigator = Navigator::create(frame());
  return m_navigator.get();
}

void LocalDOMWindow::schedulePostMessage(MessageEvent* event,
                                         PassRefPtr<SecurityOrigin> target,
                                         Document* source) {
  // Allowing unbounded amounts of messages to build up for a suspended context
  // is problematic; consider imposing a limit or other restriction if this
  // surfaces often as a problem (see crbug.com/587012).
  std::unique_ptr<SourceLocation> location = SourceLocation::capture(source);
  PostMessageTimer* timer =
      new PostMessageTimer(*this, event, std::move(target), std::move(location),
                           UserGestureIndicator::currentToken());
  timer->startOneShot(0, BLINK_FROM_HERE);
  timer->suspendIfNeeded();
  m_postMessageTimers.add(timer);
}

void LocalDOMWindow::postMessageTimerFired(PostMessageTimer* timer) {
  if (!isCurrentlyDisplayedInFrame())
    return;

  MessageEvent* event = timer->event();

  UserGestureIndicator gestureIndicator(
      DocumentUserGestureToken::adopt(document(), timer->userGestureToken()));

  event->entangleMessagePorts(document());

  dispatchMessageEventWithOriginCheck(timer->targetOrigin(), event,
                                      timer->takeLocation());
}

void LocalDOMWindow::removePostMessageTimer(PostMessageTimer* timer) {
  m_postMessageTimers.remove(timer);
}

void LocalDOMWindow::dispatchMessageEventWithOriginCheck(
    SecurityOrigin* intendedTargetOrigin,
    Event* event,
    std::unique_ptr<SourceLocation> location) {
  if (intendedTargetOrigin) {
    // Check target origin now since the target document may have changed since
    // the timer was scheduled.
    SecurityOrigin* securityOrigin = document()->getSecurityOrigin();
    bool validTarget =
        intendedTargetOrigin->isSameSchemeHostPortAndSuborigin(securityOrigin);
    if (securityOrigin->hasSuborigin() &&
        securityOrigin->suborigin()->policyContains(
            Suborigin::SuboriginPolicyOptions::UnsafePostMessageReceive))
      validTarget = intendedTargetOrigin->isSameSchemeHostPort(securityOrigin);

    if (!validTarget) {
      String message = ExceptionMessages::failedToExecute(
          "postMessage", "DOMWindow",
          "The target origin provided ('" + intendedTargetOrigin->toString() +
              "') does not match the recipient window's origin ('" +
              document()->getSecurityOrigin()->toString() + "').");
      ConsoleMessage* consoleMessage =
          ConsoleMessage::create(SecurityMessageSource, ErrorMessageLevel,
                                 message, std::move(location));
      frameConsole()->addMessage(consoleMessage);
      return;
    }
  }

  dispatchEvent(event);
}

DOMSelection* LocalDOMWindow::getSelection() {
  if (!isCurrentlyDisplayedInFrame())
    return nullptr;

  return document()->getSelection();
}

Element* LocalDOMWindow::frameElement() const {
  if (!(frame() && frame()->owner() && frame()->owner()->isLocal()))
    return nullptr;

  return toHTMLFrameOwnerElement(frame()->owner());
}

void LocalDOMWindow::blur() {}

void LocalDOMWindow::print(ScriptState* scriptState) {
  if (!frame())
    return;

  FrameHost* host = frame()->host();
  if (!host)
    return;

  if (scriptState &&
      v8::MicrotasksScope::IsRunningMicrotasks(scriptState->isolate())) {
    UseCounter::count(document(), UseCounter::During_Microtask_Print);
  }

  if (frame()->isLoading()) {
    m_shouldPrintWhenFinishedLoading = true;
    return;
  }

  UseCounter::countCrossOriginIframe(*document(),
                                     UseCounter::CrossOriginWindowPrint);

  m_shouldPrintWhenFinishedLoading = false;
  host->chromeClient().print(frame());
}

void LocalDOMWindow::stop() {
  if (!frame())
    return;
  frame()->loader().stopAllLoaders();
}

void LocalDOMWindow::alert(ScriptState* scriptState, const String& message) {
  if (!frame())
    return;

  if (document()->isSandboxed(SandboxModals)) {
    UseCounter::count(document(), UseCounter::DialogInSandboxedContext);
    frameConsole()->addMessage(ConsoleMessage::create(
        SecurityMessageSource, ErrorMessageLevel,
        "Ignored call to 'alert()'. The document is sandboxed, and the "
        "'allow-modals' keyword is not set."));
    return;
  }

  switch (document()->getEngagementLevel()) {
    case mojom::blink::EngagementLevel::NONE:
      UseCounter::count(document(), UseCounter::AlertEngagementNone);
      break;
    case mojom::blink::EngagementLevel::MINIMAL:
      UseCounter::count(document(), UseCounter::AlertEngagementMinimal);
      break;
    case mojom::blink::EngagementLevel::LOW:
      UseCounter::count(document(), UseCounter::AlertEngagementLow);
      break;
    case mojom::blink::EngagementLevel::MEDIUM:
      UseCounter::count(document(), UseCounter::AlertEngagementMedium);
      break;
    case mojom::blink::EngagementLevel::HIGH:
      UseCounter::count(document(), UseCounter::AlertEngagementHigh);
      break;
    case mojom::blink::EngagementLevel::MAX:
      UseCounter::count(document(), UseCounter::AlertEngagementMax);
      break;
  }

  if (v8::MicrotasksScope::IsRunningMicrotasks(scriptState->isolate())) {
    UseCounter::count(document(), UseCounter::During_Microtask_Alert);
  }

  document()->updateStyleAndLayoutTree();

  FrameHost* host = frame()->host();
  if (!host)
    return;

  UseCounter::countCrossOriginIframe(*document(),
                                     UseCounter::CrossOriginWindowAlert);

  host->chromeClient().openJavaScriptAlert(frame(), message);
}

bool LocalDOMWindow::confirm(ScriptState* scriptState, const String& message) {
  if (!frame())
    return false;

  if (document()->isSandboxed(SandboxModals)) {
    UseCounter::count(document(), UseCounter::DialogInSandboxedContext);
    frameConsole()->addMessage(ConsoleMessage::create(
        SecurityMessageSource, ErrorMessageLevel,
        "Ignored call to 'confirm()'. The document is sandboxed, and the "
        "'allow-modals' keyword is not set."));
    return false;
  }

  switch (document()->getEngagementLevel()) {
    case mojom::blink::EngagementLevel::NONE:
      UseCounter::count(document(), UseCounter::ConfirmEngagementNone);
      break;
    case mojom::blink::EngagementLevel::MINIMAL:
      UseCounter::count(document(), UseCounter::ConfirmEngagementMinimal);
      break;
    case mojom::blink::EngagementLevel::LOW:
      UseCounter::count(document(), UseCounter::ConfirmEngagementLow);
      break;
    case mojom::blink::EngagementLevel::MEDIUM:
      UseCounter::count(document(), UseCounter::ConfirmEngagementMedium);
      break;
    case mojom::blink::EngagementLevel::HIGH:
      UseCounter::count(document(), UseCounter::ConfirmEngagementHigh);
      break;
    case mojom::blink::EngagementLevel::MAX:
      UseCounter::count(document(), UseCounter::ConfirmEngagementMax);
      break;
  }

  if (v8::MicrotasksScope::IsRunningMicrotasks(scriptState->isolate())) {
    UseCounter::count(document(), UseCounter::During_Microtask_Confirm);
  }

  document()->updateStyleAndLayoutTree();

  FrameHost* host = frame()->host();
  if (!host)
    return false;

  UseCounter::countCrossOriginIframe(*document(),
                                     UseCounter::CrossOriginWindowConfirm);

  return host->chromeClient().openJavaScriptConfirm(frame(), message);
}

String LocalDOMWindow::prompt(ScriptState* scriptState,
                              const String& message,
                              const String& defaultValue) {
  if (!frame())
    return String();

  if (document()->isSandboxed(SandboxModals)) {
    UseCounter::count(document(), UseCounter::DialogInSandboxedContext);
    frameConsole()->addMessage(ConsoleMessage::create(
        SecurityMessageSource, ErrorMessageLevel,
        "Ignored call to 'prompt()'. The document is sandboxed, and the "
        "'allow-modals' keyword is not set."));
    return String();
  }

  switch (document()->getEngagementLevel()) {
    case mojom::blink::EngagementLevel::NONE:
      UseCounter::count(document(), UseCounter::PromptEngagementNone);
      break;
    case mojom::blink::EngagementLevel::MINIMAL:
      UseCounter::count(document(), UseCounter::PromptEngagementMinimal);
      break;
    case mojom::blink::EngagementLevel::LOW:
      UseCounter::count(document(), UseCounter::PromptEngagementLow);
      break;
    case mojom::blink::EngagementLevel::MEDIUM:
      UseCounter::count(document(), UseCounter::PromptEngagementMedium);
      break;
    case mojom::blink::EngagementLevel::HIGH:
      UseCounter::count(document(), UseCounter::PromptEngagementHigh);
      break;
    case mojom::blink::EngagementLevel::MAX:
      UseCounter::count(document(), UseCounter::PromptEngagementMax);
      break;
  }

  if (v8::MicrotasksScope::IsRunningMicrotasks(scriptState->isolate())) {
    UseCounter::count(document(), UseCounter::During_Microtask_Prompt);
  }

  document()->updateStyleAndLayoutTree();

  FrameHost* host = frame()->host();
  if (!host)
    return String();

  String returnValue;
  if (host->chromeClient().openJavaScriptPrompt(frame(), message, defaultValue,
                                                returnValue))
    return returnValue;

  UseCounter::countCrossOriginIframe(*document(),
                                     UseCounter::CrossOriginWindowPrompt);

  return String();
}

bool LocalDOMWindow::find(const String& string,
                          bool caseSensitive,
                          bool backwards,
                          bool wrap,
                          bool wholeWord,
                          bool /*searchInFrames*/,
                          bool /*showDialog*/) const {
  if (!isCurrentlyDisplayedInFrame())
    return false;

  // Up-to-date, clean tree is required for finding text in page, since it
  // relies on TextIterator to look over the text.
  document()->updateStyleAndLayoutIgnorePendingStylesheets();

  // FIXME (13016): Support searchInFrames and showDialog
  FindOptions options =
      (backwards ? Backwards : 0) | (caseSensitive ? 0 : CaseInsensitive) |
      (wrap ? WrapAround : 0) | (wholeWord ? WholeWord | AtWordStarts : 0);
  return frame()->editor().findString(string, options);
}

bool LocalDOMWindow::offscreenBuffering() const {
  return true;
}

int LocalDOMWindow::outerHeight() const {
  if (!frame())
    return 0;

  FrameHost* host = frame()->host();
  if (!host)
    return 0;

  ChromeClient& chromeClient = host->chromeClient();
  if (host->settings().getReportScreenSizeInPhysicalPixelsQuirk())
    return lroundf(chromeClient.rootWindowRect().height() *
                   chromeClient.screenInfo().deviceScaleFactor);
  return chromeClient.rootWindowRect().height();
}

int LocalDOMWindow::outerWidth() const {
  if (!frame())
    return 0;

  FrameHost* host = frame()->host();
  if (!host)
    return 0;

  ChromeClient& chromeClient = host->chromeClient();
  if (host->settings().getReportScreenSizeInPhysicalPixelsQuirk())
    return lroundf(chromeClient.rootWindowRect().width() *
                   chromeClient.screenInfo().deviceScaleFactor);

  return chromeClient.rootWindowRect().width();
}

FloatSize LocalDOMWindow::getViewportSize(
    IncludeScrollbarsInRect scrollbarInclusion) const {
  if (!frame())
    return FloatSize();

  FrameView* view = frame()->view();
  if (!view)
    return FloatSize();

  FrameHost* host = frame()->host();
  if (!host)
    return FloatSize();

  // The main frame's viewport size depends on the page scale. Since the
  // initial page scale depends on the content width and is set after a
  // layout, perform one now so queries during page load will use the up to
  // date viewport.
  if (host->settings().getViewportEnabled() && frame()->isMainFrame())
    document()->updateStyleAndLayoutIgnorePendingStylesheets();

  // FIXME: This is potentially too much work. We really only need to know the
  // dimensions of the parent frame's layoutObject.
  if (Frame* parent = frame()->tree().parent()) {
    if (parent && parent->isLocalFrame())
      toLocalFrame(parent)
          ->document()
          ->updateStyleAndLayoutIgnorePendingStylesheets();
  }

  return frame()->isMainFrame() && !host->settings().getInertVisualViewport()
             ? FloatSize(host->visualViewport().visibleRect().size())
             : FloatSize(view->visibleContentRect(scrollbarInclusion).size());
}

int LocalDOMWindow::innerHeight() const {
  if (!frame())
    return 0;

  FloatSize viewportSize = getViewportSize(IncludeScrollbars);
  return adjustForAbsoluteZoom(expandedIntSize(viewportSize).height(),
                               frame()->pageZoomFactor());
}

int LocalDOMWindow::innerWidth() const {
  if (!frame())
    return 0;

  FloatSize viewportSize = getViewportSize(IncludeScrollbars);
  return adjustForAbsoluteZoom(expandedIntSize(viewportSize).width(),
                               frame()->pageZoomFactor());
}

int LocalDOMWindow::screenX() const {
  if (!frame())
    return 0;

  FrameHost* host = frame()->host();
  if (!host)
    return 0;

  ChromeClient& chromeClient = host->chromeClient();
  if (host->settings().getReportScreenSizeInPhysicalPixelsQuirk())
    return lroundf(chromeClient.rootWindowRect().x() *
                   chromeClient.screenInfo().deviceScaleFactor);
  return chromeClient.rootWindowRect().x();
}

int LocalDOMWindow::screenY() const {
  if (!frame())
    return 0;

  FrameHost* host = frame()->host();
  if (!host)
    return 0;

  ChromeClient& chromeClient = host->chromeClient();
  if (host->settings().getReportScreenSizeInPhysicalPixelsQuirk())
    return lroundf(chromeClient.rootWindowRect().y() *
                   chromeClient.screenInfo().deviceScaleFactor);
  return chromeClient.rootWindowRect().y();
}

double LocalDOMWindow::scrollX() const {
  if (!frame() || !frame()->host())
    return 0;

  if (!frame()->host()->settings().getInertVisualViewport())
    return m_visualViewport->pageX();

  FrameView* view = frame()->view();
  if (!view)
    return 0;

  document()->updateStyleAndLayoutIgnorePendingStylesheets();

  double viewportX =
      view->layoutViewportScrollableArea()->getScrollOffset().width();
  return adjustScrollForAbsoluteZoom(viewportX, frame()->pageZoomFactor());
}

double LocalDOMWindow::scrollY() const {
  if (!frame() || !frame()->host())
    return 0;

  if (!frame()->host()->settings().getInertVisualViewport())
    return m_visualViewport->pageY();

  FrameView* view = frame()->view();
  if (!view)
    return 0;

  document()->updateStyleAndLayoutIgnorePendingStylesheets();

  double viewportY =
      view->layoutViewportScrollableArea()->getScrollOffset().height();
  return adjustScrollForAbsoluteZoom(viewportY, frame()->pageZoomFactor());
}

DOMVisualViewport* LocalDOMWindow::visualViewport() {
  if (!frame())
    return nullptr;

  return m_visualViewport;
}

const AtomicString& LocalDOMWindow::name() const {
  if (!isCurrentlyDisplayedInFrame())
    return nullAtom;

  return frame()->tree().name();
}

void LocalDOMWindow::setName(const AtomicString& name) {
  if (!isCurrentlyDisplayedInFrame())
    return;

  if (name == frame()->tree().name())
    return;

  frame()->tree().setName(name);
  ASSERT(frame()->loader().client());
  frame()->loader().client()->didChangeName(name, frame()->tree().uniqueName());
}

void LocalDOMWindow::setStatus(const String& string) {
  m_status = string;

  if (!frame())
    return;

  FrameHost* host = frame()->host();
  if (!host)
    return;

  host->chromeClient().setStatusbarText(m_status);
}

void LocalDOMWindow::setDefaultStatus(const String& string) {
  m_defaultStatus = string;

  if (!frame())
    return;

  FrameHost* host = frame()->host();
  if (!host)
    return;

  host->chromeClient().setStatusbarText(m_defaultStatus);
}

Document* LocalDOMWindow::document() const {
  return m_document.get();
}

StyleMedia* LocalDOMWindow::styleMedia() const {
  if (!m_media)
    m_media = StyleMedia::create(frame());
  return m_media.get();
}

CSSStyleDeclaration* LocalDOMWindow::getComputedStyle(
    Element* elt,
    const String& pseudoElt) const {
  ASSERT(elt);
  return CSSComputedStyleDeclaration::create(elt, false, pseudoElt);
}

CSSRuleList* LocalDOMWindow::getMatchedCSSRules(
    Element* element,
    const String& pseudoElement) const {
  if (!element)
    return nullptr;

  if (!isCurrentlyDisplayedInFrame())
    return nullptr;

  unsigned colonStart =
      pseudoElement[0] == ':' ? (pseudoElement[1] == ':' ? 2 : 1) : 0;
  CSSSelector::PseudoType pseudoType = CSSSelector::parsePseudoType(
      AtomicString(pseudoElement.substring(colonStart)), false);
  if (pseudoType == CSSSelector::PseudoUnknown && !pseudoElement.isEmpty())
    return nullptr;

  unsigned rulesToInclude = StyleResolver::AuthorCSSRules;
  PseudoId pseudoId = CSSSelector::pseudoId(pseudoType);
  element->document().updateStyleAndLayoutTree();
  return document()->ensureStyleResolver().pseudoCSSRulesForElement(
      element, pseudoId, rulesToInclude);
}

double LocalDOMWindow::devicePixelRatio() const {
  if (!frame())
    return 0.0;

  return frame()->devicePixelRatio();
}

void LocalDOMWindow::scrollBy(double x,
                              double y,
                              ScrollBehavior scrollBehavior) const {
  if (!isCurrentlyDisplayedInFrame())
    return;

  document()->updateStyleAndLayoutIgnorePendingStylesheets();

  FrameView* view = frame()->view();
  if (!view)
    return;

  FrameHost* host = frame()->host();
  if (!host)
    return;

  x = ScrollableArea::normalizeNonFiniteScroll(x);
  y = ScrollableArea::normalizeNonFiniteScroll(y);

  ScrollableArea* viewport = host->settings().getInertVisualViewport()
                                 ? view->layoutViewportScrollableArea()
                                 : view->getScrollableArea();

  ScrollOffset currentOffset = viewport->getScrollOffset();
  ScrollOffset scaledDelta(x * frame()->pageZoomFactor(),
                           y * frame()->pageZoomFactor());

  viewport->setScrollOffset(currentOffset + scaledDelta, ProgrammaticScroll,
                            scrollBehavior);
}

void LocalDOMWindow::scrollBy(const ScrollToOptions& scrollToOptions) const {
  double x = 0.0;
  double y = 0.0;
  if (scrollToOptions.hasLeft())
    x = scrollToOptions.left();
  if (scrollToOptions.hasTop())
    y = scrollToOptions.top();
  ScrollBehavior scrollBehavior = ScrollBehaviorAuto;
  ScrollableArea::scrollBehaviorFromString(scrollToOptions.behavior(),
                                           scrollBehavior);
  scrollBy(x, y, scrollBehavior);
}

void LocalDOMWindow::scrollTo(double x, double y) const {
  if (!isCurrentlyDisplayedInFrame())
    return;

  FrameView* view = frame()->view();
  if (!view)
    return;

  FrameHost* host = frame()->host();
  if (!host)
    return;

  x = ScrollableArea::normalizeNonFiniteScroll(x);
  y = ScrollableArea::normalizeNonFiniteScroll(y);

  // It is only necessary to have an up-to-date layout if the position may be
  // clamped, which is never the case for (0, 0).
  if (x || y)
    document()->updateStyleAndLayoutIgnorePendingStylesheets();

  ScrollOffset layoutOffset(x * frame()->pageZoomFactor(),
                            y * frame()->pageZoomFactor());
  ScrollableArea* viewport = host->settings().getInertVisualViewport()
                                 ? view->layoutViewportScrollableArea()
                                 : view->getScrollableArea();
  viewport->setScrollOffset(layoutOffset, ProgrammaticScroll,
                            ScrollBehaviorAuto);
}

void LocalDOMWindow::scrollTo(const ScrollToOptions& scrollToOptions) const {
  if (!isCurrentlyDisplayedInFrame())
    return;

  FrameView* view = frame()->view();
  if (!view)
    return;

  FrameHost* host = frame()->host();
  if (!host)
    return;

  // It is only necessary to have an up-to-date layout if the position may be
  // clamped, which is never the case for (0, 0).
  if (!scrollToOptions.hasLeft() || !scrollToOptions.hasTop() ||
      scrollToOptions.left() || scrollToOptions.top()) {
    document()->updateStyleAndLayoutIgnorePendingStylesheets();
  }

  double scaledX = 0.0;
  double scaledY = 0.0;

  ScrollableArea* viewport = host->settings().getInertVisualViewport()
                                 ? view->layoutViewportScrollableArea()
                                 : view->getScrollableArea();

  ScrollOffset currentOffset = viewport->getScrollOffset();
  scaledX = currentOffset.width();
  scaledY = currentOffset.height();

  if (scrollToOptions.hasLeft())
    scaledX = ScrollableArea::normalizeNonFiniteScroll(scrollToOptions.left()) *
              frame()->pageZoomFactor();

  if (scrollToOptions.hasTop())
    scaledY = ScrollableArea::normalizeNonFiniteScroll(scrollToOptions.top()) *
              frame()->pageZoomFactor();

  ScrollBehavior scrollBehavior = ScrollBehaviorAuto;
  ScrollableArea::scrollBehaviorFromString(scrollToOptions.behavior(),
                                           scrollBehavior);

  viewport->setScrollOffset(ScrollOffset(scaledX, scaledY), ProgrammaticScroll,
                            scrollBehavior);
}

void LocalDOMWindow::moveBy(int x, int y) const {
  if (!frame() || !frame()->isMainFrame())
    return;

  FrameHost* host = frame()->host();
  if (!host)
    return;

  IntRect windowRect = host->chromeClient().rootWindowRect();
  windowRect.saturatedMove(x, y);
  // Security check (the spec talks about UniversalBrowserWrite to disable this
  // check...)
  host->chromeClient().setWindowRectWithAdjustment(windowRect, *frame());
}

void LocalDOMWindow::moveTo(int x, int y) const {
  if (!frame() || !frame()->isMainFrame())
    return;

  FrameHost* host = frame()->host();
  if (!host)
    return;

  IntRect windowRect = host->chromeClient().rootWindowRect();
  windowRect.setLocation(IntPoint(x, y));
  // Security check (the spec talks about UniversalBrowserWrite to disable this
  // check...)
  host->chromeClient().setWindowRectWithAdjustment(windowRect, *frame());
}

void LocalDOMWindow::resizeBy(int x, int y) const {
  if (!frame() || !frame()->isMainFrame())
    return;

  FrameHost* host = frame()->host();
  if (!host)
    return;

  IntRect fr = host->chromeClient().rootWindowRect();
  IntSize dest = fr.size() + IntSize(x, y);
  IntRect update(fr.location(), dest);
  host->chromeClient().setWindowRectWithAdjustment(update, *frame());
}

void LocalDOMWindow::resizeTo(int width, int height) const {
  if (!frame() || !frame()->isMainFrame())
    return;

  FrameHost* host = frame()->host();
  if (!host)
    return;

  IntRect fr = host->chromeClient().rootWindowRect();
  IntSize dest = IntSize(width, height);
  IntRect update(fr.location(), dest);
  host->chromeClient().setWindowRectWithAdjustment(update, *frame());
}

int LocalDOMWindow::requestAnimationFrame(FrameRequestCallback* callback) {
  callback->m_useLegacyTimeBase = false;
  if (Document* doc = document())
    return doc->requestAnimationFrame(callback);
  return 0;
}

int LocalDOMWindow::webkitRequestAnimationFrame(
    FrameRequestCallback* callback) {
  callback->m_useLegacyTimeBase = true;
  if (Document* document = this->document())
    return document->requestAnimationFrame(callback);
  return 0;
}

void LocalDOMWindow::cancelAnimationFrame(int id) {
  if (Document* document = this->document())
    document->cancelAnimationFrame(id);
}

int LocalDOMWindow::requestIdleCallback(IdleRequestCallback* callback,
                                        const IdleRequestOptions& options) {
  if (Document* document = this->document())
    return document->requestIdleCallback(callback, options);
  return 0;
}

void LocalDOMWindow::cancelIdleCallback(int id) {
  if (Document* document = this->document())
    document->cancelIdleCallback(id);
}

CustomElementRegistry* LocalDOMWindow::customElements(
    ScriptState* scriptState) const {
  if (!scriptState->world().isMainWorld())
    return nullptr;
  return customElements();
}

CustomElementRegistry* LocalDOMWindow::customElements() const {
  if (!m_customElements && m_document)
    m_customElements = CustomElementRegistry::create(this);
  return m_customElements;
}

CustomElementRegistry* LocalDOMWindow::maybeCustomElements() const {
  return m_customElements;
}

void LocalDOMWindow::addedEventListener(
    const AtomicString& eventType,
    RegisteredEventListener& registeredListener) {
  DOMWindow::addedEventListener(eventType, registeredListener);
  if (frame() && frame()->host())
    frame()->host()->eventHandlerRegistry().didAddEventHandler(
        *this, eventType, registeredListener.options());

  if (Document* document = this->document())
    document->addListenerTypeIfNeeded(eventType);

  for (auto& it : m_eventListenerObservers) {
    it->didAddEventListener(this, eventType);
  }

  if (eventType == EventTypeNames::unload) {
    UseCounter::count(document(), UseCounter::DocumentUnloadRegistered);
    addUnloadEventListener(this);
  } else if (eventType == EventTypeNames::beforeunload) {
    UseCounter::count(document(), UseCounter::DocumentBeforeUnloadRegistered);
    if (allowsBeforeUnloadListeners(this)) {
      // This is confusingly named. It doesn't actually add the listener. It
      // just increments a count so that we know we have listeners registered
      // for the purposes of determining if we can fast terminate the renderer
      // process.
      addBeforeUnloadEventListener(this);
    } else {
      // Subframes return false from allowsBeforeUnloadListeners.
      UseCounter::count(document(), UseCounter::SubFrameBeforeUnloadRegistered);
    }
  }
}

void LocalDOMWindow::removedEventListener(
    const AtomicString& eventType,
    const RegisteredEventListener& registeredListener) {
  DOMWindow::removedEventListener(eventType, registeredListener);
  if (frame() && frame()->host())
    frame()->host()->eventHandlerRegistry().didRemoveEventHandler(
        *this, eventType, registeredListener.options());

  for (auto& it : m_eventListenerObservers) {
    it->didRemoveEventListener(this, eventType);
  }

  if (eventType == EventTypeNames::unload) {
    removeUnloadEventListener(this);
  } else if (eventType == EventTypeNames::beforeunload &&
             allowsBeforeUnloadListeners(this)) {
    removeBeforeUnloadEventListener(this);
  }
}

void LocalDOMWindow::warnUnusedPreloads(TimerBase* base) {
  if (frame() && frame()->loader().documentLoader()) {
    ResourceFetcher* fetcher = frame()->loader().documentLoader()->fetcher();
    DCHECK(fetcher);
    if (fetcher->countPreloads())
      fetcher->warnUnusedPreloads();
  }
}

void LocalDOMWindow::dispatchLoadEvent() {
  Event* loadEvent(Event::create(EventTypeNames::load));
  if (frame() && frame()->loader().documentLoader() &&
      !frame()->loader().documentLoader()->timing().loadEventStart()) {
    DocumentLoader* documentLoader = frame()->loader().documentLoader();
    DocumentLoadTiming& timing = documentLoader->timing();
    timing.markLoadEventStart();
    dispatchEvent(loadEvent, document());
    timing.markLoadEventEnd();
    DCHECK(documentLoader->fetcher());
    // If fetcher->countPreloads() is not empty here, it's full of link
    // preloads, as speculatove preloads were cleared at DCL.
    if (frame() && documentLoader == frame()->loader().documentLoader() &&
        documentLoader->fetcher()->countPreloads())
      m_unusedPreloadsTimer.startOneShot(unusedPreloadTimeoutInSeconds,
                                         BLINK_FROM_HERE);
  } else {
    dispatchEvent(loadEvent, document());
  }

  if (frame()) {
    Performance* performance = DOMWindowPerformance::performance(*this);
    DCHECK(performance);
    performance->addNavigationTiming(frame());
  }

  // For load events, send a separate load event to the enclosing frame only.
  // This is a DOM extension and is independent of bubbling/capturing rules of
  // the DOM.
  FrameOwner* owner = frame() ? frame()->owner() : nullptr;
  if (owner)
    owner->dispatchLoad();

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

DispatchEventResult LocalDOMWindow::dispatchEvent(Event* event,
                                                  EventTarget* target) {
#if DCHECK_IS_ON()
  DCHECK(!EventDispatchForbiddenScope::isEventDispatchForbidden());
#endif

  event->setTrusted(true);
  event->setTarget(target ? target : this);
  event->setCurrentTarget(this);
  event->setEventPhase(Event::kAtTarget);

  TRACE_EVENT1("devtools.timeline", "EventDispatch", "data",
               InspectorEventDispatchEvent::data(*event));
  return fireEventListeners(event);
}

void LocalDOMWindow::removeAllEventListeners() {
  EventTarget::removeAllEventListeners();

  for (auto& it : m_eventListenerObservers) {
    it->didRemoveAllEventListeners(this);
  }

  if (frame() && frame()->host())
    frame()->host()->eventHandlerRegistry().didRemoveAllEventHandlers(*this);

  removeAllUnloadEventListeners(this);
  removeAllBeforeUnloadEventListeners(this);
}

void LocalDOMWindow::finishedLoading() {
  if (m_shouldPrintWhenFinishedLoading) {
    m_shouldPrintWhenFinishedLoading = false;
    print(nullptr);
  }
}

void LocalDOMWindow::printErrorMessage(const String& message) const {
  if (!isCurrentlyDisplayedInFrame())
    return;

  if (message.isEmpty())
    return;

  frameConsole()->addMessage(
      ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, message));
}

DOMWindow* LocalDOMWindow::open(const String& urlString,
                                const AtomicString& frameName,
                                const String& windowFeaturesString,
                                LocalDOMWindow* callingWindow,
                                LocalDOMWindow* enteredWindow) {
  if (!isCurrentlyDisplayedInFrame())
    return nullptr;
  if (!callingWindow->frame())
    return nullptr;
  Document* activeDocument = callingWindow->document();
  if (!activeDocument)
    return nullptr;
  LocalFrame* firstFrame = enteredWindow->frame();
  if (!firstFrame)
    return nullptr;

  UseCounter::count(*activeDocument, UseCounter::DOMWindowOpen);
  if (!windowFeaturesString.isEmpty())
    UseCounter::count(*activeDocument, UseCounter::DOMWindowOpenFeatures);

  if (!enteredWindow->allowPopUp()) {
    // Because FrameTree::find() returns true for empty strings, we must check
    // for empty frame names.  Otherwise, illegitimate window.open() calls with
    // no name will pass right through the popup blocker.
    if (frameName.isEmpty() || !frame()->tree().find(frameName))
      return nullptr;
  }

  // Get the target frame for the special cases of _top and _parent.
  // In those cases, we schedule a location change right now and return early.
  Frame* targetFrame = nullptr;
  if (frameName == "_top") {
    targetFrame = frame()->tree().top();
  } else if (frameName == "_parent") {
    if (Frame* parent = frame()->tree().parent())
      targetFrame = parent;
    else
      targetFrame = frame();
  }

  if (targetFrame) {
    if (!activeDocument->frame() ||
        !activeDocument->frame()->canNavigate(*targetFrame))
      return nullptr;

    KURL completedURL = firstFrame->document()->completeURL(urlString);

    if (targetFrame->domWindow()->isInsecureScriptAccess(*callingWindow,
                                                         completedURL))
      return targetFrame->domWindow();

    if (urlString.isEmpty())
      return targetFrame->domWindow();

    targetFrame->navigate(*activeDocument, completedURL, false,
                          UserGestureStatus::None);
    return targetFrame->domWindow();
  }

  WindowFeatures features(windowFeaturesString);
  DOMWindow* newWindow = createWindow(urlString, frameName, features,
                                      *callingWindow, *firstFrame, *frame());
  return features.noopener ? nullptr : newWindow;
}

DEFINE_TRACE(LocalDOMWindow) {
  visitor->trace(m_document);
  visitor->trace(m_screen);
  visitor->trace(m_history);
  visitor->trace(m_locationbar);
  visitor->trace(m_menubar);
  visitor->trace(m_personalbar);
  visitor->trace(m_scrollbars);
  visitor->trace(m_statusbar);
  visitor->trace(m_toolbar);
  visitor->trace(m_navigator);
  visitor->trace(m_media);
  visitor->trace(m_customElements);
  visitor->trace(m_applicationCache);
  visitor->trace(m_eventQueue);
  visitor->trace(m_postMessageTimers);
  visitor->trace(m_visualViewport);
  visitor->trace(m_eventListenerObservers);
  DOMWindow::trace(visitor);
  Supplementable<LocalDOMWindow>::trace(visitor);
}

DEFINE_TRACE_WRAPPERS(LocalDOMWindow) {
  visitor->traceWrappers(m_customElements);
  DOMWindow::traceWrappers(visitor);
}

}  // namespace blink
