1# Copyright 2013 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(IsFormLoadedOrAlreadyLoggedIn, 60) 17 18def _SubmitFormAndWait(form_id, tab): 19 tab.ExecuteJavaScript( 20 'document.getElementById("%s").submit();' % form_id) 21 22 def FinishedLoading(): 23 return not tab.EvaluateJavaScript( 24 'document.querySelector("#%s") !== null' % form_id) 25 26 # Wait until the form is submitted and the page completes loading. 27 util.WaitFor(FinishedLoading, 60) 28 29class FormBasedCredentialsBackend(object): 30 def __init__(self): 31 self._logged_in = False 32 33 def IsAlreadyLoggedIn(self, tab): 34 raise NotImplementedError() 35 36 @property 37 def credentials_type(self): 38 raise NotImplementedError() 39 40 @property 41 def url(self): 42 raise NotImplementedError() 43 44 @property 45 def login_form_id(self): 46 raise NotImplementedError() 47 48 @property 49 def login_input_id(self): 50 raise NotImplementedError() 51 52 @property 53 def password_input_id(self): 54 raise NotImplementedError() 55 56 def IsLoggedIn(self): 57 return self._logged_in 58 59 def _ResetLoggedInState(self): 60 """Makes the backend think we're not logged in even though we are. 61 Should only be used in unit tests to simulate --dont-override-profile. 62 """ 63 self._logged_in = False 64 65 def LoginNeeded(self, tab, config): 66 """Logs in to a test account. 67 68 Raises: 69 RuntimeError: if could not get credential information. 70 """ 71 if self._logged_in: 72 return True 73 74 if 'username' not in config or 'password' not in config: 75 message = ('Credentials for "%s" must include username and password.' % 76 self.credentials_type) 77 raise RuntimeError(message) 78 79 logging.debug('Logging into %s account...' % self.credentials_type) 80 81 if 'url' in config: 82 url = config['url'] 83 else: 84 url = self.url 85 86 try: 87 logging.info('Loading %s...', url) 88 tab.Navigate(url) 89 _WaitForLoginFormToLoad(self, self.login_form_id, tab) 90 91 if self.IsAlreadyLoggedIn(tab): 92 self._logged_in = True 93 return True 94 95 tab.WaitForDocumentReadyStateToBeInteractiveOrBetter() 96 logging.info('Loaded page: %s', url) 97 98 email_id = 'document.querySelector("#%s").%s.value = "%s"; ' % ( 99 self.login_form_id, self.login_input_id, config['username']) 100 password = 'document.querySelector("#%s").%s.value = "%s"; ' % ( 101 self.login_form_id, self.password_input_id, config['password']) 102 tab.ExecuteJavaScript(email_id) 103 tab.ExecuteJavaScript(password) 104 105 _SubmitFormAndWait(self.login_form_id, tab) 106 107 self._logged_in = True 108 return True 109 except util.TimeoutException: 110 logging.warning('Timed out while loading: %s', url) 111 return False 112 113 def LoginNoLongerNeeded(self, tab): # pylint: disable=W0613 114 assert self._logged_in 115