Path: blob/trunk/py/selenium/webdriver/common/bidi/browser.py
1864 views
# Licensed to the Software Freedom Conservancy (SFC) under one1# or more contributor license agreements. See the NOTICE file2# distributed with this work for additional information3# regarding copyright ownership. The SFC licenses this file4# to you under the Apache License, Version 2.0 (the5# "License"); you may not use this file except in compliance6# with the License. You may obtain a copy of the License at7#8# http://www.apache.org/licenses/LICENSE-2.09#10# Unless required by applicable law or agreed to in writing,11# software distributed under the License is distributed on an12# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY13# KIND, either express or implied. See the License for the14# specific language governing permissions and limitations15# under the License.161718from typing import Any, Optional1920from selenium.webdriver.common.bidi.common import command_builder21from selenium.webdriver.common.bidi.session import UserPromptHandler22from selenium.webdriver.common.proxy import Proxy232425class ClientWindowState:26"""Represents a window state."""2728FULLSCREEN = "fullscreen"29MAXIMIZED = "maximized"30MINIMIZED = "minimized"31NORMAL = "normal"3233VALID_STATES = {FULLSCREEN, MAXIMIZED, MINIMIZED, NORMAL}343536class ClientWindowInfo:37"""Represents a client window information."""3839def __init__(40self,41client_window: str,42state: str,43width: int,44height: int,45x: int,46y: int,47active: bool,48):49self.client_window = client_window50self.state = state51self.width = width52self.height = height53self.x = x54self.y = y55self.active = active5657def get_state(self) -> str:58"""Gets the state of the client window.5960Returns:61-------62str: The state of the client window (one of the ClientWindowState constants).63"""64return self.state6566def get_client_window(self) -> str:67"""Gets the client window identifier.6869Returns:70-------71str: The client window identifier.72"""73return self.client_window7475def get_width(self) -> int:76"""Gets the width of the client window.7778Returns:79-------80int: The width of the client window.81"""82return self.width8384def get_height(self) -> int:85"""Gets the height of the client window.8687Returns:88-------89int: The height of the client window.90"""91return self.height9293def get_x(self) -> int:94"""Gets the x coordinate of the client window.9596Returns:97-------98int: The x coordinate of the client window.99"""100return self.x101102def get_y(self) -> int:103"""Gets the y coordinate of the client window.104105Returns:106-------107int: The y coordinate of the client window.108"""109return self.y110111def is_active(self) -> bool:112"""Checks if the client window is active.113114Returns:115-------116bool: True if the client window is active, False otherwise.117"""118return self.active119120@classmethod121def from_dict(cls, data: dict) -> "ClientWindowInfo":122"""Creates a ClientWindowInfo instance from a dictionary.123124Parameters:125-----------126data: A dictionary containing the client window information.127128Returns:129-------130ClientWindowInfo: A new instance of ClientWindowInfo.131132Raises:133------134ValueError: If required fields are missing or have invalid types.135"""136try:137client_window = data["clientWindow"]138if not isinstance(client_window, str):139raise ValueError("clientWindow must be a string")140141state = data["state"]142if not isinstance(state, str):143raise ValueError("state must be a string")144if state not in ClientWindowState.VALID_STATES:145raise ValueError(f"Invalid state: {state}. Must be one of {ClientWindowState.VALID_STATES}")146147width = data["width"]148if not isinstance(width, int) or width < 0:149raise ValueError(f"width must be a non-negative integer, got {width}")150151height = data["height"]152if not isinstance(height, int) or height < 0:153raise ValueError(f"height must be a non-negative integer, got {height}")154155x = data["x"]156if not isinstance(x, int):157raise ValueError(f"x must be an integer, got {type(x).__name__}")158159y = data["y"]160if not isinstance(y, int):161raise ValueError(f"y must be an integer, got {type(y).__name__}")162163active = data["active"]164if not isinstance(active, bool):165raise ValueError("active must be a boolean")166167return cls(168client_window=client_window,169state=state,170width=width,171height=height,172x=x,173y=y,174active=active,175)176except (KeyError, TypeError) as e:177raise ValueError(f"Invalid data format for ClientWindowInfo: {e}")178179180class Browser:181"""182BiDi implementation of the browser module.183"""184185def __init__(self, conn):186self.conn = conn187188def create_user_context(189self,190accept_insecure_certs: Optional[bool] = None,191proxy: Optional[Proxy] = None,192unhandled_prompt_behavior: Optional[UserPromptHandler] = None,193) -> str:194"""Creates a new user context.195196Parameters:197-----------198accept_insecure_certs: Optional flag to accept insecure TLS certificates199proxy: Optional proxy configuration for the user context200unhandled_prompt_behavior: Optional configuration for handling user prompts201202Returns:203-------204str: The ID of the created user context.205"""206params: dict[str, Any] = {}207208if accept_insecure_certs is not None:209params["acceptInsecureCerts"] = accept_insecure_certs210211if proxy is not None:212params["proxy"] = proxy.to_bidi_dict()213214if unhandled_prompt_behavior is not None:215params["unhandledPromptBehavior"] = unhandled_prompt_behavior.to_dict()216217result = self.conn.execute(command_builder("browser.createUserContext", params))218return result["userContext"]219220def get_user_contexts(self) -> list[str]:221"""Gets all user contexts.222223Returns:224-------225List[str]: A list of user context IDs.226"""227result = self.conn.execute(command_builder("browser.getUserContexts", {}))228return [context_info["userContext"] for context_info in result["userContexts"]]229230def remove_user_context(self, user_context_id: str) -> None:231"""Removes a user context.232233Parameters:234-----------235user_context_id: The ID of the user context to remove.236237Raises:238------239Exception: If the user context ID is "default" or does not exist.240"""241if user_context_id == "default":242raise Exception("Cannot remove the default user context")243244params = {"userContext": user_context_id}245self.conn.execute(command_builder("browser.removeUserContext", params))246247def get_client_windows(self) -> list[ClientWindowInfo]:248"""Gets all client windows.249250Returns:251-------252List[ClientWindowInfo]: A list of client window information.253"""254result = self.conn.execute(command_builder("browser.getClientWindows", {}))255return [ClientWindowInfo.from_dict(window) for window in result["clientWindows"]]256257258