#include <memory>
#include "base/run_loop.h"
#include "base/test/run_until.h"
#include "build/build_config.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/exclusive_access/exclusive_access_test.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/interactive_test_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chrome/test/permissions/permission_request_manager_test_api.h"
#include "components/permissions/features.h"
#include "components/permissions/request_type.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test.h"
#include "ui/base/test/ui_controls.h"
#include "ui/events/base_event_utils.h"
#include "ui/views/test/button_test_api.h"
#include "ui/views/test/views_test_utils.h"
#include "ui/views/test/widget_activation_waiter.h"
#include "ui/views/test/widget_test.h"
enum ChipFeatureConfig {
REQUEST_CHIP,
REQUEST_CHIP_LOCATION_BAR_ICON_OVERRIDE
};
class PermissionBubbleInteractiveUITest : public InProcessBrowserTest {
public:
PermissionBubbleInteractiveUITest() = default;
PermissionBubbleInteractiveUITest(const PermissionBubbleInteractiveUITest&) =
delete;
PermissionBubbleInteractiveUITest& operator=(
const PermissionBubbleInteractiveUITest&) = delete;
void EnsureWindowActive(ui::BaseWindow* window, const char* message) {
EnsureWindowActive(
views::Widget::GetWidgetForNativeWindow(window->GetNativeWindow()),
message);
}
void EnsureWindowActive(views::Widget* widget, const char* message) {
SCOPED_TRACE(message);
EXPECT_TRUE(widget);
views::test::WaitForWidgetActive(widget, true);
}
void SendAcceleratorSync(ui::KeyboardCode keycode, bool shift, bool alt) {
#if BUILDFLAG(IS_MAC)
bool control = false;
bool command = true;
#else
bool control = true;
bool command = false;
#endif
ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
browser(), keycode, control, shift, alt, command,
ui_controls::KeyEventType::kKeyPress));
}
void SetUpOnMainThread() override {
EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
test_api_ =
std::make_unique<test::PermissionRequestManagerTestApi>(browser());
EXPECT_TRUE(test_api_->manager());
test_api_->AddSimpleRequest(browser()
->tab_strip_model()
->GetActiveWebContents()
->GetPrimaryMainFrame(),
permissions::RequestType::kGeolocation);
EXPECT_TRUE(browser()->window()->IsActive());
base::RunLoop().RunUntilIdle();
OpenBubbleIfRequestChipUiIsShown();
EnsureWindowActive(test_api_->GetPromptWindow(), "show permission bubble");
}
void JumpToNextOpenTab() {
#if BUILDFLAG(IS_MAC)
SendAcceleratorSync(ui::VKEY_RIGHT, false, true);
#else
SendAcceleratorSync(ui::VKEY_TAB, false, false);
#endif
}
void JumpToPreviousOpenTab() {
#if BUILDFLAG(IS_MAC)
SendAcceleratorSync(ui::VKEY_LEFT, false, true);
#else
SendAcceleratorSync(ui::VKEY_TAB, true, false);
#endif
views::test::RunScheduledLayout(
BrowserView::GetBrowserViewForBrowser(browser()));
}
void OpenBubbleIfRequestChipUiIsShown() {
BrowserView* browser_view =
BrowserView::GetBrowserViewForBrowser(browser());
LocationBarView* lbv = browser_view->toolbar()->location_bar();
if (lbv->GetChipController()->IsPermissionPromptChipVisible() &&
!lbv->GetChipController()->IsBubbleShowing()) {
views::test::ButtonTestApi(lbv->GetChipController()->chip())
.NotifyClick(ui::MouseEvent(
ui::EventType::kMousePressed, gfx::Point(), gfx::Point(),
ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0));
base::RunLoop().RunUntilIdle();
}
}
void TestSwitchingTabsWithCurlyBraces() {
chrome::FocusLocationBar(browser());
SendAcceleratorSync(ui::VKEY_OEM_4, true, false);
EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
OpenBubbleIfRequestChipUiIsShown();
EnsureWindowActive(test_api_->GetPromptWindow(),
"switch to permission tab with curly brace");
EXPECT_TRUE(test_api_->GetPromptWindow());
SendAcceleratorSync(ui::VKEY_OEM_4, true, false);
EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
browser()->window()->Activate();
EnsureWindowActive(browser()->window(), "switch away with curly brace");
EXPECT_FALSE(test_api_->GetPromptWindow());
}
protected:
std::unique_ptr<test::PermissionRequestManagerTestApi> test_api_;
};
#if BUILDFLAG(IS_CHROMEOS)
#define MAYBE_CmdWClosesWindow DISABLED_CmdWClosesWindow
#else
#define MAYBE_CmdWClosesWindow CmdWClosesWindow
#endif
IN_PROC_BROWSER_TEST_F(PermissionBubbleInteractiveUITest,
MAYBE_CmdWClosesWindow) {
EXPECT_TRUE(browser()->window()->IsVisible());
SendAcceleratorSync(ui::VKEY_W, false, false);
EXPECT_TRUE(base::test::RunUntil(
[&] { return views::test::WidgetTest::GetAllWidgets().empty(); }));
}
#if BUILDFLAG(IS_MAC)
#define MAYBE_SwitchTabs DISABLED_SwitchTabs
#else
#define MAYBE_SwitchTabs SwitchTabs
#endif
IN_PROC_BROWSER_TEST_F(PermissionBubbleInteractiveUITest, MAYBE_SwitchTabs) {
EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
EXPECT_TRUE(test_api_->GetPromptWindow());
AddBlankTabAndShow(browser());
EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
#if BUILDFLAG(IS_MAC)
browser()->window()->Activate();
EnsureWindowActive(browser()->window(), "tab added");
#endif
EXPECT_FALSE(test_api_->GetPromptWindow());
chrome::FocusLocationBar(browser());
JumpToPreviousOpenTab();
EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
OpenBubbleIfRequestChipUiIsShown();
EnsureWindowActive(
test_api_->GetPromptWindow(),
"switched to permission tab with ctrl+shift+tab or arrow at mac os");
EXPECT_TRUE(test_api_->GetPromptWindow());
JumpToNextOpenTab();
EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
browser()->window()->Activate();
EnsureWindowActive(browser()->window(),
"switch away with ctrl+tab or arrow at mac os");
EXPECT_FALSE(test_api_->GetPromptWindow());
#if BUILDFLAG(IS_MAC)
TestSwitchingTabsWithCurlyBraces();
#endif
}