// Copyright (c) 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

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

#include "build/build_config.h"
#include "third_party/blink/public/common/input/web_mouse_event.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/css/css_font_selector.h"
#include "third_party/blink/renderer/core/css/css_value_id_mappings.h"
#include "third_party/blink/renderer/core/css/pseudo_style_request.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html/forms/chooser_resource_loader.h"
#include "third_party/blink/renderer/core/html/forms/html_opt_group_element.h"
#include "third_party/blink/renderer/core/html/forms/html_option_element.h"
#include "third_party/blink/renderer/core/html/forms/html_select_element.h"
#include "third_party/blink/renderer/core/html/html_hr_element.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page_popup.h"
#include "third_party/blink/renderer/core/scroll/scrollable_area.h"
#include "third_party/blink/renderer/platform/fonts/font_selector.h"
#include "third_party/blink/renderer/platform/fonts/font_selector_client.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
#include "ui/base/ui_base_features.h"

namespace blink {

namespace {

// TODO crbug.com/516675 Add stretch to serialization

const char* FontStyleToString(FontSelectionValue slope) {
  if (slope == ItalicSlopeValue())
    return "italic";
  return "normal";
}

const char* TextTransformToString(ETextTransform transform) {
  return getValueName(PlatformEnumToCSSValueID(transform));
}

const String SerializeComputedStyleForProperty(const ComputedStyle& style,
                                               CSSPropertyID id) {
  const CSSProperty& property = CSSProperty::Get(id);
  const CSSValue* value =
      property.CSSValueFromComputedStyle(style, nullptr, false);
  return String::Format("%s : %s;\n", property.GetPropertyName(),
                        value->CssText().Utf8().c_str());
}

ScrollbarPart ScrollbarPartFromPseudoId(PseudoId id) {
  switch (id) {
    case kPseudoIdScrollbar:
      return kScrollbarBGPart;
    case kPseudoIdScrollbarThumb:
      return kThumbPart;
    case kPseudoIdScrollbarTrack:
    case kPseudoIdScrollbarTrackPiece:
      return kBackTrackPart;
    default:
      break;
  }
  return kNoPart;
}

scoped_refptr<const ComputedStyle> StyleForHoveredScrollbarPart(
    HTMLSelectElement& element,
    const ComputedStyle* style,
    Scrollbar* scrollbar,
    PseudoId target_id) {
  ScrollbarPart part = ScrollbarPartFromPseudoId(target_id);
  if (part == kNoPart)
    return nullptr;
  scrollbar->SetHoveredPart(part);
  scoped_refptr<const ComputedStyle> part_style =
      element.UncachedStyleForPseudoElement(
          PseudoElementStyleRequest(target_id, To<CustomScrollbar>(scrollbar),
                                    part),
          style);
  return part_style;
}

}  // anonymous namespace

class PopupMenuCSSFontSelector : public CSSFontSelector,
                                 private FontSelectorClient {
 public:
  PopupMenuCSSFontSelector(Document&, CSSFontSelector*);
  ~PopupMenuCSSFontSelector() override;

  // We don't override willUseFontData() for now because the old PopupListBox
  // only worked with fonts loaded when opening the popup.
  scoped_refptr<FontData> GetFontData(const FontDescription&,
                                      const AtomicString&) override;

  void Trace(Visitor*) const override;

 private:
  void FontsNeedUpdate(FontSelector*, FontInvalidationReason) override;

  Member<CSSFontSelector> owner_font_selector_;
};

PopupMenuCSSFontSelector::PopupMenuCSSFontSelector(
    Document& document,
    CSSFontSelector* owner_font_selector)
    : CSSFontSelector(document), owner_font_selector_(owner_font_selector) {
  owner_font_selector_->RegisterForInvalidationCallbacks(this);
}

PopupMenuCSSFontSelector::~PopupMenuCSSFontSelector() = default;

scoped_refptr<FontData> PopupMenuCSSFontSelector::GetFontData(
    const FontDescription& description,
    const AtomicString& name) {
  return owner_font_selector_->GetFontData(description, name);
}

void PopupMenuCSSFontSelector::FontsNeedUpdate(FontSelector* font_selector,
                                               FontInvalidationReason reason) {
  DispatchInvalidationCallbacks(reason);
}

void PopupMenuCSSFontSelector::Trace(Visitor* visitor) const {
  visitor->Trace(owner_font_selector_);
  CSSFontSelector::Trace(visitor);
  FontSelectorClient::Trace(visitor);
}

// ----------------------------------------------------------------

class InternalPopupMenu::ItemIterationContext {
  STACK_ALLOCATED();

 public:
  ItemIterationContext(const ComputedStyle& style, SharedBuffer* buffer)
      : base_style_(style),
        background_color_(
            style.VisitedDependentColor(GetCSSPropertyBackgroundColor())),
        list_index_(0),
        is_in_group_(false),
        buffer_(buffer) {
    DCHECK(buffer_);
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
    // On other platforms, the <option> background color is the same as the
    // <select> background color. On Linux, that makes the <option>
    // background color very dark, so by default, try to use a lighter
    // background color for <option>s.
    if (LayoutTheme::GetTheme().SystemColor(CSSValueID::kButtonface,
                                            style.UsedColorScheme()) ==
        background_color_) {
      background_color_ = LayoutTheme::GetTheme().SystemColor(
          CSSValueID::kMenu, style.UsedColorScheme());
    }
#endif
  }

  void SerializeBaseStyle() {
    DCHECK(!is_in_group_);
    PagePopupClient::AddString("baseStyle: {", buffer_);
    AddProperty("backgroundColor", background_color_.Serialized(), buffer_);
    AddProperty(
        "color",
        BaseStyle().VisitedDependentColor(GetCSSPropertyColor()).Serialized(),
        buffer_);
    AddProperty("textTransform",
                String(TextTransformToString(BaseStyle().TextTransform())),
                buffer_);
    AddProperty("fontSize", BaseFont().ComputedPixelSize(), buffer_);
    AddProperty("fontStyle", String(FontStyleToString(BaseFont().Style())),
                buffer_);
    AddProperty("fontVariant",
                BaseFont().VariantCaps() == FontDescription::kSmallCaps
                    ? String("small-caps")
                    : String(),
                buffer_);

    PagePopupClient::AddString("fontFamily: [", buffer_);
    for (const FontFamily* f = &BaseFont().Family(); f; f = f->Next()) {
      AddJavaScriptString(f->Family().GetString(), buffer_);
      if (f->Next())
        PagePopupClient::AddString(",", buffer_);
    }
    PagePopupClient::AddString("]", buffer_);
    PagePopupClient::AddString("},\n", buffer_);
  }

  Color BackgroundColor() const {
    return is_in_group_ ? group_style_->VisitedDependentColor(
                              GetCSSPropertyBackgroundColor())
                        : background_color_;
  }
  // Do not use baseStyle() for background-color, use backgroundColor()
  // instead.
  const ComputedStyle& BaseStyle() {
    return is_in_group_ ? *group_style_ : base_style_;
  }
  const FontDescription& BaseFont() {
    return is_in_group_ ? group_style_->GetFontDescription()
                        : base_style_.GetFontDescription();
  }
  void StartGroupChildren(const ComputedStyle& group_style) {
    DCHECK(!is_in_group_);
    PagePopupClient::AddString("children: [", buffer_);
    is_in_group_ = true;
    group_style_ = &group_style;
  }
  void FinishGroupIfNecessary() {
    if (!is_in_group_)
      return;
    PagePopupClient::AddString("],},\n", buffer_);
    is_in_group_ = false;
    group_style_ = nullptr;
  }

  const ComputedStyle& base_style_;
  Color background_color_;
  const ComputedStyle* group_style_;

  unsigned list_index_;
  bool is_in_group_;
  SharedBuffer* buffer_;
};

// ----------------------------------------------------------------

InternalPopupMenu::InternalPopupMenu(ChromeClient* chrome_client,
                                     HTMLSelectElement& owner_element)
    : chrome_client_(chrome_client),
      owner_element_(owner_element),
      popup_(nullptr),
      needs_update_(false) {}

InternalPopupMenu::~InternalPopupMenu() {
  DCHECK(!popup_);
}

void InternalPopupMenu::Trace(Visitor* visitor) const {
  visitor->Trace(chrome_client_);
  visitor->Trace(owner_element_);
  PopupMenu::Trace(visitor);
}

void InternalPopupMenu::WriteDocument(SharedBuffer* data) {
  HTMLSelectElement& owner_element = *owner_element_;
  // When writing the document, we ensure the ComputedStyle of the select
  // element's items (see AddElementStyle). This requires a style-clean tree.
  // See Element::EnsureComputedStyle for further explanation.
  DCHECK(!owner_element.GetDocument().NeedsLayoutTreeUpdate());
  IntRect anchor_rect_in_screen = chrome_client_->ViewportToScreen(
      owner_element.VisibleBoundsInVisualViewport(),
      owner_element.GetDocument().View());

  float scale_factor = chrome_client_->WindowToViewportScalar(
      owner_element.GetDocument().GetFrame(), 1.f);
  PagePopupClient::AddString(
      "<!DOCTYPE html><head><meta charset='UTF-8'><style>\n", data);

  LayoutObject* owner_layout = owner_element.GetLayoutObject();

  std::pair<PseudoId, const String> targets[] = {
      {kPseudoIdScrollbar, "select::-webkit-scrollbar"},
      {kPseudoIdScrollbarThumb, "select::-webkit-scrollbar-thumb"},
      {kPseudoIdScrollbarTrack, "select::-webkit-scrollbar-track"},
      {kPseudoIdScrollbarTrackPiece, "select::-webkit-scrollbar-track-piece"},
      {kPseudoIdScrollbarCorner, "select::-webkit-scrollbar-corner"}};

  Scrollbar* temp_scrollbar = nullptr;
  const LayoutBox* box = owner_element.InnerElement().GetLayoutBox();
  if (box && box->GetScrollableArea()) {
    if (ScrollableArea* scrollable = box->GetScrollableArea()) {
      temp_scrollbar = MakeGarbageCollected<CustomScrollbar>(
          scrollable, kVerticalScrollbar, &owner_element.InnerElement());
    }
  }
  for (auto target : targets) {
    if (const ComputedStyle* style =
            owner_layout->GetCachedPseudoElementStyle(target.first)) {
      AppendOwnerElementPseudoStyles(target.second, data, *style);
    }
    // For Pseudo-class styles, Style should be calculated via that status.
    if (temp_scrollbar) {
      scoped_refptr<const ComputedStyle> part_style =
          StyleForHoveredScrollbarPart(owner_element,
                                       owner_element.GetComputedStyle(),
                                       temp_scrollbar, target.first);
      if (part_style) {
        AppendOwnerElementPseudoStyles(target.second + ":hover", data,
                                       *part_style);
      }
    }
  }
  if (temp_scrollbar)
    temp_scrollbar->DisconnectFromScrollableArea();

  data->Append(ChooserResourceLoader::GetPickerCommonStyleSheet());
  data->Append(ChooserResourceLoader::GetListPickerStyleSheet());
  if (!RuntimeEnabledFeatures::ForceTallerSelectPopupEnabled())
    PagePopupClient::AddString("@media (any-pointer:coarse) {", data);
  int padding = static_cast<int>(roundf(4 * scale_factor));
  int min_height = static_cast<int>(roundf(24 * scale_factor));
  PagePopupClient::AddString(String::Format("option, optgroup {"
                                            "padding-top: %dpx;"
                                            "}\n"
                                            "option {"
                                            "padding-bottom: %dpx;"
                                            "min-height: %dpx;"
                                            "display: flex;"
                                            "align-items: center;"
                                            "}",
                                            padding, padding, min_height),
                             data);
  if (!RuntimeEnabledFeatures::ForceTallerSelectPopupEnabled()) {
    // Closes @media.
    PagePopupClient::AddString("}", data);
  }

  PagePopupClient::AddString(
      "</style></head><body><div id=main>Loading...</div><script>\n"
      "window.dialogArguments = {\n",
      data);
  AddProperty("selectedIndex", owner_element.SelectedListIndex(), data);
  const ComputedStyle* owner_style = owner_element.GetComputedStyle();
  ItemIterationContext context(*owner_style, data);
  context.SerializeBaseStyle();
  PagePopupClient::AddString("children: [\n", data);
  const HeapVector<Member<HTMLElement>>& items = owner_element.GetListItems();
  for (; context.list_index_ < items.size(); ++context.list_index_) {
    Element& child = *items[context.list_index_];
    if (!IsA<HTMLOptGroupElement>(child.parentNode()))
      context.FinishGroupIfNecessary();
    if (auto* option = DynamicTo<HTMLOptionElement>(child))
      AddOption(context, *option);
    else if (auto* optgroup = DynamicTo<HTMLOptGroupElement>(child))
      AddOptGroup(context, *optgroup);
    else if (auto* hr = DynamicTo<HTMLHRElement>(child))
      AddSeparator(context, *hr);
  }
  context.FinishGroupIfNecessary();
  PagePopupClient::AddString("],\n", data);

  AddProperty("anchorRectInScreen", anchor_rect_in_screen, data);
  AddProperty("zoomFactor", 1, data);
  AddProperty("scaleFactor", scale_factor, data);
  bool is_rtl = !owner_style->IsLeftToRightDirection();
  AddProperty("isRTL", is_rtl, data);
  AddProperty("isFormControlsRefreshEnabled",
              features::IsFormControlsRefreshEnabled(), data);
  AddProperty("paddingStart",
              is_rtl ? owner_element.ClientPaddingRight().ToDouble()
                     : owner_element.ClientPaddingLeft().ToDouble(),
              data);
  PagePopupClient::AddString("};\n", data);
  data->Append(ChooserResourceLoader::GetPickerCommonJS());
  data->Append(ChooserResourceLoader::GetListPickerJS());

  PagePopupClient::AddString("</script></body>\n", data);
}

void InternalPopupMenu::AddElementStyle(ItemIterationContext& context,
                                        HTMLElement& element) {
  const ComputedStyle* style = owner_element_->ItemComputedStyle(element);
  DCHECK(style);
  SharedBuffer* data = context.buffer_;
  // TODO(tkent): We generate unnecessary "style: {\n},\n" even if no
  // additional style.
  PagePopupClient::AddString("style: {\n", data);
  if (style->Visibility() == EVisibility::kHidden)
    AddProperty("visibility", String("hidden"), data);
  if (style->Display() == EDisplay::kNone)
    AddProperty("display", String("none"), data);
  const ComputedStyle& base_style = context.BaseStyle();
  if (base_style.Direction() != style->Direction()) {
    AddProperty(
        "direction",
        String(style->Direction() == TextDirection::kRtl ? "rtl" : "ltr"),
        data);
  }
  if (IsOverride(style->GetUnicodeBidi()))
    AddProperty("unicodeBidi", String("bidi-override"), data);
  Color foreground_color = style->VisitedDependentColor(GetCSSPropertyColor());
  if (base_style.VisitedDependentColor(GetCSSPropertyColor()) !=
      foreground_color)
    AddProperty("color", foreground_color.Serialized(), data);
  Color background_color =
      style->VisitedDependentColor(GetCSSPropertyBackgroundColor());
  if (context.BackgroundColor() != background_color &&
      background_color != Color::kTransparent)
    AddProperty("backgroundColor", background_color.Serialized(), data);
  const FontDescription& base_font = context.BaseFont();
  const FontDescription& font_description =
      style->GetFont().GetFontDescription();
  if (base_font.ComputedPixelSize() != font_description.ComputedPixelSize()) {
    // We don't use FontDescription::specifiedSize() because this element
    // might have its own zoom level.
    AddProperty("fontSize", font_description.ComputedPixelSize(), data);
  }
  // Our UA stylesheet has font-weight:normal for OPTION.
  if (NormalWeightValue() != font_description.Weight()) {
    AddProperty("fontWeight", font_description.Weight().ToString(), data);
  }
  if (base_font.Family() != font_description.Family()) {
    PagePopupClient::AddString("fontFamily: [\n", data);
    for (const FontFamily* f = &font_description.Family(); f; f = f->Next()) {
      AddJavaScriptString(f->Family().GetString(), data);
      if (f->Next())
        PagePopupClient::AddString(",\n", data);
    }
    PagePopupClient::AddString("],\n", data);
  }
  if (base_font.Style() != font_description.Style()) {
    AddProperty("fontStyle",
                String(FontStyleToString(font_description.Style())), data);
  }

  if (base_font.VariantCaps() != font_description.VariantCaps() &&
      font_description.VariantCaps() == FontDescription::kSmallCaps)
    AddProperty("fontVariant", String("small-caps"), data);

  if (base_style.TextTransform() != style->TextTransform()) {
    AddProperty("textTransform",
                String(TextTransformToString(style->TextTransform())), data);
  }

  PagePopupClient::AddString("},\n", data);
}

void InternalPopupMenu::AddOption(ItemIterationContext& context,
                                  HTMLOptionElement& element) {
  SharedBuffer* data = context.buffer_;
  PagePopupClient::AddString("{", data);
  AddProperty("label", element.DisplayLabel(), data);
  AddProperty("value", context.list_index_, data);
  if (!element.title().IsEmpty())
    AddProperty("title", element.title(), data);
  const AtomicString& aria_label =
      element.FastGetAttribute(html_names::kAriaLabelAttr);
  if (!aria_label.IsEmpty())
    AddProperty("ariaLabel", aria_label, data);
  if (element.IsDisabledFormControl())
    AddProperty("disabled", true, data);
  AddElementStyle(context, element);
  PagePopupClient::AddString("},", data);
}

void InternalPopupMenu::AddOptGroup(ItemIterationContext& context,
                                    HTMLOptGroupElement& element) {
  SharedBuffer* data = context.buffer_;
  PagePopupClient::AddString("{\n", data);
  PagePopupClient::AddString("type: \"optgroup\",\n", data);
  AddProperty("label", element.GroupLabelText(), data);
  AddProperty("title", element.title(), data);
  AddProperty("ariaLabel", element.FastGetAttribute(html_names::kAriaLabelAttr),
              data);
  AddProperty("disabled", element.IsDisabledFormControl(), data);
  AddElementStyle(context, element);
  context.StartGroupChildren(*owner_element_->ItemComputedStyle(element));
  // We should call ItemIterationContext::finishGroupIfNecessary() later.
}

void InternalPopupMenu::AddSeparator(ItemIterationContext& context,
                                     HTMLHRElement& element) {
  SharedBuffer* data = context.buffer_;
  PagePopupClient::AddString("{\n", data);
  PagePopupClient::AddString("type: \"separator\",\n", data);
  AddProperty("title", element.title(), data);
  AddProperty("ariaLabel", element.FastGetAttribute(html_names::kAriaLabelAttr),
              data);
  AddProperty("disabled", element.IsDisabledFormControl(), data);
  AddElementStyle(context, element);
  PagePopupClient::AddString("},\n", data);
}

void InternalPopupMenu::AppendOwnerElementPseudoStyles(
    const String& target,
    SharedBuffer* data,
    const ComputedStyle& style) {
  PagePopupClient::AddString(target + "{ \n", data);

  const CSSPropertyID serialize_targets[] = {
      CSSPropertyID::kDisplay,        CSSPropertyID::kBackgroundColor,
      CSSPropertyID::kWidth,          CSSPropertyID::kBorderBottom,
      CSSPropertyID::kBorderLeft,     CSSPropertyID::kBorderRight,
      CSSPropertyID::kBorderTop,      CSSPropertyID::kBorderRadius,
      CSSPropertyID::kBackgroundClip, CSSPropertyID::kBoxShadow};

  for (CSSPropertyID id : serialize_targets) {
    PagePopupClient::AddString(SerializeComputedStyleForProperty(style, id),
                               data);
  }

  PagePopupClient::AddString("}\n", data);
}

CSSFontSelector* InternalPopupMenu::CreateCSSFontSelector(
    Document& popup_document) {
  Document& owner_document = OwnerElement().GetDocument();
  return MakeGarbageCollected<PopupMenuCSSFontSelector>(
      popup_document, owner_document.GetStyleEngine().GetFontSelector());
}

void InternalPopupMenu::SetValueAndClosePopup(int num_value,
                                              const String& string_value) {
  DCHECK(popup_);
  DCHECK(owner_element_);
  if (!string_value.IsEmpty()) {
    bool success;
    int list_index = string_value.ToInt(&success);
    DCHECK(success);

    EventQueueScope scope;
    owner_element_->SelectOptionByPopup(list_index);
    if (popup_)
      chrome_client_->ClosePagePopup(popup_);
    // 'change' event is dispatched here.  For compatbility with
    // Angular 1.2, we need to dispatch a change event before
    // mouseup/click events.
  } else {
    if (popup_)
      chrome_client_->ClosePagePopup(popup_);
  }
  // We dispatch events on the owner element to match the legacy behavior.
  // Other browsers dispatch click events before and after showing the popup.
  if (owner_element_) {
    // TODO(dtapuska): Why is this event positionless?
    WebMouseEvent event;
    event.SetFrameScale(1);
    Element* owner = &OwnerElement();
    if (LocalFrame* frame = owner->GetDocument().GetFrame()) {
      frame->GetEventHandler().HandleTargetedMouseEvent(
          owner, event, event_type_names::kMouseup, Vector<WebMouseEvent>(),
          Vector<WebMouseEvent>());
      frame->GetEventHandler().HandleTargetedMouseEvent(
          owner, event, event_type_names::kClick, Vector<WebMouseEvent>(),
          Vector<WebMouseEvent>());
    }
  }
}

void InternalPopupMenu::SetValue(const String& value) {
  DCHECK(owner_element_);
  bool success;
  int list_index = value.ToInt(&success);
  DCHECK(success);
  owner_element_->ProvisionalSelectionChanged(list_index);
}

void InternalPopupMenu::DidClosePopup() {
  // Clearing popup_ first to prevent from trying to close the popup again.
  popup_ = nullptr;
  if (owner_element_)
    owner_element_->PopupDidHide();
}

Element& InternalPopupMenu::OwnerElement() {
  return *owner_element_;
}

ChromeClient& InternalPopupMenu::GetChromeClient() {
  return *chrome_client_;
}

Locale& InternalPopupMenu::GetLocale() {
  return Locale::DefaultLocale();
}

void InternalPopupMenu::CancelPopup() {
  if (popup_)
    chrome_client_->ClosePagePopup(popup_);
  if (owner_element_)
    owner_element_->PopupDidCancel();
}

void InternalPopupMenu::Dispose() {
  if (popup_)
    chrome_client_->ClosePagePopup(popup_);
}

void InternalPopupMenu::Show() {
  DCHECK(!popup_);
  popup_ = chrome_client_->OpenPagePopup(this);
}

void InternalPopupMenu::Hide() {
  CancelPopup();
}

void InternalPopupMenu::UpdateFromElement(UpdateReason) {
  needs_update_ = true;
}

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

void InternalPopupMenu::Update(bool force_update) {
  if (!popup_ || !owner_element_ || (!needs_update_ && !force_update))
    return;
  // disconnectClient() might have been called.
  if (!owner_element_)
    return;
  needs_update_ = false;

  if (!IntRect(IntPoint(), OwnerElement().GetDocument().View()->Size())
           .Intersects(OwnerElement().PixelSnappedBoundingBox())) {
    Hide();
    return;
  }

  scoped_refptr<SharedBuffer> data = SharedBuffer::Create();
  PagePopupClient::AddString("window.updateData = {\n", data.get());
  PagePopupClient::AddString("type: \"update\",\n", data.get());
  ItemIterationContext context(*owner_element_->GetComputedStyle(), data.get());
  context.SerializeBaseStyle();
  PagePopupClient::AddString("children: [", data.get());
  const HeapVector<Member<HTMLElement>>& items = owner_element_->GetListItems();
  for (; context.list_index_ < items.size(); ++context.list_index_) {
    Element& child = *items[context.list_index_];
    if (!IsA<HTMLOptGroupElement>(child.parentNode()))
      context.FinishGroupIfNecessary();
    if (auto* option = DynamicTo<HTMLOptionElement>(child))
      AddOption(context, *option);
    else if (auto* optgroup = DynamicTo<HTMLOptGroupElement>(child))
      AddOptGroup(context, *optgroup);
    else if (auto* hr = DynamicTo<HTMLHRElement>(child))
      AddSeparator(context, *hr);
  }
  context.FinishGroupIfNecessary();
  PagePopupClient::AddString("],\n", data.get());
  IntRect anchor_rect_in_screen = chrome_client_->ViewportToScreen(
      owner_element_->VisibleBoundsInVisualViewport(),
      OwnerElement().GetDocument().View());
  AddProperty("anchorRectInScreen", anchor_rect_in_screen, data.get());
  PagePopupClient::AddString("}\n", data.get());
  popup_->PostMessageToPopup(String::FromUTF8(data->Data(), data->size()));
}

void InternalPopupMenu::DisconnectClient() {
  owner_element_ = nullptr;
  // Cannot be done during finalization, so instead done when the
  // layout object is destroyed and disconnected.
  Dispose();
}

}  // namespace blink
