blob: e3cca481b9a6e12fd16df9b156bde1feafda5b27 [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/test/test_future.h"
#include "chrome/browser/actor/actor_test_util.h"
#include "chrome/browser/actor/tools/tool_request.h"
#include "chrome/browser/actor/tools/tools_test_util.h"
#include "chrome/browser/actor/tools/window_management_tool_request.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h"
#include "chrome/common/actor.mojom.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/test/browser_test.h"
#include "ui/base/ozone_buildflags.h"
using base::test::TestFuture;
namespace actor {
namespace {
class ActorWindowManagementToolBrowserTest : public ActorToolsTest {
public:
ActorWindowManagementToolBrowserTest() = default;
~ActorWindowManagementToolBrowserTest() override = default;
void SetUpOnMainThread() override {
ActorToolsTest::SetUpOnMainThread();
ASSERT_TRUE(embedded_test_server()->Start());
ASSERT_TRUE(embedded_https_test_server().Start());
}
std::unique_ptr<ToolRequest> MakeCreateWindowRequest() {
return std::make_unique<CreateWindowToolRequest>();
}
std::unique_ptr<ToolRequest> MakeCloseWindowRequest(int32_t window_id) {
return std::make_unique<CloseWindowToolRequest>(window_id);
}
std::unique_ptr<ToolRequest> MakeActivateWindowRequest(int32_t window_id) {
return std::make_unique<ActivateWindowToolRequest>(window_id);
}
};
class NewWindowObserver : public BrowserListObserver {
public:
NewWindowObserver() { BrowserList::AddObserver(this); }
~NewWindowObserver() override { BrowserList::RemoveObserver(this); }
void OnBrowserAdded(Browser* browser) override { added_browser_ = browser; }
Browser* added_browser() const { return added_browser_; }
private:
raw_ptr<Browser> added_browser_ = nullptr;
};
// Ensure CreateWindow creates a new window and makes it the active window.
IN_PROC_BROWSER_TEST_F(ActorWindowManagementToolBrowserTest, CreateWindow) {
const size_t initial_browser_count = BrowserList::GetInstance()->size();
NewWindowObserver new_window_observer;
std::unique_ptr<ToolRequest> action = MakeCreateWindowRequest();
ActResultFuture result;
actor_task().Act(ToRequestList(action), result.GetCallback());
ExpectOkResult(result);
BrowserWindowInterface* new_window = new_window_observer.added_browser();
EXPECT_TRUE(new_window);
EXPECT_EQ(initial_browser_count + 1, BrowserList::GetInstance()->size());
ui_test_utils::WaitForBrowserSetLastActive(
new_window->GetBrowserForMigrationOnly());
EXPECT_EQ(new_window, GetLastActiveBrowserWindowInterfaceWithAnyProfile());
}
// Ensure a created window includes a new tab and that tab is added to the
// acting tab set.
IN_PROC_BROWSER_TEST_F(ActorWindowManagementToolBrowserTest,
CreateWindowAddsTab) {
NewWindowObserver new_window_observer;
std::unique_ptr<ToolRequest> action = MakeCreateWindowRequest();
ActResultFuture result;
actor_task().Act(ToRequestList(action), result.GetCallback());
ExpectOkResult(result);
EXPECT_EQ(new_window_observer.added_browser()->GetTabStripModel()->count(),
1);
EXPECT_EQ(actor_task().GetTabs().size(), 1ul);
}
// Ensure a created window only adds the new window's tab to the acting set if
// the acting set is empty.
// TODO(crbug.com/420669167): This can be updated to add multiple tabs once
// multi-tab is supported.
IN_PROC_BROWSER_TEST_F(ActorWindowManagementToolBrowserTest,
CreateWindowAddsOnlyOneActingTab) {
tabs::TabInterface* first_new_window_tab = nullptr;
// Create a new window and so its tab is added to the acting set.
{
NewWindowObserver new_window_observer;
std::unique_ptr<ToolRequest> action = MakeCreateWindowRequest();
ActResultFuture result;
actor_task().Act(ToRequestList(action), result.GetCallback());
ExpectOkResult(result);
first_new_window_tab =
new_window_observer.added_browser()->GetTabStripModel()->GetActiveTab();
}
// Create another new window; its tab should not be added to the acting set
// since the acting set is not empty.
{
std::unique_ptr<ToolRequest> action = MakeCreateWindowRequest();
ActResultFuture result;
actor_task().Act(ToRequestList(action), result.GetCallback());
ExpectOkResult(result);
}
EXPECT_EQ(actor_task().GetTabs().size(), 1ul);
EXPECT_EQ(*actor_task().GetTabs().begin(), first_new_window_tab->GetHandle());
}
// Ensure CloseWindow closes the window with the given ID.
IN_PROC_BROWSER_TEST_F(ActorWindowManagementToolBrowserTest, CloseWindow) {
const size_t initial_browser_count = BrowserList::GetInstance()->size();
BrowserWindowInterface* initial_active_browser =
GetLastActiveBrowserWindowInterfaceWithAnyProfile();
// Create a new window to close.
std::unique_ptr<ToolRequest> create_action = MakeCreateWindowRequest();
ActResultFuture create_result;
actor_task().Act(ToRequestList(create_action), create_result.GetCallback());
ExpectOkResult(create_result);
ASSERT_EQ(initial_browser_count + 1, BrowserList::GetInstance()->size());
// Close the new window.
const int32_t window_id_to_close =
GetLastActiveBrowserWindowInterfaceWithAnyProfile()->GetSessionID().id();
std::unique_ptr<ToolRequest> close_action =
MakeCloseWindowRequest(window_id_to_close);
ActResultFuture close_result;
actor_task().Act(ToRequestList(close_action), close_result.GetCallback());
ExpectOkResult(close_result);
EXPECT_EQ(initial_browser_count, BrowserList::GetInstance()->size());
ui_test_utils::WaitForBrowserSetLastActive(
initial_active_browser->GetBrowserForMigrationOnly());
EXPECT_EQ(initial_active_browser,
GetLastActiveBrowserWindowInterfaceWithAnyProfile());
}
// Ensure CloseWindow removes the window's tab from the acting set.
IN_PROC_BROWSER_TEST_F(ActorWindowManagementToolBrowserTest,
CloseWindowRemovesTabFromActingSet) {
BrowserWindowInterface* new_window = nullptr;
// Create a new window to close.
{
NewWindowObserver new_window_observer;
std::unique_ptr<ToolRequest> create_action = MakeCreateWindowRequest();
ActResultFuture create_result;
actor_task().Act(ToRequestList(create_action), create_result.GetCallback());
ExpectOkResult(create_result);
new_window = new_window_observer.added_browser();
}
ASSERT_EQ(actor_task().GetTabs().size(), 1ul);
// Close the new window.
{
std::unique_ptr<ToolRequest> close_action =
MakeCloseWindowRequest(new_window->GetSessionID().id());
ActResultFuture close_result;
actor_task().Act(ToRequestList(close_action), close_result.GetCallback());
ExpectOkResult(close_result);
}
EXPECT_TRUE(actor_task().GetTabs().empty());
}
#if BUILDFLAG(IS_OZONE_WAYLAND)
// Wayland doesn't support programmatic window activation at all so this test
// (and functionality?) isn't relevant.
#define MAYBE_ActivateWindow DISABLED_ActivateWindow
#else
#define MAYBE_ActivateWindow ActivateWindow
#endif
// Ensure ActivateWindow activates the window with the given ID.
IN_PROC_BROWSER_TEST_F(ActorWindowManagementToolBrowserTest,
MAYBE_ActivateWindow) {
Browser* initial_window = browser();
// Create a new window, which should become active.
NewWindowObserver new_window_observer;
std::unique_ptr<ToolRequest> create_action = MakeCreateWindowRequest();
ActResultFuture create_result;
actor_task().Act(ToRequestList(create_action), create_result.GetCallback());
ExpectOkResult(create_result);
BrowserWindowInterface* new_window = new_window_observer.added_browser();
ASSERT_NE(new_window, initial_window);
ui_test_utils::WaitForBrowserSetLastActive(
new_window->GetBrowserForMigrationOnly());
// Activate the original window.
std::unique_ptr<ToolRequest> activate_action =
MakeActivateWindowRequest(initial_window->session_id().id());
ActResultFuture activate_result;
actor_task().Act(ToRequestList(activate_action),
activate_result.GetCallback());
ExpectOkResult(activate_result);
ui_test_utils::WaitForBrowserSetLastActive(initial_window);
EXPECT_EQ(initial_window,
GetLastActiveBrowserWindowInterfaceWithAnyProfile());
}
} // namespace
} // namespace actor