Skip to content

Commit 0040119

Browse files
kalutesV8 LUCI CQ
authored andcommitted
Add close_all_tabs action
Add a new action type 'close_all_tabs' that will iterate through all active tabs and close them. Change-Id: I8f1adb3640aa43ea12dfd72c045e3774d3b1b3d7 Reviewed-on: https://chromium-review.googlesource.com/c/crossbench/+/6677852 Reviewed-by: Charles Dick <[email protected]> Commit-Queue: Kameron Lutes <[email protected]>
1 parent 35b5a8e commit 0040119

File tree

8 files changed

+64
-0
lines changed

8 files changed

+64
-0
lines changed

crossbench/action_runner/action/action_type.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class ActionType(ConfigEnum):
2929
"Only supported in chromium-based browsers."))
3030
SCREENSHOT = ("screenshot", "Take a screenshot")
3131
SWITCH_TAB = ("switch_tab", "Switch the tab that actions are sent to")
32+
CLOSE_ALL_TABS = ("close_all_tabs", "Close all tabs")
3233
CLOSE_TAB = ("close_tab", "Close the specified tab")
3334
WAIT_FOR_DOWNLOAD = ("wait_for_download", "wait for a download to complete")
3435
WAIT_FOR_READY_STATE = ("wait_for_ready_state",

crossbench/action_runner/action/all.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from crossbench.action_runner.action.action import ACTIONS, Action
1010
from crossbench.action_runner.action.click import ClickAction
1111
from crossbench.action_runner.action.close_tab import CloseTabAction
12+
from crossbench.action_runner.action.close_all_tabs import CloseAllTabsAction
1213
from crossbench.action_runner.action.dump_html import DumpHtmlAction
1314
from crossbench.action_runner.action.get import GetAction
1415
from crossbench.action_runner.action.inject_new_document_script import \
@@ -35,6 +36,7 @@
3536
ACTIONS_TUPLE: tuple[Type[Action], ...] = (
3637
ClickAction,
3738
CloseTabAction,
39+
CloseAllTabsAction,
3840
DumpHtmlAction,
3941
GetAction,
4042
InjectNewDocumentScriptAction,
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Copyright 2025 The Chromium Authors
2+
# Use of this source code is governed by a BSD-style license that can be
3+
# found in the LICENSE file.
4+
5+
from __future__ import annotations
6+
7+
from typing import TYPE_CHECKING
8+
9+
from typing_extensions import override
10+
11+
from crossbench.action_runner.action.action import Action
12+
from crossbench.action_runner.action.action_type import ActionType
13+
14+
if TYPE_CHECKING:
15+
from crossbench.action_runner.base import ActionRunner
16+
from crossbench.runner.run import Run
17+
18+
19+
class CloseAllTabsAction(Action):
20+
TYPE: ActionType = ActionType.CLOSE_ALL_TABS
21+
22+
@override
23+
def run_with(self, run: Run, action_runner: ActionRunner) -> None:
24+
action_runner.close_all_tabs(run, self)

crossbench/action_runner/base.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,5 +308,8 @@ def switch_tab(self, run: Run, action: i_action.SwitchTabAction):
308308
def close_tab(self, run: Run, action: i_action.CloseTabAction):
309309
raise ActionNotImplementedError(self, action)
310310

311+
def close_all_tabs(self, run: Run, action: i_action.CloseAllTabsAction):
312+
raise ActionNotImplementedError(self, action)
313+
311314
def wait_for_download(self, run: Run, action: i_action.WaitForDownloadAction):
312315
raise ActionNotImplementedError(self, action)

crossbench/action_runner/default_action_runner.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,13 @@ def close_tab(self, run: Run, action: i_action.CloseTabAction) -> None:
295295
run.browser.close_tab(action.title, action.url, action.tab_index,
296296
action.relative_tab_index, action.timeout)
297297

298+
@override
299+
def close_all_tabs(self, run: Run,
300+
action: i_action.CloseAllTabsAction) -> None:
301+
del action
302+
with run.actions("CloseAllTabsAction", measure=False):
303+
run.browser.close_all_tabs()
304+
298305
def _get_scroll_field(self, has_selector: bool) -> str:
299306
if has_selector:
300307
return "scrollTop"

crossbench/browsers/browser.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,9 @@ def close_tab(
441441
del timeout
442442
raise NotImplementedError(f"Closing tabs is not supported by {self}")
443443

444+
def close_all_tabs(self) -> None:
445+
raise NotImplementedError(f"Closing all tabs is not supported by {self}")
446+
444447
@property
445448
def current_url(self) -> str:
446449
raise NotImplementedError(f"Getting current url is not supported by {self}")

crossbench/browsers/chromium_based/webdriver.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,22 @@ def close_tab(
299299
# to switching to the first tab.
300300
driver.switch_to.window(driver.window_handles[0])
301301

302+
@override
303+
def close_all_tabs(self) -> None:
304+
driver = self._private_driver
305+
current_handle = driver.current_window_handle
306+
307+
for handle in driver.window_handles:
308+
driver.switch_to.window(handle)
309+
if handle != current_handle:
310+
driver.close()
311+
312+
# Closing every tab will cause the browser to exit.
313+
# As a workaround navigate the final tab to about:blank.
314+
driver.switch_to.window(current_handle)
315+
self.show_url("about:blank")
316+
317+
302318
@property
303319
def current_url(self) -> str:
304320
return self._private_driver.current_url

tests/crossbench/benchmarks/loading/test_action.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
Action)
1212
from crossbench.action_runner.action.action_type import ActionType
1313
from crossbench.action_runner.action.click import ClickAction
14+
from crossbench.action_runner.action.close_all_tabs import CloseAllTabsAction
1415
from crossbench.action_runner.action.close_tab import CloseTabAction
1516
from crossbench.action_runner.action.enums import ReadyState, WindowTarget
1617
from crossbench.action_runner.action.get import GetAction
@@ -896,6 +897,13 @@ def test_parse_switch_tab_only_relative_tab_index(self):
896897

897898
self.assertEqual(action.relative_tab_index, 17)
898899

900+
def test_parse_close_all_tabs(self):
901+
config_dict = {"action": "close_all_tabs"}
902+
903+
action = CloseAllTabsAction.parse(config_dict)
904+
905+
self.assertEqual(action.TYPE, ActionType.CLOSE_ALL_TABS)
906+
899907
def test_parse_close_tab_all_args(self):
900908
config_dict = {
901909
"action": "close_tab",

0 commit comments

Comments
 (0)