browser_credentials.py revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
1# Copyright 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. 4 5import json 6import logging 7import os 8 9from telemetry.core import util 10from telemetry.core.backends import facebook_credentials_backend 11from telemetry.core.backends import google_credentials_backend 12from telemetry.unittest import options_for_unittests 13 14 15class CredentialsError(Exception): 16 """Error that can be thrown when logging in.""" 17 18 19class BrowserCredentials(object): 20 def __init__(self, backends = None): 21 self._credentials = {} 22 self._credentials_path = None 23 self._extra_credentials = {} 24 25 if backends is None: 26 backends = [ 27 facebook_credentials_backend.FacebookCredentialsBackend(), 28 google_credentials_backend.GoogleCredentialsBackend()] 29 30 self._backends = {} 31 for backend in backends: 32 self._backends[backend.credentials_type] = backend 33 34 def AddBackend(self, backend): 35 assert backend.credentials_type not in self._backends 36 self._backends[backend.credentials_type] = backend 37 38 def IsLoggedIn(self, credentials_type): 39 if credentials_type not in self._backends: 40 raise CredentialsError( 41 'Unrecognized credentials type: %s', credentials_type) 42 if credentials_type not in self._credentials: 43 return False 44 return self._backends[credentials_type].IsLoggedIn() 45 46 def CanLogin(self, credentials_type): 47 if credentials_type not in self._backends: 48 raise CredentialsError( 49 'Unrecognized credentials type: %s', credentials_type) 50 return credentials_type in self._credentials 51 52 def LoginNeeded(self, tab, credentials_type): 53 if credentials_type not in self._backends: 54 raise CredentialsError( 55 'Unrecognized credentials type: %s', credentials_type) 56 if credentials_type not in self._credentials: 57 return False 58 return self._backends[credentials_type].LoginNeeded( 59 tab, self._credentials[credentials_type]) 60 61 def LoginNoLongerNeeded(self, tab, credentials_type): 62 assert credentials_type in self._backends 63 self._backends[credentials_type].LoginNoLongerNeeded(tab) 64 65 @property 66 def credentials_path(self): 67 return self._credentials_path 68 69 @credentials_path.setter 70 def credentials_path(self, credentials_path): 71 self._credentials_path = credentials_path 72 self._RebuildCredentials() 73 74 def Add(self, credentials_type, data): 75 if credentials_type not in self._extra_credentials: 76 self._extra_credentials[credentials_type] = {} 77 for k, v in data.items(): 78 assert k not in self._extra_credentials[credentials_type] 79 self._extra_credentials[credentials_type][k] = v 80 self._RebuildCredentials() 81 82 def _ResetLoggedInState(self): 83 """Makes the backends think we're not logged in even though we are. 84 Should only be used in unit tests to simulate --dont-override-profile. 85 """ 86 for backend in self._backends.keys(): 87 self._backends[backend]._ResetLoggedInState() # pylint: disable=W0212 88 89 def _RebuildCredentials(self): 90 credentials = {} 91 if self._credentials_path == None: 92 pass 93 elif os.path.exists(self._credentials_path): 94 with open(self._credentials_path, 'r') as f: 95 credentials = json.loads(f.read()) 96 97 # TODO(nduca): use system keychain, if possible. 98 homedir_credentials_path = os.path.expanduser('~/.telemetry-credentials') 99 homedir_credentials = {} 100 101 if (not options_for_unittests.GetCopy() and 102 os.path.exists(homedir_credentials_path)): 103 logging.info("Found ~/.telemetry-credentials. Its contents will be used " 104 "when no other credentials can be found.") 105 with open(homedir_credentials_path, 'r') as f: 106 homedir_credentials = json.loads(f.read()) 107 108 self._credentials = {} 109 all_keys = set(credentials.keys()).union( 110 homedir_credentials.keys()).union( 111 self._extra_credentials.keys()) 112 113 for k in all_keys: 114 if k in credentials: 115 self._credentials[k] = credentials[k] 116 if k in homedir_credentials: 117 logging.info("Will use ~/.telemetry-credentials for %s logins." % k) 118 self._credentials[k] = homedir_credentials[k] 119 if k in self._extra_credentials: 120 self._credentials[k] = self._extra_credentials[k] 121 122 def WarnIfMissingCredentials(self, page_set): 123 num_pages_missing_login = 0 124 missing_credentials = set() 125 for page in page_set: 126 if (page.credentials 127 and not self.CanLogin(page.credentials)): 128 num_pages_missing_login += 1 129 missing_credentials.add(page.credentials) 130 131 if num_pages_missing_login > 0: 132 files_to_tweak = [] 133 if page_set.credentials_path: 134 files_to_tweak.append( 135 os.path.relpath(os.path.join(os.path.dirname(page_set.file_path), 136 page_set.credentials_path))) 137 files_to_tweak.append('~/.telemetry-credentials') 138 139 example_credentials_file = os.path.join( 140 util.GetTelemetryDir(), 'examples', 'credentials_example.json') 141 142 logging.warning(""" 143 Credentials for %s were not found. %i pages will not be tested. 144 145 To fix this, either add svn-internal to your .gclient using 146 http://goto/read-src-internal, or add your own credentials to: 147 %s 148 An example credentials file you can copy from is here: 149 %s\n""" % (', '.join(missing_credentials), 150 num_pages_missing_login, 151 ' or '.join(files_to_tweak), 152 example_credentials_file)) 153