1*9c5db199SXin Li# Lint as: python2, python3 2*9c5db199SXin Li# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 3*9c5db199SXin Li# Use of this source code is governed by a BSD-style license that can be 4*9c5db199SXin Li# found in the LICENSE file. 5*9c5db199SXin Li 6*9c5db199SXin Lifrom __future__ import absolute_import 7*9c5db199SXin Lifrom __future__ import division 8*9c5db199SXin Lifrom __future__ import print_function 9*9c5db199SXin Li 10*9c5db199SXin Liimport logging 11*9c5db199SXin Liimport os 12*9c5db199SXin Liimport re 13*9c5db199SXin Li 14*9c5db199SXin Lifrom autotest_lib.client.common_lib.cros import arc_common 15*9c5db199SXin Lifrom autotest_lib.client.common_lib.cros import arc_util 16*9c5db199SXin Lifrom autotest_lib.client.common_lib.cros import assistant_util 17*9c5db199SXin Lifrom autotest_lib.client.cros import constants 18*9c5db199SXin Lifrom autotest_lib.client.bin import utils 19*9c5db199SXin Lifrom six.moves import range 20*9c5db199SXin Lifrom telemetry.core import cros_interface, exceptions 21*9c5db199SXin Lifrom telemetry.internal.browser import browser_finder, browser_options 22*9c5db199SXin Lifrom telemetry.internal.browser import extension_to_load 23*9c5db199SXin Li 24*9c5db199SXin Liimport py_utils 25*9c5db199SXin Li 26*9c5db199SXin LiError = exceptions.Error 27*9c5db199SXin Li 28*9c5db199SXin Li 29*9c5db199SXin Lidef NormalizeEmail(username): 30*9c5db199SXin Li """Remove dots from username. Add @gmail.com if necessary. 31*9c5db199SXin Li 32*9c5db199SXin Li TODO(achuith): Get rid of this when crbug.com/358427 is fixed. 33*9c5db199SXin Li 34*9c5db199SXin Li @param username: username/email to be scrubbed. 35*9c5db199SXin Li """ 36*9c5db199SXin Li parts = re.split('@', username) 37*9c5db199SXin Li parts[0] = re.sub('\.', '', parts[0]) 38*9c5db199SXin Li 39*9c5db199SXin Li if len(parts) == 1: 40*9c5db199SXin Li parts.append('gmail.com') 41*9c5db199SXin Li return '@'.join(parts) 42*9c5db199SXin Li 43*9c5db199SXin Li 44*9c5db199SXin Liclass Chrome(object): 45*9c5db199SXin Li """Wrapper for creating a telemetry browser instance with extensions. 46*9c5db199SXin Li 47*9c5db199SXin Li The recommended way to use this class is to create the instance using the 48*9c5db199SXin Li with statement: 49*9c5db199SXin Li 50*9c5db199SXin Li >>> with chrome.Chrome(...) as cr: 51*9c5db199SXin Li >>> # Do whatever you need with cr. 52*9c5db199SXin Li >>> pass 53*9c5db199SXin Li 54*9c5db199SXin Li This will make sure all the clean-up functions are called. If you really 55*9c5db199SXin Li need to use this class without the with statement, make sure to call the 56*9c5db199SXin Li close() method once you're done with the Chrome instance. 57*9c5db199SXin Li """ 58*9c5db199SXin Li 59*9c5db199SXin Li BROWSER_TYPE_LOGIN = 'system' 60*9c5db199SXin Li BROWSER_TYPE_GUEST = 'system-guest' 61*9c5db199SXin Li AUTOTEST_EXT_ID = 'behllobkkfkfnphdnhnkndlbkcpglgmj' 62*9c5db199SXin Li 63*9c5db199SXin Li def __init__(self, 64*9c5db199SXin Li logged_in=True, 65*9c5db199SXin Li extension_paths=None, 66*9c5db199SXin Li autotest_ext=False, 67*9c5db199SXin Li num_tries=3, 68*9c5db199SXin Li extra_browser_args=None, 69*9c5db199SXin Li clear_enterprise_policy=True, 70*9c5db199SXin Li expect_policy_fetch=False, 71*9c5db199SXin Li dont_override_profile=False, 72*9c5db199SXin Li disable_gaia_services=True, 73*9c5db199SXin Li disable_default_apps=True, 74*9c5db199SXin Li auto_login=True, 75*9c5db199SXin Li gaia_login=False, 76*9c5db199SXin Li username=None, 77*9c5db199SXin Li password=None, 78*9c5db199SXin Li gaia_id=None, 79*9c5db199SXin Li arc_mode=None, 80*9c5db199SXin Li arc_timeout=None, 81*9c5db199SXin Li enable_web_app_auto_install=False, 82*9c5db199SXin Li disable_arc_opt_in=True, 83*9c5db199SXin Li disable_arc_opt_in_verification=True, 84*9c5db199SXin Li disable_arc_cpu_restriction=True, 85*9c5db199SXin Li disable_app_sync=False, 86*9c5db199SXin Li disable_play_auto_install=False, 87*9c5db199SXin Li disable_locale_sync=True, 88*9c5db199SXin Li disable_play_store_auto_update=True, 89*9c5db199SXin Li enable_assistant=False, 90*9c5db199SXin Li enterprise_arc_test=False, 91*9c5db199SXin Li init_network_controller=False, 92*9c5db199SXin Li mute_audio=False, 93*9c5db199SXin Li proxy_server=None, 94*9c5db199SXin Li login_delay=0, 95*9c5db199SXin Li enable_features=None): 96*9c5db199SXin Li """ 97*9c5db199SXin Li Constructor of telemetry wrapper. 98*9c5db199SXin Li 99*9c5db199SXin Li @param logged_in: Regular user (True) or guest user (False). 100*9c5db199SXin Li @param extension_paths: path of unpacked extension to install. 101*9c5db199SXin Li @param autotest_ext: Load a component extension with privileges to 102*9c5db199SXin Li invoke chrome.autotestPrivate. 103*9c5db199SXin Li @param num_tries: Number of attempts to log in. 104*9c5db199SXin Li @param extra_browser_args: Additional argument(s) to pass to the 105*9c5db199SXin Li browser. It can be a string or a list. 106*9c5db199SXin Li @param clear_enterprise_policy: Clear enterprise policy before 107*9c5db199SXin Li logging in. 108*9c5db199SXin Li @param expect_policy_fetch: Expect that chrome can reach the device 109*9c5db199SXin Li management server and download policy. 110*9c5db199SXin Li @param dont_override_profile: Don't delete cryptohome before login. 111*9c5db199SXin Li Telemetry will output a warning with this 112*9c5db199SXin Li option. 113*9c5db199SXin Li @param disable_gaia_services: For enterprise autotests, this option may 114*9c5db199SXin Li be used to enable policy fetch. 115*9c5db199SXin Li @param disable_default_apps: For tests that exercise default apps. 116*9c5db199SXin Li @param auto_login: Does not login automatically if this is False. 117*9c5db199SXin Li Useful if you need to examine oobe. 118*9c5db199SXin Li @param gaia_login: Logs in to real gaia. 119*9c5db199SXin Li @param username: Log in using this username instead of the default. 120*9c5db199SXin Li @param password: Log in using this password instead of the default. 121*9c5db199SXin Li @param gaia_id: Log in using this gaia_id instead of the default. 122*9c5db199SXin Li @param arc_mode: How ARC instance should be started. Default is to not 123*9c5db199SXin Li start. 124*9c5db199SXin Li @param arc_timeout: Timeout to wait for ARC to boot. 125*9c5db199SXin Li @param enable_web_app_auto_install: For tests that require to auto download and install default web applications. By default it is disabled. 126*9c5db199SXin Li @param disable_arc_opt_in: For opt in flow autotest. This option is used 127*9c5db199SXin Li to disable the arc opt in flow. 128*9c5db199SXin Li @param disable_arc_opt_in_verification: 129*9c5db199SXin Li Adds --disable-arc-opt-in-verification to browser args. This should 130*9c5db199SXin Li generally be enabled when disable_arc_opt_in is enabled. However, 131*9c5db199SXin Li for data migration tests where user's home data is already set up 132*9c5db199SXin Li with opted-in state before login, this option needs to be set to 133*9c5db199SXin Li False with disable_arc_opt_in=True to make ARC container work. 134*9c5db199SXin Li @param disable_arc_cpu_restriction: 135*9c5db199SXin Li Adds --disable-arc-cpu-restriction to browser args. This is enabled 136*9c5db199SXin Li by default and will make tests run faster and is generally 137*9c5db199SXin Li desirable unless a test is actually trying to test performance 138*9c5db199SXin Li where ARC is running in the background for some porition of the 139*9c5db199SXin Li test. 140*9c5db199SXin Li @param disable_app_sync: 141*9c5db199SXin Li Adds --arc-disable-app-sync to browser args and this disables ARC 142*9c5db199SXin Li app sync flow. By default it is enabled. 143*9c5db199SXin Li @param disable_play_auto_install: 144*9c5db199SXin Li Adds --arc-disable-play-auto-install to browser args and this 145*9c5db199SXin Li disables ARC Play Auto Install flow. By default it is enabled. 146*9c5db199SXin Li @param enable_assistant: For tests that require to enable Google 147*9c5db199SXin Li Assistant service. Default is False. 148*9c5db199SXin Li @param enterprise_arc_test: Skips opt_in causing enterprise tests to fail 149*9c5db199SXin Li @param disable_locale_sync: 150*9c5db199SXin Li Adds --arc-disable-locale-sync to browser args and this 151*9c5db199SXin Li disables locale sync between Chrome and Android container. In case 152*9c5db199SXin Li of disabling sync, Android container is started with language and 153*9c5db199SXin Li preference language list as it was set on the moment of starting 154*9c5db199SXin Li full instance. Used to prevent random app restarts caused by racy 155*9c5db199SXin Li locale change, coming from profile sync. By default locale sync is 156*9c5db199SXin Li disabled. 157*9c5db199SXin Li @param disable_play_store_auto_update: 158*9c5db199SXin Li Adds --arc-play-store-auto-update=off to browser args and this 159*9c5db199SXin Li disables Play Store, GMS Core and third-party apps auto-update. 160*9c5db199SXin Li By default auto-update is off to have stable autotest environment. 161*9c5db199SXin Li @param mute_audio: Mute audio. 162*9c5db199SXin Li @param proxy_server: To launch the chrome with --proxy-server 163*9c5db199SXin Li Adds '--proxy-server="http://$HTTP_PROXY:PORT"' to browser args. By 164*9c5db199SXin Li default proxy-server is disabled 165*9c5db199SXin Li @param login_delay: Time for idle in login screen to simulate the time 166*9c5db199SXin Li required for password typing. 167*9c5db199SXin Li @param enable_features: Comma separated list of features to enable. 168*9c5db199SXin Li """ 169*9c5db199SXin Li self._autotest_ext_path = None 170*9c5db199SXin Li 171*9c5db199SXin Li # Force autotest extension if we need enable Play Store. 172*9c5db199SXin Li if (utils.is_arc_available() and (arc_util.should_start_arc(arc_mode) 173*9c5db199SXin Li or not disable_arc_opt_in)): 174*9c5db199SXin Li autotest_ext = True 175*9c5db199SXin Li 176*9c5db199SXin Li if extension_paths is None: 177*9c5db199SXin Li extension_paths = [] 178*9c5db199SXin Li 179*9c5db199SXin Li finder_options = browser_options.BrowserFinderOptions() 180*9c5db199SXin Li if proxy_server: 181*9c5db199SXin Li finder_options.browser_options.AppendExtraBrowserArgs( 182*9c5db199SXin Li ['--proxy-server="%s"' % proxy_server]) 183*9c5db199SXin Li if utils.is_arc_available() and arc_util.should_start_arc(arc_mode): 184*9c5db199SXin Li if disable_arc_opt_in and disable_arc_opt_in_verification: 185*9c5db199SXin Li finder_options.browser_options.AppendExtraBrowserArgs( 186*9c5db199SXin Li ['--disable-arc-opt-in-verification']) 187*9c5db199SXin Li if disable_arc_cpu_restriction: 188*9c5db199SXin Li finder_options.browser_options.AppendExtraBrowserArgs( 189*9c5db199SXin Li ['--disable-arc-cpu-restriction']) 190*9c5db199SXin Li if disable_app_sync: 191*9c5db199SXin Li finder_options.browser_options.AppendExtraBrowserArgs( 192*9c5db199SXin Li ['--arc-disable-app-sync']) 193*9c5db199SXin Li if disable_play_auto_install: 194*9c5db199SXin Li finder_options.browser_options.AppendExtraBrowserArgs( 195*9c5db199SXin Li ['--arc-disable-play-auto-install']) 196*9c5db199SXin Li if disable_locale_sync: 197*9c5db199SXin Li finder_options.browser_options.AppendExtraBrowserArgs( 198*9c5db199SXin Li ['--arc-disable-locale-sync']) 199*9c5db199SXin Li if disable_play_store_auto_update: 200*9c5db199SXin Li finder_options.browser_options.AppendExtraBrowserArgs( 201*9c5db199SXin Li ['--arc-play-store-auto-update=off']) 202*9c5db199SXin Li logged_in = True 203*9c5db199SXin Li 204*9c5db199SXin Li if autotest_ext: 205*9c5db199SXin Li self._autotest_ext_path = os.path.join(os.path.dirname(__file__), 206*9c5db199SXin Li 'autotest_private_ext') 207*9c5db199SXin Li extension_paths.append(self._autotest_ext_path) 208*9c5db199SXin Li finder_options.browser_options.AppendExtraBrowserArgs( 209*9c5db199SXin Li ['--allowlisted-extension-id=%s' % self.AUTOTEST_EXT_ID]) 210*9c5db199SXin Li 211*9c5db199SXin Li self._browser_type = (self.BROWSER_TYPE_LOGIN 212*9c5db199SXin Li if logged_in else self.BROWSER_TYPE_GUEST) 213*9c5db199SXin Li finder_options.browser_type = self.browser_type 214*9c5db199SXin Li 215*9c5db199SXin Li if not enable_web_app_auto_install: 216*9c5db199SXin Li finder_options.browser_options.AppendExtraBrowserArgs( 217*9c5db199SXin Li ['--disable-features=DefaultWebAppInstallation']) 218*9c5db199SXin Li 219*9c5db199SXin Li if not auto_login: 220*9c5db199SXin Li finder_options.browser_options.AppendExtraBrowserArgs( 221*9c5db199SXin Li ['--enable-oobe-test-api']) 222*9c5db199SXin Li 223*9c5db199SXin Li if extra_browser_args: 224*9c5db199SXin Li finder_options.browser_options.AppendExtraBrowserArgs( 225*9c5db199SXin Li extra_browser_args) 226*9c5db199SXin Li 227*9c5db199SXin Li if enable_features: 228*9c5db199SXin Li finder_options.browser_options.AppendExtraBrowserArgs( 229*9c5db199SXin Li ['--enable-features=%s' % enable_features]) 230*9c5db199SXin Li 231*9c5db199SXin Li # finder options must be set before parse_args(), browser options must 232*9c5db199SXin Li # be set before Create(). 233*9c5db199SXin Li # TODO(crbug.com/360890) Below MUST be '2' so that it doesn't inhibit 234*9c5db199SXin Li # autotest debug logs 235*9c5db199SXin Li finder_options.verbosity = 2 236*9c5db199SXin Li finder_options.CreateParser().parse_args(args=[]) 237*9c5db199SXin Li b_options = finder_options.browser_options 238*9c5db199SXin Li b_options.disable_component_extensions_with_background_pages = False 239*9c5db199SXin Li b_options.create_browser_with_oobe = True 240*9c5db199SXin Li b_options.clear_enterprise_policy = clear_enterprise_policy 241*9c5db199SXin Li b_options.dont_override_profile = dont_override_profile 242*9c5db199SXin Li b_options.disable_gaia_services = disable_gaia_services 243*9c5db199SXin Li b_options.disable_default_apps = disable_default_apps 244*9c5db199SXin Li b_options.disable_component_extensions_with_background_pages = disable_default_apps 245*9c5db199SXin Li b_options.disable_background_networking = False 246*9c5db199SXin Li b_options.expect_policy_fetch = expect_policy_fetch 247*9c5db199SXin Li b_options.auto_login = auto_login 248*9c5db199SXin Li b_options.gaia_login = gaia_login 249*9c5db199SXin Li b_options.mute_audio = mute_audio 250*9c5db199SXin Li b_options.login_delay = login_delay 251*9c5db199SXin Li 252*9c5db199SXin Li if utils.is_arc_available() and not disable_arc_opt_in: 253*9c5db199SXin Li arc_util.set_browser_options_for_opt_in(b_options) 254*9c5db199SXin Li 255*9c5db199SXin Li self.username = b_options.username if username is None else username 256*9c5db199SXin Li self.password = b_options.password if password is None else password 257*9c5db199SXin Li self.username = NormalizeEmail(self.username) 258*9c5db199SXin Li b_options.username = self.username 259*9c5db199SXin Li b_options.password = self.password 260*9c5db199SXin Li self.gaia_id = b_options.gaia_id if gaia_id is None else gaia_id 261*9c5db199SXin Li b_options.gaia_id = self.gaia_id 262*9c5db199SXin Li 263*9c5db199SXin Li self.arc_mode = arc_mode 264*9c5db199SXin Li 265*9c5db199SXin Li if logged_in: 266*9c5db199SXin Li extensions_to_load = b_options.extensions_to_load 267*9c5db199SXin Li for path in extension_paths: 268*9c5db199SXin Li extension = extension_to_load.ExtensionToLoad( 269*9c5db199SXin Li path, self.browser_type) 270*9c5db199SXin Li extensions_to_load.append(extension) 271*9c5db199SXin Li self._extensions_to_load = extensions_to_load 272*9c5db199SXin Li 273*9c5db199SXin Li # Turn on collection of Chrome coredumps via creation of a magic file. 274*9c5db199SXin Li # (Without this, Chrome coredumps are trashed.) 275*9c5db199SXin Li open(constants.CHROME_CORE_MAGIC_FILE, 'w').close() 276*9c5db199SXin Li 277*9c5db199SXin Li self._browser_to_create = browser_finder.FindBrowser( 278*9c5db199SXin Li finder_options) 279*9c5db199SXin Li self._browser_to_create.SetUpEnvironment(b_options) 280*9c5db199SXin Li for i in range(num_tries): 281*9c5db199SXin Li try: 282*9c5db199SXin Li self._browser = self._browser_to_create.Create() 283*9c5db199SXin Li self._browser_pid = \ 284*9c5db199SXin Li cros_interface.CrOSInterface().GetChromePid() 285*9c5db199SXin Li if utils.is_arc_available(): 286*9c5db199SXin Li if disable_arc_opt_in: 287*9c5db199SXin Li if arc_util.should_start_arc(arc_mode): 288*9c5db199SXin Li arc_util.enable_play_store(self.autotest_ext, True) 289*9c5db199SXin Li else: 290*9c5db199SXin Li if not enterprise_arc_test: 291*9c5db199SXin Li wait_for_provisioning = \ 292*9c5db199SXin Li arc_mode != arc_common.ARC_MODE_ENABLED_ASYNC 293*9c5db199SXin Li arc_util.opt_in( 294*9c5db199SXin Li browser=self.browser, 295*9c5db199SXin Li autotest_ext=self.autotest_ext, 296*9c5db199SXin Li wait_for_provisioning=wait_for_provisioning) 297*9c5db199SXin Li arc_util.post_processing_after_browser(self, arc_timeout) 298*9c5db199SXin Li if enable_assistant: 299*9c5db199SXin Li assistant_util.enable_assistant(self.autotest_ext) 300*9c5db199SXin Li break 301*9c5db199SXin Li except exceptions.LoginException as e: 302*9c5db199SXin Li logging.error('Timed out logging in, tries=%d, error=%s', 303*9c5db199SXin Li i, repr(e)) 304*9c5db199SXin Li if i == num_tries-1: 305*9c5db199SXin Li raise 306*9c5db199SXin Li if init_network_controller: 307*9c5db199SXin Li self._browser.platform.network_controller.Open() 308*9c5db199SXin Li 309*9c5db199SXin Li def __enter__(self): 310*9c5db199SXin Li return self 311*9c5db199SXin Li 312*9c5db199SXin Li def __exit__(self, *args): 313*9c5db199SXin Li # Turn off collection of Chrome coredumps turned on in init. 314*9c5db199SXin Li if os.path.exists(constants.CHROME_CORE_MAGIC_FILE): 315*9c5db199SXin Li os.remove(constants.CHROME_CORE_MAGIC_FILE) 316*9c5db199SXin Li self.close() 317*9c5db199SXin Li 318*9c5db199SXin Li @property 319*9c5db199SXin Li def browser(self): 320*9c5db199SXin Li """Returns a telemetry browser instance.""" 321*9c5db199SXin Li return self._browser 322*9c5db199SXin Li 323*9c5db199SXin Li def get_extension(self, extension_path, retry=5): 324*9c5db199SXin Li """Fetches a telemetry extension instance given the extension path.""" 325*9c5db199SXin Li def _has_ext(ext): 326*9c5db199SXin Li """ 327*9c5db199SXin Li Return True if the extension is fully loaded. 328*9c5db199SXin Li 329*9c5db199SXin Li Sometimes an extension will be in the _extensions_to_load, but not 330*9c5db199SXin Li be fully loaded, and will error when trying to fetch from 331*9c5db199SXin Li self.browser.extensions. Happens most common when ARC is enabled. 332*9c5db199SXin Li This will add a wait/retry. 333*9c5db199SXin Li 334*9c5db199SXin Li @param ext: the extension to look for 335*9c5db199SXin Li @returns True if found, False if not. 336*9c5db199SXin Li """ 337*9c5db199SXin Li try: 338*9c5db199SXin Li return bool(self.browser.extensions[ext]) 339*9c5db199SXin Li except KeyError: 340*9c5db199SXin Li return False 341*9c5db199SXin Li 342*9c5db199SXin Li for ext in self._extensions_to_load: 343*9c5db199SXin Li if extension_path == ext.path: 344*9c5db199SXin Li utils.poll_for_condition(lambda: _has_ext(ext), 345*9c5db199SXin Li timeout=retry) 346*9c5db199SXin Li return self.browser.extensions[ext] 347*9c5db199SXin Li return None 348*9c5db199SXin Li 349*9c5db199SXin Li @property 350*9c5db199SXin Li def autotest_ext(self): 351*9c5db199SXin Li """Returns the autotest extension.""" 352*9c5db199SXin Li return self.get_extension(self._autotest_ext_path) 353*9c5db199SXin Li 354*9c5db199SXin Li @property 355*9c5db199SXin Li def login_status(self): 356*9c5db199SXin Li """Returns login status.""" 357*9c5db199SXin Li ext = self.autotest_ext 358*9c5db199SXin Li if not ext: 359*9c5db199SXin Li return None 360*9c5db199SXin Li 361*9c5db199SXin Li ext.ExecuteJavaScript(''' 362*9c5db199SXin Li window.__login_status = null; 363*9c5db199SXin Li chrome.autotestPrivate.loginStatus(function(s) { 364*9c5db199SXin Li window.__login_status = s; 365*9c5db199SXin Li }); 366*9c5db199SXin Li ''') 367*9c5db199SXin Li return utils.poll_for_condition( 368*9c5db199SXin Li lambda: ext.EvaluateJavaScript('window.__login_status'), 369*9c5db199SXin Li timeout=10) 370*9c5db199SXin Li 371*9c5db199SXin Li def disable_dim_display(self): 372*9c5db199SXin Li """Avoid dim display. 373*9c5db199SXin Li 374*9c5db199SXin Li @returns True if success otherwise False. 375*9c5db199SXin Li """ 376*9c5db199SXin Li ext = self.autotest_ext 377*9c5db199SXin Li if not ext: 378*9c5db199SXin Li return False 379*9c5db199SXin Li try: 380*9c5db199SXin Li ext.ExecuteJavaScript( 381*9c5db199SXin Li '''chrome.power.requestKeepAwake("display")''') 382*9c5db199SXin Li except: 383*9c5db199SXin Li logging.error("failed to disable dim display") 384*9c5db199SXin Li return False 385*9c5db199SXin Li return True 386*9c5db199SXin Li 387*9c5db199SXin Li def get_visible_notifications(self): 388*9c5db199SXin Li """Returns an array of visible notifications of Chrome. 389*9c5db199SXin Li 390*9c5db199SXin Li For specific type of each notification, please refer to Chromium's 391*9c5db199SXin Li chrome/common/extensions/api/autotest_private.idl. 392*9c5db199SXin Li """ 393*9c5db199SXin Li ext = self.autotest_ext 394*9c5db199SXin Li if not ext: 395*9c5db199SXin Li return None 396*9c5db199SXin Li 397*9c5db199SXin Li ext.ExecuteJavaScript(''' 398*9c5db199SXin Li window.__items = null; 399*9c5db199SXin Li chrome.autotestPrivate.getVisibleNotifications(function(items) { 400*9c5db199SXin Li window.__items = items; 401*9c5db199SXin Li }); 402*9c5db199SXin Li ''') 403*9c5db199SXin Li if ext.EvaluateJavaScript('window.__items') is None: 404*9c5db199SXin Li return None 405*9c5db199SXin Li return ext.EvaluateJavaScript('window.__items') 406*9c5db199SXin Li 407*9c5db199SXin Li @property 408*9c5db199SXin Li def browser_type(self): 409*9c5db199SXin Li """Returns the browser_type.""" 410*9c5db199SXin Li return self._browser_type 411*9c5db199SXin Li 412*9c5db199SXin Li @staticmethod 413*9c5db199SXin Li def did_browser_crash(func): 414*9c5db199SXin Li """Runs func, returns True if the browser crashed, False otherwise. 415*9c5db199SXin Li 416*9c5db199SXin Li @param func: function to run. 417*9c5db199SXin Li 418*9c5db199SXin Li """ 419*9c5db199SXin Li try: 420*9c5db199SXin Li func() 421*9c5db199SXin Li except Error: 422*9c5db199SXin Li return True 423*9c5db199SXin Li return False 424*9c5db199SXin Li 425*9c5db199SXin Li @staticmethod 426*9c5db199SXin Li def wait_for_browser_restart(func, browser): 427*9c5db199SXin Li """Runs func, and waits for a browser restart. 428*9c5db199SXin Li 429*9c5db199SXin Li @param func: function to run. 430*9c5db199SXin Li 431*9c5db199SXin Li """ 432*9c5db199SXin Li _cri = cros_interface.CrOSInterface() 433*9c5db199SXin Li pid = _cri.GetChromePid() 434*9c5db199SXin Li Chrome.did_browser_crash(func) 435*9c5db199SXin Li utils.poll_for_condition( 436*9c5db199SXin Li lambda: pid != _cri.GetChromePid(), timeout=60) 437*9c5db199SXin Li browser.WaitForBrowserToComeUp() 438*9c5db199SXin Li 439*9c5db199SXin Li def wait_for_browser_to_come_up(self): 440*9c5db199SXin Li """Waits for the browser to come up. This should only be called after a 441*9c5db199SXin Li browser crash. 442*9c5db199SXin Li """ 443*9c5db199SXin Li def _BrowserReady(cr): 444*9c5db199SXin Li tabs = [] # Wrapper for pass by reference. 445*9c5db199SXin Li if self.did_browser_crash( 446*9c5db199SXin Li lambda: tabs.append(cr.browser.tabs.New())): 447*9c5db199SXin Li return False 448*9c5db199SXin Li try: 449*9c5db199SXin Li tabs[0].Close() 450*9c5db199SXin Li except: 451*9c5db199SXin Li # crbug.com/350941 452*9c5db199SXin Li logging.error('Timed out closing tab') 453*9c5db199SXin Li return True 454*9c5db199SXin Li py_utils.WaitFor(lambda: _BrowserReady(self), timeout=10) 455*9c5db199SXin Li 456*9c5db199SXin Li def close(self): 457*9c5db199SXin Li """Closes the browser. 458*9c5db199SXin Li """ 459*9c5db199SXin Li try: 460*9c5db199SXin Li if utils.is_arc_available(): 461*9c5db199SXin Li arc_util.pre_processing_before_close(self) 462*9c5db199SXin Li finally: 463*9c5db199SXin Li # Calling platform.StopAllLocalServers() to tear down the telemetry 464*9c5db199SXin Li # server processes such as the one started by 465*9c5db199SXin Li # platform.SetHTTPServerDirectories(). Not calling this function 466*9c5db199SXin Li # will leak the process and may affect test results. 467*9c5db199SXin Li # (crbug.com/663387) 468*9c5db199SXin Li self._browser.platform.StopAllLocalServers() 469*9c5db199SXin Li self._browser.Close() 470*9c5db199SXin Li self._browser_to_create.CleanUpEnvironment() 471*9c5db199SXin Li self._browser.platform.network_controller.Close() 472