blob: 2e8360073e8dd75a38a0138dbc103ac2c33f52a8 [file] [log] [blame]
# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Finds CrOS browsers that can be started and controlled by telemetry."""
import logging
import os
import posixpath
from telemetry.core import cros_interface
from telemetry.core import platform as platform_module
from telemetry.internal.backends.chrome import chrome_startup_args
from telemetry.internal.backends.chrome import cros_browser_backend
from telemetry.internal.backends.chrome import cros_browser_with_oobe
from telemetry.internal.backends.chrome import gpu_compositing_checker
from telemetry.internal.browser import browser
from telemetry.internal.browser import browser_finder_exceptions
from telemetry.internal.browser import possible_browser
from telemetry.internal.platform import cros_device
import py_utils
class PossibleCrOSBrowser(possible_browser.PossibleBrowser):
"""A launchable CrOS browser instance."""
def __init__(self, browser_type, finder_options, cros_platform, is_guest):
super(PossibleCrOSBrowser, self).__init__(browser_type, 'cros', True)
assert browser_type in FindAllBrowserTypes(finder_options), (
'Please add %s to cros_browser_finder.FindAllBrowserTypes()' %
browser_type)
self._platform = cros_platform
self._platform_backend = (
cros_platform._platform_backend) # pylint: disable=protected-access
self._is_guest = is_guest
def __repr__(self):
return 'PossibleCrOSBrowser(browser_type=%s)' % self.browser_type
@property
def browser_directory(self):
result = self._platform_backend.cri.GetChromeProcess()
if result and 'path' in result:
return posixpath.dirname(result['path'])
return None
@property
def profile_directory(self):
return '/home/chronos/Default'
def _InitPlatformIfNeeded(self):
pass
def _GetPathsForOsPageCacheFlushing(self):
return [self.profile_directory, self.browser_directory]
def SetUpEnvironment(self, browser_options):
super(PossibleCrOSBrowser, self).SetUpEnvironment(browser_options)
# Copy extensions to temp directories on the device.
# Note that we also perform this copy locally to ensure that
# the owner of the extensions is set to chronos.
cri = self._platform_backend.cri
for extension in self._browser_options.extensions_to_load:
extension_dir = cri.RunCmdOnDevice(
['mktemp', '-d', '/tmp/extension_XXXXX'])[0].rstrip()
# TODO(crbug.com/807645): We should avoid having mutable objects
# stored within the browser options.
extension.local_path = posixpath.join(
extension_dir, os.path.basename(extension.path))
cri.PushFile(extension.path, extension_dir)
cri.Chown(extension_dir)
def browser_ready():
return cri.GetChromePid() is not None
cri.RestartUI(self._browser_options.clear_enterprise_policy)
py_utils.WaitFor(browser_ready, timeout=20)
# Delete test user's cryptohome vault (user data directory).
if not self._browser_options.dont_override_profile:
cri.RunCmdOnDevice(['cryptohome', '--action=remove', '--force',
'--user=%s' % self._browser_options.username])
def _TearDownEnvironment(self):
for extension in self._browser_options.extensions_to_load:
self._platform_backend.cri.RmRF(posixpath.dirname(extension.local_path))
def Create(self, clear_caches=True):
startup_args = self.GetBrowserStartupArgs(self._browser_options)
browser_backend = cros_browser_backend.CrOSBrowserBackend(
self._platform_backend, self._browser_options,
self.browser_directory, self.profile_directory,
self._is_guest)
# TODO(crbug.com/811244): Remove when this is handled by shared state.
if clear_caches:
self._ClearCachesOnStart()
if self._browser_options.create_browser_with_oobe:
return cros_browser_with_oobe.CrOSBrowserWithOOBE(
browser_backend, self._platform_backend, startup_args)
returned_browser = browser.Browser(
browser_backend, self._platform_backend, startup_args)
# TODO(crbug.com/916086): Move this assertion to callers.
if self._browser_options.assert_gpu_compositing:
gpu_compositing_checker.AssertGpuCompositingEnabled(
returned_browser.GetSystemInfo())
return returned_browser
def GetBrowserStartupArgs(self, browser_options):
startup_args = chrome_startup_args.GetFromBrowserOptions(browser_options)
startup_args.extend(chrome_startup_args.GetReplayArgs(
self._platform_backend.network_controller_backend))
vmodule = ','.join('%s=2' % pattern for pattern in [
'*/chromeos/net/*',
'*/chromeos/login/*',
'chrome_browser_main_posix'])
startup_args.extend([
'--enable-smooth-scrolling',
'--enable-threaded-compositing',
# Allow devtools to connect to chrome.
'--remote-debugging-port=0',
# Open a maximized window.
'--start-maximized',
# Disable sounds.
'--ash-disable-system-sounds',
'--mute-audio',
# Skip user image selection screen, and post login screens.
'--oobe-skip-postlogin',
# Disable chrome logging redirect. crbug.com/724273.
'--disable-logging-redirect',
# Debug logging.
'--vmodule=%s' % vmodule,
])
if not browser_options.expect_policy_fetch:
startup_args.append('--allow-failed-policy-fetch-for-test')
# If we're using GAIA, skip to login screen, and do not disable GAIA
# services.
if browser_options.gaia_login:
startup_args.append('--oobe-skip-to-login')
elif browser_options.disable_gaia_services:
startup_args.append('--disable-gaia-services')
trace_config_file = (self._platform_backend.tracing_controller_backend
.GetChromeTraceConfigFile())
if trace_config_file:
startup_args.append('--trace-config-file=%s' % trace_config_file)
return startup_args
def SupportsOptions(self, browser_options):
return (len(browser_options.extensions_to_load) == 0) or not self._is_guest
def UpdateExecutableIfNeeded(self):
pass
def SelectDefaultBrowser(possible_browsers):
if cros_device.IsRunningOnCrOS():
for b in possible_browsers:
if b.browser_type == 'system':
return b
return None
def CanFindAvailableBrowsers(finder_options):
return (cros_device.IsRunningOnCrOS() or finder_options.cros_remote or
cros_interface.HasSSH())
def FindAllBrowserTypes(_):
return [
'cros-chrome',
'cros-chrome-guest',
'system',
'system-guest',
]
def FindAllAvailableBrowsers(finder_options, device):
"""Finds all available CrOS browsers, locally and remotely."""
browsers = []
if not isinstance(device, cros_device.CrOSDevice):
return browsers
if cros_device.IsRunningOnCrOS():
browsers = [
PossibleCrOSBrowser(
'system',
finder_options,
platform_module.GetHostPlatform(),
is_guest=False),
PossibleCrOSBrowser(
'system-guest',
finder_options,
platform_module.GetHostPlatform(),
is_guest=True)
]
# Check ssh
try:
platform = platform_module.GetPlatformForDevice(device, finder_options)
except cros_interface.LoginException, ex:
if isinstance(ex, cros_interface.KeylessLoginRequiredException):
logging.warn('Could not ssh into %s. Your device must be configured',
finder_options.cros_remote)
logging.warn('to allow passwordless login as root.')
logging.warn('For a test-build device, pass this to your script:')
logging.warn(' --identity $(CHROMITE)/ssh_keys/testing_rsa')
logging.warn('')
logging.warn('For a developer-mode device, the steps are:')
logging.warn(' - Ensure you have an id_rsa.pub (etc) on this computer')
logging.warn(' - On the chromebook:')
logging.warn(' - Control-Alt-T; shell; sudo -s')
logging.warn(' - openssh-server start')
logging.warn(' - scp <this machine>:.ssh/id_rsa.pub /tmp/')
logging.warn(' - mkdir /root/.ssh')
logging.warn(' - chown go-rx /root/.ssh')
logging.warn(' - cat /tmp/id_rsa.pub >> /root/.ssh/authorized_keys')
logging.warn(' - chown 0600 /root/.ssh/authorized_keys')
raise browser_finder_exceptions.BrowserFinderException(str(ex))
browsers.extend([
PossibleCrOSBrowser(
'cros-chrome', finder_options, platform, is_guest=False),
PossibleCrOSBrowser(
'cros-chrome-guest', finder_options, platform, is_guest=True)
])
return browsers