/*
 * 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/fetch/ResourceFetcher.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/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
