browser_credentials.py revision 3551c9c881056c480085172ff9840cab31610854
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 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)import json 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 83551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)from telemetry.core import util 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.core.chrome import facebook_credentials_backend 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.core.chrome import google_credentials_backend 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)from telemetry.unittest import options_for_unittests 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BrowserCredentials(object): 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self, backends = None): 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._credentials = {} 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._credentials_path = None 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._extra_credentials = {} 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if backends is None: 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backends = [ 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) facebook_credentials_backend.FacebookCredentialsBackend(), 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) google_credentials_backend.GoogleCredentialsBackend()] 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._backends = {} 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for backend in backends: 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._backends[backend.credentials_type] = backend 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def AddBackend(self, backend): 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert backend.credentials_type not in self._backends 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._backends[backend.credentials_type] = backend 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def IsLoggedIn(self, credentials_type): 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if credentials_type not in self._backends: 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) raise Exception('Unrecognized credentials type: %s', credentials_type) 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if credentials_type not in self._credentials: 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return False 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return self._backends[credentials_type].IsLoggedIn() 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def CanLogin(self, credentials_type): 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if credentials_type not in self._backends: 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise Exception('Unrecognized credentials type: %s', credentials_type) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return credentials_type in self._credentials 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def LoginNeeded(self, tab, credentials_type): 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if credentials_type not in self._backends: 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise Exception('Unrecognized credentials type: %s', credentials_type) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if credentials_type not in self._credentials: 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return False 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self._backends[credentials_type].LoginNeeded( 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab, self._credentials[credentials_type]) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def LoginNoLongerNeeded(self, tab, credentials_type): 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert credentials_type in self._backends 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._backends[credentials_type].LoginNoLongerNeeded(tab) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @property 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def credentials_path(self): 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self._credentials_path 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @credentials_path.setter 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def credentials_path(self, credentials_path): 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._credentials_path = credentials_path 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._RebuildCredentials() 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Add(self, credentials_type, data): 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if credentials_type not in self._extra_credentials: 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._extra_credentials[credentials_type] = {} 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for k, v in data.items(): 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert k not in self._extra_credentials[credentials_type] 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._extra_credentials[credentials_type][k] = v 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._RebuildCredentials() 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def _ResetLoggedInState(self): 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Makes the backends think we're not logged in even though we are. 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Should only be used in unit tests to simulate --dont-override-profile. 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """ 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for backend in self._backends.keys(): 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._backends[backend]._ResetLoggedInState() # pylint: disable=W0212 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def _RebuildCredentials(self): 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) credentials = {} 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self._credentials_path == None: 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pass 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif os.path.exists(self._credentials_path): 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) with open(self._credentials_path, 'r') as f: 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) credentials = json.loads(f.read()) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # TODO(nduca): use system keychain, if possible. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) homedir_credentials_path = os.path.expanduser('~/.telemetry-credentials') 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) homedir_credentials = {} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (not options_for_unittests.GetCopy() and 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.path.exists(homedir_credentials_path)): 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("Found ~/.telemetry-credentials. Its contents will be used " 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "when no other credentials can be found.") 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) with open(homedir_credentials_path, 'r') as f: 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) homedir_credentials = json.loads(f.read()) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._credentials = {} 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) all_keys = set(credentials.keys()).union( 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) homedir_credentials.keys()).union( 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._extra_credentials.keys()) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for k in all_keys: 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if k in credentials: 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._credentials[k] = credentials[k] 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if k in homedir_credentials: 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("Will use ~/.telemetry-credentials for %s logins." % k) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._credentials[k] = homedir_credentials[k] 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if k in self._extra_credentials: 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._credentials[k] = self._extra_credentials[k] 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def WarnIfMissingCredentials(self, page_set): 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_pages_missing_login = 0 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) missing_credentials = set() 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for page in page_set: 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (page.credentials 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) and not self.CanLogin(page.credentials)): 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_pages_missing_login += 1 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) missing_credentials.add(page.credentials) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if num_pages_missing_login > 0: 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) files_to_tweak = [] 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if page_set.credentials_path: 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) files_to_tweak.append( 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) os.path.relpath(os.path.join(os.path.dirname(page_set.file_path), 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) page_set.credentials_path))) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) files_to_tweak.append('~/.telemetry-credentials') 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) example_credentials_file = os.path.join( 1313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) util.GetTelemetryDir(), 'examples', 'credentials_example.json') 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.warning(""" 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Credentials for %s were not found. %i pages will not be tested. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) To fix this, either add svn-internal to your .gclient using 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http://goto/read-src-internal, or add your own credentials to: 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) %s 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) An example credentials file you can copy from is here: 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) %s\n""" % (', '.join(missing_credentials), 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_pages_missing_login, 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ' or '.join(files_to_tweak), 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) example_credentials_file)) 144