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