[Telemetry] Fixing credentials login behaviour in case the user is already...

[Telemetry] Fixing credentials login behaviour in case the user is already logged in and using --dont-override-profile.

Currently the page will timeout and fail if it's already logged in, since it doesn't see the login form.
I also added a warning when users specify --dont-override-profile, and a facebook_backend_unittest.py.

Note that this depends on https://codereview.chromium.org/11745002/ to work properly, since currently
the extra quotes around the user-agent string will cause us to be redirected to the wrong version of
accounts.google.com, so we won't correctly detect that we're logged in.

BUG=160268


Review URL: https://chromiumcodereview.appspot.com/11828048

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@176152 0039d316-1c4b-4281-b951-d872f2087c98
parent 832fcca9
...@@ -7,6 +7,7 @@ import httplib ...@@ -7,6 +7,7 @@ import httplib
import socket import socket
import json import json
import re import re
import sys
import weakref import weakref
from telemetry import browser_gone_exception from telemetry import browser_gone_exception
...@@ -146,6 +147,12 @@ class BrowserBackend(object): ...@@ -146,6 +147,12 @@ class BrowserBackend(object):
self._webkit_base_revision = 0 self._webkit_base_revision = 0
self._tracing_backend = None self._tracing_backend = None
if options.dont_override_profile:
sys.stderr.write('Warning: Not overriding profile. This can cause '
'unexpected effects due to profile-specific settings, '
'such as about:flags settings, cookies, and '
'extensions.\n')
def SetBrowser(self, browser): def SetBrowser(self, browser):
self.tabs = TabController(browser, self) self.tabs = TabController(browser, self)
......
...@@ -15,9 +15,13 @@ class FacebookCredentialsBackend( ...@@ -15,9 +15,13 @@ class FacebookCredentialsBackend(
return 'http://www.facebook.com/' return 'http://www.facebook.com/'
@property @property
def form_id(self): def login_form_id(self):
return 'login_form' return 'login_form'
@property
def already_logged_in_element_id(self):
return 'fbNotificationsList'
@property @property
def login_input_id(self): def login_input_id(self):
return 'email' return 'email'
......
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import unittest
from telemetry import browser_finder
from telemetry import facebook_credentials_backend
from telemetry import simple_mock
from telemetry import options_for_unittests
_ = simple_mock.DONT_CARE
class MockTab(simple_mock.MockObject):
def __init__(self):
super(MockTab, self).__init__()
self.runtime = simple_mock.MockObject(self)
self.page = simple_mock.MockObject(self)
class TestFacebookCredentialsBackend(unittest.TestCase):
def testRealLoginIfPossible(self):
credentials_path = os.path.join(
os.path.dirname(__file__),
'..', '..', 'perf', 'data', 'credentials.json')
if not os.path.exists(credentials_path):
return
options = options_for_unittests.GetCopy()
with browser_finder.FindBrowser(options).Create() as b:
b.credentials.credentials_path = credentials_path
if not b.credentials.CanLogin('facebook'):
return
ret = b.credentials.LoginNeeded(b.tabs[0], 'facebook')
self.assertTrue(ret)
def testRealLoginWithDontOverrideProfileIfPossible(self):
credentials_path = os.path.join(
os.path.dirname(__file__),
'..', '..', 'perf', 'data', 'credentials.json')
if not os.path.exists(credentials_path):
return
options = options_for_unittests.GetCopy()
options.dont_override_profile = True
# Login once to make sure our default profile is logged in.
with browser_finder.FindBrowser(options).Create() as b:
b.credentials.credentials_path = credentials_path
if not b.credentials.CanLogin('facebook'):
return
ret = b.credentials.LoginNeeded(b.tabs[0], 'facebook')
self.assertTrue(ret)
# Second time will test that we behave correctly if we're logged in,
# but our b.credentials doesn't know yet.
with browser_finder.FindBrowser(options).Create() as b:
b.credentials.credentials_path = credentials_path
if not b.credentials.CanLogin('facebook'):
return
ret = b.credentials.LoginNeeded(b.tabs[0], 'facebook')
self.assertTrue(ret)
def testLoginUsingMock(self): # pylint: disable=R0201
tab = MockTab()
backend = facebook_credentials_backend.FacebookCredentialsBackend()
config = {'username': 'blah',
'password': 'blargh'}
tab.page.ExpectCall('Navigate', 'http://www.facebook.com/')
tab.runtime.ExpectCall('Evaluate', _).WillReturn(False)
tab.runtime.ExpectCall('Evaluate', _).WillReturn(True)
tab.runtime.ExpectCall('Evaluate', _).WillReturn(False)
tab.ExpectCall('WaitForDocumentReadyStateToBeInteractiveOrBetter')
def VerifyEmail(js):
assert 'email' in js
assert 'blah' in js
tab.runtime.ExpectCall('Execute', _).WhenCalled(VerifyEmail)
def VerifyPw(js):
assert 'pass' in js
assert 'largh' in js
tab.runtime.ExpectCall('Execute', _).WhenCalled(VerifyPw)
def VerifySubmit(js):
assert '.submit' in js
tab.runtime.ExpectCall('Execute', _).WhenCalled(VerifySubmit)
# Checking for form still up.
tab.runtime.ExpectCall('Evaluate', _).WillReturn(False)
backend.LoginNeeded(tab, config)
...@@ -7,13 +7,21 @@ import logging ...@@ -7,13 +7,21 @@ import logging
import telemetry import telemetry
from telemetry import util from telemetry import util
def _WaitForFormToLoad(form_id, tab):
def IsFormLoaded(): def _IsAlreadyLoggedIn(already_logged_in_element_id, tab):
return tab.runtime.Evaluate(
'document.getElementById("%s")!== null' % \
already_logged_in_element_id)
def _WaitForLoginFormToLoad(login_form_id, already_logged_in_element_id, tab):
def IsFormLoadedOrAlreadyLoggedIn():
return tab.runtime.Evaluate( return tab.runtime.Evaluate(
'document.querySelector("#%s")!== null' % form_id) 'document.querySelector("#%s")!== null' % login_form_id) or \
_IsAlreadyLoggedIn(already_logged_in_element_id, tab)
# Wait until the form is submitted and the page completes loading. # Wait until the form is submitted and the page completes loading.
util.WaitFor(lambda: IsFormLoaded(), 60) # pylint: disable=W0108 util.WaitFor(lambda: IsFormLoadedOrAlreadyLoggedIn(), # pylint: disable=W0108
60)
def _SubmitFormAndWait(form_id, tab): def _SubmitFormAndWait(form_id, tab):
js = 'document.getElementById("%s").submit();' % form_id js = 'document.getElementById("%s").submit();' % form_id
...@@ -39,13 +47,17 @@ class FormBasedCredentialsBackend(object): ...@@ -39,13 +47,17 @@ class FormBasedCredentialsBackend(object):
raise NotImplementedError() raise NotImplementedError()
@property @property
def form_id(self): def login_form_id(self):
raise NotImplementedError() raise NotImplementedError()
@property @property
def login_input_id(self): def login_input_id(self):
raise NotImplementedError() raise NotImplementedError()
@property
def already_logged_in_element_id(self):
raise NotImplementedError()
@property @property
def password_input_id(self): def password_input_id(self):
raise NotImplementedError() raise NotImplementedError()
...@@ -69,7 +81,14 @@ class FormBasedCredentialsBackend(object): ...@@ -69,7 +81,14 @@ class FormBasedCredentialsBackend(object):
try: try:
logging.info('Loading %s...', self.url) logging.info('Loading %s...', self.url)
tab.page.Navigate(self.url) tab.page.Navigate(self.url)
_WaitForFormToLoad(self.form_id, tab) _WaitForLoginFormToLoad(self.login_form_id,
self.already_logged_in_element_id,
tab)
if _IsAlreadyLoggedIn(self.already_logged_in_element_id, tab):
self._logged_in = True
return True
tab.WaitForDocumentReadyStateToBeInteractiveOrBetter() tab.WaitForDocumentReadyStateToBeInteractiveOrBetter()
logging.info('Loaded page: %s', self.url) logging.info('Loaded page: %s', self.url)
...@@ -80,7 +99,7 @@ class FormBasedCredentialsBackend(object): ...@@ -80,7 +99,7 @@ class FormBasedCredentialsBackend(object):
tab.runtime.Execute(email_id) tab.runtime.Execute(email_id)
tab.runtime.Execute(password) tab.runtime.Execute(password)
_SubmitFormAndWait(self.form_id, tab) _SubmitFormAndWait(self.login_form_id, tab)
self._logged_in = True self._logged_in = True
return True return True
......
...@@ -15,9 +15,13 @@ class GoogleCredentialsBackend( ...@@ -15,9 +15,13 @@ class GoogleCredentialsBackend(
return 'https://accounts.google.com/' return 'https://accounts.google.com/'
@property @property
def form_id(self): def login_form_id(self):
return 'gaia_loginform' return 'gaia_loginform'
@property
def already_logged_in_element_id(self):
return 'gb'
@property @property
def login_input_id(self): def login_input_id(self):
return 'Email' return 'Email'
......
...@@ -33,6 +33,33 @@ class TestGoogleCredentialsBackend(unittest.TestCase): ...@@ -33,6 +33,33 @@ class TestGoogleCredentialsBackend(unittest.TestCase):
ret = b.credentials.LoginNeeded(b.tabs[0], 'google') ret = b.credentials.LoginNeeded(b.tabs[0], 'google')
self.assertTrue(ret) self.assertTrue(ret)
def testRealLoginWithDontOverrideProfileIfPossible(self):
credentials_path = os.path.join(
os.path.dirname(__file__),
'..', '..', 'perf', 'data', 'credentials.json')
if not os.path.exists(credentials_path):
return
options = options_for_unittests.GetCopy()
options.dont_override_profile = True
# Login once to make sure our default profile is logged in.
with browser_finder.FindBrowser(options).Create() as b:
b.credentials.credentials_path = credentials_path
if not b.credentials.CanLogin('google'):
return
ret = b.credentials.LoginNeeded(b.tabs[0], 'google')
self.assertTrue(ret)
# Second time will test that we behave correctly if we're logged in,
# but our b.credentials doesn't know yet.
with browser_finder.FindBrowser(options).Create() as b:
b.credentials.credentials_path = credentials_path
if not b.credentials.CanLogin('google'):
return
ret = b.credentials.LoginNeeded(b.tabs[0], 'google')
self.assertTrue(ret)
def testLoginUsingMock(self): # pylint: disable=R0201 def testLoginUsingMock(self): # pylint: disable=R0201
tab = MockTab() tab = MockTab()
...@@ -43,6 +70,7 @@ class TestGoogleCredentialsBackend(unittest.TestCase): ...@@ -43,6 +70,7 @@ class TestGoogleCredentialsBackend(unittest.TestCase):
tab.page.ExpectCall('Navigate', 'https://accounts.google.com/') tab.page.ExpectCall('Navigate', 'https://accounts.google.com/')
tab.runtime.ExpectCall('Evaluate', _).WillReturn(False) tab.runtime.ExpectCall('Evaluate', _).WillReturn(False)
tab.runtime.ExpectCall('Evaluate', _).WillReturn(True) tab.runtime.ExpectCall('Evaluate', _).WillReturn(True)
tab.runtime.ExpectCall('Evaluate', _).WillReturn(False)
tab.ExpectCall('WaitForDocumentReadyStateToBeInteractiveOrBetter') tab.ExpectCall('WaitForDocumentReadyStateToBeInteractiveOrBetter')
def VerifyEmail(js): def VerifyEmail(js):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment