chromium/chrome/browser/ui/views/toolbar/browser_app_menu_button_interactive_uitest_chromeos.cc

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/toolbar/browser_app_menu_button.h"

#include "base/files/file_path.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/virtual_keyboard_controller.h"
#include "ui/base/ime/virtual_keyboard_controller_stub.h"
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/widget/widget.h"
#include "url/gurl.h"

namespace {

class VirtualKeyboardWaiter : public ui::VirtualKeyboardControllerObserver {
 public:
  VirtualKeyboardWaiter(ui::VirtualKeyboardController* controller,
                        base::RepeatingClosure quit_closure)
      : controller_(controller), quit_closure_(quit_closure) {
    controller_->AddObserver(this);
  }
  VirtualKeyboardWaiter(const VirtualKeyboardWaiter&) = delete;
  VirtualKeyboardWaiter operator=(const VirtualKeyboardWaiter&) = delete;
  ~VirtualKeyboardWaiter() override { controller_->RemoveObserver(this); }

 private:
  // ui::VirtualKeyboardControllerObserver overrides
  void OnKeyboardVisible(const gfx::Rect& keyboard_rect) override {
    std::move(quit_closure_).Run();
  }
  void OnKeyboardHidden() override { std::move(quit_closure_).Run(); }

  raw_ptr<ui::VirtualKeyboardController> controller_ = nullptr;
  base::RepeatingClosure quit_closure_;
};

class BrowserAppMenuButtonVirtualKeyboardBrowserTest
    : public InProcessBrowserTest {
 public:
  BrowserAppMenuButtonVirtualKeyboardBrowserTest() = default;
  BrowserAppMenuButtonVirtualKeyboardBrowserTest(
      const BrowserAppMenuButtonVirtualKeyboardBrowserTest&) = delete;
  BrowserAppMenuButtonVirtualKeyboardBrowserTest& operator=(
      const BrowserAppMenuButtonVirtualKeyboardBrowserTest&) = delete;
  ~BrowserAppMenuButtonVirtualKeyboardBrowserTest() override = default;

  void SetUpOnMainThread() override {
    InProcessBrowserTest::SetUpOnMainThread();

    GURL test_url =
        ui_test_utils::GetTestUrl(base::FilePath("chromeos/virtual_keyboard"),
                                  base::FilePath("form.html"));
    ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_url));
    web_contents_ = browser()->tab_strip_model()->GetActiveWebContents();
    ASSERT_TRUE(web_contents_);

    // TODO(crbug.com/40233608): Make it work without needing a fake controller.
    GetWebContentInputMethod()->SetVirtualKeyboardControllerForTesting(
        std::make_unique<ui::VirtualKeyboardControllerStub>());

    ASSERT_FALSE(IsVirtualKeyboardVisible());
  }

  ui::InputMethod* GetWebContentInputMethod() {
    return views::Widget::GetTopLevelWidgetForNativeView(
               web_contents_->GetRenderWidgetHostView()->GetNativeView())
        ->GetInputMethod();
  }

  ui::VirtualKeyboardController* GetVKController() {
    return GetWebContentInputMethod()->GetVirtualKeyboardController();
  }

  bool IsVirtualKeyboardVisible() {
    return GetVKController()->IsKeyboardVisible();
  }

 protected:
  raw_ptr<content::WebContents, DanglingUntriaged> web_contents_ = nullptr;
};

// Regression test for crbug.com/1334994.
IN_PROC_BROWSER_TEST_F(BrowserAppMenuButtonVirtualKeyboardBrowserTest,
                       ShowMenuDismissesVirtualKeyboard) {
  {
    base::RunLoop run_loop;
    VirtualKeyboardWaiter waiter(GetVKController(), run_loop.QuitClosure());
    SimulateMouseClickOrTapElementWithId(web_contents_, "username");
    run_loop.Run();
    EXPECT_TRUE(IsVirtualKeyboardVisible());
  }
  {
    base::RunLoop run_loop;
    VirtualKeyboardWaiter waiter(GetVKController(), run_loop.QuitClosure());
    // Show the AppMenu.
    BrowserView::GetBrowserViewForBrowser(browser())
        ->toolbar()
        ->app_menu_button()
        ->ShowMenu(views::MenuRunner::NO_FLAGS);
    run_loop.Run();
    EXPECT_FALSE(IsVirtualKeyboardVisible());
  }
}

}  // namespace