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