|  | 
| 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 | 
| @@ -236,6 +239,7 @@ def __init__( | 
| 236 | 239 |         self._authenticator_id = None | 
| 237 | 240 |         self.start_client() | 
| 238 | 241 |         self.start_session(capabilities) | 
|  | 242 | +        self._fedcm = FedCM(self) | 
| 239 | 243 | 
 | 
| 240 | 244 |         self._websocket_connection = None | 
| 241 | 245 |         self._script = None | 
| @@ -1222,3 +1226,77 @@ def delete_downloadable_files(self) -> None: | 
| 1222 | 1226 |             raise WebDriverException("You must enable downloads in order to work with downloadable files.") | 
| 1223 | 1227 | 
 | 
| 1224 | 1228 |         self.execute(Command.DELETE_DOWNLOADABLE_FILES) | 
|  | 1229 | + | 
|  | 1230 | +    @property | 
|  | 1231 | +    def fedcm(self) -> FedCM: | 
|  | 1232 | +        """ | 
|  | 1233 | +        :Returns: | 
|  | 1234 | +            - FedCM: an object providing access to all Federated Credential Management (FedCM) dialog commands. | 
|  | 1235 | +
 | 
|  | 1236 | +        :Usage: | 
|  | 1237 | +            :: | 
|  | 1238 | +
 | 
|  | 1239 | +                title = driver.fedcm.title | 
|  | 1240 | +                subtitle = driver.fedcm.subtitle | 
|  | 1241 | +                dialog_type = driver.fedcm.dialog_type | 
|  | 1242 | +                accounts = driver.fedcm.account_list | 
|  | 1243 | +                driver.fedcm.select_account(0) | 
|  | 1244 | +                driver.fedcm.accept() | 
|  | 1245 | +                driver.fedcm.dismiss() | 
|  | 1246 | +                driver.fedcm.enable_delay() | 
|  | 1247 | +                driver.fedcm.disable_delay() | 
|  | 1248 | +                driver.fedcm.reset_cooldown() | 
|  | 1249 | +        """ | 
|  | 1250 | +        return self._fedcm | 
|  | 1251 | + | 
|  | 1252 | +    @property | 
|  | 1253 | +    def supports_fedcm(self) -> bool: | 
|  | 1254 | +        """Returns whether the browser supports FedCM capabilities.""" | 
|  | 1255 | +        return self.capabilities.get(ArgOptions.FEDCM_CAPABILITY, False) | 
|  | 1256 | + | 
|  | 1257 | +    def _require_fedcm_support(self): | 
|  | 1258 | +        """Raises an exception if FedCM is not supported.""" | 
|  | 1259 | +        if not self.supports_fedcm: | 
|  | 1260 | +            raise WebDriverException( | 
|  | 1261 | +                "This browser does not support Federated Credential Management. " | 
|  | 1262 | +                "Please ensure you're using a supported browser." | 
|  | 1263 | +            ) | 
|  | 1264 | + | 
|  | 1265 | +    @property | 
|  | 1266 | +    def dialog(self): | 
|  | 1267 | +        """Returns the FedCM dialog object for interaction.""" | 
|  | 1268 | +        self._require_fedcm_support() | 
|  | 1269 | +        return Dialog(self) | 
|  | 1270 | + | 
|  | 1271 | +    def fedcm_dialog(self, timeout=5, poll_frequency=0.5, ignored_exceptions=None): | 
|  | 1272 | +        """Waits for and returns the FedCM dialog. | 
|  | 1273 | +
 | 
|  | 1274 | +        Args: | 
|  | 1275 | +            timeout: How long to wait for the dialog | 
|  | 1276 | +            poll_frequency: How frequently to poll | 
|  | 1277 | +            ignored_exceptions: Exceptions to ignore while waiting | 
|  | 1278 | +
 | 
|  | 1279 | +        Returns: | 
|  | 1280 | +            The FedCM dialog object if found | 
|  | 1281 | +
 | 
|  | 1282 | +        Raises: | 
|  | 1283 | +            TimeoutException if dialog doesn't appear | 
|  | 1284 | +            WebDriverException if FedCM not supported | 
|  | 1285 | +        """ | 
|  | 1286 | +        from selenium.common.exceptions import NoAlertPresentException | 
|  | 1287 | +        from selenium.webdriver.support.wait import WebDriverWait | 
|  | 1288 | + | 
|  | 1289 | +        self._require_fedcm_support() | 
|  | 1290 | + | 
|  | 1291 | +        if ignored_exceptions is None: | 
|  | 1292 | +            ignored_exceptions = (NoAlertPresentException,) | 
|  | 1293 | + | 
|  | 1294 | +        def _check_fedcm(): | 
|  | 1295 | +            try: | 
|  | 1296 | +                dialog = Dialog(self) | 
|  | 1297 | +                return dialog if dialog.type else None | 
|  | 1298 | +            except NoAlertPresentException: | 
|  | 1299 | +                return None | 
|  | 1300 | + | 
|  | 1301 | +        wait = WebDriverWait(self, timeout, poll_frequency=poll_frequency, ignored_exceptions=ignored_exceptions) | 
|  | 1302 | +        return wait.until(lambda _: _check_fedcm()) | 
0 commit comments