1# Copyright 2024 The Chromium Authors 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5from __future__ import annotations 6 7from typing import TYPE_CHECKING 8 9from crossbench.benchmarks.loading.config.login.base import PresetLoginBlock 10from crossbench.cli.config.secret_type import SecretType 11 12if TYPE_CHECKING: 13 from crossbench.action_runner.base import ActionRunner 14 from crossbench.benchmarks.loading.page.interactive import InteractivePage 15 from crossbench.cli.config.secrets import Secret 16 from crossbench.runner.actions import Actions 17 from crossbench.runner.run import Run 18 19GOOGLE_LOGIN_URL: str = ( 20 "https://accounts.google.com/Logout?" 21 "continue=https%3A%2F%2Faccounts.google.com%2Fv3%2Fsignin%2Fidentifier%3F" 22 "flowName%3DGlifWebSignIn%26flowEntry%3DServiceLogin") 23 24TRUSTED_EMAIL_CHECK: str = ( 25 "return document.getElementById('verifycontactNext') != null") 26 27 28class GoogleLogin(PresetLoginBlock): 29 """Google-specific login steps.""" 30 31 def _submit_login_field(self, action: Actions, aria_label: str, 32 input_val: str, button_name: str) -> None: 33 action.wait_js_condition( 34 ("return " 35 f"document.querySelector(\"[aria-label='{aria_label}']\") != null &&" 36 f"document.getElementById({repr(button_name)}) != null;"), 0.2, 10) 37 action.js("const inputField =" 38 f" document.querySelector(\"[aria-label='{aria_label}']\");" 39 f"inputField.value = {repr(input_val)};" 40 f"document.getElementById({repr(button_name)}).click();") 41 42 def run_with(self, runner: ActionRunner, run: Run, 43 page: InteractivePage) -> None: 44 secret: Secret = self.get_secret(run, page, SecretType.GOOGLE) 45 46 if self.is_logged_in(run, secret, strict=True): 47 return 48 49 with run.actions("Login", measure=False) as action: 50 action.show_url(GOOGLE_LOGIN_URL) 51 self._submit_login_field(action, "Email or phone", secret.username, 52 "identifierNext") 53 action.wait_js_condition( 54 "return document.getElementById('verifycontactNext') || " 55 "document.getElementById('passwordNext') != null;", 0.2, 10) 56 if action.js(TRUSTED_EMAIL_CHECK): 57 self._test_account_login(action, secret) 58 else: 59 self._standard_login(action, secret) 60 61 def _standard_login(self, action, secret): 62 self._submit_login_field(action, "Enter your password", secret.password, 63 "passwordNext") 64 action.wait_js_condition( 65 "return document.URL.startsWith('https://myaccount.google.com');", 0.2, 66 10) 67 68 def _test_account_login(self, action, secret): 69 self._submit_login_field(action, "Enter trusted contact\\’s email", 70 secret.password, "verifycontactNext") 71 # TODO: handle account passkey setup, for now each test account needs a 72 # one time manual interaction. 73 action.wait_js_condition( 74 "return document.URL.startsWith('https://myaccount.google.com')", 0.2, 75 60) 76