/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
 *           (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
 *
 * 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/events/EventTarget.h"

#include <memory>
#include "bindings/core/v8/AddEventListenerOptionsOrBoolean.h"
#include "bindings/core/v8/EventListenerOptionsOrBoolean.h"
#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/ScriptEventListener.h"
#include "bindings/core/v8/SourceLocation.h"
#include "bindings/core/v8/V8DOMActivityLogger.h"
#include "core/dom/ExceptionCode.h"
#include "core/editing/Editor.h"
#include "core/events/Event.h"
#include "core/events/EventUtil.h"
#include "core/events/PointerEvent.h"
#include "core/frame/FrameConsole.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/PerformanceMonitor.h"
#include "core/frame/Settings.h"
#include "core/frame/UseCounter.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/probe/CoreProbes.h"
#include "platform/EventDispatchForbiddenScope.h"
#include "platform/Histogram.h"
#include "platform/wtf/PtrUtil.h"
#include "platform/wtf/StdLibExtras.h"
#include "platform/wtf/Threading.h"
#include "platform/wtf/Vector.h"

namespace blink {
namespace {

enum PassiveForcedListenerResultType {
  kPreventDefaultNotCalled,
  kDocumentLevelTouchPreventDefaultCalled,
  kPassiveForcedListenerResultTypeMax
};

Event::PassiveMode EventPassiveMode(
    const RegisteredEventListener& event_listener) {
  if (!event_listener.Passive()) {
    if (event_listener.PassiveSpecified())
      return Event::PassiveMode::kNotPassive;
    return Event::PassiveMode::kNotPassiveDefault;
  }
  if (event_listener.PassiveForcedForDocumentTarget())
    return Event::PassiveMode::kPassiveForcedDocumentLevel;
  if (event_listener.PassiveSpecified())
    return Event::PassiveMode::kPassive;
  return Event::PassiveMode::kPassiveDefault;
}

Settings* WindowSettings(LocalDOMWindow* executing_window) {
  if (executing_window) {
    if (LocalFrame* frame = executing_window->GetFrame()) {
      return frame->GetSettings();
    }
  }
  return nullptr;
}

bool IsTouchScrollBlockingEvent(const AtomicString& event_type) {
  return event_type == EventTypeNames::touchstart ||
         event_type == EventTypeNames::touchmove;
}

bool IsScrollBlockingEvent(const AtomicString& event_type) {
  return IsTouchScrollBlockingEvent(event_type) ||
         event_type == EventTypeNames::mousewheel ||
         event_type == EventTypeNames::wheel;
}

double BlockedEventsWarningThreshold(ExecutionContext* context,
                                     const Event* event) {
  if (!event->cancelable())
    return 0.0;
  if (!IsScrollBlockingEvent(event->type()))
    return 0.0;
  return PerformanceMonitor::Threshold(context,
                                       PerformanceMonitor::kBlockedEvent);
}

void ReportBlockedEvent(ExecutionContext* context,
                        const Event* event,
                        RegisteredEventListener* registered_listener,
                        double delayed_seconds) {
  if (registered_listener->Listener()->GetType() !=
      EventListener::kJSEventListenerType)
    return;

  String message_text = String::Format(
      "Handling of '%s' input event was delayed for %ld ms due to main thread "
      "being busy. "
      "Consider marking event handler as 'passive' to make the page more "
      "responsive.",
      event->type().GetString().Utf8().data(), lround(delayed_seconds * 1000));

  PerformanceMonitor::ReportGenericViolation(
      context, PerformanceMonitor::kBlockedEvent, message_text, delayed_seconds,
      GetFunctionLocation(context, registered_listener->Listener()));
  registered_listener->SetBlockedEventWarningEmitted();
}

}  // namespace

EventTargetData::EventTargetData() {}

EventTargetData::~EventTargetData() {}

DEFINE_TRACE(EventTargetData) {
  visitor->Trace(event_listener_map);
}

DEFINE_TRACE_WRAPPERS(EventTarget) {
  EventListenerIterator iterator(const_cast<EventTarget*>(this));
  while (EventListener* listener = iterator.NextListener()) {
    if (listener->GetType() != EventListener::kJSEventListenerType)
      continue;
    visitor->TraceWrappers(static_cast<V8AbstractEventListener*>(listener));
  }
}

EventTarget::EventTarget() {}

EventTarget::~EventTarget() {}

Node* EventTarget::ToNode() {
  return nullptr;
}

const DOMWindow* EventTarget::ToDOMWindow() const {
  return nullptr;
}

const LocalDOMWindow* EventTarget::ToLocalDOMWindow() const {
  return nullptr;
}

LocalDOMWindow* EventTarget::ToLocalDOMWindow() {
  return nullptr;
}

MessagePort* EventTarget::ToMessagePort() {
  return nullptr;
}

ServiceWorker* EventTarget::ToServiceWorker() {
  return nullptr;
}

inline LocalDOMWindow* EventTarget::ExecutingWindow() {
  if (ExecutionContext* context = GetExecutionContext())
    return context->ExecutingWindow();
  return nullptr;
}

void EventTarget::SetDefaultAddEventListenerOptions(
    const AtomicString& event_type,
    EventListener* event_listener,
    AddEventListenerOptionsResolved& options) {
  options.SetPassiveSpecified(options.hasPassive());

  if (!IsScrollBlockingEvent(event_type)) {
    if (!options.hasPassive())
      options.setPassive(false);
    return;
  }

  LocalDOMWindow* executing_window = this->ExecutingWindow();
  if (executing_window) {
    if (options.hasPassive()) {
      UseCounter::Count(executing_window->document(),
                        options.passive()
                            ? WebFeature::kAddEventListenerPassiveTrue
                            : WebFeature::kAddEventListenerPassiveFalse);
    }
  }

  if (RuntimeEnabledFeatures::PassiveDocumentEventListenersEnabled() &&
      IsTouchScrollBlockingEvent(event_type)) {
    if (!options.hasPassive()) {
      if (Node* node = ToNode()) {
        if (node->IsDocumentNode() ||
            node->GetDocument().documentElement() == node ||
            node->GetDocument().body() == node) {
          options.setPassive(true);
          options.SetPassiveForcedForDocumentTarget(true);
          return;
        }
      } else if (ToLocalDOMWindow()) {
        options.setPassive(true);
        options.SetPassiveForcedForDocumentTarget(true);
        return;
      }
    }
  }

  // For mousewheel event listeners that have the target as the window and
  // a bound function name of "ssc_wheel" treat and no passive value default
  // passive to true. See crbug.com/501568.
  if (RuntimeEnabledFeatures::SmoothScrollJSInterventionEnabled() &&
      event_type == EventTypeNames::mousewheel && ToLocalDOMWindow() &&
      event_listener && !options.hasPassive()) {
    if (V8AbstractEventListener* v8_listener =
            V8AbstractEventListener::Cast(event_listener)) {
      v8::Local<v8::Object> function = v8_listener->GetExistingListenerObject();
      if (function->IsFunction() &&
          strcmp("ssc_wheel",
                 *v8::String::Utf8Value(
                     v8::Local<v8::Function>::Cast(function)->GetName())) ==
              0) {
        options.setPassive(true);
        if (executing_window) {
          UseCounter::Count(executing_window->document(),
                            WebFeature::kSmoothScrollJSInterventionActivated);

          executing_window->GetFrame()->Console().AddMessage(
              ConsoleMessage::Create(
                  kInterventionMessageSource, kWarningMessageLevel,
                  "Registering mousewheel event as passive due to "
                  "smoothscroll.js usage. The smoothscroll.js library is "
                  "buggy, no longer necessary and degrades performance. See "
                  "https://www.chromestatus.com/feature/5749447073988608"));
        }

        return;
      }
    }
  }

  if (Settings* settings = WindowSettings(ExecutingWindow())) {
    switch (settings->GetPassiveListenerDefault()) {
      case PassiveListenerDefault::kFalse:
        if (!options.hasPassive())
          options.setPassive(false);
        break;
      case PassiveListenerDefault::kTrue:
        if (!options.hasPassive())
          options.setPassive(true);
        break;
      case PassiveListenerDefault::kForceAllTrue:
        options.setPassive(true);
        break;
    }
  } else {
    if (!options.hasPassive())
      options.setPassive(false);
  }

  if (!options.passive()) {
    String message_text = String::Format(
        "Added non-passive event listener to a scroll-blocking '%s' event. "
        "Consider marking event handler as 'passive' to make the page more "
        "responsive. See "
        "https://www.chromestatus.com/feature/5745543795965952",
        event_type.GetString().Utf8().data());

    PerformanceMonitor::ReportGenericViolation(
        GetExecutionContext(), PerformanceMonitor::kDiscouragedAPIUse,
        message_text, 0, nullptr);
  }
}

bool EventTarget::addEventListener(const AtomicString& event_type,
                                   EventListener* listener,
                                   bool use_capture) {
  AddEventListenerOptionsResolved options;
  options.setCapture(use_capture);
  SetDefaultAddEventListenerOptions(event_type, listener, options);
  return AddEventListenerInternal(event_type, listener, options);
}

bool EventTarget::addEventListener(
    const AtomicString& event_type,
    EventListener* listener,
    const AddEventListenerOptionsOrBoolean& options_union) {
  if (options_union.isBoolean())
    return addEventListener(event_type, listener, options_union.getAsBoolean());
  if (options_union.isAddEventListenerOptions()) {
    AddEventListenerOptionsResolved options =
        options_union.getAsAddEventListenerOptions();
    return addEventListener(event_type, listener, options);
  }
  return addEventListener(event_type, listener);
}

bool EventTarget::addEventListener(const AtomicString& event_type,
                                   EventListener* listener,
                                   AddEventListenerOptionsResolved& options) {
  SetDefaultAddEventListenerOptions(event_type, listener, options);
  return AddEventListenerInternal(event_type, listener, options);
}

bool EventTarget::AddEventListenerInternal(
    const AtomicString& event_type,
    EventListener* listener,
    const AddEventListenerOptionsResolved& options) {
  if (!listener)
    return false;

  V8DOMActivityLogger* activity_logger =
      V8DOMActivityLogger::CurrentActivityLoggerIfIsolatedWorld();
  if (activity_logger) {
    Vector<String> argv;
    argv.push_back(ToNode() ? ToNode()->nodeName() : InterfaceName());
    argv.push_back(event_type);
    activity_logger->LogEvent("blinkAddEventListener", argv.size(),
                              argv.data());
  }

  RegisteredEventListener registered_listener;
  bool added = EnsureEventTargetData().event_listener_map.Add(
      event_type, listener, options, &registered_listener);
  if (added) {
    if (listener->GetType() == EventListener::kJSEventListenerType) {
      ScriptWrappableVisitor::WriteBarrier(
          this, static_cast<V8AbstractEventListener*>(listener));
    }
    AddedEventListener(event_type, registered_listener);
  }
  return added;
}

void EventTarget::AddedEventListener(
    const AtomicString& event_type,
    RegisteredEventListener& registered_listener) {
  if (event_type == EventTypeNames::auxclick) {
    if (LocalDOMWindow* executing_window = this->ExecutingWindow()) {
      UseCounter::Count(executing_window->document(),
                        WebFeature::kAuxclickAddListenerCount);
    }
  } else if (event_type == EventTypeNames::appinstalled) {
    if (LocalDOMWindow* executing_window = this->ExecutingWindow()) {
      UseCounter::Count(executing_window->document(),
                        WebFeature::kAppInstalledEventAddListener);
    }
  } else if (EventUtil::IsPointerEventType(event_type)) {
    if (LocalDOMWindow* executing_window = this->ExecutingWindow()) {
      UseCounter::Count(executing_window->document(),
                        WebFeature::kPointerEventAddListenerCount);
    }
  } else if (event_type == EventTypeNames::slotchange) {
    if (LocalDOMWindow* executing_window = this->ExecutingWindow()) {
      UseCounter::Count(executing_window->document(),
                        WebFeature::kSlotChangeEventAddListener);
    }
  } else if (EventUtil::IsDOMMutationEventType(event_type)) {
    if (ExecutionContext* context = GetExecutionContext()) {
      String message_text = String::Format(
          "Added synchronous DOM mutation listener to a '%s' event. "
          "Consider using MutationObserver to make the page more responsive.",
          event_type.GetString().Utf8().data());
      PerformanceMonitor::ReportGenericViolation(
          context, PerformanceMonitor::kDiscouragedAPIUse, message_text, 0,
          nullptr);
    }
  }
}

bool EventTarget::removeEventListener(const AtomicString& event_type,
                                      const EventListener* listener,
                                      bool use_capture) {
  EventListenerOptions options;
  options.setCapture(use_capture);
  return RemoveEventListenerInternal(event_type, listener, options);
}

bool EventTarget::removeEventListener(
    const AtomicString& event_type,
    const EventListener* listener,
    const EventListenerOptionsOrBoolean& options_union) {
  if (options_union.isBoolean())
    return removeEventListener(event_type, listener,
                               options_union.getAsBoolean());
  if (options_union.isEventListenerOptions()) {
    EventListenerOptions options = options_union.getAsEventListenerOptions();
    return removeEventListener(event_type, listener, options);
  }
  return removeEventListener(event_type, listener);
}

bool EventTarget::removeEventListener(const AtomicString& event_type,
                                      const EventListener* listener,
                                      EventListenerOptions& options) {
  return RemoveEventListenerInternal(event_type, listener, options);
}

bool EventTarget::RemoveEventListenerInternal(
    const AtomicString& event_type,
    const EventListener* listener,
    const EventListenerOptions& options) {
  if (!listener)
    return false;

  EventTargetData* d = GetEventTargetData();
  if (!d)
    return false;

  size_t index_of_removed_listener;
  RegisteredEventListener registered_listener;

  if (!d->event_listener_map.Remove(event_type, listener, options,
                                    &index_of_removed_listener,
                                    &registered_listener))
    return false;

  // Notify firing events planning to invoke the listener at 'index' that
  // they have one less listener to invoke.
  if (d->firing_event_iterators) {
    for (const auto& firing_iterator : *d->firing_event_iterators) {
      if (event_type != firing_iterator.event_type)
        continue;

      if (index_of_removed_listener >= firing_iterator.end)
        continue;

      --firing_iterator.end;
      // Note that when firing an event listener,
      // firingIterator.iterator indicates the next event listener
      // that would fire, not the currently firing event
      // listener. See EventTarget::fireEventListeners.
      if (index_of_removed_listener < firing_iterator.iterator)
        --firing_iterator.iterator;
    }
  }
  RemovedEventListener(event_type, registered_listener);
  return true;
}

void EventTarget::RemovedEventListener(
    const AtomicString& event_type,
    const RegisteredEventListener& registered_listener) {}

bool EventTarget::SetAttributeEventListener(const AtomicString& event_type,
                                            EventListener* listener) {
  ClearAttributeEventListener(event_type);
  if (!listener)
    return false;
  return addEventListener(event_type, listener, false);
}

EventListener* EventTarget::GetAttributeEventListener(
    const AtomicString& event_type) {
  EventListenerVector* listener_vector = GetEventListeners(event_type);
  if (!listener_vector)
    return nullptr;

  for (auto& event_listener : *listener_vector) {
    EventListener* listener = event_listener.Listener();
    if (listener->IsAttribute() &&
        listener->BelongsToTheCurrentWorld(GetExecutionContext()))
      return listener;
  }
  return nullptr;
}

bool EventTarget::ClearAttributeEventListener(const AtomicString& event_type) {
  EventListener* listener = GetAttributeEventListener(event_type);
  if (!listener)
    return false;
  return removeEventListener(event_type, listener, false);
}

bool EventTarget::dispatchEventForBindings(Event* event,
                                           ExceptionState& exception_state) {
  if (!event->WasInitialized()) {
    exception_state.ThrowDOMException(kInvalidStateError,
                                      "The event provided is uninitialized.");
    return false;
  }
  if (event->IsBeingDispatched()) {
    exception_state.ThrowDOMException(kInvalidStateError,
                                      "The event is already being dispatched.");
    return false;
  }

  if (!GetExecutionContext())
    return false;

  event->SetTrusted(false);

  // Return whether the event was cancelled or not to JS not that it
  // might have actually been default handled; so check only against
  // CanceledByEventHandler.
  return DispatchEventInternal(event) !=
         DispatchEventResult::kCanceledByEventHandler;
}

DispatchEventResult EventTarget::DispatchEvent(Event* event) {
  event->SetTrusted(true);
  return DispatchEventInternal(event);
}

DispatchEventResult EventTarget::DispatchEventInternal(Event* event) {
  event->SetTarget(this);
  event->SetCurrentTarget(this);
  event->SetEventPhase(Event::kAtTarget);
  DispatchEventResult dispatch_result = FireEventListeners(event);
  event->SetEventPhase(0);
  return dispatch_result;
}

void EventTarget::UncaughtExceptionInEventHandler() {}

static const AtomicString& LegacyType(const Event* event) {
  if (event->type() == EventTypeNames::transitionend)
    return EventTypeNames::webkitTransitionEnd;

  if (event->type() == EventTypeNames::animationstart)
    return EventTypeNames::webkitAnimationStart;

  if (event->type() == EventTypeNames::animationend)
    return EventTypeNames::webkitAnimationEnd;

  if (event->type() == EventTypeNames::animationiteration)
    return EventTypeNames::webkitAnimationIteration;

  if (event->type() == EventTypeNames::wheel)
    return EventTypeNames::mousewheel;

  return g_empty_atom;
}

void EventTarget::CountLegacyEvents(
    const AtomicString& legacy_type_name,
    EventListenerVector* listeners_vector,
    EventListenerVector* legacy_listeners_vector) {
  WebFeature unprefixed_feature;
  WebFeature prefixed_feature;
  WebFeature prefixed_and_unprefixed_feature;
  if (legacy_type_name == EventTypeNames::webkitTransitionEnd) {
    prefixed_feature = WebFeature::kPrefixedTransitionEndEvent;
    unprefixed_feature = WebFeature::kUnprefixedTransitionEndEvent;
    prefixed_and_unprefixed_feature =
        WebFeature::kPrefixedAndUnprefixedTransitionEndEvent;
  } else if (legacy_type_name == EventTypeNames::webkitAnimationEnd) {
    prefixed_feature = WebFeature::kPrefixedAnimationEndEvent;
    unprefixed_feature = WebFeature::kUnprefixedAnimationEndEvent;
    prefixed_and_unprefixed_feature =
        WebFeature::kPrefixedAndUnprefixedAnimationEndEvent;
  } else if (legacy_type_name == EventTypeNames::webkitAnimationStart) {
    prefixed_feature = WebFeature::kPrefixedAnimationStartEvent;
    unprefixed_feature = WebFeature::kUnprefixedAnimationStartEvent;
    prefixed_and_unprefixed_feature =
        WebFeature::kPrefixedAndUnprefixedAnimationStartEvent;
  } else if (legacy_type_name == EventTypeNames::webkitAnimationIteration) {
    prefixed_feature = WebFeature::kPrefixedAnimationIterationEvent;
    unprefixed_feature = WebFeature::kUnprefixedAnimationIterationEvent;
    prefixed_and_unprefixed_feature =
        WebFeature::kPrefixedAndUnprefixedAnimationIterationEvent;
  } else if (legacy_type_name == EventTypeNames::mousewheel) {
    prefixed_feature = WebFeature::kMouseWheelEvent;
    unprefixed_feature = WebFeature::kWheelEvent;
    prefixed_and_unprefixed_feature = WebFeature::kMouseWheelAndWheelEvent;
  } else {
    return;
  }

  if (LocalDOMWindow* executing_window = this->ExecutingWindow()) {
    if (legacy_listeners_vector) {
      if (listeners_vector)
        UseCounter::Count(executing_window->document(),
                          prefixed_and_unprefixed_feature);
      else
        UseCounter::Count(executing_window->document(), prefixed_feature);
    } else if (listeners_vector) {
      UseCounter::Count(executing_window->document(), unprefixed_feature);
    }
  }
}

DispatchEventResult EventTarget::FireEventListeners(Event* event) {
#if DCHECK_IS_ON()
  DCHECK(!EventDispatchForbiddenScope::IsEventDispatchForbidden());
#endif
  DCHECK(event);
  DCHECK(event->WasInitialized());

  EventTargetData* d = GetEventTargetData();
  if (!d)
    return DispatchEventResult::kNotCanceled;

  EventListenerVector* legacy_listeners_vector = nullptr;
  AtomicString legacy_type_name = LegacyType(event);
  if (!legacy_type_name.IsEmpty())
    legacy_listeners_vector = d->event_listener_map.Find(legacy_type_name);

  EventListenerVector* listeners_vector =
      d->event_listener_map.Find(event->type());

  bool fired_event_listeners = false;
  if (listeners_vector) {
    fired_event_listeners = FireEventListeners(event, d, *listeners_vector);
  } else if (legacy_listeners_vector) {
    AtomicString unprefixed_type_name = event->type();
    event->SetType(legacy_type_name);
    fired_event_listeners =
        FireEventListeners(event, d, *legacy_listeners_vector);
    event->SetType(unprefixed_type_name);
  }

  // Only invoke the callback if event listeners were fired for this phase.
  if (fired_event_listeners) {
    event->DoneDispatchingEventAtCurrentTarget();

    // Only count uma metrics if we really fired an event listener.
    Editor::CountEvent(GetExecutionContext(), event);
    CountLegacyEvents(legacy_type_name, listeners_vector,
                      legacy_listeners_vector);
  }
  return GetDispatchEventResult(*event);
}

bool EventTarget::CheckTypeThenUseCount(const Event* event,
                                        const AtomicString& event_type_to_count,
                                        const WebFeature feature) {
  if (event->type() == event_type_to_count) {
    if (LocalDOMWindow* executing_window = this->ExecutingWindow())
      UseCounter::Count(executing_window->document(), feature);
    return true;
  }
  return false;
}

bool EventTarget::FireEventListeners(Event* event,
                                     EventTargetData* d,
                                     EventListenerVector& entry) {
  // Fire all listeners registered for this event. Don't fire listeners removed
  // during event dispatch. Also, don't fire event listeners added during event
  // dispatch. Conveniently, all new event listeners will be added after or at
  // index |size|, so iterating up to (but not including) |size| naturally
  // excludes new event listeners.

  if (CheckTypeThenUseCount(event, EventTypeNames::beforeunload,
                            WebFeature::kDocumentBeforeUnloadFired)) {
    if (LocalDOMWindow* executing_window = this->ExecutingWindow()) {
      if (executing_window != executing_window->top()) {
        UseCounter::Count(executing_window->document(),
                          WebFeature::kSubFrameBeforeUnloadFired);
      }
    }
  } else if (CheckTypeThenUseCount(event, EventTypeNames::unload,
                                   WebFeature::kDocumentUnloadFired)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::DOMFocusIn,
                                   WebFeature::kDOMFocusInOutEvent)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::DOMFocusOut,
                                   WebFeature::kDOMFocusInOutEvent)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::focusin,
                                   WebFeature::kFocusInOutEvent)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::focusout,
                                   WebFeature::kFocusInOutEvent)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::textInput,
                                   WebFeature::kTextInputFired)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::touchstart,
                                   WebFeature::kTouchStartFired)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::mousedown,
                                   WebFeature::kMouseDownFired)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::pointerdown,
                                   WebFeature::kPointerDownFired)) {
    if (LocalDOMWindow* executing_window = this->ExecutingWindow()) {
      if (event->IsPointerEvent() &&
          static_cast<PointerEvent*>(event)->pointerType() == "touch") {
        UseCounter::Count(executing_window->document(),
                          WebFeature::kPointerDownFiredForTouch);
      }
    }
  } else if (CheckTypeThenUseCount(event, EventTypeNames::pointerenter,
                                   WebFeature::kPointerEnterLeaveFired)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::pointerleave,
                                   WebFeature::kPointerEnterLeaveFired)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::pointerover,
                                   WebFeature::kPointerOverOutFired)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::pointerout,
                                   WebFeature::kPointerOverOutFired)) {
  }

  ExecutionContext* context = GetExecutionContext();
  if (!context)
    return false;

  size_t i = 0;
  size_t size = entry.size();
  if (!d->firing_event_iterators)
    d->firing_event_iterators = WTF::WrapUnique(new FiringEventIteratorVector);
  d->firing_event_iterators->push_back(
      FiringEventIterator(event->type(), i, size));

  double blocked_event_threshold =
      BlockedEventsWarningThreshold(context, event);
  TimeTicks now;
  bool should_report_blocked_event = false;
  if (blocked_event_threshold) {
    now = TimeTicks::Now();
    should_report_blocked_event =
        (now - event->PlatformTimeStamp()).InSecondsF() >
        blocked_event_threshold;
  }
  bool fired_listener = false;

  while (i < size) {
    RegisteredEventListener registered_listener = entry[i];

    // Move the iterator past this event listener. This must match
    // the handling of the FiringEventIterator::iterator in
    // EventTarget::removeEventListener.
    ++i;

    if (event->eventPhase() == Event::kCapturingPhase &&
        !registered_listener.Capture())
      continue;
    if (event->eventPhase() == Event::kBubblingPhase &&
        registered_listener.Capture())
      continue;

    EventListener* listener = registered_listener.Listener();
    // The listener will be retained by Member<EventListener> in the
    // registeredListener, i and size are updated with the firing event iterator
    // in case the listener is removed from the listener vector below.
    if (registered_listener.Once())
      removeEventListener(event->type(), listener,
                          registered_listener.Capture());

    // If stopImmediatePropagation has been called, we just break out
    // immediately, without handling any more events on this target.
    if (event->ImmediatePropagationStopped())
      break;

    event->SetHandlingPassive(EventPassiveMode(registered_listener));
    bool passive_forced = registered_listener.PassiveForcedForDocumentTarget();

    probe::UserCallback probe(context, nullptr, event->type(), false, this);

    // To match Mozilla, the AT_TARGET phase fires both capturing and bubbling
    // event listeners, even though that violates some versions of the DOM spec.
    listener->handleEvent(context, event);
    fired_listener = true;

    // If we're about to report this event listener as blocking, make sure it
    // wasn't removed while handling the event.
    if (should_report_blocked_event && i > 0 &&
        entry[i - 1].Listener() == listener && !entry[i - 1].Passive() &&
        !entry[i - 1].BlockedEventWarningEmitted() &&
        !event->defaultPrevented()) {
      ReportBlockedEvent(context, event, &entry[i - 1],
                         (now - event->PlatformTimeStamp()).InSecondsF());
    }

    if (passive_forced) {
      DEFINE_STATIC_LOCAL(EnumerationHistogram, passive_forced_histogram,
                          ("Event.PassiveForcedEventDispatchCancelled",
                           kPassiveForcedListenerResultTypeMax));
      PassiveForcedListenerResultType breakage_type = kPreventDefaultNotCalled;
      if (event->PreventDefaultCalledDuringPassive())
        breakage_type = kDocumentLevelTouchPreventDefaultCalled;

      passive_forced_histogram.Count(breakage_type);
    }

    event->SetHandlingPassive(Event::PassiveMode::kNotPassive);

    CHECK_LE(i, size);
  }
  d->firing_event_iterators->pop_back();
  return fired_listener;
}

DispatchEventResult EventTarget::GetDispatchEventResult(const Event& event) {
  if (event.defaultPrevented())
    return DispatchEventResult::kCanceledByEventHandler;
  if (event.DefaultHandled())
    return DispatchEventResult::kCanceledByDefaultEventHandler;
  return DispatchEventResult::kNotCanceled;
}

EventListenerVector* EventTarget::GetEventListeners(
    const AtomicString& event_type) {
  EventTargetData* data = GetEventTargetData();
  if (!data)
    return nullptr;
  return data->event_listener_map.Find(event_type);
}

Vector<AtomicString> EventTarget::EventTypes() {
  EventTargetData* d = GetEventTargetData();
  return d ? d->event_listener_map.EventTypes() : Vector<AtomicString>();
}

void EventTarget::RemoveAllEventListeners() {
  EventTargetData* d = GetEventTargetData();
  if (!d)
    return;
  d->event_listener_map.Clear();

  // Notify firing events planning to invoke the listener at 'index' that
  // they have one less listener to invoke.
  if (d->firing_event_iterators) {
    for (const auto& iterator : *d->firing_event_iterators) {
      iterator.iterator = 0;
      iterator.end = 0;
    }
  }
}

}  // namespace blink
