form_based_credentials_backend.py revision 424c4d7b64af9d0d8fd9624f381f469654d5e3d2
1424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import logging
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.core import util
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def _WaitForLoginFormToLoad(backend, login_form_id, tab):
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def IsFormLoadedOrAlreadyLoggedIn():
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return tab.EvaluateJavaScript(
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        'document.querySelector("#%s")!== null' % login_form_id) or \
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            backend.IsAlreadyLoggedIn(tab)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Wait until the form is submitted and the page completes loading.
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  util.WaitFor(lambda: IsFormLoadedOrAlreadyLoggedIn(), # pylint: disable=W0108
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               60)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def _SubmitFormAndWait(form_id, tab):
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  js = 'document.getElementById("%s").submit();' % form_id
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tab.ExecuteJavaScript(js)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def IsLoginStillHappening():
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return tab.EvaluateJavaScript(
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'document.querySelector("#%s")!== null' % form_id)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Wait until the form is submitted and the page completes loading.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  util.WaitFor(lambda: not IsLoginStillHappening(), 60)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FormBasedCredentialsBackend(object):
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self):
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._logged_in = False
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def IsAlreadyLoggedIn(self, tab):
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    raise NotImplementedError()
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  @property
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def credentials_type(self):
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError()
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  @property
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def url(self):
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError()
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  @property
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def login_form_id(self):
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError()
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  @property
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def login_input_id(self):
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError()
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  @property
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def password_input_id(self):
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError()
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def IsLoggedIn(self):
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return self._logged_in
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def _ResetLoggedInState(self):
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Makes the backend think we're not logged in even though we are.
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Should only be used in unit tests to simulate --dont-override-profile.
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._logged_in = False
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def LoginNeeded(self, tab, config):
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Logs in to a test account.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Raises:
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RuntimeError: if could not get credential information.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if self._logged_in:
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return True
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if 'username' not in config or 'password' not in config:
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      message = ('Credentials for "%s" must include username and password.' %
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 self.credentials_type)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise RuntimeError(message)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    logging.debug('Logging into %s account...' % self.credentials_type)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    try:
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      logging.info('Loading %s...', self.url)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tab.Navigate(self.url)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      _WaitForLoginFormToLoad(self, self.login_form_id, tab)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if self.IsAlreadyLoggedIn(tab):
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self._logged_in = True
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return True
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab.WaitForDocumentReadyStateToBeInteractiveOrBetter()
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      logging.info('Loaded page: %s', self.url)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      email_id = 'document.querySelector("#%s").%s.value = "%s"; ' % (
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          self.login_form_id, self.login_input_id, config['username'])
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      password = 'document.querySelector("#%s").%s.value = "%s"; ' % (
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          self.login_form_id, self.password_input_id, config['password'])
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tab.ExecuteJavaScript(email_id)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tab.ExecuteJavaScript(password)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      _SubmitFormAndWait(self.login_form_id, tab)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self._logged_in = True
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return True
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    except util.TimeoutException:
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      logging.warning('Timed out while loading: %s', self.url)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return False
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def LoginNoLongerNeeded(self, tab): # pylint: disable=W0613
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert self._logged_in
111