/*
 * 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/LocalDOMWindow.h"
#include "core/frame/PerformanceMonitor.h"
#include "core/frame/Settings.h"
#include "core/frame/UseCounter.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()
                            ? UseCounter::kAddEventListenerPassiveTrue
                            : UseCounter::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(),
                            UseCounter::kSmoothScrollJSInterventionActivated);
        }
        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.",
        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(),
                        UseCounter::kAuxclickAddListenerCount);
    }
  } else if (event_type == EventTypeNames::appinstalled) {
    if (LocalDOMWindow* executing_window = this->ExecutingWindow()) {
      UseCounter::Count(executing_window->document(),
                        UseCounter::kAppInstalledEventAddListener);
    }
  } else if (EventUtil::IsPointerEventType(event_type)) {
    if (LocalDOMWindow* executing_window = this->ExecutingWindow()) {
      UseCounter::Count(executing_window->document(),
                        UseCounter::kPointerEventAddListenerCount);
    }
  } else if (event_type == EventTypeNames::slotchange) {
    if (LocalDOMWindow* executing_window = this->ExecutingWindow()) {
      UseCounter::Count(executing_window->document(),
                        UseCounter::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) {
  UseCounter::Feature unprefixed_feature;
  UseCounter::Feature prefixed_feature;
  UseCounter::Feature prefixed_and_unprefixed_feature;
  if (legacy_type_name == EventTypeNames::webkitTransitionEnd) {
    prefixed_feature = UseCounter::kPrefixedTransitionEndEvent;
    unprefixed_feature = UseCounter::kUnprefixedTransitionEndEvent;
    prefixed_and_unprefixed_feature =
        UseCounter::kPrefixedAndUnprefixedTransitionEndEvent;
  } else if (legacy_type_name == EventTypeNames::webkitAnimationEnd) {
    prefixed_feature = UseCounter::kPrefixedAnimationEndEvent;
    unprefixed_feature = UseCounter::kUnprefixedAnimationEndEvent;
    prefixed_and_unprefixed_feature =
        UseCounter::kPrefixedAndUnprefixedAnimationEndEvent;
  } else if (legacy_type_name == EventTypeNames::webkitAnimationStart) {
    prefixed_feature = UseCounter::kPrefixedAnimationStartEvent;
    unprefixed_feature = UseCounter::kUnprefixedAnimationStartEvent;
    prefixed_and_unprefixed_feature =
        UseCounter::kPrefixedAndUnprefixedAnimationStartEvent;
  } else if (legacy_type_name == EventTypeNames::webkitAnimationIteration) {
    prefixed_feature = UseCounter::kPrefixedAnimationIterationEvent;
    unprefixed_feature = UseCounter::kUnprefixedAnimationIterationEvent;
    prefixed_and_unprefixed_feature =
        UseCounter::kPrefixedAndUnprefixedAnimationIterationEvent;
  } else if (legacy_type_name == EventTypeNames::mousewheel) {
    prefixed_feature = UseCounter::kMouseWheelEvent;
    unprefixed_feature = UseCounter::kWheelEvent;
    prefixed_and_unprefixed_feature = UseCounter::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 UseCounter::Feature 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,
                            UseCounter::kDocumentBeforeUnloadFired)) {
    if (LocalDOMWindow* executing_window = this->ExecutingWindow()) {
      if (executing_window != executing_window->top())
        UseCounter::Count(executing_window->document(),
                          UseCounter::kSubFrameBeforeUnloadFired);
    }
  } else if (CheckTypeThenUseCount(event, EventTypeNames::unload,
                                   UseCounter::kDocumentUnloadFired)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::DOMFocusIn,
                                   UseCounter::kDOMFocusInOutEvent)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::DOMFocusOut,
                                   UseCounter::kDOMFocusInOutEvent)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::focusin,
                                   UseCounter::kFocusInOutEvent)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::focusout,
                                   UseCounter::kFocusInOutEvent)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::textInput,
                                   UseCounter::kTextInputFired)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::touchstart,
                                   UseCounter::kTouchStartFired)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::mousedown,
                                   UseCounter::kMouseDownFired)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::pointerdown,
                                   UseCounter::kPointerDownFired)) {
    if (LocalDOMWindow* executing_window = this->ExecutingWindow()) {
      if (event->IsPointerEvent() &&
          static_cast<PointerEvent*>(event)->pointerType() == "touch")
        UseCounter::Count(executing_window->document(),
                          UseCounter::kPointerDownFiredForTouch);
    }
  } else if (CheckTypeThenUseCount(event, EventTypeNames::pointerenter,
                                   UseCounter::kPointerEnterLeaveFired)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::pointerleave,
                                   UseCounter::kPointerEnterLeaveFired)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::pointerover,
                                   UseCounter::kPointerOverOutFired)) {
  } else if (CheckTypeThenUseCount(event, EventTypeNames::pointerout,
                                   UseCounter::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
