// Copyright (c) 2016 The Chromium Embedded Framework 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 "include/base/cef_bind.h"
#include "include/views/cef_button.h"
#include "include/views/cef_button_delegate.h"
#include "include/views/cef_label_button.h"
#include "include/views/cef_menu_button.h"
#include "include/views/cef_menu_button_delegate.h"
#include "include/wrapper/cef_closure_task.h"
#include "tests/ceftests/image_util.h"
#include "tests/ceftests/test_handler.h"
#include "tests/ceftests/thread_helper.h"
#include "tests/ceftests/views/test_window_delegate.h"
#include "tests/gtest/include/gtest/gtest.h"

#define BUTTON_TEST(name) UI_THREAD_TEST(ViewsButtonTest, name)
#define BUTTON_TEST_ASYNC(name) UI_THREAD_TEST_ASYNC(ViewsButtonTest, name)

namespace {

CefRefPtr<CefImage> CreateIconImage() {
  CefRefPtr<CefImage> image = CefImage::CreateImage();
  image_util::LoadIconImage(image, 1.0);
  image_util::LoadIconImage(image, 2.0);
  return image;
}

const char kButtonText[] = "My Button";

void VerifyButtonStyle(CefRefPtr<CefButton> button) {
  // Test state.
  EXPECT_EQ(CEF_BUTTON_STATE_NORMAL, button->GetState());
  button->SetState(CEF_BUTTON_STATE_HOVERED);
  EXPECT_EQ(CEF_BUTTON_STATE_HOVERED, button->GetState());
  button->SetState(CEF_BUTTON_STATE_PRESSED);
  EXPECT_EQ(CEF_BUTTON_STATE_PRESSED, button->GetState());
  button->SetState(CEF_BUTTON_STATE_DISABLED);
  EXPECT_EQ(CEF_BUTTON_STATE_DISABLED, button->GetState());
  button->SetState(CEF_BUTTON_STATE_NORMAL);

  button->SetTooltipText("Some tooltip text");
  button->SetAccessibleName("MyButton");
}

void VerifyLabelButtonImage(CefRefPtr<CefLabelButton> button,
                            cef_button_state_t state,
                            CefRefPtr<CefImage> image) {
  EXPECT_FALSE(button->GetImage(state).get()) << "state = " << state;
  button->SetImage(state, image);
  EXPECT_TRUE(image->IsSame(button->GetImage(state))) << "state = " << state;
  button->SetImage(state, nullptr);
  EXPECT_FALSE(button->GetImage(state).get()) << "state = " << state;
}

void VerifyLabelButtonStyle(CefRefPtr<CefLabelButton> button) {
  VerifyButtonStyle(button);

  // Test set/get text.
  EXPECT_STREQ(kButtonText, button->GetText().ToString().c_str());
  const char kText[] = "My text";
  button->SetText(kText);
  EXPECT_STREQ(kText, button->GetText().ToString().c_str());

  // Test images.
  CefRefPtr<CefImage> image = CreateIconImage();
  VerifyLabelButtonImage(button, CEF_BUTTON_STATE_NORMAL, image);
  VerifyLabelButtonImage(button, CEF_BUTTON_STATE_HOVERED, image);
  VerifyLabelButtonImage(button, CEF_BUTTON_STATE_PRESSED, image);
  VerifyLabelButtonImage(button, CEF_BUTTON_STATE_DISABLED, image);

  // Test colors.
  const cef_color_t color = CefColorSetARGB(255, 255, 0, 255);
  button->SetTextColor(CEF_BUTTON_STATE_NORMAL, color);
  button->SetTextColor(CEF_BUTTON_STATE_HOVERED, color);
  button->SetTextColor(CEF_BUTTON_STATE_PRESSED, color);
  button->SetTextColor(CEF_BUTTON_STATE_DISABLED, color);
  button->SetEnabledTextColors(color);

  // Test alignment.
  button->SetHorizontalAlignment(CEF_HORIZONTAL_ALIGNMENT_LEFT);
  button->SetHorizontalAlignment(CEF_HORIZONTAL_ALIGNMENT_CENTER);
  button->SetHorizontalAlignment(CEF_HORIZONTAL_ALIGNMENT_RIGHT);

  // Test fonts.
  button->SetFontList("Arial, 14px");

  // Test sizes.
  button->SetMinimumSize(CefSize(100, 100));
  button->SetMaximumSize(CefSize(100, 100));
}

void VerifyMenuButtonStyle(CefRefPtr<CefMenuButton> button) {
  VerifyLabelButtonStyle(button);
}

class EmptyMenuButtonDelegate : public CefMenuButtonDelegate {
 public:
  EmptyMenuButtonDelegate() {}

  void OnMenuButtonPressed(
      CefRefPtr<CefMenuButton> menu_button,
      const CefPoint& screen_point,
      CefRefPtr<CefMenuButtonPressedLock> button_pressed_lock) override {
    EXPECT_TRUE(false);  // Not reached.
  }

  void OnButtonPressed(CefRefPtr<CefButton> button) override {
    EXPECT_TRUE(false);  // Not reached.
  }

 private:
  IMPLEMENT_REFCOUNTING(EmptyMenuButtonDelegate);
  DISALLOW_COPY_AND_ASSIGN(EmptyMenuButtonDelegate);
};

void LabelButtonStyle() {
  CefRefPtr<CefLabelButton> button = CefLabelButton::CreateLabelButton(
      new EmptyMenuButtonDelegate(), kButtonText);
  VerifyLabelButtonStyle(button);
}

void LabelButtonStyleFramelessImpl() {
  LabelButtonStyle();
}

void MenuButtonStyle() {
  CefRefPtr<CefMenuButton> button = CefMenuButton::CreateMenuButton(
      new EmptyMenuButtonDelegate(), kButtonText);
  VerifyMenuButtonStyle(button);
}

void MenuButtonStyleFramelessImpl() {
  MenuButtonStyle();
}

}  // namespace

// Test Button getters/setters.
BUTTON_TEST(LabelButtonStyleFrameless)
BUTTON_TEST(MenuButtonStyleFrameless)

namespace {

// Mouse click delay in MS.
const int kClickDelayMS = 100;

const int kButtonID = 1;

class TestButtonDelegate : public CefButtonDelegate {
 public:
  TestButtonDelegate() {}

  void OnButtonPressed(CefRefPtr<CefButton> button) override {
    EXPECT_TRUE(button.get());
    EXPECT_EQ(button->GetID(), kButtonID);

    // Complete the test by closing the window.
    button->GetWindow()->Close();
  }

 private:
  IMPLEMENT_REFCOUNTING(TestButtonDelegate);
  DISALLOW_COPY_AND_ASSIGN(TestButtonDelegate);
};

void ClickButton(CefRefPtr<CefWindow> window, int button_id) {
  CefRefPtr<CefView> button = window->GetViewForID(button_id);
  EXPECT_TRUE(button->AsButton());

  // Determine the middle of the button in screen coordinates.
  const CefRect& bounds = button->GetBoundsInScreen();
  const CefPoint& click_point =
      CefPoint(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2);

  // Click the button.
  window->SendMouseMove(click_point.x, click_point.y);
  window->SendMouseEvents(MBT_LEFT, true, true);
}

void AddImage(CefRefPtr<CefLabelButton> button) {
  CefRefPtr<CefImage> image = CreateIconImage();
  button->SetImage(CEF_BUTTON_STATE_NORMAL, image);
}

void RunLabelButtonClick(bool with_text,
                         bool with_image,
                         CefRefPtr<CefWindow> window) {
  CefRefPtr<CefLabelButton> button = CefLabelButton::CreateLabelButton(
      new TestButtonDelegate(), with_text ? kButtonText : "");
  button->SetID(kButtonID);

  EXPECT_TRUE(button->AsButton());
  EXPECT_TRUE(button->AsButton()->AsLabelButton());
  EXPECT_EQ(kButtonID, button->GetID());
  EXPECT_TRUE(button->IsVisible());
  EXPECT_FALSE(button->IsDrawn());

  if (with_text)
    EXPECT_STREQ(kButtonText, button->GetText().ToString().c_str());
  else
    EXPECT_TRUE(button->GetText().empty());

  if (with_image)
    AddImage(button);

  window->AddChildView(button);
  window->Layout();

  EXPECT_TRUE(window->IsSame(button->GetWindow()));
  EXPECT_TRUE(window->IsSame(button->GetParentView()));
  EXPECT_TRUE(button->IsSame(window->GetViewForID(kButtonID)));
  EXPECT_TRUE(button->IsVisible());
  EXPECT_TRUE(button->IsDrawn());

  window->Show();

  // Wait a bit before trying to click the button.
  CefPostDelayedTask(TID_UI, base::Bind(ClickButton, window, kButtonID),
                     kClickDelayMS);
}

void LabelButtonClick(CefRefPtr<CefWaitableEvent> event,
                      bool with_button_frame,
                      bool with_button_text,
                      bool with_button_image) {
  TestWindowDelegate::Config config;
  config.on_window_created =
      base::Bind(RunLabelButtonClick, with_button_text, with_button_image);
  config.frameless = false;
  config.close_window = false;
  TestWindowDelegate::RunTest(event, config);
}

void LabelButtonClickFramedWithTextWithImageFramelessWindowImpl(
    CefRefPtr<CefWaitableEvent> event) {
  LabelButtonClick(event, true, true, true);
}

void LabelButtonClickFramedWithTextNoImageFramelessWindowImpl(
    CefRefPtr<CefWaitableEvent> event) {
  LabelButtonClick(event, true, true, false);
}

void LabelButtonClickFramedNoTextWithImageFramelessWindowImpl(
    CefRefPtr<CefWaitableEvent> event) {
  LabelButtonClick(event, true, false, true);
}

void LabelButtonClickFramedNoTextNoImageFramelessWindowImpl(
    CefRefPtr<CefWaitableEvent> event) {
  LabelButtonClick(event, true, false, false);
}

void LabelButtonClickFramelessWithTextWithImageFramelessWindowImpl(
    CefRefPtr<CefWaitableEvent> event) {
  LabelButtonClick(event, false, true, true);
}

void LabelButtonClickFramelessWithTextNoImageFramelessWindowImpl(
    CefRefPtr<CefWaitableEvent> event) {
  LabelButtonClick(event, false, true, false);
}

void LabelButtonClickFramelessNoTextWithImageFramelessWindowImpl(
    CefRefPtr<CefWaitableEvent> event) {
  LabelButtonClick(event, false, false, true);
}

void LabelButtonClickFramelessNoTextNoImageFramelessWindowImpl(
    CefRefPtr<CefWaitableEvent> event) {
  LabelButtonClick(event, false, false, false);
}

}  // namespace

// Test LabelButton functionality. This is primarily to exercise exposed CEF
// APIs and is not intended to comprehensively test button-related behavior
// (which we presume that Chromium is testing).
BUTTON_TEST_ASYNC(LabelButtonClickFramedWithTextWithImageFramelessWindow)
BUTTON_TEST_ASYNC(LabelButtonClickFramedWithTextNoImageFramelessWindow)
BUTTON_TEST_ASYNC(LabelButtonClickFramedNoTextWithImageFramelessWindow)
BUTTON_TEST_ASYNC(LabelButtonClickFramedNoTextNoImageFramelessWindow)
BUTTON_TEST_ASYNC(LabelButtonClickFramelessWithTextWithImageFramelessWindow)
BUTTON_TEST_ASYNC(LabelButtonClickFramelessWithTextNoImageFramelessWindow)
BUTTON_TEST_ASYNC(LabelButtonClickFramelessNoTextWithImageFramelessWindow)
BUTTON_TEST_ASYNC(LabelButtonClickFramelessNoTextNoImageFramelessWindow)

namespace {

const int kMenuItemID = 2;
const char kMenuItemLabel[] = "My Menu Item";

void ClickMenuItem(CefRefPtr<CefMenuButton> menu_button) {
  // Determine the lower-right corner of the menu button, then offset a bit to
  // hit the first menu item.
  const CefRect& bounds = menu_button->GetBoundsInScreen();
  const CefPoint& click_point =
      CefPoint(bounds.x + bounds.width + 10, bounds.y + bounds.height + 10);

  // Click the menu item.
  CefRefPtr<CefWindow> window = menu_button->GetWindow();
  window->SendMouseMove(click_point.x, click_point.y);
  window->SendMouseEvents(MBT_LEFT, true, true);
}

class TestMenuButtonDelegate : public CefMenuButtonDelegate,
                               public CefMenuModelDelegate {
 public:
  TestMenuButtonDelegate() {}

  void OnMenuButtonPressed(
      CefRefPtr<CefMenuButton> menu_button,
      const CefPoint& screen_point,
      CefRefPtr<CefMenuButtonPressedLock> button_pressed_lock) override {
    window_ = menu_button->GetWindow();

    CefRefPtr<CefMenuModel> model = CefMenuModel::CreateMenuModel(this);
    model->AddItem(kMenuItemID, kMenuItemLabel);

    // Verify color accessors.
    for (int i = 0; i < CEF_MENU_COLOR_COUNT; ++i) {
      cef_menu_color_type_t color_type = static_cast<cef_menu_color_type_t>(i);
      cef_color_t color_out;
      cef_color_t color = CefColorSetARGB(255, 255, 255, i);

      // No color set yet.
      color_out = 1;
      EXPECT_TRUE(model->GetColor(kMenuItemID, color_type, color_out));
      EXPECT_EQ(0U, color_out);
      color_out = 1;
      EXPECT_TRUE(model->GetColorAt(0, color_type, color_out));
      EXPECT_EQ(0U, color_out);
      color_out = 1;
      EXPECT_TRUE(model->GetColorAt(-1, color_type, color_out));
      EXPECT_EQ(0U, color_out);

      // Set the default color.
      EXPECT_TRUE(model->SetColorAt(-1, color_type, color));
      color_out = 1;
      EXPECT_TRUE(model->GetColorAt(-1, color_type, color_out));
      EXPECT_EQ(color, color_out);

      // Clear the default color.
      EXPECT_TRUE(model->SetColorAt(-1, color_type, 0));
      color_out = 1;
      EXPECT_TRUE(model->GetColorAt(-1, color_type, color_out));
      EXPECT_EQ(0U, color_out);

      // Set the index color.
      EXPECT_TRUE(model->SetColorAt(0, color_type, color));
      color_out = 1;
      EXPECT_TRUE(model->GetColorAt(0, color_type, color_out));
      EXPECT_EQ(color, color_out);

      // Clear the index color.
      EXPECT_TRUE(model->SetColorAt(0, color_type, 0));
      color_out = 1;
      EXPECT_TRUE(model->GetColorAt(0, color_type, color_out));
      EXPECT_EQ(0U, color_out);

      // Set the ID color.
      EXPECT_TRUE(model->SetColor(kMenuItemID, color_type, color));
      color_out = 1;
      EXPECT_TRUE(model->GetColor(kMenuItemID, color_type, color_out));
      EXPECT_EQ(color, color_out);

      // Clear the ID color.
      EXPECT_TRUE(model->SetColor(kMenuItemID, color_type, 0));
      color_out = 1;
      EXPECT_TRUE(model->GetColor(kMenuItemID, color_type, color_out));
      EXPECT_EQ(0U, color_out);

      // Index/ID doesn't exist.
      EXPECT_FALSE(model->SetColorAt(4, color_type, color));
      EXPECT_FALSE(model->SetColor(4, color_type, color));
      color_out = 1;
      EXPECT_FALSE(model->GetColorAt(4, color_type, color_out));
      EXPECT_FALSE(model->GetColor(4, color_type, color_out));
      EXPECT_EQ(1U, color_out);
    }

    // Verify font accessors.
    const std::string& font = "Tahoma, 12px";
    EXPECT_TRUE(model->SetFontListAt(0, font));
    EXPECT_TRUE(model->SetFontListAt(0, CefString()));
    EXPECT_TRUE(model->SetFontList(kMenuItemID, font));
    EXPECT_TRUE(model->SetFontList(kMenuItemID, CefString()));

    // Index/ID doesn't exist.
    EXPECT_FALSE(model->SetFontListAt(4, font));
    EXPECT_FALSE(model->SetFontList(4, font));

    // Wait a bit before trying to click the menu item.
    CefPostDelayedTask(TID_UI, base::Bind(ClickMenuItem, menu_button),
                       kClickDelayMS);

    menu_button->ShowMenu(model, screen_point, CEF_MENU_ANCHOR_TOPLEFT);
  }

  void OnButtonPressed(CefRefPtr<CefButton> button) override {}

  void ExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
                      int command_id,
                      cef_event_flags_t event_flags) override {
    EXPECT_TRUE(menu_model.get());
    EXPECT_EQ(command_id, kMenuItemID);

    // Complete the test by closing the window.
    window_->GetWindow()->Close();
    window_ = nullptr;
  }

 private:
  CefRefPtr<CefWindow> window_;

  IMPLEMENT_REFCOUNTING(TestMenuButtonDelegate);
  DISALLOW_COPY_AND_ASSIGN(TestMenuButtonDelegate);
};

void RunMenuButtonClick(bool with_text,
                        bool with_image,
                        CefRefPtr<CefWindow> window) {
  CefRefPtr<CefMenuButton> button = CefMenuButton::CreateMenuButton(
      new TestMenuButtonDelegate(), with_text ? kButtonText : "");
  button->SetID(kButtonID);

  EXPECT_TRUE(button->AsButton());
  EXPECT_TRUE(button->AsButton()->AsLabelButton());
  EXPECT_TRUE(button->AsButton()->AsLabelButton()->AsMenuButton());
  EXPECT_EQ(kButtonID, button->GetID());
  EXPECT_TRUE(button->IsVisible());
  EXPECT_FALSE(button->IsDrawn());

  if (with_text)
    EXPECT_STREQ(kButtonText, button->GetText().ToString().c_str());
  else
    EXPECT_TRUE(button->GetText().empty());

  if (with_image)
    AddImage(button);

  window->AddChildView(button);
  window->Layout();

  EXPECT_TRUE(window->IsSame(button->GetWindow()));
  EXPECT_TRUE(window->IsSame(button->GetParentView()));
  EXPECT_TRUE(button->IsSame(window->GetViewForID(kButtonID)));
  EXPECT_TRUE(button->IsVisible());
  EXPECT_TRUE(button->IsDrawn());

  window->Show();

  // Wait a bit before trying to click the button.
  CefPostDelayedTask(TID_UI, base::Bind(ClickButton, window, kButtonID),
                     kClickDelayMS);
}

void MenuButtonClick(CefRefPtr<CefWaitableEvent> event,
                     bool with_button_frame,
                     bool with_button_text,
                     bool with_button_image) {
  TestWindowDelegate::Config config;
  config.on_window_created =
      base::Bind(RunMenuButtonClick, with_button_text, with_button_image);
  config.frameless = false;
  config.close_window = false;
  TestWindowDelegate::RunTest(event, config);
}

void MenuButtonClickFramedWithTextWithImageFramelessWindowImpl(
    CefRefPtr<CefWaitableEvent> event) {
  MenuButtonClick(event, true, true, true);
}

void MenuButtonClickFramedWithTextNoImageFramelessWindowImpl(
    CefRefPtr<CefWaitableEvent> event) {
  MenuButtonClick(event, true, true, false);
}

void MenuButtonClickFramedNoTextWithImageFramelessWindowImpl(
    CefRefPtr<CefWaitableEvent> event) {
  MenuButtonClick(event, true, false, true);
}

void MenuButtonClickFramedNoTextNoImageFramelessWindowImpl(
    CefRefPtr<CefWaitableEvent> event) {
  MenuButtonClick(event, true, false, false);
}

void MenuButtonClickFramelessWithTextWithImageFramelessWindowImpl(
    CefRefPtr<CefWaitableEvent> event) {
  MenuButtonClick(event, false, true, true);
}

void MenuButtonClickFramelessWithTextNoImageFramelessWindowImpl(
    CefRefPtr<CefWaitableEvent> event) {
  MenuButtonClick(event, false, true, false);
}

void MenuButtonClickFramelessNoTextWithImageFramelessWindowImpl(
    CefRefPtr<CefWaitableEvent> event) {
  MenuButtonClick(event, false, false, true);
}

void MenuButtonClickFramelessNoTextNoImageFramelessWindowImpl(
    CefRefPtr<CefWaitableEvent> event) {
  MenuButtonClick(event, false, false, false);
}

}  // namespace

// Test MenuButton functionality. This is primarily to exercise exposed CEF
// APIs and is not intended to comprehensively test button-related behavior
// (which we presume that Chromium is testing).
BUTTON_TEST_ASYNC(MenuButtonClickFramedWithTextWithImageFramelessWindow)
BUTTON_TEST_ASYNC(MenuButtonClickFramedWithTextNoImageFramelessWindow)
BUTTON_TEST_ASYNC(MenuButtonClickFramedNoTextWithImageFramelessWindow)
BUTTON_TEST_ASYNC(MenuButtonClickFramedNoTextNoImageFramelessWindow)
BUTTON_TEST_ASYNC(MenuButtonClickFramelessWithTextWithImageFramelessWindow)
BUTTON_TEST_ASYNC(MenuButtonClickFramelessWithTextNoImageFramelessWindow)
BUTTON_TEST_ASYNC(MenuButtonClickFramelessNoTextWithImageFramelessWindow)
BUTTON_TEST_ASYNC(MenuButtonClickFramelessNoTextNoImageFramelessWindow)

namespace {

class TestMenuButtonCustomPopupDelegate : public CefMenuButtonDelegate,
                                          public CefWindowDelegate {
 public:
  explicit TestMenuButtonCustomPopupDelegate(bool can_activate)
      : can_activate_(can_activate) {}

  void OnMenuButtonPressed(
      CefRefPtr<CefMenuButton> menu_button,
      const CefPoint& screen_point,
      CefRefPtr<CefMenuButtonPressedLock> button_pressed_lock) override {
    parent_window_ = menu_button->GetWindow();
    button_pressed_lock_ = button_pressed_lock;

    popup_window_ = CefWindow::CreateTopLevelWindow(this);
    popup_window_->SetBounds(CefRect(screen_point.x, screen_point.y, 100, 100));

    CefRefPtr<CefLabelButton> button =
        CefLabelButton::CreateLabelButton(this, "Button");
    button->SetFocusable(can_activate_);
    popup_window_->AddChildView(button);

    popup_window_->Show();

    // Wait a bit before trying to click the popup button.
    CefPostDelayedTask(TID_UI, base::Bind(ClickMenuItem, menu_button),
                       kClickDelayMS);
  }

  void OnButtonPressed(CefRefPtr<CefButton> button) override {
    EXPECT_TRUE(button->GetWindow()->IsSame(popup_window_));
    popup_window_->Close();
    popup_window_ = nullptr;
    button_pressed_lock_ = nullptr;
  }

  CefRefPtr<CefWindow> GetParentWindow(CefRefPtr<CefWindow> window,
                                       bool* is_menu,
                                       bool* can_activate_menu) override {
    EXPECT_TRUE(parent_window_);
    *is_menu = true;
    *can_activate_menu = can_activate_;
    return parent_window_;
  }

  bool IsFrameless(CefRefPtr<CefWindow> window) override { return true; }

  void OnFocus(CefRefPtr<CefView> view) override {
    if (popup_window_ && view->GetWindow()->IsSame(popup_window_)) {
      EXPECT_TRUE(can_activate_);
      got_focus_.yes();
    }
  }

  void OnWindowDestroyed(CefRefPtr<CefWindow> window) override {
    if (can_activate_)
      EXPECT_TRUE(got_focus_);
    else
      EXPECT_FALSE(got_focus_);

    // Complete the test by closing the parent window.
    parent_window_->Close();
    parent_window_ = nullptr;
  }

 private:
  const bool can_activate_;

  CefRefPtr<CefWindow> parent_window_;
  CefRefPtr<CefWindow> popup_window_;
  CefRefPtr<CefMenuButtonPressedLock> button_pressed_lock_;

  TrackCallback got_focus_;

  IMPLEMENT_REFCOUNTING(TestMenuButtonCustomPopupDelegate);
  DISALLOW_COPY_AND_ASSIGN(TestMenuButtonCustomPopupDelegate);
};

void RunMenuButtonCustomPopupClick(bool can_activate,
                                   CefRefPtr<CefWindow> window) {
  CefRefPtr<CefMenuButton> button = CefMenuButton::CreateMenuButton(
      new TestMenuButtonCustomPopupDelegate(can_activate), "Custom");
  button->SetID(kButtonID);

  window->AddChildView(button);
  window->Layout();

  window->Show();

  // Wait a bit before trying to click the button.
  CefPostDelayedTask(TID_UI, base::Bind(ClickButton, window, kButtonID),
                     kClickDelayMS);
}

void MenuButtonCustomPopupClick(CefRefPtr<CefWaitableEvent> event,
                                bool can_activate) {
  TestWindowDelegate::Config config;
  config.on_window_created =
      base::Bind(RunMenuButtonCustomPopupClick, can_activate);
  config.close_window = false;
  TestWindowDelegate::RunTest(event, config);
}

void MenuButtonCustomPopupActivateImpl(CefRefPtr<CefWaitableEvent> event) {
  MenuButtonCustomPopupClick(event, true);
}

void MenuButtonCustomPopupNoActivateImpl(CefRefPtr<CefWaitableEvent> event) {
  MenuButtonCustomPopupClick(event, false);
}

}  // namespace

BUTTON_TEST_ASYNC(MenuButtonCustomPopupActivate)
BUTTON_TEST_ASYNC(MenuButtonCustomPopupNoActivate)
