blob: 946e7b9cd85678275407140ed088e35cc899d5ee [file] [log] [blame]
// Copyright 2017 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 <memory>
#include "base/run_loop.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/tabs/tab_strip_model.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 "content/public/test/browser_test.h"
#include "ui/base/test/ui_controls.h"
#include "ui/views/test/widget_test.h"
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::WidgetActivationWaiter waiter(widget, true);
waiter.Wait();
}
// Send Ctrl/Cmd+keycode in the key window to the browser.
void SendAcceleratorSync(ui::KeyboardCode keycode, bool shift, bool alt) {
#if defined(OS_MACOSX)
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));
}
void SetUpOnMainThread() override {
// Make the browser active (ensures the app can receive key events).
EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
test_api_ =
std::make_unique<test::PermissionRequestManagerTestApi>(browser());
EXPECT_TRUE(test_api_->manager());
test_api_->AddSimpleRequest(ContentSettingsType::GEOLOCATION);
EXPECT_TRUE(browser()->window()->IsActive());
// The permission prompt is shown asynchronously.
base::RunLoop().RunUntilIdle();
EnsureWindowActive(test_api_->GetPromptWindow(), "show permission bubble");
}
void JumpToNextOpenTab() {
#if defined(OS_MACOSX)
SendAcceleratorSync(ui::VKEY_RIGHT, false, true);
#else
SendAcceleratorSync(ui::VKEY_TAB, false, false);
#endif
}
void JumpToPreviousOpenTab() {
#if defined(OS_MACOSX)
SendAcceleratorSync(ui::VKEY_LEFT, false, true);
#else
SendAcceleratorSync(ui::VKEY_TAB, true, false);
#endif
}
void TestSwitchingTabsWithCurlyBraces() {
// Also test switching tabs with curly braces. "VKEY_OEM_4" is
// LeftBracket/Brace on a US keyboard, which ui::MacKeyCodeForWindowsKeyCode
// will map to '{' when shift is passed. Also note there are only two tabs
// so it doesn't matter which direction is taken (it wraps).
chrome::FocusLocationBar(browser());
SendAcceleratorSync(ui::VKEY_OEM_4, true, false);
EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
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 defined(OS_CHROMEOS)
// TODO(crbug.com/1072425): views::test::WidgetTest::GetAllWidgets() crashes
// on Chrome OS, need to investigate\fix that.
#define MAYBE_CmdWClosesWindow DISABLED_CmdWClosesWindow
#else
#define MAYBE_CmdWClosesWindow CmdWClosesWindow
#endif
// There is only one tab. Ctrl/Cmd+w will close it along with the browser
// window.
IN_PROC_BROWSER_TEST_F(PermissionBubbleInteractiveUITest,
MAYBE_CmdWClosesWindow) {
EXPECT_TRUE(browser()->window()->IsVisible());
SendAcceleratorSync(ui::VKEY_W, false, false);
// The window has been destroyed so there should be no widgets hanging around.
EXPECT_EQ(0u, views::test::WidgetTest::GetAllWidgets().size());
}
// Add a tab, ensure we can switch away and back using Ctrl+Tab and
// Ctrl+Shift+Tab at aura and using Cmd+Alt+Left/Right and curly braces at
// MacOS.
IN_PROC_BROWSER_TEST_F(PermissionBubbleInteractiveUITest, SwitchTabs) {
EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
EXPECT_TRUE(test_api_->GetPromptWindow());
// Add a blank tab in the foreground.
AddBlankTabAndShow(browser());
EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
#if defined(OS_MACOSX)
// The bubble should hide and give focus back to the browser. However, the
// test environment can't guarantee that macOS decides that the Browser window
// is actually the "best" window to activate upon closing the current key
// window. So activate it manually.
browser()->window()->Activate();
EnsureWindowActive(browser()->window(), "tab added");
#endif
// Prompt is hidden while its tab is not active.
EXPECT_FALSE(test_api_->GetPromptWindow());
// Now a webcontents is active, it gets a first shot at processing the
// accelerator before sending it back unhandled to the browser via IPC. That's
// all a bit much to handle in a test, so activate the location bar.
chrome::FocusLocationBar(browser());
JumpToPreviousOpenTab();
EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
// Note we don't need to makeKeyAndOrderFront for mac os: the permission
// window will take focus when it is shown again.
EnsureWindowActive(
test_api_->GetPromptWindow(),
"switched to permission tab with ctrl+shift+tab or arrow at mac os");
EXPECT_TRUE(test_api_->GetPromptWindow());
// Ensure we can switch away with the bubble active.
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 defined(OS_MACOSX)
TestSwitchingTabsWithCurlyBraces();
#endif
}