chrome.py revision ef243fecf5fa3634efc0191aa44f59ecd4641d90
1# Copyright (c) 2013 The Chromium OS 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 inspect, logging, os 6 7from telemetry.core import browser_finder, browser_options, exceptions 8from telemetry.core import extension_to_load, util 9 10 11class Chrome(object): 12 """Wrapper for creating a telemetry browser instance with extensions.""" 13 14 15 BROWSER_TYPE_LOGIN = 'system' 16 BROWSER_TYPE_GUEST = 'system-guest' 17 18 19 def __init__(self, logged_in=True, extension_paths=[], autotest_ext=False, 20 is_component=True, num_tries=3, extra_browser_args=None, 21 clear_enterprise_policy=True, dont_override_profile=False, 22 disable_gaia_services=True, auto_login=True, gaia_login=False, 23 username=None, password=None): 24 """ 25 Constructor of telemetry wrapper. 26 27 @param logged_in: Regular user (True) or guest user (False). 28 @param extension_paths: path of unpacked extension to install. 29 @param autotest_ext: Load a component extension with privileges to 30 invoke chrome.autotestPrivate. 31 @param is_component: Whether extensions should be loaded as component 32 extensions. 33 @param num_tries: Number of attempts to log in. 34 @param extra_browser_args: Additional argument(s) to pass to the 35 browser. It can be a string or a list. 36 @param clear_enterprise_policy: Clear enterprise policy before 37 logging in. 38 @param dont_override_profile: Don't delete cryptohome before login. 39 Telemetry will output a warning with this 40 option. 41 @param disable_gaia_services: For enterprise autotests, this option may 42 be used to enable policy fetch. 43 @param auto_login: Does not login automatically if this is False. 44 Useful if you need to examine oobe. 45 @param gaia_login: Logs in to real gaia. 46 @param username: Log in using this username instead of the default. 47 @param username: Log in using this password instead of the default. 48 """ 49 self._autotest_ext_path = None 50 if autotest_ext: 51 self._autotest_ext_path = os.path.join(os.path.dirname(__file__), 52 'autotest_private_ext') 53 extension_paths.append(self._autotest_ext_path) 54 55 finder_options = browser_options.BrowserFinderOptions() 56 self._browser_type = (self.BROWSER_TYPE_LOGIN 57 if logged_in else self.BROWSER_TYPE_GUEST) 58 finder_options.browser_type = self.browser_type 59 if extra_browser_args: 60 finder_options.browser_options.AppendExtraBrowserArgs( 61 extra_browser_args) 62 63 if logged_in: 64 extensions_to_load = finder_options.extensions_to_load 65 for path in extension_paths: 66 extension = extension_to_load.ExtensionToLoad( 67 path, self.browser_type, is_component=is_component) 68 extensions_to_load.append(extension) 69 self._extensions_to_load = extensions_to_load 70 71 # finder options must be set before parse_args(), browser options must 72 # be set before Create(). 73 # TODO(crbug.com/360890) Below MUST be '2' so that it doesn't inhibit 74 # autotest debug logs 75 finder_options.verbosity = 2 76 finder_options.CreateParser().parse_args(args=[]) 77 b_options = finder_options.browser_options 78 b_options.disable_component_extensions_with_background_pages = False 79 b_options.create_browser_with_oobe = True 80 b_options.clear_enterprise_policy = clear_enterprise_policy 81 b_options.dont_override_profile = dont_override_profile 82 b_options.disable_gaia_services = disable_gaia_services 83 b_options.disable_default_apps = False 84 85 b_options.auto_login = auto_login 86 b_options.gaia_login = gaia_login 87 self.username = b_options.username if username is None else username 88 self.password = b_options.password if password is None else password 89 b_options.username = self.username 90 b_options.password = self.password 91 92 for i in range(num_tries): 93 try: 94 browser_to_create = browser_finder.FindBrowser(finder_options) 95 # TODO(achuith): Remove inspect and old Create call. 96 # crbug.com/428967. 97 if len(inspect.getargspec(browser_to_create.Create).args) == 1: 98 self._browser = browser_to_create.Create() 99 else: 100 self._browser = browser_to_create.Create(finder_options) 101 break 102 except (util.TimeoutException, exceptions.LoginException) as e: 103 logging.error('Timed out logging in, tries=%d, error=%s', 104 i, repr(e)) 105 if i == num_tries-1: 106 raise 107 108 109 def __enter__(self): 110 return self 111 112 113 def __exit__(self, *args): 114 self.close() 115 116 117 @property 118 def browser(self): 119 """Returns a telemetry browser instance.""" 120 return self._browser 121 122 123 def get_extension(self, extension_path): 124 """Fetches a telemetry extension instance given the extension path.""" 125 for ext in self._extensions_to_load: 126 if extension_path == ext.path: 127 return self.browser.extensions[ext] 128 return None 129 130 131 @property 132 def autotest_ext(self): 133 """Returns the autotest extension.""" 134 return self.get_extension(self._autotest_ext_path) 135 136 137 @property 138 def login_status(self): 139 """Returns login status.""" 140 ext = self.autotest_ext 141 if not ext: 142 return None 143 144 ext.ExecuteJavaScript(''' 145 window.__login_status = null; 146 chrome.autotestPrivate.loginStatus(function(s) { 147 window.__login_status = s; 148 }); 149 ''') 150 return ext.EvaluateJavaScript('window.__login_status') 151 152 153 @property 154 def browser_type(self): 155 """Returns the browser_type.""" 156 return self._browser_type 157 158 159 def wait_for_browser_to_come_up(self): 160 """Waits for the browser to come up. This should only be called after a 161 browser crash. 162 """ 163 def _BrowserReady(cr): 164 try: 165 tab = cr.browser.tabs.New() 166 except (exceptions.BrowserGoneException, 167 exceptions.BrowserConnectionGoneException): 168 return False 169 try: 170 tab.Close() 171 except (util.TimeoutException): 172 # crbug.com/350941 173 logging.error('Timed out closing tab') 174 return True 175 util.WaitFor(lambda: _BrowserReady(self), timeout=10) 176 177 178 def did_browser_crash(self, func): 179 """Runs func, returns True if the browser crashed, False otherwise. 180 181 @param func: function to run. 182 183 """ 184 try: 185 func() 186 except (exceptions.BrowserGoneException, 187 exceptions.BrowserConnectionGoneException): 188 return True 189 return False 190 191 192 def close(self): 193 """Closes the browser.""" 194 self._browser.Close() 195