# Copyright 2023 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. from __future__ import annotations import abc import html import urllib.parse from argparse import ArgumentTypeError from typing import TYPE_CHECKING, Any, Dict from crossbench import path as pth if TYPE_CHECKING: from crossbench.runner.run import Run class SplashScreen: NONE: SplashScreen MINIMAL: SplashScreen DETAILED: SplashScreen DEFAULT: SplashScreen @classmethod def parse(cls, value: str) -> SplashScreen: if not value or value == "default": return cls.DEFAULT if value in ("none", "skip"): return cls.NONE if value == "minimal": return cls.MINIMAL if value == "detailed": return cls.DETAILED if value.startswith("http:") or value.startswith("https:"): return URLSplashScreen(value) maybe_path = pth.LocalPath(value) if maybe_path.exists(): return URLSplashScreen(maybe_path.absolute().as_uri()) raise ArgumentTypeError(f"Unknown splashscreen: {value}") def run(self, run: Run) -> None: pass _BLANK_PAGE_HTML = "" _BLANK_PAGE_DATA_URL = ( f"data:text/html;charset=utf-8,{urllib.parse.quote(_BLANK_PAGE_HTML)}") class BaseURLSplashScreen(SplashScreen, metaclass=abc.ABCMeta): def __init__(self, timeout: float = 2) -> None: super().__init__() self._timeout = timeout def run(self, run: Run) -> None: with run.actions("SplashScreen") as action: action.show_url(self.get_url(run)) action.wait(self._timeout) action.show_url(_BLANK_PAGE_DATA_URL) @abc.abstractmethod def get_url(self, run: Run) -> str: pass class DetailedSplashScreen(BaseURLSplashScreen): def get_url(self, run: Run) -> str: browser = run.browser title = html.escape(browser.app_name.title()) version = html.escape(browser.version) run_type = "Run" bg_color = "#000" if run.is_warmup: title = f"Warmup: {title}" run_type = "Warmup Run" bg_color = "#444" page = "".join(( "" f"{run_type} Details", "", "", f"

{title} {version}

", self._render_browser_details(run), self._render_run_details(run), "", )) data_url = f"data:text/html;charset=utf-8,{urllib.parse.quote(page)}" return data_url def _render_properties(self, title: str, properties: Dict[str, Any]) -> str: section = f"

{html.escape(title)}

" for property_name, value in properties.items(): section += f"
{html.escape(property_name)}
" section += f"
{html.escape(str(value))}
" section += "
" return section def _render_browser_details(self, run: Run) -> str: browser = run.browser properties = {"User Agent": browser.user_agent(), **browser.details_json()} return self._render_properties("Browser Details", properties) def _render_run_details(self, run: Run) -> str: return self._render_properties("Run Details", run.details_json()) class MinimalSplashScreen(DetailedSplashScreen): def _render_browser_details(self, run: Run) -> str: properties = {"User Agent": run.browser.user_agent()} return self._render_properties("Browser Details", properties) class URLSplashScreen(BaseURLSplashScreen): def __init__(self, url: str, timeout: float = 2) -> None: super().__init__(timeout) self._url = url def get_url(self, run: Run) -> str: return self._url @property def url(self) -> str: return self._url SplashScreen.NONE = SplashScreen() SplashScreen.MINIMAL = MinimalSplashScreen() SplashScreen.DETAILED = DetailedSplashScreen() SplashScreen.DEFAULT = SplashScreen.DETAILED