Path: blob/trunk/py/selenium/webdriver/firefox/options.py
4005 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 Any1819from selenium.webdriver.common.desired_capabilities import DesiredCapabilities20from selenium.webdriver.common.options import ArgOptions21from selenium.webdriver.firefox.firefox_profile import FirefoxProfile222324class Log:25def __init__(self) -> None:26self.level = None2728def to_capabilities(self) -> dict:29if self.level:30return {"log": {"level": self.level}}31return {}323334class Options(ArgOptions):35KEY = "moz:firefoxOptions"3637def __init__(self) -> None:38super().__init__()39self._binary_location = ""40self._preferences: dict = {}41# https://fxdx.dev/deprecating-cdp-support-in-firefox-embracing-the-future-with-webdriver-bidi/.42# Enable BiDi only43self._preferences["remote.active-protocols"] = 144self._profile: FirefoxProfile | None = None45self.log = Log()4647@property48def binary_location(self) -> str:49"""Returns the location of the binary."""50return self._binary_location5152@binary_location.setter53def binary_location(self, value: str) -> None:54"""Sets the location of the browser binary by string."""55if not isinstance(value, str):56raise TypeError(self.BINARY_LOCATION_ERROR)57self._binary_location = value5859@property60def preferences(self) -> dict:61"""Returns a dict of preferences."""62return self._preferences6364def set_preference(self, name: str, value: str | int | bool):65"""Sets a preference."""66self._preferences[name] = value6768@property69def profile(self) -> FirefoxProfile | None:70"""Returns the Firefox profile to use."""71return self._profile7273@profile.setter74def profile(self, new_profile: str | FirefoxProfile) -> None:75"""Set the location of the browser profile to use (string or FirefoxProfile object)."""76if not isinstance(new_profile, FirefoxProfile):77new_profile = FirefoxProfile(new_profile)78self._profile = new_profile7980def enable_mobile(81self, android_package: str | None = "org.mozilla.firefox", android_activity=None, device_serial=None82):83super().enable_mobile(android_package, android_activity, device_serial)8485def to_capabilities(self) -> dict:86"""Marshals the Firefox options to a `moz:firefoxOptions` object."""87# This intentionally looks at the internal properties88# so if a binary or profile has _not_ been set,89# it will defer to geckodriver to find the system Firefox90# and generate a fresh profile.91caps = self._caps92opts: dict[str, Any] = {}9394if self._binary_location:95opts["binary"] = self._binary_location96if self._preferences:97opts["prefs"] = self._preferences98if self._profile:99opts["profile"] = self._profile.encoded100if self._arguments:101opts["args"] = self._arguments102if self.mobile_options:103opts.update(self.mobile_options)104105opts.update(self.log.to_capabilities())106107if opts:108caps[Options.KEY] = opts109110return caps111112@property113def default_capabilities(self) -> dict:114return DesiredCapabilities.FIREFOX.copy()115116117