def _WaitForBrowserToComeUp(self): """ Wait for browser to come up. """ try: timeout = self.browser_options.browser_startup_timeout util.WaitFor(self.HasBrowserFinishedLaunching, timeout=timeout) except (exceptions.TimeoutException, exceptions.ProcessGoneException) as e: if not self.IsBrowserRunning(): raise exceptions.BrowserGoneException(self.browser, e) raise exceptions.BrowserConnectionGoneException(self.browser, e)
def testLogout(self): """Tests autotestPrivate.logout""" with self._CreateBrowser(autotest_ext=True) as b: extension = self._GetAutotestExtension(b) try: extension.ExecuteJavaScript('chrome.autotestPrivate.logout();') except (exceptions.BrowserConnectionGoneException, exceptions.BrowserGoneException): pass util.WaitFor(lambda: not self._IsCryptohomeMounted(), 20)
def WaitForPageToFinish(): print "Waiting for page to finish." try: util.WaitFor( lambda: tab.EvaluateJavaScript( 'window.domAutomationController._finished'), wait_timeout) return True except exceptions.TimeoutException: return False
def _NavigateIFrameLogin(self, username, password): """Logs into the IFrame-based GAIA screen""" gaia_iframe_context = util.WaitFor(self._GaiaIFrameContext, timeout=30) self.ExecuteJavaScriptInContext( """ document.getElementById('Email').value='%s'; document.getElementById('Passwd').value='%s'; document.getElementById('signIn').click();""" % (username, password), gaia_iframe_context)
def Close(self): super(DesktopBrowserBackend, self).Close() if self._proc: def IsClosed(): if not self._proc: return True return self._proc.poll() != None # Try to politely shutdown, first. if not IsClosed(): self._proc.terminate() try: util.WaitFor(IsClosed, timeout=5) self._proc = None except util.TimeoutException: logging.warning('Failed to gracefully shutdown. Proceeding to kill.') # Kill it. if not IsClosed(): self._proc.kill() try: util.WaitFor(IsClosed, timeout=10) except util.TimeoutException: raise Exception('Could not shutdown the browser.') finally: self._proc = None if self._output_profile_path: # If we need the output then double check that it exists. if not (self._tmp_profile_dir and os.path.exists(self._tmp_profile_dir)): raise Exception("No profile directory generated by Chrome: '%s'." % self._tmp_profile_dir) else: # If we don't need the profile after the run then cleanup. if self._tmp_profile_dir and os.path.exists(self._tmp_profile_dir): shutil.rmtree(self._tmp_profile_dir, ignore_errors=True) self._tmp_profile_dir = None if self._tmp_output_file: self._tmp_output_file.close() self._tmp_output_file = None
def WaitForJavaScriptExpression(self, expr, timeout, dump_page_state_on_timeout=True): """Waits for the given JavaScript expression to be True. This method is robust against any given Evaluation timing out. Args: expr: The expression to evaluate. timeout: The number of seconds to wait for the expression to be True. dump_page_state_on_timeout: Whether to provide additional information on the page state if a TimeoutException is thrown. Raises: exceptions.TimeoutException: On a timeout. exceptions.Error: See EvaluateJavaScript() for a detailed list of possible exceptions. """ def IsJavaScriptExpressionTrue(): try: return bool(self.EvaluateJavaScript(expr)) except exceptions.TimeoutException: # If the main thread is busy for longer than Evaluate's timeout, we # may time out here early. Instead, we want to wait for the full # timeout of this method. return False try: util.WaitFor(IsJavaScriptExpressionTrue, timeout) except exceptions.TimeoutException as e: if not dump_page_state_on_timeout: raise # Try to make timeouts a little more actionable by dumping |this|. raise exceptions.TimeoutException(e.message + self.EvaluateJavaScript(""" (function() { var error = '\\n\\nJavaScript |this|:\\n'; for (name in this) { try { error += '\\t' + name + ': ' + this[name] + '\\n'; } catch (e) { error += '\\t' + name + ': ???\\n'; } } if (window && window.document) { error += '\\n\\nJavaScript window.document:\\n'; for (name in window.document) { try { error += '\\t' + name + ': ' + window.document[name] + '\\n'; } catch (e) { error += '\\t' + name + ': ???\\n'; } } } return error; })(); """))
def _DumpJavaHeap(self, wait_for_completion): device_dump_file = None for pid in self._GetProcessOutputFileMap().iterkeys(): device_dump_file = '%s%s.%s.aprof' % (self._DEFAULT_DEVICE_DIR, pid, self._run_count) self._browser_backend.adb.RunShellCommand('am dumpheap %s %s' % (pid, device_dump_file)) if device_dump_file and wait_for_completion: util.WaitFor(lambda: self._FileSize(device_dump_file) > 0, timeout=2, poll_interval=0.5) self._run_count += 1
def NavigateGaiaLogin(self, username, password): """Logs in using the GAIA webview or IFrame, whichever is present.""" def _GetGaiaFunction(): self._ExecuteOobeApi('Oobe.showAddUserForTesting') if self._GaiaIFrameContext() is not None: return Oobe._NavigateIFrameLogin elif self._GaiaWebViewContext() is not None: return Oobe._NavigateWebViewLogin return None util.WaitFor(_GetGaiaFunction, 20)(self, username, password)
def _NavigateLogin(self): """Navigates through oobe login screen""" # Dismiss the user image selection screen. try: util.WaitFor(lambda: self._IsLoggedIn(), 60) # pylint: disable=W0108 except util.TimeoutException: self._cri.TakeScreenShot('login-screen') raise exceptions.LoginException( 'Timed out going through oobe screen. Make sure the custom auth ' 'extension passed through --auth-ext-path is valid and belongs ' 'to user "chronos".') if self.chrome_branch_number < 1500: # Wait for the startup window, then close it. Startup window doesn't exist # post-M27. crrev.com/197900 util.WaitFor(lambda: self._StartupWindow() is not None, 20) self._StartupWindow().Close() else: # Open a new window/tab. self.tab_list_backend.New(15)
def WaitForEvent(self, tab, selector, event_name, timeout): """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: Timeout to check for event, throws an exception if not fired. """ util.WaitFor(lambda: self.HasEventCompleted(tab, selector, event_name), timeout=timeout)
def MeasurePage(self, page, tab, results): def _IsDone(): return bool(tab.EvaluateJavaScript('__pc_load_time')) util.WaitFor(_IsDone, 60) for h in self._histograms: h.GetValue(page, tab, results) results.Add('page_load_time', 'ms', int(float(tab.EvaluateJavaScript('__pc_load_time'))), chart_name='times')
def testGaiaLogin(self): """Tests gaia login. Credentials are expected to be found in a credentials.txt file, with a single line of format username:password.""" if self._is_guest: return (username, password) = self._Credentials('credentials.txt') if username and password: with self._CreateBrowser(gaia_login=True, username=username, password=password): self.assertTrue(util.WaitFor(self._IsCryptohomeMounted, 10))
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: util.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 StartSetupAndReturnApp(self): """ Runs the setup and returns the wrapper to the setup app. After clicking the setup button in the settings page, enter the password to reauthenticate the user before the app launches. Returns: A SmartLockApp object of the app that was launched. Raises: TimeoutException: Timed out waiting for app. """ self.StartSetup() util.WaitFor( lambda: (self._chromeos.session_state == ChromeOS.SessionState. LOCK_SCREEN), 5) lock_screen = self._chromeos.GetAccountPickerScreen() lock_screen.EnterPassword() util.WaitFor(lambda: self._chromeos.GetSmartLockApp() is not None, 10) return self._chromeos.GetSmartLockApp()
def _WaitForLogin(self): # Wait for cryptohome to mount. util.WaitFor(self._IsLoggedIn, 60) # 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 util.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 util.WaitFor(_GetGaiaFunction, 20)(self, username, password)
def MeasurePage(self, _, tab, results): util.WaitFor( lambda: tab.EvaluateJavaScript( '!document.getElementById("start-performance-tests").disabled' ), 60) tab.ExecuteJavaScript(""" window.__results = {}; window.console.log = function(str) { if (!str) return; var key_val = str.split(': '); if (!key_val.length == 2) return; __results[key_val[0]] = key_val[1]; }; document.getElementById('start-performance-tests').click(); """) js_get_results = 'JSON.stringify(window.__results)' num_tests_complete = [0] # A list to work around closure issue. def _IsDone(): num_tests_in_measurement = 24 num_results = len(eval(tab.EvaluateJavaScript(js_get_results))) if num_results > num_tests_complete[0]: num_tests_complete[0] = num_results logging.info('Completed measurement %d of %d' % (num_tests_complete[0], num_tests_in_measurement)) return num_tests_complete[0] >= num_tests_in_measurement util.WaitFor(_IsDone, 1200, poll_interval=5) result_dict = eval(tab.EvaluateJavaScript(js_get_results)) for key in result_dict: chart, trace = key.split('.', 1) results.Add(trace, 'objects (bigger is better)', float(result_dict[key]), chart_name=chart, data_type='unimportant') results.Add('Score', 'objects (bigger is better)', [float(x) for x in result_dict.values()])
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 util.WaitFor( lambda: extension.EvaluateJavaScript('window.__login_status'), 10)
def StartVideoCapture(self, min_bitrate_mbps): """Starts the video capture at specified bitrate.""" min_bitrate_mbps = max(min_bitrate_mbps, 0.1) if min_bitrate_mbps > 100: raise ValueError('Android video capture cannot capture at %dmbps. ' 'Max capture rate is 100mbps.' % min_bitrate_mbps) if self.is_video_capture_running: self._video_recorder.Stop() self._video_recorder = screenshot.VideoRecorder( self._device, megabits_per_second=min_bitrate_mbps) self._video_recorder.Start() util.WaitFor(self._video_recorder.IsStarted, 5)
def _WaitForSigninScreen(self): """Waits for oobe to be on the signin or account picker screen.""" def OnAccountPickerScreen(): signin_state = self._SigninUIState() # GAIA_SIGNIN or ACCOUNT_PICKER screens. return signin_state == 1 or signin_state == 2 try: util.WaitFor(OnAccountPickerScreen, 60) except util.TimeoutException: self._cri.TakeScreenShot('guest-screen') raise exceptions.LoginException('Timed out waiting for signin screen, ' 'signin state %d' % self._SigninUIState())
def NavigateGaiaLogin(self, username, password): """Logs in to GAIA with provided credentials.""" self._ExecuteOobeApi('Oobe.addUserForTesting') gaia_context = util.WaitFor(self._GaiaLoginContext, timeout=30) self.ExecuteJavaScriptInContext( """ document.getElementById('Email').value='%s'; document.getElementById('Passwd').value='%s'; document.getElementById('signIn').click();""" % (username, password), gaia_context)
def Start(self, local_app_path=None): """ Connects to the ChromeOS device and logs in. Args: local_app_path: A path on the local device containing the Smart Lock app to use instead of the app on the ChromeOS device. Return: |self| for using in a "with" statement. """ assert (self._browser is None) finder_opts = browser_options.BrowserFinderOptions('cros-chrome') finder_opts.CreateParser().parse_args(args=[]) finder_opts.cros_remote = self._remote_address if self._ssh_port is not None: finder_opts.cros_remote_ssh_port = self._ssh_port finder_opts.verbosity = 1 browser_opts = finder_opts.browser_options browser_opts.create_browser_with_oobe = True browser_opts.disable_component_extensions_with_background_pages = False browser_opts.gaia_login = True browser_opts.username = self._username browser_opts.password = self._password browser_opts.auto_login = True self._cros_interface = cros_interface.CrOSInterface( finder_opts.cros_remote, finder_opts.cros_remote_ssh_port, finder_opts.cros_ssh_identity) browser_opts.disable_default_apps = local_app_path is not None if local_app_path is not None: easy_unlock_app = extension_to_load.ExtensionToLoad( path=local_app_path, browser_type='cros-chrome', is_component=True) finder_opts.extensions_to_load.append(easy_unlock_app) retries = 3 while self._browser is not None or retries > 0: try: browser_to_create = browser_finder.FindBrowser(finder_opts) self._browser = browser_to_create.Create(finder_opts) break except (exceptions.LoginException) as e: logger.error('Timed out logging in: %s' % e) if retries == 1: raise bg_page_path = '/_generated_background_page.html' util.WaitFor( lambda: self._FindSmartLockAppPage(bg_page_path) is not None, 10) self._background_page = self._FindSmartLockAppPage(bg_page_path) return self
def _TryCooperativeShutdown(self): if self.browser.platform.IsCooperativeShutdownSupported(): if self.browser.platform.CooperativelyShutdown( self._proc, "mandoline"): try: util.WaitFor(lambda: not self.IsBrowserRunning(), timeout=5) logging.info( 'Successfully shut down browser cooperatively') except exceptions.TimeoutException as e: logging.warning('Failed to cooperatively shutdown. ' + 'Proceeding to terminate: ' + str(e))
def MeasurePage(self, _, tab, results): tab.ExecuteJavaScript('ToggleRoboHornet()') done = 'document.getElementById("results").innerHTML.indexOf("Total") != -1' def _IsDone(): return tab.EvaluateJavaScript(done) util.WaitFor(_IsDone, 60) result = int(tab.EvaluateJavaScript('stopTime - startTime')) results.Add('Total', 'ms', result)
def __init__(self, browser_options, cri, is_guest, extensions_to_load): super(CrOSBrowserBackend, self).__init__(supports_tab_control=True, supports_extensions=not is_guest, browser_options=browser_options, output_profile_path=None, extensions_to_load=extensions_to_load) # Initialize fields so that an explosion during init doesn't break in Close. self._cri = cri self._is_guest = is_guest self._forwarder = None from telemetry.core.backends.chrome import chrome_browser_options assert isinstance(browser_options, chrome_browser_options.CrosBrowserOptions) self.wpr_port_pairs = forwarders.PortPairs( http=forwarders.PortPair( self.wpr_port_pairs.http.local_port, self.GetRemotePort(self.wpr_port_pairs.http.local_port)), https=forwarders.PortPair( self.wpr_port_pairs.https.local_port, self.GetRemotePort(self.wpr_port_pairs.http.local_port)), dns=None) self._remote_debugging_port = self._cri.GetRemotePort() self._port = self._remote_debugging_port # Copy extensions to temp directories on the device. # Note that we also perform this copy locally to ensure that # the owner of the extensions is set to chronos. for e in extensions_to_load: extension_dir = cri.RunCmdOnDevice( ['mktemp', '-d', '/tmp/extension_XXXXX'])[0].rstrip() cri.PushFile(e.path, extension_dir) cri.Chown(extension_dir) e.local_path = os.path.join(extension_dir, os.path.basename(e.path)) self._cri.RestartUI(self.browser_options.clear_enterprise_policy) util.WaitFor(self.IsBrowserRunning, 20) # Delete test user's cryptohome vault (user data directory). if not self.browser_options.dont_override_profile: self._cri.RunCmdOnDevice([ 'cryptohome', '--action=remove', '--force', '--user=%s' % self._username ]) if self.browser_options.profile_dir: cri.RmRF(self.profile_directory) cri.PushFile(self.browser_options.profile_dir + '/Default', self.profile_directory) cri.Chown(self.profile_directory)
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('%s', 'bad'); ''' % self._username) util.WaitFor(ErrorBubbleVisible, 10) self.assertTrue(self._IsScreenLocked(browser))
def EnsureScreenOn(self): """If device screen is off, turn screen on. If the screen is already on, return immediately. Raises: Timeout: If the screen is off and device fails to turn screen on. """ if self._platform_backend.IsScreenOn(): return self._ToggleScreenOn() util.WaitFor(self._platform_backend.IsScreenOn, 5)
def _NavigateIFrameLogin(self, username, password, add_user_for_testing): """Logs into the IFrame-based GAIA screen""" gaia_iframe_context = util.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 WaitForPageToLoad(obj, tab, timeout, poll_interval=0.1): """Waits for various wait conditions present in obj.""" if hasattr(obj, 'post_navigate_javascript_to_execute'): tab.EvaluateJavaScript(obj.post_navigate_javascript_to_execute) if hasattr(obj, 'wait_seconds'): time.sleep(obj.wait_seconds) if hasattr(obj, 'wait_for_element_with_text'): callback_code = 'function(element) { return element != null; }' util.WaitFor( lambda: util.FindElementAndPerformAction( tab, obj.wait_for_element_with_text, callback_code), timeout, poll_interval) if hasattr(obj, 'wait_for_element_with_selector'): util.WaitFor(lambda: tab.EvaluateJavaScript( 'document.querySelector(\'' + obj.wait_for_element_with_selector + '\') != null'), timeout, poll_interval) if hasattr(obj, 'wait_for_javascript_expression'): util.WaitFor( lambda: tab.EvaluateJavaScript(obj.wait_for_javascript_expression), timeout, poll_interval)