1# Copyright 2013 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.
4
5"""Finds CrOS browsers that can be controlled by telemetry."""
6
7import logging
8
9from telemetry.core import cros_interface
10from telemetry.core import platform as platform_module
11from telemetry.internal.backends.chrome import cros_browser_backend
12from telemetry.internal.backends.chrome import cros_browser_with_oobe
13from telemetry.internal.browser import browser
14from telemetry.internal.browser import browser_finder_exceptions
15from telemetry.internal.browser import possible_browser
16from telemetry.internal.platform import cros_device
17
18
19class PossibleCrOSBrowser(possible_browser.PossibleBrowser):
20  """A launchable CrOS browser instance."""
21  def __init__(self, browser_type, finder_options, cros_platform, is_guest):
22    super(PossibleCrOSBrowser, self).__init__(browser_type, 'cros', True)
23    assert browser_type in FindAllBrowserTypes(finder_options), (
24        'Please add %s to cros_browser_finder.FindAllBrowserTypes()' %
25         browser_type)
26    self._platform = cros_platform
27    self._platform_backend = (
28        cros_platform._platform_backend)  # pylint: disable=protected-access
29    self._is_guest = is_guest
30
31  def __repr__(self):
32    return 'PossibleCrOSBrowser(browser_type=%s)' % self.browser_type
33
34  def _InitPlatformIfNeeded(self):
35    pass
36
37  def Create(self, finder_options):
38    if finder_options.output_profile_path:
39      raise NotImplementedError(
40          'Profile generation is not yet supported on CrOS.')
41
42    browser_options = finder_options.browser_options
43    browser_backend = cros_browser_backend.CrOSBrowserBackend(
44        self._platform_backend,
45        browser_options, self._platform_backend.cri, self._is_guest,
46        extensions_to_load=finder_options.extensions_to_load)
47    if browser_options.create_browser_with_oobe:
48      return cros_browser_with_oobe.CrOSBrowserWithOOBE(
49          browser_backend,
50          self._platform_backend,
51          self._credentials_path)
52    return browser.Browser(
53        browser_backend, self._platform_backend, self._credentials_path)
54
55  def SupportsOptions(self, finder_options):
56    if (len(finder_options.extensions_to_load) != 0) and self._is_guest:
57      return False
58    return True
59
60  def UpdateExecutableIfNeeded(self):
61    pass
62
63def SelectDefaultBrowser(possible_browsers):
64  if cros_device.IsRunningOnCrOS():
65    for b in possible_browsers:
66      if b.browser_type == 'system':
67        return b
68  return None
69
70def CanFindAvailableBrowsers(finder_options):
71  return (cros_device.IsRunningOnCrOS() or
72          finder_options.cros_remote or
73          cros_interface.HasSSH())
74
75def FindAllBrowserTypes(_):
76  return [
77      'cros-chrome',
78      'cros-chrome-guest',
79      'system',
80      'system-guest',
81  ]
82
83def FindAllAvailableBrowsers(finder_options, device):
84  """Finds all available CrOS browsers, locally and remotely."""
85  browsers = []
86  if not isinstance(device, cros_device.CrOSDevice):
87    return browsers
88
89  if cros_device.IsRunningOnCrOS():
90    browsers = [PossibleCrOSBrowser('system', finder_options,
91                                    platform_module.GetHostPlatform(),
92                                    is_guest=False),
93                PossibleCrOSBrowser('system-guest', finder_options,
94                                    platform_module.GetHostPlatform(),
95                                    is_guest=True)]
96
97  # Check ssh
98  try:
99    # Retries required because of DNS issue in the lab documented in
100    # http://crbug/484726
101    retries = 0
102    while True:
103      try:
104        platform = platform_module.GetPlatformForDevice(device, finder_options)
105        break
106      except cros_interface.DNSFailureException, ex:
107        logging.warn('DNS Failure: %s', str(ex))
108        retries += 1
109        if retries > 1:
110          raise ex
111  except cros_interface.LoginException, ex:
112    if isinstance(ex, cros_interface.KeylessLoginRequiredException):
113      logging.warn('Could not ssh into %s. Your device must be configured',
114                   finder_options.cros_remote)
115      logging.warn('to allow passwordless login as root.')
116      logging.warn('For a test-build device, pass this to your script:')
117      logging.warn('   --identity $(CHROMITE)/ssh_keys/testing_rsa')
118      logging.warn('')
119      logging.warn('For a developer-mode device, the steps are:')
120      logging.warn(' - Ensure you have an id_rsa.pub (etc) on this computer')
121      logging.warn(' - On the chromebook:')
122      logging.warn('   -  Control-Alt-T; shell; sudo -s')
123      logging.warn('   -  openssh-server start')
124      logging.warn('   -  scp <this machine>:.ssh/id_rsa.pub /tmp/')
125      logging.warn('   -  mkdir /root/.ssh')
126      logging.warn('   -  chown go-rx /root/.ssh')
127      logging.warn('   -  cat /tmp/id_rsa.pub >> /root/.ssh/authorized_keys')
128      logging.warn('   -  chown 0600 /root/.ssh/authorized_keys')
129    raise browser_finder_exceptions.BrowserFinderException(str(ex))
130
131  browsers.extend([PossibleCrOSBrowser('cros-chrome', finder_options,
132                                       platform, is_guest=False),
133                   PossibleCrOSBrowser('cros-chrome-guest',
134                                       finder_options, platform,
135                                       is_guest=True)])
136  return browsers
137