#include "base/functional/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/ui/browser_element_identifiers.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/ui/view_ids.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
#include "chrome/browser/ui/views/frame/webui_tab_strip_container_view.h"
#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
#include "chrome/browser/ui/views/omnibox/omnibox_view_views.h"
#include "chrome/browser/ui/views/toolbar/reload_button.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/interaction/interaction_test_util_browser.h"
#include "chrome/test/interaction/interactive_browser_test.h"
#include "chrome/test/interaction/webcontents_interaction_test_util.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "ui/base/interaction/element_identifier.h"
#include "ui/base/interaction/element_tracker.h"
#include "ui/base/interaction/expect_call_in_scope.h"
#include "ui/base/interaction/interaction_sequence.h"
#include "ui/base/page_transition_types.h"
#include "ui/base/pointer/touch_ui_controller.h"
#include "ui/base/test/ui_controls.h"
#include "ui/gfx/geometry/point.h"
#include "ui/views/controls/webview/webview.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "base/scoped_observation.h"
#include "chromeos/ui/frame/immersive/immersive_fullscreen_controller.h"
#include "chromeos/ui/frame/immersive/immersive_fullscreen_controller_test_api.h"
#include "ui/aura/client/drag_drop_client.h"
#include "ui/aura/client/drag_drop_client_observer.h"
#include "ui/aura/window.h"
#endif
namespace {
class WebUITabStripTestHelper { … };
}
class WebUITabStripInteractiveTest : public InProcessBrowserTest { … };
IN_PROC_BROWSER_TEST_F(WebUITabStripInteractiveTest,
CanTypeInOmniboxAfterTabStripClose) { … }
IN_PROC_BROWSER_TEST_F(WebUITabStripInteractiveTest,
EventInTabContentClosesContainer) { … }
IN_PROC_BROWSER_TEST_F(WebUITabStripInteractiveTest,
EventInContainerDoesNotClose) { … }
#if BUILDFLAG(IS_CHROMEOS_ASH)
IN_PROC_BROWSER_TEST_F(WebUITabStripInteractiveTest, CanUseInImmersiveMode) {
BrowserView* const browser_view =
BrowserView::GetBrowserViewForBrowser(browser());
chromeos::ImmersiveFullscreenControllerTestApi immersive_test_api(
chromeos::ImmersiveFullscreenController::Get(browser_view->GetWidget()));
immersive_test_api.SetupForTest();
ImmersiveModeController* const immersive_mode_controller =
browser_view->immersive_mode_controller();
immersive_mode_controller->SetEnabled(true);
WebUITabStripContainerView* const container = browser_view->webui_tab_strip();
ASSERT_NE(nullptr, container);
EXPECT_FALSE(immersive_mode_controller->IsRevealed());
container->SetVisibleForTesting(true);
RunScheduledLayouts();
EXPECT_TRUE(container->GetVisible());
EXPECT_FALSE(container->bounds().IsEmpty());
EXPECT_TRUE(immersive_mode_controller->IsRevealed());
base::RunLoop click_loop_1;
ui_test_utils::MoveMouseToCenterAndPress(container, ui_controls::LEFT,
ui_controls::DOWN | ui_controls::UP,
click_loop_1.QuitClosure());
click_loop_1.Run();
container->FinishAnimationForTesting();
EXPECT_TRUE(container->GetVisible());
EXPECT_FALSE(container->bounds().IsEmpty());
EXPECT_TRUE(immersive_mode_controller->IsRevealed());
base::RunLoop click_loop_2;
ui_test_utils::MoveMouseToCenterAndPress(
browser_view->toolbar()->reload_button(), ui_controls::LEFT,
ui_controls::DOWN | ui_controls::UP, click_loop_2.QuitClosure());
click_loop_2.Run();
container->FinishAnimationForTesting();
EXPECT_TRUE(container->GetVisible());
EXPECT_FALSE(container->bounds().IsEmpty());
EXPECT_TRUE(immersive_mode_controller->IsRevealed());
}
class WebUITabStripDragInteractiveTest
: public InteractiveBrowserTest,
public testing::WithParamInterface<bool> {
public:
WebUITabStripDragInteractiveTest() = default;
~WebUITabStripDragInteractiveTest() override = default;
private:
WebUITabStripTestHelper helper_;
};
#if BUILDFLAG(IS_CHROMEOS_ASH)
INSTANTIATE_TEST_SUITE_P(,
WebUITabStripDragInteractiveTest,
testing::Bool());
#else
INSTANTIATE_TEST_SUITE_P(,
WebUITabStripDragInteractiveTest,
testing::Values(false));
#endif
#if BUILDFLAG(IS_CHROMEOS_ASH)
#define MAYBE_CloseTabDuringDragDoesNotCrash …
#else
#define MAYBE_CloseTabDuringDragDoesNotCrash …
#endif
IN_PROC_BROWSER_TEST_P(WebUITabStripDragInteractiveTest,
MAYBE_CloseTabDuringDragDoesNotCrash) {
DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kSecondTabElementId);
DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kWebUiTabStripElementId);
auto* const browser_view = BrowserView::GetBrowserViewForBrowser(browser());
const DeepQuery kSecondTabQuery{"tabstrip-tab-list",
"tabstrip-tab + tabstrip-tab"};
DEFINE_LOCAL_CUSTOM_ELEMENT_EVENT_TYPE(kTabPopulatedCustomEvent);
StateChange tab_populated_change;
tab_populated_change.event = kTabPopulatedCustomEvent;
tab_populated_change.where = kSecondTabQuery;
tab_populated_change.type = StateChange::Type::kExistsAndConditionTrue;
tab_populated_change.test_function =
"el => (el.getBoundingClientRect().width > 0)";
auto get_point_not_in_tabstrip = base::BindLambdaForTesting([browser_view]() {
return browser_view->contents_web_view()->bounds().CenterPoint();
});
auto close_tab = base::BindRepeating([](ui::TrackedElement* tab) {
AsInstrumentedWebContents(tab)->Execute("() => window.close()");
});
auto get_tab_count = base::BindRepeating(
[](Browser* browser) { return browser->tab_strip_model()->count(); },
base::Unretained(browser()));
auto get_tabstrip_webview =
base::BindLambdaForTesting([browser_view]() -> views::View* {
browser_view->GetWidget()->LayoutRootViewIfNecessary();
return browser_view->webui_tab_strip()->web_view_for_testing();
});
RunTestSequence(
Check([this]() { return mouse_util().SetTouchMode(GetParam()); }),
AddInstrumentedTab(kSecondTabElementId, GURL("about:blank")),
PressButton(kToolbarTabCounterButtonElementId),
InstrumentNonTabWebView(kWebUiTabStripElementId, get_tabstrip_webview),
CheckResult(get_tab_count, 2),
WaitForStateChange(kWebUiTabStripElementId, tab_populated_change),
MoveMouseTo(kWebUiTabStripElementId, kSecondTabQuery),
DragMouseTo(get_point_not_in_tabstrip, false),
CheckResult(get_tab_count, 2),
WithElement(kSecondTabElementId, close_tab),
WaitForHide(kSecondTabElementId, true),
CheckResult(get_tab_count, 1),
ReleaseMouse());
}
#endif