1# Copyright (c) 2012 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4import logging 5 6from telemetry.core import util 7 8 9def _WaitForLoginFormToLoad(backend, login_form_id, tab): 10 def IsFormLoadedOrAlreadyLoggedIn(): 11 return tab.EvaluateJavaScript( 12 'document.querySelector("#%s")!== null' % login_form_id) or \ 13 backend.IsAlreadyLoggedIn(tab) 14 15 # Wait until the form is submitted and the page completes loading. 16 util.WaitFor(lambda: IsFormLoadedOrAlreadyLoggedIn(), # pylint: disable=W0108 17 60) 18 19def _SubmitFormAndWait(form_id, tab): 20 js = 'document.getElementById("%s").submit();' % form_id 21 tab.ExecuteJavaScript(js) 22 23 def IsLoginStillHappening(): 24 return tab.EvaluateJavaScript( 25 'document.querySelector("#%s")!== null' % form_id) 26 27 # Wait until the form is submitted and the page completes loading. 28 util.WaitFor(lambda: not IsLoginStillHappening(), 60) 29 30class FormBasedCredentialsBackend(object): 31 def __init__(self): 32 self._logged_in = False 33 34 def IsAlreadyLoggedIn(self, tab): 35 raise NotImplementedError() 36 37 @property 38 def credentials_type(self): 39 raise NotImplementedError() 40 41 @property 42 def url(self): 43 raise NotImplementedError() 44 45 @property 46 def login_form_id(self): 47 raise NotImplementedError() 48 49 @property 50 def login_input_id(self): 51 raise NotImplementedError() 52 53 @property 54 def password_input_id(self): 55 raise NotImplementedError() 56 57 def IsLoggedIn(self): 58 return self._logged_in 59 60 def _ResetLoggedInState(self): 61 """Makes the backend think we're not logged in even though we are. 62 Should only be used in unit tests to simulate --dont-override-profile. 63 """ 64 self._logged_in = False 65 66 def LoginNeeded(self, tab, config): 67 """Logs in to a test account. 68 69 Raises: 70 RuntimeError: if could not get credential information. 71 """ 72 if self._logged_in: 73 return True 74 75 if 'username' not in config or 'password' not in config: 76 message = ('Credentials for "%s" must include username and password.' % 77 self.credentials_type) 78 raise RuntimeError(message) 79 80 logging.debug('Logging into %s account...' % self.credentials_type) 81 82 try: 83 logging.info('Loading %s...', self.url) 84 tab.Navigate(self.url) 85 _WaitForLoginFormToLoad(self, self.login_form_id, tab) 86 87 if self.IsAlreadyLoggedIn(tab): 88 self._logged_in = True 89 return True 90 91 tab.WaitForDocumentReadyStateToBeInteractiveOrBetter() 92 logging.info('Loaded page: %s', self.url) 93 94 email_id = 'document.querySelector("#%s").%s.value = "%s"; ' % ( 95 self.login_form_id, self.login_input_id, config['username']) 96 password = 'document.querySelector("#%s").%s.value = "%s"; ' % ( 97 self.login_form_id, self.password_input_id, config['password']) 98 tab.ExecuteJavaScript(email_id) 99 tab.ExecuteJavaScript(password) 100 101 _SubmitFormAndWait(self.login_form_id, tab) 102 103 self._logged_in = True 104 return True 105 except util.TimeoutException: 106 logging.warning('Timed out while loading: %s', self.url) 107 return False 108 109 def LoginNoLongerNeeded(self, tab): # pylint: disable=W0613 110 assert self._logged_in 111