/*
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 * 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, 2009, 2010, 2011 Apple Inc. All rights
 * reserved.
 *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
 * Copyright (C) 2010 Google Inc. All rights reserved.
 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved.
 * (http://www.torchmobile.com/)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "third_party/blink/renderer/core/html/forms/select_type.h"

#include "build/build_config.h"
#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_mutation_observer_init.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/focus_params.h"
#include "third_party/blink/renderer/core/dom/mutation_observer.h"
#include "third_party/blink/renderer/core/dom/mutation_record.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/events/gesture_event.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
#include "third_party/blink/renderer/core/events/mouse_event.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/forms/html_form_element.h"
#include "third_party/blink/renderer/core/html/forms/html_select_element.h"
#include "third_party/blink/renderer/core/html/forms/menu_list_inner_element.h"
#include "third_party/blink/renderer/core/html/forms/popup_menu.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
#include "third_party/blink/renderer/core/input/input_device_capabilities.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/page/autoscroll_controller.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/spatial_navigation.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/scroll/scroll_alignment.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
#include "ui/base/ui_base_features.h"

namespace blink {

class PopupUpdater;

namespace {

HTMLOptionElement* EventTargetOption(const Event& event) {
  return DynamicTo<HTMLOptionElement>(event.target()->ToNode());
}

}  // anonymous namespace

class MenuListSelectType final : public SelectType {
 public:
  explicit MenuListSelectType(HTMLSelectElement& select) : SelectType(select) {}
  void Trace(Visitor* visitor) const override;

  bool DefaultEventHandler(const Event& event) override;
  void DidSelectOption(HTMLOptionElement* element,
                       HTMLSelectElement::SelectOptionFlags flags,
                       bool should_update_popup) override;
  void DidBlur() override;
  void DidDetachLayoutTree() override;
  void DidRecalcStyle(const StyleRecalcChange change) override;
  void DidSetSuggestedOption(HTMLOptionElement* option) override;
  void SaveLastSelection() override;

  void UpdateTextStyle() override { UpdateTextStyleInternal(); }
  void UpdateTextStyleAndContent() override;
  HTMLOptionElement* OptionToBeShown() const override;
  const ComputedStyle* OptionStyle() const override {
    return option_style_.get();
  }
  void MaximumOptionWidthMightBeChanged() const override;

  void CreateShadowSubtree(ShadowRoot& root) override;
  Element& InnerElement() const override;
  void ShowPopup() override;
  void HidePopup() override;
  void PopupDidHide() override;
  bool PopupIsVisible() const override;
  PopupMenu* PopupForTesting() const override;
  AXObject* PopupRootAXObject() const override;

  void DidMutateSubtree();

 private:
  bool ShouldOpenPopupForKeyDownEvent(const KeyboardEvent& event);
  bool ShouldOpenPopupForKeyPressEvent(const KeyboardEvent& event);
  // Returns true if this function handled the event.
  bool HandlePopupOpenKeyboardEvent();
  void SetPopupIsVisible(bool popup_is_visible);
  void DispatchEventsIfSelectedOptionChanged();
  String UpdateTextStyleInternal();
  void DidUpdateActiveOption(HTMLOptionElement* option);
  void ObserveTreeMutation();
  void UnobserveTreeMutation();

  Member<PopupMenu> popup_;
  Member<PopupUpdater> popup_updater_;
  scoped_refptr<const ComputedStyle> option_style_;
  int ax_menulist_last_active_index_ = -1;
  bool has_updated_menulist_active_option_ = false;
  bool popup_is_visible_ = false;
  bool snav_arrow_key_selection_ = false;
};

void MenuListSelectType::Trace(Visitor* visitor) const {
  visitor->Trace(popup_);
  visitor->Trace(popup_updater_);
  SelectType::Trace(visitor);
}

bool MenuListSelectType::DefaultEventHandler(const Event& event) {
  // We need to make the layout tree up-to-date to have GetLayoutObject() give
  // the correct result below. An author event handler may have set display to
  // some element to none which will cause a layout tree detach.
  select_->GetDocument().UpdateStyleAndLayoutTree();

  const auto* key_event = DynamicTo<KeyboardEvent>(event);
  if (event.type() == event_type_names::kKeydown) {
    if (!select_->GetLayoutObject() || !key_event)
      return false;

    if (ShouldOpenPopupForKeyDownEvent(*key_event))
      return HandlePopupOpenKeyboardEvent();

    // When using spatial navigation, we want to be able to navigate away
    // from the select element when the user hits any of the arrow keys,
    // instead of changing the selection.
    if (IsSpatialNavigationEnabled(select_->GetDocument().GetFrame())) {
      if (!snav_arrow_key_selection_)
        return false;
    }

    // The key handling below shouldn't be used for non spatial navigation
    // mode Mac
    if (LayoutTheme::GetTheme().PopsMenuByArrowKeys() &&
        !IsSpatialNavigationEnabled(select_->GetDocument().GetFrame()))
      return false;

    int ignore_modifiers = WebInputEvent::kShiftKey |
                           WebInputEvent::kControlKey | WebInputEvent::kAltKey |
                           WebInputEvent::kMetaKey;
    if (key_event->GetModifiers() & ignore_modifiers)
      return false;

    const String& key = key_event->key();
    bool handled = true;
    HTMLOptionElement* option = select_->SelectedOption();
    int list_index = option ? option->ListIndex() : -1;

    if (key == "ArrowDown" || key == "ArrowRight") {
      option = NextValidOption(list_index, kSkipForwards, 1);
    } else if (key == "ArrowUp" || key == "ArrowLeft") {
      option = NextValidOption(list_index, kSkipBackwards, 1);
    } else if (key == "PageDown") {
      option = NextValidOption(list_index, kSkipForwards, 3);
    } else if (key == "PageUp") {
      option = NextValidOption(list_index, kSkipBackwards, 3);
    } else if (key == "Home") {
      option = FirstSelectableOption();
    } else if (key == "End") {
      option = LastSelectableOption();
    } else {
      handled = false;
    }

    if (handled && option) {
      select_->SelectOption(
          option, HTMLSelectElement::kDeselectOtherOptionsFlag |
                      HTMLSelectElement::kMakeOptionDirtyFlag |
                      HTMLSelectElement::kDispatchInputAndChangeEventFlag);
    }
    return handled;
  }

  if (event.type() == event_type_names::kKeypress) {
    if (!select_->GetLayoutObject() || !key_event)
      return false;

    int key_code = key_event->keyCode();
    if (key_code == ' ' &&
        IsSpatialNavigationEnabled(select_->GetDocument().GetFrame())) {
      // Use space to toggle arrow key handling for selection change or
      // spatial navigation.
      snav_arrow_key_selection_ = !snav_arrow_key_selection_;
      return true;
    }

    if (ShouldOpenPopupForKeyPressEvent(*key_event))
      return HandlePopupOpenKeyboardEvent();

    if (!LayoutTheme::GetTheme().PopsMenuByReturnKey() && key_code == '\r') {
      if (HTMLFormElement* form = select_->Form())
        form->SubmitImplicitly(event, false);
      DispatchEventsIfSelectedOptionChanged();
      return true;
    }
    return false;
  }

  const auto* mouse_event = DynamicTo<MouseEvent>(event);
  if (event.type() == event_type_names::kMousedown && mouse_event &&
      mouse_event->button() ==
          static_cast<int16_t>(WebPointerProperties::Button::kLeft)) {
    InputDeviceCapabilities* source_capabilities =
        select_->GetDocument()
            .domWindow()
            ->GetInputDeviceCapabilities()
            ->FiresTouchEvents(mouse_event->FromTouch());
    select_->focus(FocusParams(SelectionBehaviorOnFocus::kRestore,
                               mojom::blink::FocusType::kMouse,
                               source_capabilities));
    if (select_->GetLayoutObject() && !will_be_destroyed_ &&
        !select_->IsDisabledFormControl()) {
      if (PopupIsVisible()) {
        HidePopup();
      } else {
        // Save the selection so it can be compared to the new selection
        // when we call onChange during selectOption, which gets called
        // from selectOptionByPopup, which gets called after the user
        // makes a selection from the menu.
        SaveLastSelection();
        // TODO(lanwei): Will check if we need to add
        // InputDeviceCapabilities here when select menu list gets
        // focus, see https://crbug.com/476530.
        ShowPopup();
      }
    }
    return true;
  }
  return false;
}

bool MenuListSelectType::ShouldOpenPopupForKeyDownEvent(
    const KeyboardEvent& event) {
  const String& key = event.key();
  LayoutTheme& layout_theme = LayoutTheme::GetTheme();

  if (IsSpatialNavigationEnabled(select_->GetDocument().GetFrame()))
    return false;

  return ((layout_theme.PopsMenuByArrowKeys() &&
           (key == "ArrowDown" || key == "ArrowUp")) ||
          ((key == "ArrowDown" || key == "ArrowUp") && event.altKey()) ||
          ((!event.altKey() && !event.ctrlKey() && key == "F4")));
}

bool MenuListSelectType::ShouldOpenPopupForKeyPressEvent(
    const KeyboardEvent& event) {
  LayoutTheme& layout_theme = LayoutTheme::GetTheme();
  int key_code = event.keyCode();

  return ((key_code == ' ' && !select_->type_ahead_.HasActiveSession(event)) ||
          (layout_theme.PopsMenuByReturnKey() && key_code == '\r'));
}

bool MenuListSelectType::HandlePopupOpenKeyboardEvent() {
  select_->focus();
  // Calling focus() may cause us to lose our LayoutObject. Return true so
  // that our caller doesn't process the event further, but don't set
  // the event as handled.
  if (!select_->GetLayoutObject() || will_be_destroyed_ ||
      select_->IsDisabledFormControl())
    return false;
  // Save the selection so it can be compared to the new selection when
  // dispatching change events during SelectOption, which gets called from
  // SelectOptionByPopup, which gets called after the user makes a selection
  // from the menu.
  SaveLastSelection();
  ShowPopup();
  return true;
}

void MenuListSelectType::CreateShadowSubtree(ShadowRoot& root) {
  Document& doc = select_->GetDocument();
  Element* inner_element = MakeGarbageCollected<MenuListInnerElement>(doc);
  inner_element->setAttribute(html_names::kAriaHiddenAttr, "true");
  // Make sure InnerElement() always has a Text node.
  inner_element->appendChild(Text::Create(doc, g_empty_string));
  root.insertBefore(inner_element, root.firstChild());
}

Element& MenuListSelectType::InnerElement() const {
  auto* inner_element =
      DynamicTo<Element>(select_->UserAgentShadowRoot()->firstChild());
  DCHECK(inner_element);
  return *inner_element;
}

void MenuListSelectType::ShowPopup() {
  if (PopupIsVisible())
    return;
  Document& document = select_->GetDocument();
  if (document.GetPage()->GetChromeClient().HasOpenedPopup())
    return;
  if (!select_->GetLayoutObject())
    return;
  if (select_->VisibleBoundsInVisualViewport().IsEmpty())
    return;

  if (!popup_) {
    popup_ = document.GetPage()->GetChromeClient().OpenPopupMenu(
        *document.GetFrame(), *select_);
  }
  if (!popup_)
    return;

  SetPopupIsVisible(true);
  ObserveTreeMutation();

  popup_->Show();
  if (AXObjectCache* cache = document.ExistingAXObjectCache())
    cache->DidShowMenuListPopup(select_->GetLayoutObject());
}

void MenuListSelectType::HidePopup() {
  if (popup_)
    popup_->Hide();
}

void MenuListSelectType::PopupDidHide() {
  SetPopupIsVisible(false);
  UnobserveTreeMutation();
  if (AXObjectCache* cache = select_->GetDocument().ExistingAXObjectCache()) {
    if (auto* layout_object = select_->GetLayoutObject())
      cache->DidHideMenuListPopup(layout_object);
  }
}

bool MenuListSelectType::PopupIsVisible() const {
  return popup_is_visible_;
}

void MenuListSelectType::SetPopupIsVisible(bool popup_is_visible) {
  popup_is_visible_ = popup_is_visible;
  if (!::features::IsFormControlsRefreshEnabled())
    return;
  if (auto* layout_object = select_->GetLayoutObject()) {
    // Invalidate paint to ensure that the focus ring is updated.
    layout_object->SetShouldDoFullPaintInvalidation();
  }
}

PopupMenu* MenuListSelectType::PopupForTesting() const {
  return popup_.Get();
}

AXObject* MenuListSelectType::PopupRootAXObject() const {
  return popup_ ? popup_->PopupRootAXObject() : nullptr;
}

void MenuListSelectType::DidSelectOption(
    HTMLOptionElement* element,
    HTMLSelectElement::SelectOptionFlags flags,
    bool should_update_popup) {
  // Need to update last_on_change_option_ before UpdateFromElement().
  const bool should_dispatch_events =
      (flags & HTMLSelectElement::kDispatchInputAndChangeEventFlag) &&
      select_->last_on_change_option_ != element;
  select_->last_on_change_option_ = element;

  UpdateTextStyleAndContent();
  // PopupMenu::UpdateFromElement() posts an O(N) task.
  if (PopupIsVisible() && should_update_popup)
    popup_->UpdateFromElement(PopupMenu::kBySelectionChange);

  select_->SetNeedsValidityCheck();

  if (should_dispatch_events) {
    select_->DispatchInputEvent();
    select_->DispatchChangeEvent();
  }
  if (select_->GetLayoutObject()) {
    // Need to check will_be_destroyed_ because event handlers might
    // disassociate |this| and select_.
    if (!will_be_destroyed_) {
      // DidUpdateActiveOption() is O(N) because of HTMLOptionElement::index().
      DidUpdateActiveOption(element);
    }
  }
}

void MenuListSelectType::DispatchEventsIfSelectedOptionChanged() {
  HTMLOptionElement* selected_option = select_->SelectedOption();
  if (select_->last_on_change_option_.Get() != selected_option) {
    select_->last_on_change_option_ = selected_option;
    select_->DispatchInputEvent();
    select_->DispatchChangeEvent();
  }
}

void MenuListSelectType::DidBlur() {
  // We only need to fire change events here for menu lists, because we fire
  // change events for list boxes whenever the selection change is actually
  // made.  This matches other browsers' behavior.
  DispatchEventsIfSelectedOptionChanged();
  if (PopupIsVisible())
    HidePopup();
}

void MenuListSelectType::DidSetSuggestedOption(HTMLOptionElement*) {
  UpdateTextStyleAndContent();
  if (PopupIsVisible())
    popup_->UpdateFromElement(PopupMenu::kBySelectionChange);
}

void MenuListSelectType::SaveLastSelection() {
  select_->last_on_change_option_ = select_->SelectedOption();
}

void MenuListSelectType::DidDetachLayoutTree() {
  if (popup_)
    popup_->DisconnectClient();
  SetPopupIsVisible(false);
  popup_ = nullptr;
  UnobserveTreeMutation();
}

void MenuListSelectType::DidRecalcStyle(const StyleRecalcChange change) {
  if (change.ReattachLayoutTree())
    return;
  UpdateTextStyle();
  if (PopupIsVisible())
    popup_->UpdateFromElement(PopupMenu::kByStyleChange);
}

String MenuListSelectType::UpdateTextStyleInternal() {
  HTMLOptionElement* option_to_be_shown = OptionToBeShown();
  String text = g_empty_string;
  const ComputedStyle* option_style = nullptr;

  if (select_->IsMultiple()) {
    unsigned selected_count = 0;
    HTMLOptionElement* selected_option_element = nullptr;
    for (auto* const option : select_->GetOptionList()) {
      if (option->Selected()) {
        if (++selected_count == 1)
          selected_option_element = option;
      }
    }

    if (selected_count == 1) {
      text = selected_option_element->TextIndentedToRespectGroupLabel();
      option_style = selected_option_element->GetComputedStyle();
    } else {
      Locale& locale = select_->GetLocale();
      String localized_number_string =
          locale.ConvertToLocalizedNumber(String::Number(selected_count));
      text = locale.QueryString(IDS_FORM_SELECT_MENU_LIST_TEXT,
                                localized_number_string);
      DCHECK(!option_style);
    }
  } else {
    if (option_to_be_shown) {
      text = option_to_be_shown->TextIndentedToRespectGroupLabel();
      option_style = option_to_be_shown->GetComputedStyle();
    }
  }
  option_style_ = option_style;

  auto& inner_element = select_->InnerElement();
  const ComputedStyle* inner_style = inner_element.GetComputedStyle();
  if (inner_style && option_style &&
      ((option_style->Direction() != inner_style->Direction() ||
        option_style->GetUnicodeBidi() != inner_style->GetUnicodeBidi()))) {
    scoped_refptr<ComputedStyle> cloned_style =
        ComputedStyle::Clone(*inner_style);
    cloned_style->SetDirection(option_style->Direction());
    cloned_style->SetUnicodeBidi(option_style->GetUnicodeBidi());
    if (auto* inner_layout = inner_element.GetLayoutObject()) {
      inner_layout->SetModifiedStyleOutsideStyleRecalc(
          std::move(cloned_style), LayoutObject::ApplyStyleChanges::kYes);
    } else {
      inner_element.SetComputedStyle(std::move(cloned_style));
    }
  }
  if (select_->GetLayoutObject())
    DidUpdateActiveOption(option_to_be_shown);

  return text.StripWhiteSpace();
}

void MenuListSelectType::UpdateTextStyleAndContent() {
  select_->InnerElement().firstChild()->setNodeValue(UpdateTextStyleInternal());
  if (auto* box = select_->GetLayoutBox()) {
    if (auto* cache = select_->GetDocument().ExistingAXObjectCache())
      cache->TextChanged(box);
  }
}

void MenuListSelectType::DidUpdateActiveOption(HTMLOptionElement* option) {
  Document& document = select_->GetDocument();
  if (!document.ExistingAXObjectCache())
    return;

  int option_index = option ? option->index() : -1;
  if (ax_menulist_last_active_index_ == option_index)
    return;
  ax_menulist_last_active_index_ = option_index;

  // We skip sending accessiblity notifications for the very first option,
  // otherwise we get extra focus and select events that are undesired.
  if (!has_updated_menulist_active_option_) {
    has_updated_menulist_active_option_ = true;
    return;
  }

  document.ExistingAXObjectCache()->HandleUpdateActiveMenuOption(
      select_->GetLayoutObject(), option_index);
}

HTMLOptionElement* MenuListSelectType::OptionToBeShown() const {
  if (auto* option =
          select_->OptionAtListIndex(select_->index_to_select_on_cancel_))
    return option;
  if (select_->suggested_option_)
    return select_->suggested_option_;
  // TODO(tkent): We should not call OptionToBeShown() in IsMultiple() case.
  if (select_->IsMultiple())
    return select_->SelectedOption();
  DCHECK_EQ(select_->SelectedOption(), select_->last_on_change_option_);
  return select_->last_on_change_option_;
}

void MenuListSelectType::MaximumOptionWidthMightBeChanged() const {
  if (LayoutObject* layout_object = select_->GetLayoutObject()) {
    layout_object->SetNeedsLayoutAndIntrinsicWidthsRecalc(
        layout_invalidation_reason::kMenuOptionsChanged);
  }
}

// PopupUpdater notifies updates of the specified SELECT element subtree to
// a PopupMenu object.
class PopupUpdater : public MutationObserver::Delegate {
 public:
  explicit PopupUpdater(MenuListSelectType& select_type,
                        HTMLSelectElement& select)
      : select_type_(select_type),
        select_(select),
        observer_(MutationObserver::Create(this)) {
    MutationObserverInit* init = MutationObserverInit::Create();
    init->setAttributeOldValue(true);
    init->setAttributes(true);
    // Observe only attributes which affect popup content.
    init->setAttributeFilter({"disabled", "label", "selected", "value"});
    init->setCharacterData(true);
    init->setCharacterDataOldValue(true);
    init->setChildList(true);
    init->setSubtree(true);
    observer_->observe(select_, init, ASSERT_NO_EXCEPTION);
  }

  ExecutionContext* GetExecutionContext() const override {
    return select_->GetExecutionContext();
  }

  void Deliver(const MutationRecordVector& records,
               MutationObserver&) override {
    // We disconnect the MutationObserver when a popup is closed.  However
    // MutationObserver can call back after disconnection.
    if (!select_type_->PopupIsVisible())
      return;
    for (const auto& record : records) {
      if (record->type() == "attributes") {
        const auto& element = *To<Element>(record->target());
        if (record->oldValue() == element.getAttribute(record->attributeName()))
          continue;
      } else if (record->type() == "characterData") {
        if (record->oldValue() == record->target()->nodeValue())
          continue;
      }
      select_type_->DidMutateSubtree();
      return;
    }
  }

  void Dispose() { observer_->disconnect(); }

  void Trace(Visitor* visitor) const override {
    visitor->Trace(select_type_);
    visitor->Trace(select_);
    visitor->Trace(observer_);
    MutationObserver::Delegate::Trace(visitor);
  }

 private:
  Member<MenuListSelectType> select_type_;
  Member<HTMLSelectElement> select_;
  Member<MutationObserver> observer_;
};

void MenuListSelectType::ObserveTreeMutation() {
  DCHECK(!popup_updater_);
  popup_updater_ = MakeGarbageCollected<PopupUpdater>(*this, *select_);
}

void MenuListSelectType::UnobserveTreeMutation() {
  if (!popup_updater_)
    return;
  popup_updater_->Dispose();
  popup_updater_ = nullptr;
}

void MenuListSelectType::DidMutateSubtree() {
  DCHECK(PopupIsVisible());
  DCHECK(popup_);
  popup_->UpdateFromElement(PopupMenu::kByDOMChange);
}

// ============================================================================

class ListBoxSelectType final : public SelectType {
 public:
  explicit ListBoxSelectType(HTMLSelectElement& select) : SelectType(select) {}
  void Trace(Visitor* visitor) const override;

  bool DefaultEventHandler(const Event& event) override;
  void DidSelectOption(HTMLOptionElement* element,
                       HTMLSelectElement::SelectOptionFlags flags,
                       bool should_update_popup) override;
  void OptionRemoved(HTMLOptionElement& option) override;
  void DidBlur() override;
  void DidSetSuggestedOption(HTMLOptionElement* option) override;
  void SaveLastSelection() override;
  HTMLOptionElement* SpatialNavigationFocusedOption() override;
  HTMLOptionElement* ActiveSelectionEnd() const override;
  void ScrollToSelection() override;
  void ScrollToOption(HTMLOptionElement* option) override;
  void SelectAll() override;
  void SaveListboxActiveSelection() override;
  void HandleMouseRelease() override;
  void ListBoxOnChange() override;
  void ClearLastOnChangeSelection() override;

 private:
  HTMLOptionElement* NextSelectableOptionPageAway(HTMLOptionElement*,
                                                  SkipDirection) const;
  // Update :-internal-multi-select-focus state of selected OPTIONs.
  void UpdateMultiSelectFocus();
  void ToggleSelection(HTMLOptionElement& option);
  enum class SelectionMode {
    kDeselectOthers,
    kRange,
    kNotChangeOthers,
  };
  void UpdateSelectedState(HTMLOptionElement* clicked_option,
                           SelectionMode mode);
  void UpdateListBoxSelection(bool deselect_other_options, bool scroll = true);
  void SetActiveSelectionAnchor(HTMLOptionElement*);
  void SetActiveSelectionEnd(HTMLOptionElement*);
  void ScrollToOptionTask();

  Vector<bool> cached_state_for_active_selection_;
  Vector<bool> last_on_change_selection_;
  Member<HTMLOptionElement> option_to_scroll_to_;
  Member<HTMLOptionElement> active_selection_anchor_;
  Member<HTMLOptionElement> active_selection_end_;
  bool is_in_non_contiguous_selection_ = false;
  bool active_selection_state_ = false;
};

void ListBoxSelectType::Trace(Visitor* visitor) const {
  visitor->Trace(option_to_scroll_to_);
  visitor->Trace(active_selection_anchor_);
  visitor->Trace(active_selection_end_);
  SelectType::Trace(visitor);
}

bool ListBoxSelectType::DefaultEventHandler(const Event& event) {
  const auto* mouse_event = DynamicTo<MouseEvent>(event);
  const auto* gesture_event = DynamicTo<GestureEvent>(event);
  if (event.type() == event_type_names::kGesturetap && gesture_event) {
    select_->focus();
    // Calling focus() may cause us to lose our layoutObject or change the
    // layoutObject type, in which case do not want to handle the event.
    if (!select_->GetLayoutObject() || will_be_destroyed_)
      return false;

    // Convert to coords relative to the list box if needed.
    if (HTMLOptionElement* option = EventTargetOption(*gesture_event)) {
      if (!select_->IsDisabledFormControl()) {
        UpdateSelectedState(option, gesture_event->shiftKey()
                                        ? SelectionMode::kRange
                                        : SelectionMode::kNotChangeOthers);
        ListBoxOnChange();
      }
      return true;
    }
    return false;
  }

  if (event.type() == event_type_names::kMousedown && mouse_event &&
      mouse_event->button() ==
          static_cast<int16_t>(WebPointerProperties::Button::kLeft)) {
    select_->focus();
    // Calling focus() may cause us to lose our layoutObject, in which case
    // do not want to handle the event.
    if (!select_->GetLayoutObject() || will_be_destroyed_ ||
        select_->IsDisabledFormControl())
      return false;

    // Convert to coords relative to the list box if needed.
    if (HTMLOptionElement* option = EventTargetOption(*mouse_event)) {
      if (!option->IsDisabledFormControl()) {
#if defined(OS_MAC)
        const bool meta_or_ctrl = mouse_event->metaKey();
#else
        const bool meta_or_ctrl = mouse_event->ctrlKey();
#endif
        UpdateSelectedState(option, mouse_event->shiftKey()
                                        ? SelectionMode::kRange
                                        : meta_or_ctrl
                                              ? SelectionMode::kNotChangeOthers
                                              : SelectionMode::kDeselectOthers);
      }
      if (LocalFrame* frame = select_->GetDocument().GetFrame())
        frame->GetEventHandler().SetMouseDownMayStartAutoscroll();

      return true;
    }
    return false;
  }

  if (event.type() == event_type_names::kMousemove && mouse_event) {
    if (mouse_event->button() !=
            static_cast<int16_t>(WebPointerProperties::Button::kLeft) ||
        !mouse_event->ButtonDown())
      return false;

    if (auto* layout_object = select_->GetLayoutObject()) {
      layout_object->GetFrameView()->UpdateAllLifecyclePhasesExceptPaint(
          DocumentUpdateReason::kScroll);

      if (Page* page = select_->GetDocument().GetPage()) {
        page->GetAutoscrollController().StartAutoscrollForSelection(
            select_->GetLayoutObject());
      }
    }
    // Mousedown didn't happen in this element.
    if (last_on_change_selection_.IsEmpty())
      return false;

    if (HTMLOptionElement* option = EventTargetOption(*mouse_event)) {
      if (!select_->IsDisabledFormControl()) {
        if (select_->is_multiple_) {
          // Only extend selection if there is something selected.
          if (!active_selection_anchor_)
            return false;

          SetActiveSelectionEnd(option);
          UpdateListBoxSelection(false);
        } else {
          SetActiveSelectionAnchor(option);
          SetActiveSelectionEnd(option);
          UpdateListBoxSelection(true);
        }
      }
    }
    return false;
  }

  if (event.type() == event_type_names::kMouseup && mouse_event &&
      mouse_event->button() ==
          static_cast<int16_t>(WebPointerProperties::Button::kLeft) &&
      select_->GetLayoutObject()) {
    auto* page = select_->GetDocument().GetPage();
    if (page && page->GetAutoscrollController().AutoscrollInProgressFor(
                    select_->GetLayoutBox()))
      page->GetAutoscrollController().StopAutoscroll();
    else
      HandleMouseRelease();
    return false;
  }

  if (event.type() == event_type_names::kKeydown) {
    const auto* keyboard_event = DynamicTo<KeyboardEvent>(event);
    if (!keyboard_event)
      return false;
    const String& key = keyboard_event->key();

    bool handled = false;
    HTMLOptionElement* end_option = nullptr;
    if (!active_selection_end_) {
      // Initialize the end index
      if (key == "ArrowDown" || key == "PageDown") {
        HTMLOptionElement* start_option = select_->LastSelectedOption();
        handled = true;
        if (key == "ArrowDown") {
          end_option = NextSelectableOption(start_option);
        } else {
          end_option =
              NextSelectableOptionPageAway(start_option, kSkipForwards);
        }
      } else if (key == "ArrowUp" || key == "PageUp") {
        HTMLOptionElement* start_option = select_->SelectedOption();
        handled = true;
        if (key == "ArrowUp") {
          end_option = PreviousSelectableOption(start_option);
        } else {
          end_option =
              NextSelectableOptionPageAway(start_option, kSkipBackwards);
        }
      }
    } else {
      // Set the end index based on the current end index.
      if (key == "ArrowDown") {
        end_option = NextSelectableOption(active_selection_end_);
        handled = true;
      } else if (key == "ArrowUp") {
        end_option = PreviousSelectableOption(active_selection_end_);
        handled = true;
      } else if (key == "PageDown") {
        end_option =
            NextSelectableOptionPageAway(active_selection_end_, kSkipForwards);
        handled = true;
      } else if (key == "PageUp") {
        end_option =
            NextSelectableOptionPageAway(active_selection_end_, kSkipBackwards);
        handled = true;
      }
    }
    if (key == "Home") {
      end_option = FirstSelectableOption();
      handled = true;
    } else if (key == "End") {
      end_option = LastSelectableOption();
      handled = true;
    }

    if (IsSpatialNavigationEnabled(select_->GetDocument().GetFrame())) {
      // Check if the selection moves to the boundary.
      if (key == "ArrowLeft" || key == "ArrowRight" ||
          ((key == "ArrowDown" || key == "ArrowUp") &&
           end_option == active_selection_end_))
        return false;
    }

    bool is_control_key = false;
#if defined(OS_MAC)
    is_control_key = keyboard_event->metaKey();
#else
    is_control_key = keyboard_event->ctrlKey();
#endif

    if (select_->is_multiple_ && keyboard_event->keyCode() == ' ' &&
        is_control_key && active_selection_end_) {
      // Use ctrl+space to toggle selection change.
      ToggleSelection(*active_selection_end_);
      return true;
    }

    if (end_option && handled) {
      // Save the selection so it can be compared to the new selection
      // when dispatching change events immediately after making the new
      // selection.
      SaveLastSelection();

      SetActiveSelectionEnd(end_option);

      is_in_non_contiguous_selection_ = select_->is_multiple_ && is_control_key;
      bool select_new_item =
          !select_->is_multiple_ || keyboard_event->shiftKey() ||
          (!IsSpatialNavigationEnabled(select_->GetDocument().GetFrame()) &&
           !is_in_non_contiguous_selection_);
      if (select_new_item)
        active_selection_state_ = true;
      // If the anchor is uninitialized, or if we're going to deselect all
      // other options, then set the anchor index equal to the end index.
      bool deselect_others = !select_->is_multiple_ ||
                             (!keyboard_event->shiftKey() && select_new_item);
      if (!active_selection_anchor_ || deselect_others) {
        if (deselect_others)
          select_->DeselectItemsWithoutValidation();
        SetActiveSelectionAnchor(active_selection_end_.Get());
      }

      ScrollToOption(end_option);
      if (select_new_item || is_in_non_contiguous_selection_) {
        if (select_new_item) {
          UpdateListBoxSelection(deselect_others);
          ListBoxOnChange();
        }
        UpdateMultiSelectFocus();
      } else {
        ScrollToSelection();
      }

      return true;
    }
    return false;
  }

  if (event.type() == event_type_names::kKeypress) {
    auto* keyboard_event = DynamicTo<KeyboardEvent>(event);
    if (!keyboard_event)
      return false;
    int key_code = keyboard_event->keyCode();

    if (key_code == '\r') {
      if (HTMLFormElement* form = select_->Form())
        form->SubmitImplicitly(event, false);
      return true;
    } else if (select_->is_multiple_ && key_code == ' ' &&
               (IsSpatialNavigationEnabled(select_->GetDocument().GetFrame()) ||
                is_in_non_contiguous_selection_)) {
      HTMLOptionElement* option = active_selection_end_;
      // If there's no active selection,
      // act as if "ArrowDown" had been pressed.
      if (!option)
        option = NextSelectableOption(select_->LastSelectedOption());
      if (option) {
        // Use space to toggle selection change.
        ToggleSelection(*option);
        return true;
      }
    }
    return false;
  }
  return false;
}

void ListBoxSelectType::DidSelectOption(
    HTMLOptionElement* element,
    HTMLSelectElement::SelectOptionFlags flags,
    bool should_update_popup) {
  // We should update active selection after finishing OPTION state change
  // because SetActiveSelectionAnchor() stores OPTION's selection state.
  if (element) {
    const bool is_single = !select_->IsMultiple();
    const bool deselect_other_options =
        flags & HTMLSelectElement::kDeselectOtherOptionsFlag;
    // SetActiveSelectionAnchor is O(N).
    if (!active_selection_anchor_ || is_single || deselect_other_options)
      SetActiveSelectionAnchor(element);
    if (!active_selection_end_ || is_single || deselect_other_options)
      SetActiveSelectionEnd(element);
  }

  ScrollToSelection();
  select_->SetNeedsValidityCheck();
}

void ListBoxSelectType::OptionRemoved(HTMLOptionElement& option) {
  if (option_to_scroll_to_ == &option)
    option_to_scroll_to_.Clear();
  if (active_selection_anchor_ == &option)
    active_selection_anchor_.Clear();
  if (active_selection_end_ == &option)
    active_selection_end_.Clear();
}

void ListBoxSelectType::DidBlur() {
  ClearLastOnChangeSelection();
}

void ListBoxSelectType::DidSetSuggestedOption(HTMLOptionElement* option) {
  if (select_->GetLayoutObject())
    ScrollToOption(option);
}

void ListBoxSelectType::SaveLastSelection() {
  last_on_change_selection_.clear();
  for (auto& element : select_->GetListItems()) {
    auto* option_element = DynamicTo<HTMLOptionElement>(element.Get());
    last_on_change_selection_.push_back(option_element &&
                                        option_element->Selected());
  }
}

void ListBoxSelectType::UpdateMultiSelectFocus() {
  if (!select_->is_multiple_)
    return;

  for (auto* const option : select_->GetOptionList()) {
    if (option->IsDisabledFormControl() || !option->GetLayoutObject())
      continue;
    bool is_focused =
        (option == active_selection_end_) && is_in_non_contiguous_selection_;
    option->SetMultiSelectFocusedState(is_focused);
  }
  ScrollToSelection();
}

HTMLOptionElement* ListBoxSelectType::SpatialNavigationFocusedOption() {
  if (!IsSpatialNavigationEnabled(select_->GetDocument().GetFrame()))
    return nullptr;
  if (HTMLOptionElement* option = ActiveSelectionEnd())
    return option;
  return FirstSelectableOption();
}

void ListBoxSelectType::SetActiveSelectionAnchor(HTMLOptionElement* option) {
  active_selection_anchor_ = option;
  SaveListboxActiveSelection();
}

void ListBoxSelectType::SetActiveSelectionEnd(HTMLOptionElement* option) {
  active_selection_end_ = option;
}

HTMLOptionElement* ListBoxSelectType::ActiveSelectionEnd() const {
  if (active_selection_end_)
    return active_selection_end_;
  return select_->LastSelectedOption();
}

void ListBoxSelectType::ScrollToSelection() {
  if (!select_->IsFinishedParsingChildren())
    return;
  ScrollToOption(ActiveSelectionEnd());
  if (AXObjectCache* cache = select_->GetDocument().ExistingAXObjectCache())
    cache->ListboxActiveIndexChanged(select_);
}

void ListBoxSelectType::ScrollToOption(HTMLOptionElement* option) {
  if (!option)
    return;
  bool has_pending_task = option_to_scroll_to_;
  // We'd like to keep an HTMLOptionElement reference rather than the index of
  // the option because the task should work even if unselected option is
  // inserted before executing ScrollToOptionTask().
  option_to_scroll_to_ = option;
  if (!has_pending_task) {
    select_->GetDocument()
        .GetTaskRunner(TaskType::kUserInteraction)
        ->PostTask(FROM_HERE, WTF::Bind(&ListBoxSelectType::ScrollToOptionTask,
                                        WrapPersistent(this)));
  }
}

void ListBoxSelectType::ScrollToOptionTask() {
  HTMLOptionElement* option = option_to_scroll_to_.Release();
  if (!option || !select_->isConnected() || will_be_destroyed_)
    return;
  // OptionRemoved() makes sure option_to_scroll_to_ doesn't have an option
  // with another owner.
  DCHECK_EQ(option->OwnerSelectElement(), select_);
  select_->GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kScroll);
  if (!select_->GetLayoutObject())
    return;
  PhysicalRect bounds = option->BoundingBoxForScrollIntoView();

  // The following code will not scroll parent boxes unlike ScrollRectToVisible.
  auto* box = select_->GetLayoutBox();
  if (!box->IsScrollContainer())
    return;
  DCHECK(box->Layer());
  DCHECK(box->Layer()->GetScrollableArea());
  box->Layer()->GetScrollableArea()->ScrollIntoView(
      bounds,
      ScrollAlignment::CreateScrollIntoViewParams(
          ScrollAlignment::ToEdgeIfNeeded(), ScrollAlignment::ToEdgeIfNeeded(),
          mojom::blink::ScrollType::kProgrammatic, false,
          mojom::blink::ScrollBehavior::kInstant));
}

void ListBoxSelectType::SelectAll() {
  if (!select_->GetLayoutObject() || !select_->is_multiple_)
    return;

  // Save the selection so it can be compared to the new selectAll selection
  // when dispatching change events.
  SaveLastSelection();

  active_selection_state_ = true;
  SetActiveSelectionAnchor(NextSelectableOption(nullptr));
  SetActiveSelectionEnd(PreviousSelectableOption(nullptr));

  UpdateListBoxSelection(false, false);
  ListBoxOnChange();
  select_->SetNeedsValidityCheck();
}

// Returns the index of the next valid item one page away from |start_option|
// in direction |direction|.
HTMLOptionElement* ListBoxSelectType::NextSelectableOptionPageAway(
    HTMLOptionElement* start_option,
    SkipDirection direction) const {
  const auto& items = select_->GetListItems();
  // -1 so we still show context.
  int page_size = select_->ListBoxSize() - 1;

  // One page away, but not outside valid bounds.
  // If there is a valid option item one page away, the index is chosen.
  // If there is no exact one page away valid option, returns start_index or
  // the most far index.
  int start_index = start_option ? start_option->ListIndex() : -1;
  int edge_index = (direction == kSkipForwards) ? 0 : (items.size() - 1);
  int skip_amount =
      page_size +
      ((direction == kSkipForwards) ? start_index : (edge_index - start_index));
  return NextValidOption(edge_index, direction, skip_amount);
}

void ListBoxSelectType::ToggleSelection(HTMLOptionElement& option) {
  active_selection_state_ = !active_selection_state_;
  UpdateSelectedState(&option, SelectionMode::kNotChangeOthers);
  ListBoxOnChange();
}

void ListBoxSelectType::UpdateSelectedState(HTMLOptionElement* clicked_option,
                                            SelectionMode mode) {
  DCHECK(clicked_option);
  // Save the selection so it can be compared to the new selection when
  // dispatching change events during mouseup, or after autoscroll finishes.
  SaveLastSelection();

  active_selection_state_ = true;

  if (!select_->is_multiple_)
    mode = SelectionMode::kDeselectOthers;

  // Keep track of whether an active selection (like during drag selection),
  // should select or deselect.
  if (clicked_option->Selected() && mode == SelectionMode::kNotChangeOthers) {
    active_selection_state_ = false;
    clicked_option->SetSelectedState(false);
    clicked_option->SetDirty(true);
  }

  // If we're not in any special multiple selection mode, then deselect all
  // other items, excluding the clicked OPTION. If no option was clicked, then
  // this will deselect all items in the list.
  if (mode == SelectionMode::kDeselectOthers)
    select_->DeselectItemsWithoutValidation(clicked_option);

  // If the anchor hasn't been set, and we're doing kDeselectOthers or kRange,
  // then initialize the anchor to the first selected OPTION.
  if (!active_selection_anchor_ && mode != SelectionMode::kNotChangeOthers)
    SetActiveSelectionAnchor(select_->SelectedOption());

  // Set the selection state of the clicked OPTION.
  if (!clicked_option->IsDisabledFormControl()) {
    clicked_option->SetSelectedState(true);
    clicked_option->SetDirty(true);
  }

  // If there was no selectedIndex() for the previous initialization, or if
  // we're doing kDeselectOthers, or kNotChangeOthers (using cmd or ctrl),
  // then initialize the anchor OPTION to the clicked OPTION.
  if (!active_selection_anchor_ || mode != SelectionMode::kRange)
    SetActiveSelectionAnchor(clicked_option);

  SetActiveSelectionEnd(clicked_option);
  UpdateListBoxSelection(mode != SelectionMode::kNotChangeOthers);
}

void ListBoxSelectType::UpdateListBoxSelection(bool deselect_other_options,
                                               bool scroll) {
  DCHECK(select_->GetLayoutObject());
  HTMLOptionElement* const anchor_option = active_selection_anchor_;
  HTMLOptionElement* const end_option = active_selection_end_;
  const int anchor_index = anchor_option ? anchor_option->index() : -1;
  const int end_index = end_option ? end_option->index() : -1;
  const int start = std::min(anchor_index, end_index);
  const int end = std::max(anchor_index, end_index);

  int i = 0;
  for (auto* const option : select_->GetOptionList()) {
    if (option->IsDisabledFormControl() || !option->GetLayoutObject()) {
      ++i;
      continue;
    }
    if (i >= start && i <= end) {
      option->SetSelectedState(active_selection_state_);
      option->SetDirty(true);
    } else if (deselect_other_options ||
               i >= static_cast<int>(
                        cached_state_for_active_selection_.size())) {
      option->SetSelectedState(false);
      option->SetDirty(true);
    } else {
      option->SetSelectedState(cached_state_for_active_selection_[i]);
    }
    ++i;
  }

  UpdateMultiSelectFocus();
  select_->SetNeedsValidityCheck();
  if (scroll)
    ScrollToSelection();
  select_->NotifyFormStateChanged();
}

void ListBoxSelectType::SaveListboxActiveSelection() {
  // Cache the selection state so we can restore the old selection as the new
  // selection pivots around this anchor index.
  // Example:
  // 1. Press the mouse button on the second OPTION
  //   active_selection_anchor_ points the second OPTION.
  // 2. Drag the mouse pointer onto the fifth OPTION
  //   active_selection_end_ points the fifth OPTION, OPTIONs at 1-4 indices
  //   are selected.
  // 3. Drag the mouse pointer onto the fourth OPTION
  //   active_selection_end_ points the fourth OPTION, OPTIONs at 1-3 indices
  //   are selected.
  //   UpdateListBoxSelection needs to clear selection of the fifth OPTION.
  cached_state_for_active_selection_.resize(0);
  for (auto* const option : select_->GetOptionList()) {
    cached_state_for_active_selection_.push_back(option->Selected());
  }
}

void ListBoxSelectType::HandleMouseRelease() {
  // We didn't start this click/drag on any options.
  if (last_on_change_selection_.IsEmpty())
    return;
  ListBoxOnChange();
}

void ListBoxSelectType::ListBoxOnChange() {
  const auto& items = select_->GetListItems();

  // If the cached selection list is empty, or the size has changed, then fire
  // 'change' event, and return early.
  // FIXME: Why? This looks unreasonable.
  if (last_on_change_selection_.IsEmpty() ||
      last_on_change_selection_.size() != items.size()) {
    select_->DispatchChangeEvent();
    return;
  }

  // Update last_on_change_selection_ and fire a 'change' event.
  bool fire_on_change = false;
  for (unsigned i = 0; i < items.size(); ++i) {
    HTMLElement* element = items[i];
    auto* option_element = DynamicTo<HTMLOptionElement>(element);
    bool selected = option_element && option_element->Selected();
    if (selected != last_on_change_selection_[i])
      fire_on_change = true;
    last_on_change_selection_[i] = selected;
  }

  if (fire_on_change) {
    select_->DispatchInputEvent();
    select_->DispatchChangeEvent();
  }
}

void ListBoxSelectType::ClearLastOnChangeSelection() {
  last_on_change_selection_.clear();
}

// ============================================================================

SelectType::SelectType(HTMLSelectElement& select) : select_(select) {}

SelectType* SelectType::Create(HTMLSelectElement& select) {
  if (select.UsesMenuList())
    return MakeGarbageCollected<MenuListSelectType>(select);
  else
    return MakeGarbageCollected<ListBoxSelectType>(select);
}

void SelectType::WillBeDestroyed() {
  will_be_destroyed_ = true;
}

void SelectType::Trace(Visitor* visitor) const {
  visitor->Trace(select_);
}

void SelectType::OptionRemoved(HTMLOptionElement& option) {}

void SelectType::DidDetachLayoutTree() {}

void SelectType::DidRecalcStyle(const StyleRecalcChange) {}

void SelectType::UpdateTextStyle() {}

void SelectType::UpdateTextStyleAndContent() {}

HTMLOptionElement* SelectType::OptionToBeShown() const {
  NOTREACHED();
  return nullptr;
}

const ComputedStyle* SelectType::OptionStyle() const {
  NOTREACHED();
  return nullptr;
}

void SelectType::MaximumOptionWidthMightBeChanged() const {}

HTMLOptionElement* SelectType::SpatialNavigationFocusedOption() {
  return nullptr;
}

HTMLOptionElement* SelectType::ActiveSelectionEnd() const {
  NOTREACHED();
  return nullptr;
}

void SelectType::ScrollToSelection() {}

void SelectType::ScrollToOption(HTMLOptionElement* option) {}

void SelectType::SelectAll() {
  NOTREACHED();
}

void SelectType::SaveListboxActiveSelection() {}

void SelectType::HandleMouseRelease() {}

void SelectType::ListBoxOnChange() {}

void SelectType::ClearLastOnChangeSelection() {}

void SelectType::CreateShadowSubtree(ShadowRoot& root) {}

Element& SelectType::InnerElement() const {
  NOTREACHED();
  // Returning select_ doesn't make sense, but we need to return an element
  // to compile this source. This function must not be called.
  return *select_;
}

void SelectType::ShowPopup() {
  NOTREACHED();
}

void SelectType::HidePopup() {
  NOTREACHED();
}

void SelectType::PopupDidHide() {
  NOTREACHED();
}

bool SelectType::PopupIsVisible() const {
  return false;
}

PopupMenu* SelectType::PopupForTesting() const {
  NOTREACHED();
  return nullptr;
}

AXObject* SelectType::PopupRootAXObject() const {
  NOTREACHED();
  return nullptr;
}

// Returns the 1st valid OPTION |skip| items from |list_index| in direction
// |direction| if there is one.
// Otherwise, it returns the valid OPTION closest to that boundary which is past
// |list_index| if there is one.
// Otherwise, it returns nullptr.
// Valid means that it is enabled and visible.
HTMLOptionElement* SelectType::NextValidOption(int list_index,
                                               SkipDirection direction,
                                               int skip) const {
  DCHECK(direction == kSkipBackwards || direction == kSkipForwards);
  const auto& list_items = select_->GetListItems();
  HTMLOptionElement* last_good_option = nullptr;
  int size = list_items.size();
  for (list_index += direction; list_index >= 0 && list_index < size;
       list_index += direction) {
    --skip;
    HTMLElement* element = list_items[list_index];
    auto* option_element = DynamicTo<HTMLOptionElement>(element);
    if (!option_element)
      continue;
    if (option_element->IsDisplayNone())
      continue;
    if (element->IsDisabledFormControl())
      continue;
    if (!select_->UsesMenuList() && !element->GetLayoutObject())
      continue;
    last_good_option = option_element;
    if (skip <= 0)
      break;
  }
  return last_good_option;
}

HTMLOptionElement* SelectType::NextSelectableOption(
    HTMLOptionElement* start_option) const {
  return NextValidOption(start_option ? start_option->ListIndex() : -1,
                         kSkipForwards, 1);
}

HTMLOptionElement* SelectType::PreviousSelectableOption(
    HTMLOptionElement* start_option) const {
  return NextValidOption(
      start_option ? start_option->ListIndex() : select_->GetListItems().size(),
      kSkipBackwards, 1);
}

HTMLOptionElement* SelectType::FirstSelectableOption() const {
  return NextValidOption(-1, kSkipForwards, 1);
}

HTMLOptionElement* SelectType::LastSelectableOption() const {
  return NextValidOption(select_->GetListItems().size(), kSkipBackwards, 1);
}

}  // namespace blink
