def _TerminateOrKillProcess(process, process_name): done = False pid = process.id try: process.terminate() py_utils.WaitFor(lambda: process.poll() is not None, 10) done = True except py_utils.TimeoutException: try: process.kill() py_utils.WaitFor(lambda: process.poll() is not None, 10) done = True except py_utils.TimeoutException: pass if not done: logging.warning( 'Failed to terminate/kill the process %s (pid: %s) after 20 seconds.' % (process_name, pid)) return
def _ReadLineTsProxyStdout(self, timeout): def ReadSingleLine(): try: return self._proc.stdout.readline().strip() except IOError: # Add a sleep to avoid trying to read self._proc.stdout too often. if self._non_blocking: time.sleep(0.5) return None return py_utils.WaitFor(ReadSingleLine, timeout)
def WaitForAndCreate(self, timeout=None): """Wait for the DevTools agent to be ready and connect to it. Args: timeout: Number of seconds to wait for the DevTools agent to become available (defaults to 1 minute). """ assert not self._created, 'DevTools client has already been created' py_utils.WaitFor(self.IsAgentReady, timeout=timeout or 60) return self.Create()
def TurnScreenOn(self): """If presentation.device screen is off, turn screen on. If the screen is already on, log a warning and return immediately. Raises: Timeout: If the screen is off and presentation.device fails to turn screen on. """ self._platform_backend.presentation.device.SetScreen(True) py_utils.WaitFor(self._platform_backend.presentation.device.IsScreenOn, 5)
def NavigateUnicornLogin(self, child_user, child_pass, parent_user, parent_pass): """Logs into a unicorn account.""" self._ExecuteOobeApi('Oobe.skipToLoginForTesting') py_utils.WaitFor(self._GaiaWebviewContext, 20) logging.info('Entering child credentials') self._NavigateWebviewLogin(child_user, child_pass, False) logging.info('Clicking on parent button') parent_user = self.Canonicalize(parent_user, remove_dots=False) self._ClickGaiaButton(parent_user, self._UnicornObfuscated(parent_user)) logging.info('Entering parent credentials') self._NavigateWebviewEntry('password', parent_pass) self._ClickPrimaryActionButton() logging.info('Clicking Yes (or I agree)') self._ClickGaiaButton('Yes', 'agree') py_utils.WaitFor(lambda: not self._GaiaWebviewContext(), 60) logging.info('Logged in as unicorn user')
def Inspect(browser, url): # Wait for url to be inspectable. browser.supports_inspecting_webui = True tabs = browser.tabs py_utils.WaitFor(lambda: any([True for tab in tabs if tab.url == url]), 10) # Wait for url to load. tab = next(iter([tab for tab in tabs if tab.url == url])) action_runner = ActionRunner(tab) # Recreate action_runner. tab.WaitForDocumentReadyStateToBeComplete() return action_runner
def RunNavigateSteps(self, action_runner): action_runner.Navigate('about:blank') action_runner.PrepareForLeakDetection() action_runner.MeasureMemory(True) action_runner.Navigate(self.url) py_utils.WaitFor(action_runner.tab.HasReachedQuiescence, timeout=30) action_runner.Navigate('about:blank') action_runner.PrepareForLeakDetection() action_runner.MeasureMemory(True)
def _WaitForBrowserToComeUp(self): """ Wait for browser to come up. """ try: timeout = self.browser_options.browser_startup_timeout py_utils.WaitFor(self.HasBrowserFinishedLaunching, timeout=timeout) except (py_utils.TimeoutException, exceptions.ProcessGoneException) as e: if not self.IsBrowserRunning(): raise exceptions.BrowserGoneException(self.browser, e) raise exceptions.BrowserConnectionGoneException(self.browser, e)
def testWaitForEventuallyTrue(self): # Use list to pass to inner function in order to allow modifying the # variable from the outer scope. c = [0] def ReturnCounterBasedValue(): c[0] += 1 return c[0] > 2 self.assertTrue(py_utils.WaitFor(ReturnCounterBasedValue, .5))
def _WaitForLogin(self): # Wait for cryptohome to mount. py_utils.WaitFor(self._IsLoggedIn, 900) # For incognito mode, the session manager actually relaunches chrome with # new arguments, so we have to wait for the browser to come up. self._WaitForBrowserToComeUp() # Wait for extensions to load. if self._supports_extensions: self._WaitForExtensionsToLoad()
def testLogout(self): """Tests autotestPrivate.logout""" if self._is_guest: return with self._CreateBrowser(autotest_ext=True) as b: extension = self._GetAutotestExtension(b) try: extension.ExecuteJavaScript('chrome.autotestPrivate.logout();') except exceptions.Error: pass py_utils.WaitFor(lambda: not self._IsCryptohomeMounted(), 20)
def _NavigateGaiaLogin(self, username, password, enterprise_enroll): """Invokes NavigateIFrameLogin or NavigateWebViewLogin as appropriate.""" def _GetGaiaFunction(): if self._GaiaWebviewContext() is not None: return partial(Oobe._NavigateWebViewLogin, wait_for_close=not enterprise_enroll) elif self._GaiaIFrameContext() is not None: return partial(Oobe._NavigateIFrameLogin, add_user_for_testing=not enterprise_enroll) return None py_utils.WaitFor(_GetGaiaFunction, 20)(self, username, password)
def _WaitForEnterpriseWebview(self, username): """Waits for enterprise webview to be visible. We look for a span with the title set to the domain, for example <span title="managedchrome.com">.""" _, domain = username.split('@') def _EnterpriseWebviewVisible(): webview = self._GaiaWebviewContext() return webview and webview.EvaluateJavaScript( "document.querySelectorAll('span[title= {{ domain }}]').length;", domain=domain) py_utils.WaitFor(_EnterpriseWebviewVisible, 60)
def WaitForNetworkQuiescence(self, timeout_in_seconds=10): """ Wait for network quiesence on the page. Args: timeout_in_seconds: maximum amount of time (seconds) to wait for network quiesence before raising exception. Raises: py_utils.TimeoutException when the timeout is reached but the page's network is not quiet. """ py_utils.WaitFor(self.tab.HasReachedQuiescence, timeout_in_seconds)
def TurnScreenOff(self): """If device screen is on, turn screen off. If the screen is already off, log a warning and return immediately. Raises: Timeout: If the screen is on and device fails to turn screen off. """ def is_screen_off(): return not self._platform_backend.device.IsScreenOn() self._platform_backend.device.SetScreen(False) py_utils.WaitFor(is_screen_off, 5)
def WaitForJavaScriptCondition(self, condition, **kwargs): """Wait for a JavaScript condition to become truthy. Example: runner.WaitForJavaScriptCondition('window.foo == 10'); Args: condition: The JavaScript condition (provided as string). Optional keyword args: timeout: The number in seconds to wait for the condition to become True (default to 60). context_id: The id of an iframe where to execute the code; the main page has context_id=1, the first iframe context_id=2, etc. Additional keyword arguments provide values to be interpolated within the expression. See telemetry.util.js_template for details. Returns: The value returned by the JavaScript condition that got interpreted as true. Raises: py_utils.TimeoutException exceptions.EvaluationException exceptions.WebSocketException exceptions.DevtoolsTargetCrashException """ # Use the default both when timeout=None or the option is ommited. timeout = kwargs.pop('timeout', None) or 60 context_id = kwargs.pop('context_id', None) condition = js_template.Render(condition, **kwargs) def IsJavaScriptExpressionTrue(): return self._EvaluateJavaScript(condition, context_id, timeout) try: return py_utils.WaitFor(IsJavaScriptExpressionTrue, timeout) except py_utils.TimeoutException as e: # Try to make timeouts a little more actionable by dumping console output. debug_message = None try: debug_message = ( 'Console output:\n%s' % self.GetCurrentConsoleOutputBuffer()) except Exception as e: # pylint: disable=broad-except debug_message = ( 'Exception thrown when trying to capture console output: %s' % repr(e)) # Rethrow with the original stack trace for better debugging. raise py_utils.TimeoutException, \ py_utils.TimeoutException( 'Timeout after %ss while waiting for JavaScript:' % timeout + condition + '\n' + e.message + '\n' + debug_message), \ sys.exc_info()[2]
def _NavigateIFrameLogin(self, username, password, add_user_for_testing): """Logs into the IFrame-based GAIA screen""" gaia_iframe_context = py_utils.WaitFor(self._GaiaIFrameContext, timeout=30) if add_user_for_testing: self._ExecuteOobeApi('Oobe.showAddUserForTesting') self.ExecuteJavaScriptInContext(""" document.getElementById('Email').value='%s'; document.getElementById('Passwd').value='%s'; document.getElementById('signIn').click();""" % (username, password), gaia_iframe_context)
def _WaitForLogin(self): # Wait for cryptohome to mount. py_utils.WaitFor(self._IsLoggedIn, 900) # For incognito mode, the session manager actually relaunches chrome with # new arguments, so we have to wait for the browser to come up and bind # the new DevTools agent to this backend. self.BindDevToolsClient() # Wait for extensions to load. if self._supports_extensions: self._WaitForExtensionsToLoad()
def testRestoreBrowserWithMultipleTabs(self): with self._browser_to_create.Create(self._options) as browser: # The number of tabs will be self._number_of_tabs + 1 as it includes the # old tabs and a new blank tab. expected_number_of_tabs = self._number_of_tabs + 1 try: py_utils.WaitFor( lambda: len(browser.tabs) == expected_number_of_tabs, 10) except: logging.error('Number of tabs is %s' % len(browser.tabs)) raise self.assertEquals(expected_number_of_tabs, len(browser.tabs))
def StopShell(self, timeout=None): """Stop BattOr binary shell.""" assert self._battor_shell, 'Attempting to stop a non-running BattOr shell.' assert not self._tracing, 'Attempting to stop a BattOr shell while tracing.' timeout = timeout if timeout else DEFAULT_SHELL_CLOSE_TIMEOUT_S self._SendBattOrCommand(self._EXIT_CMD, check_return=False) try: py_utils.WaitFor(lambda: self.GetShellReturnCode() != None, timeout) except py_utils.TimeoutException: self.KillBattOrShell() finally: self._battor_shell = None
def GetTabSwitchHistogramRetry(browser): """Retries getting histogram as it may fail when a context was discarded. Args: browser: Gets histogram from this browser. Returns: A json serialization of a histogram. Raises: py_utils.TimeoutException: There is no valid histogram in 10 seconds. """ return py_utils.WaitFor(lambda: _GetTabSwitchHistogram(browser), 10)
def _WaitForConnectionEstablished(self): address = (self.host_ip, self.local_port) def CanConnect(): with contextlib.closing(socket.socket()) as s: return s.connect_ex(address) == 0 try: py_utils.WaitFor(CanConnect, timeout=10) logging.debug('Connection test succeeded for %s:%d', *address) except py_utils.TimeoutException: raise ConnectionError('Unable to connect to address: %s:%d' % address)
def Close(self): super(CrOSBrowserBackend, self).Close() if self._cri: self._cri.RestartUI(False) # Logs out. self._cri.CloseConnection() py_utils.WaitFor(lambda: not self._IsCryptohomeMounted(), 180) self._cri = None if self._tmp_minidump_dir: shutil.rmtree(self._tmp_minidump_dir, ignore_errors=True) self._tmp_minidump_dir = None
def _GetLoginStatus(self, browser): extension = self._GetAutotestExtension(browser) self.assertTrue( extension.EvaluateJavaScript( "typeof('chrome.autotestPrivate') != 'undefined'")) extension.ExecuteJavaScript(''' window.__login_status = null; chrome.autotestPrivate.loginStatus(function(s) { window.__login_status = s; }); ''') return py_utils.WaitFor( lambda: extension.EvaluateJavaScript('window.__login_status'), 10)
def WaitForEvent(self, tab, selector, event_name, timeout_in_seconds): """Halts media action until the selector's event is fired. Args: tab: The tab to check for event on. selector: Media element selector. event_name: Name of the event to check if fired or not. timeout_in_seconds: Timeout to check for event, throws an exception if not fired. """ py_utils.WaitFor( lambda: self.HasEventCompletedOrError(tab, selector, event_name), timeout=timeout_in_seconds)
def _AttemptUnlockBadPassword(self, browser): logging.info('Trying a bad password') def ErrorBubbleVisible(): return not browser.oobe.EvaluateJavaScript(''' document.getElementById('bubble').hidden ''') self.assertFalse(ErrorBubbleVisible()) # TODO(catapult:#3028): Fix interpolation of JavaScript values. browser.oobe.ExecuteJavaScript(''' Oobe.authenticateForTesting('%s', 'bad'); ''' % self._username) py_utils.WaitFor(ErrorBubbleVisible, 10) self.assertTrue(self._IsScreenLocked(browser))
def RunNavigateSteps(self, action_runner): action_runner.Navigate('about:blank') action_runner.PrepareForLeakDetection() action_runner.MeasureMemory(True) action_runner.Navigate(self.url) try: py_utils.WaitFor(action_runner.tab.HasReachedQuiescence, timeout=30) except py_utils.TimeoutException: # Conduct leak detection whether or not loading has finished pass action_runner.Navigate('about:blank') action_runner.PrepareForLeakDetection() action_runner.MeasureMemory(True)
def _ReadRemotePort(filename): def TryReadingPort(f): # When we specify the remote port '0' in ssh remote port forwarding, # the remote ssh server should return the port it binds to in stderr. # e.g. 'Allocated port 42360 for remote forward to localhost:12345', # the port 42360 is the port created remotely and the traffic to the # port will be relayed to localhost port 12345. line = f.readline() tokens = re.search(r'port (\d+) for remote forward to', line) return int(tokens.group(1)) if tokens else None with open(filename, 'r') as f: return py_utils.WaitFor(lambda: TryReadingPort(f), timeout=60)
def _AttemptUnlockBadPassword(self, browser): logging.info('Trying a bad password') def ErrorBubbleVisible(): return not browser.oobe.EvaluateJavaScript( "document.getElementById('bubble').hidden") self.assertFalse(ErrorBubbleVisible()) browser.oobe.ExecuteJavaScript( "Oobe.authenticateForTesting({{ username }}, 'bad');", username=self._username) py_utils.WaitFor(ErrorBubbleVisible, 10) self.assertTrue(self._IsScreenLocked(browser))
def _WaitForLogin(self): # For incognito mode, the session manager actually relaunches chrome with # new arguments, so we have to wait for the browser to restart and then # bind the new DevTools agent to this backend. It's important to do this # before waiting for _IsLoggedIn, otherwise the devtools connection check # will still try to reach the older DevTools agent (and fail to do so). self.BindDevToolsClient() # Wait for cryptohome to mount. py_utils.WaitFor(self._IsLoggedIn, 900) # Wait for extensions to load. if self._supports_extensions: self._WaitForExtensionsToLoad()