Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/py/selenium/webdriver/firefox/options.py
4005 views
1
# Licensed to the Software Freedom Conservancy (SFC) under one
2
# or more contributor license agreements. See the NOTICE file
3
# distributed with this work for additional information
4
# regarding copyright ownership. The SFC licenses this file
5
# to you under the Apache License, Version 2.0 (the
6
# "License"); you may not use this file except in compliance
7
# with the License. You may obtain a copy of the License at
8
#
9
# http://www.apache.org/licenses/LICENSE-2.0
10
#
11
# Unless required by applicable law or agreed to in writing,
12
# software distributed under the License is distributed on an
13
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
# KIND, either express or implied. See the License for the
15
# specific language governing permissions and limitations
16
# under the License.
17
18
from typing import Any
19
20
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
21
from selenium.webdriver.common.options import ArgOptions
22
from selenium.webdriver.firefox.firefox_profile import FirefoxProfile
23
24
25
class Log:
26
def __init__(self) -> None:
27
self.level = None
28
29
def to_capabilities(self) -> dict:
30
if self.level:
31
return {"log": {"level": self.level}}
32
return {}
33
34
35
class Options(ArgOptions):
36
KEY = "moz:firefoxOptions"
37
38
def __init__(self) -> None:
39
super().__init__()
40
self._binary_location = ""
41
self._preferences: dict = {}
42
# https://fxdx.dev/deprecating-cdp-support-in-firefox-embracing-the-future-with-webdriver-bidi/.
43
# Enable BiDi only
44
self._preferences["remote.active-protocols"] = 1
45
self._profile: FirefoxProfile | None = None
46
self.log = Log()
47
48
@property
49
def binary_location(self) -> str:
50
"""Returns the location of the binary."""
51
return self._binary_location
52
53
@binary_location.setter
54
def binary_location(self, value: str) -> None:
55
"""Sets the location of the browser binary by string."""
56
if not isinstance(value, str):
57
raise TypeError(self.BINARY_LOCATION_ERROR)
58
self._binary_location = value
59
60
@property
61
def preferences(self) -> dict:
62
"""Returns a dict of preferences."""
63
return self._preferences
64
65
def set_preference(self, name: str, value: str | int | bool):
66
"""Sets a preference."""
67
self._preferences[name] = value
68
69
@property
70
def profile(self) -> FirefoxProfile | None:
71
"""Returns the Firefox profile to use."""
72
return self._profile
73
74
@profile.setter
75
def profile(self, new_profile: str | FirefoxProfile) -> None:
76
"""Set the location of the browser profile to use (string or FirefoxProfile object)."""
77
if not isinstance(new_profile, FirefoxProfile):
78
new_profile = FirefoxProfile(new_profile)
79
self._profile = new_profile
80
81
def enable_mobile(
82
self, android_package: str | None = "org.mozilla.firefox", android_activity=None, device_serial=None
83
):
84
super().enable_mobile(android_package, android_activity, device_serial)
85
86
def to_capabilities(self) -> dict:
87
"""Marshals the Firefox options to a `moz:firefoxOptions` object."""
88
# This intentionally looks at the internal properties
89
# so if a binary or profile has _not_ been set,
90
# it will defer to geckodriver to find the system Firefox
91
# and generate a fresh profile.
92
caps = self._caps
93
opts: dict[str, Any] = {}
94
95
if self._binary_location:
96
opts["binary"] = self._binary_location
97
if self._preferences:
98
opts["prefs"] = self._preferences
99
if self._profile:
100
opts["profile"] = self._profile.encoded
101
if self._arguments:
102
opts["args"] = self._arguments
103
if self.mobile_options:
104
opts.update(self.mobile_options)
105
106
opts.update(self.log.to_capabilities())
107
108
if opts:
109
caps[Options.KEY] = opts
110
111
return caps
112
113
@property
114
def default_capabilities(self) -> dict:
115
return DesiredCapabilities.FIREFOX.copy()
116
117