Path: blob/trunk/py/selenium/webdriver/common/bidi/emulation.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.1617from typing import Any, Optional, Union1819from selenium.webdriver.common.bidi.common import command_builder202122class GeolocationCoordinates:23"""Represents geolocation coordinates."""2425def __init__(26self,27latitude: float,28longitude: float,29accuracy: float = 1.0,30altitude: Optional[float] = None,31altitude_accuracy: Optional[float] = None,32heading: Optional[float] = None,33speed: Optional[float] = None,34):35"""Initialize GeolocationCoordinates.3637Parameters:38-----------39latitude: Latitude coordinate (-90.0 to 90.0).40longitude: Longitude coordinate (-180.0 to 180.0).41accuracy: Accuracy in meters (>= 0.0), defaults to 1.0.42altitude: Altitude in meters or None, defaults to None.43altitude_accuracy: Altitude accuracy in meters (>= 0.0) or None, defaults to None.44heading: Heading in degrees (0.0 to 360.0) or None, defaults to None.45speed: Speed in meters per second (>= 0.0) or None, defaults to None.4647Raises:48------49ValueError: If coordinates are out of valid range or if altitude_accuracy is provided without altitude.50"""51self.latitude = latitude52self.longitude = longitude53self.accuracy = accuracy54self.altitude = altitude55self.altitude_accuracy = altitude_accuracy56self.heading = heading57self.speed = speed5859@property60def latitude(self):61return self._latitude6263@latitude.setter64def latitude(self, value):65if not (-90.0 <= value <= 90.0):66raise ValueError("latitude must be between -90.0 and 90.0")67self._latitude = value6869@property70def longitude(self):71return self._longitude7273@longitude.setter74def longitude(self, value):75if not (-180.0 <= value <= 180.0):76raise ValueError("longitude must be between -180.0 and 180.0")77self._longitude = value7879@property80def accuracy(self):81return self._accuracy8283@accuracy.setter84def accuracy(self, value):85if value < 0.0:86raise ValueError("accuracy must be >= 0.0")87self._accuracy = value8889@property90def altitude(self):91return self._altitude9293@altitude.setter94def altitude(self, value):95self._altitude = value9697@property98def altitude_accuracy(self):99return self._altitude_accuracy100101@altitude_accuracy.setter102def altitude_accuracy(self, value):103if value is not None and self.altitude is None:104raise ValueError("altitude_accuracy cannot be set without altitude")105if value is not None and value < 0.0:106raise ValueError("altitude_accuracy must be >= 0.0")107self._altitude_accuracy = value108109@property110def heading(self):111return self._heading112113@heading.setter114def heading(self, value):115if value is not None and not (0.0 <= value < 360.0):116raise ValueError("heading must be between 0.0 and 360.0")117self._heading = value118119@property120def speed(self):121return self._speed122123@speed.setter124def speed(self, value):125if value is not None and value < 0.0:126raise ValueError("speed must be >= 0.0")127self._speed = value128129def to_dict(self) -> dict[str, Union[float, None]]:130result: dict[str, Union[float, None]] = {131"latitude": self.latitude,132"longitude": self.longitude,133"accuracy": self.accuracy,134}135136if self.altitude is not None:137result["altitude"] = self.altitude138139if self.altitude_accuracy is not None:140result["altitudeAccuracy"] = self.altitude_accuracy141142if self.heading is not None:143result["heading"] = self.heading144145if self.speed is not None:146result["speed"] = self.speed147148return result149150151class GeolocationPositionError:152"""Represents a geolocation position error."""153154TYPE_POSITION_UNAVAILABLE = "positionUnavailable"155156def __init__(self, type: str = TYPE_POSITION_UNAVAILABLE):157if type != self.TYPE_POSITION_UNAVAILABLE:158raise ValueError(f'type must be "{self.TYPE_POSITION_UNAVAILABLE}"')159self.type = type160161def to_dict(self) -> dict[str, str]:162return {"type": self.type}163164165class Emulation:166"""167BiDi implementation of the emulation module.168"""169170def __init__(self, conn):171self.conn = conn172173def set_geolocation_override(174self,175coordinates: Optional[GeolocationCoordinates] = None,176error: Optional[GeolocationPositionError] = None,177contexts: Optional[list[str]] = None,178user_contexts: Optional[list[str]] = None,179) -> None:180"""Set geolocation override for the given contexts or user contexts.181182Parameters:183-----------184coordinates: Geolocation coordinates to emulate, or None.185error: Geolocation error to emulate, or None.186contexts: List of browsing context IDs to apply the override to.187user_contexts: List of user context IDs to apply the override to.188189Raises:190------191ValueError: If both coordinates and error are provided, or if both contexts192and user_contexts are provided, or if neither contexts nor193user_contexts are provided.194"""195if coordinates is not None and error is not None:196raise ValueError("Cannot specify both coordinates and error")197198if contexts is not None and user_contexts is not None:199raise ValueError("Cannot specify both contexts and userContexts")200201if contexts is None and user_contexts is None:202raise ValueError("Must specify either contexts or userContexts")203204params: dict[str, Any] = {}205206if coordinates is not None:207params["coordinates"] = coordinates.to_dict()208elif error is not None:209params["error"] = error.to_dict()210211if contexts is not None:212params["contexts"] = contexts213elif user_contexts is not None:214params["userContexts"] = user_contexts215216self.conn.execute(command_builder("emulation.setGeolocationOverride", params))217218219