|
43 | 43 | from selenium.common.exceptions import WebDriverException |
44 | 44 | from selenium.webdriver.common.bidi.script import Script |
45 | 45 | from selenium.webdriver.common.by import By |
| 46 | +from selenium.webdriver.common.options import ArgOptions |
46 | 47 | from selenium.webdriver.common.options import BaseOptions |
47 | 48 | from selenium.webdriver.common.print_page_options import PrintOptions |
48 | 49 | from selenium.webdriver.common.timeouts import Timeouts |
|
53 | 54 | ) |
54 | 55 | from selenium.webdriver.support.relative_locator import RelativeBy |
55 | 56 |
|
| 57 | +from ..common.fedcm.dialog import Dialog |
56 | 58 | from .bidi_connection import BidiConnection |
57 | 59 | from .client_config import ClientConfig |
58 | 60 | from .command import Command |
59 | 61 | from .errorhandler import ErrorHandler |
| 62 | +from .fedcm import FedCM |
60 | 63 | from .file_detector import FileDetector |
61 | 64 | from .file_detector import LocalFileDetector |
62 | 65 | from .locator_converter import LocatorConverter |
@@ -237,6 +240,7 @@ def __init__( |
237 | 240 | self._authenticator_id = None |
238 | 241 | self.start_client() |
239 | 242 | self.start_session(capabilities) |
| 243 | + self._fedcm = FedCM(self) |
240 | 244 |
|
241 | 245 | self._websocket_connection = None |
242 | 246 | self._script = None |
@@ -1231,3 +1235,77 @@ def delete_downloadable_files(self) -> None: |
1231 | 1235 | raise WebDriverException("You must enable downloads in order to work with downloadable files.") |
1232 | 1236 |
|
1233 | 1237 | self.execute(Command.DELETE_DOWNLOADABLE_FILES) |
| 1238 | + |
| 1239 | + @property |
| 1240 | + def fedcm(self) -> FedCM: |
| 1241 | + """ |
| 1242 | + :Returns: |
| 1243 | + - FedCM: an object providing access to all Federated Credential Management (FedCM) dialog commands. |
| 1244 | +
|
| 1245 | + :Usage: |
| 1246 | + :: |
| 1247 | +
|
| 1248 | + title = driver.fedcm.title |
| 1249 | + subtitle = driver.fedcm.subtitle |
| 1250 | + dialog_type = driver.fedcm.dialog_type |
| 1251 | + accounts = driver.fedcm.account_list |
| 1252 | + driver.fedcm.select_account(0) |
| 1253 | + driver.fedcm.accept() |
| 1254 | + driver.fedcm.dismiss() |
| 1255 | + driver.fedcm.enable_delay() |
| 1256 | + driver.fedcm.disable_delay() |
| 1257 | + driver.fedcm.reset_cooldown() |
| 1258 | + """ |
| 1259 | + return self._fedcm |
| 1260 | + |
| 1261 | + @property |
| 1262 | + def supports_fedcm(self) -> bool: |
| 1263 | + """Returns whether the browser supports FedCM capabilities.""" |
| 1264 | + return self.capabilities.get(ArgOptions.FEDCM_CAPABILITY, False) |
| 1265 | + |
| 1266 | + def _require_fedcm_support(self): |
| 1267 | + """Raises an exception if FedCM is not supported.""" |
| 1268 | + if not self.supports_fedcm: |
| 1269 | + raise WebDriverException( |
| 1270 | + "This browser does not support Federated Credential Management. " |
| 1271 | + "Please ensure you're using a supported browser." |
| 1272 | + ) |
| 1273 | + |
| 1274 | + @property |
| 1275 | + def dialog(self): |
| 1276 | + """Returns the FedCM dialog object for interaction.""" |
| 1277 | + self._require_fedcm_support() |
| 1278 | + return Dialog(self) |
| 1279 | + |
| 1280 | + def fedcm_dialog(self, timeout=5, poll_frequency=0.5, ignored_exceptions=None): |
| 1281 | + """Waits for and returns the FedCM dialog. |
| 1282 | +
|
| 1283 | + Args: |
| 1284 | + timeout: How long to wait for the dialog |
| 1285 | + poll_frequency: How frequently to poll |
| 1286 | + ignored_exceptions: Exceptions to ignore while waiting |
| 1287 | +
|
| 1288 | + Returns: |
| 1289 | + The FedCM dialog object if found |
| 1290 | +
|
| 1291 | + Raises: |
| 1292 | + TimeoutException if dialog doesn't appear |
| 1293 | + WebDriverException if FedCM not supported |
| 1294 | + """ |
| 1295 | + from selenium.common.exceptions import NoAlertPresentException |
| 1296 | + from selenium.webdriver.support.wait import WebDriverWait |
| 1297 | + |
| 1298 | + self._require_fedcm_support() |
| 1299 | + |
| 1300 | + if ignored_exceptions is None: |
| 1301 | + ignored_exceptions = (NoAlertPresentException,) |
| 1302 | + |
| 1303 | + def _check_fedcm(): |
| 1304 | + try: |
| 1305 | + dialog = Dialog(self) |
| 1306 | + return dialog if dialog.type else None |
| 1307 | + except NoAlertPresentException: |
| 1308 | + return None |
| 1309 | + |
| 1310 | + wait = WebDriverWait(self, timeout, poll_frequency=poll_frequency, ignored_exceptions=ignored_exceptions) |
| 1311 | + return wait.until(lambda _: _check_fedcm()) |
0 commit comments