1# Copyright 2024 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 5from __future__ import annotations 6 7import abc 8import datetime as dt 9from typing import TYPE_CHECKING, List, Tuple, cast 10 11from crossbench.benchmarks.loading.playback_controller import \ 12 PlaybackController 13from crossbench.benchmarks.loading.tab_controller import TabController 14from crossbench.stories.story import Story 15 16if TYPE_CHECKING: 17 from crossbench.action_runner.base import ActionRunner 18 from crossbench.benchmarks.loading.loading_benchmark import PageLoadBenchmark 19 from crossbench.runner.run import Run 20 21DEFAULT_DURATION_SECONDS = 15 22DEFAULT_DURATION = dt.timedelta(seconds=DEFAULT_DURATION_SECONDS) 23 24# This is initialized in interactive.py to avoid circular dependencies 25PAGE_LIST: List[Page] = [] 26 27class Page(Story, metaclass=abc.ABCMeta): 28 29 @classmethod 30 def all_story_names(cls) -> Tuple[str, ...]: 31 assert PAGE_LIST, "Missing predefined page list" 32 # TODO: move all story names magic to the dedicated StoryFilter. 33 # Use module instead of direct import to avoid import cycle 34 return tuple(page.name for page in PAGE_LIST) 35 36 def __init__(self, 37 name: str, 38 duration: dt.timedelta = DEFAULT_DURATION, 39 playback: PlaybackController = PlaybackController.default(), 40 tabs: TabController = TabController.default(), 41 about_blank_duration: dt.timedelta = dt.timedelta()): 42 self._playback: PlaybackController = playback 43 self._tabs: TabController = tabs 44 self._about_blank_duration = about_blank_duration 45 super().__init__(name, duration) 46 47 @property 48 def about_blank_duration(self) -> dt.timedelta: 49 return self._about_blank_duration 50 51 def set_parent(self, parent: Page) -> None: 52 # TODO: support nested playback controllers. 53 self._playback = PlaybackController.default() 54 self._tabs = TabController.default() 55 del parent 56 57 @abc.abstractmethod 58 def run_with(self, run: Run, action_runner: ActionRunner, 59 multiple_tabs: bool) -> None: 60 pass 61 62 @property 63 @abc.abstractmethod 64 def first_url(self) -> str: 65 pass 66 67 @property 68 def tabs(self) -> TabController: 69 return self._tabs 70 71 72def get_action_runner(run: Run) -> ActionRunner: 73 # TODO: make sure we have a single instance per Run 74 benchmark = cast("PageLoadBenchmark", run.benchmark) 75 return benchmark.action_runner 76