146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)# Copyright 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file.
4a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
5a3f7b4e666c476898878fa745f637129375cd889Ben Murdochimport copy
6a3f7b4e666c476898878fa745f637129375cd889Ben Murdochimport logging
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import optparse
8a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)import os
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import shlex
10a3f7b4e666c476898878fa745f637129375cd889Ben Murdochimport sys
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.core import browser_finder
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.core import profile_types
14a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)from telemetry.core import util
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.core import wpr_modes
16b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from telemetry.core.platform.profiler import profiler_finder
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)util.AddDirToPythonPath(
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    util.GetChromiumSrcDir(), 'third_party', 'webpagereplay')
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import net_configs  # pylint: disable=F0401
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
23424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)class BrowserFinderOptions(optparse.Values):
2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  """Options to be used for discovering a browser."""
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self, browser_type=None):
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    optparse.Values.__init__(self)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.browser_type = browser_type
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.browser_executable = None
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.chrome_root = None
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.android_device = None
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.cros_ssh_identity = None
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.extensions_to_load = []
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    # If set, copy the generated profile to this path on exit.
38424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    self.output_profile_path = None
39424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.cros_remote = None
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    self.profiler = None
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.verbosity = 0
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    self.browser_options = BrowserOptions()
463240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    self.output_file = None
47a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    self.android_rndis = False
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    self.no_performance_mode = False
5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def __repr__(self):
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return str(sorted(self.__dict__.items()))
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Copy(self):
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return copy.deepcopy(self)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def CreateParser(self, *args, **kwargs):
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parser = optparse.OptionParser(*args, **kwargs)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Selection group
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    group = optparse.OptionGroup(parser, 'Which browser to use')
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    group.add_option('--browser',
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dest='browser_type',
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default=None,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        help='Browser type to run, '
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             'in order of priority. Supported values: list,%s' %
6703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)             ','.join(browser_finder.FindAllBrowserTypes(self)))
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    group.add_option('--browser-executable',
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dest='browser_executable',
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        help='The exact browser to run.')
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    group.add_option('--chrome-root',
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dest='chrome_root',
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        help='Where to look for chrome builds.'
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             'Defaults to searching parent dirs by default.')
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    group.add_option('--device',
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dest='android_device',
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        help='The android device ID to use'
7803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)             'If not specified, only 0 or 1 connected devices are supported.')
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    group.add_option('--target-arch',
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        dest='target_arch',
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        help='The target architecture of the browser. Options available are: '
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)             'x64, x86_64, arm, arm64 and mips. '
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)             'Defaults to the default architecture of the platform if omitted.')
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    group.add_option(
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        '--remote',
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dest='cros_remote',
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        help='The IP address of a remote ChromeOS device to use.')
88ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    identity = None
89ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    testing_rsa = os.path.join(
90ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        util.GetChromiumSrcDir(),
91ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        'third_party', 'chromite', 'ssh_keys', 'testing_rsa')
92ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if os.path.exists(testing_rsa):
93ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      identity = testing_rsa
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    group.add_option('--identity',
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dest='cros_ssh_identity',
96ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        default=identity,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        help='The identity file to use when ssh\'ing into the ChromeOS device')
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parser.add_option_group(group)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Debugging options
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    group = optparse.OptionGroup(parser, 'When things go wrong')
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    profiler_choices = profiler_finder.GetAllAvailableProfilers()
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    group.add_option(
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        '--profiler', default=None, type='choice',
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        choices=profiler_choices,
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        help='Record profiling data using this tool. Supported values: ' +
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             ', '.join(profiler_choices))
108b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    group.add_option(
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        '--interactive', dest='interactive', action='store_true',
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        help='Let the user interact with the page; the actions specified for '
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             'the page are not run.')
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    group.add_option(
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        '-v', '--verbose', action='count', dest='verbosity',
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        help='Increase verbosity level (repeat as needed)')
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    group.add_option('--print-bootstrap-deps',
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     action='store_true',
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     help='Output bootstrap deps list.')
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    parser.add_option_group(group)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # Platform options
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    group = optparse.OptionGroup(parser, 'Platform options')
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    group.add_option('--no-performance-mode', action='store_true',
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        help='Some platforms run on "full performance mode" where the '
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        'test is executed at maximum CPU speed in order to minimize noise '
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        '(specially important for dashboards / continuous builds). '
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        'This option prevents Telemetry from tweaking such platform settings.')
12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    group.add_option('--android-rndis', dest='android_rndis', default=False,
12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        action='store_true', help='Use RNDIS forwarding on Android.')
12958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    group.add_option('--no-android-rndis', dest='android_rndis',
13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        action='store_false', help='Do not use RNDIS forwarding on Android.'
13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        ' [default]')
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parser.add_option_group(group)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    # Browser options.
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    self.browser_options.AddCommandLineArgs(parser)
136a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    real_parse = parser.parse_args
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def ParseArgs(args=None):
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      defaults = parser.get_default_values()
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for k, v in defaults.__dict__.items():
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if k in self.__dict__ and self.__dict__[k] != None:
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          continue
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.__dict__[k] = v
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ret = real_parse(args, self) # pylint: disable=E1121
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if self.verbosity >= 2:
1473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        logging.getLogger().setLevel(logging.DEBUG)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      elif self.verbosity:
1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        logging.getLogger().setLevel(logging.INFO)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        logging.getLogger().setLevel(logging.WARNING)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if self.browser_executable and not self.browser_type:
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.browser_type = 'exact'
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if self.browser_type == 'list':
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        try:
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          types = browser_finder.GetAllAvailableBrowserTypes(self)
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        except browser_finder.BrowserFinderException, ex:
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          sys.stderr.write('ERROR: ' + str(ex))
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          sys.exit(1)
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sys.stdout.write('Available browsers:\n')
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sys.stdout.write('  %s\n' % '\n  '.join(types))
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sys.exit(0)
164a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
16558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      # Parse browser options.
16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      self.browser_options.UpdateFromParseResults(self)
167ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ret
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parser.parse_args = ParseArgs
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return parser
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  def AppendExtraBrowserArgs(self, args):
17358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    self.browser_options.AppendExtraBrowserArgs(args)
174ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
175ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  def MergeDefaultValues(self, defaults):
176ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    for k, v in defaults.__dict__.items():
177ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      self.ensure_value(k, v)
17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
17968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)class BrowserOptions(object):
18058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  """Options to be used for launching a browser."""
18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  def __init__(self):
18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    self.browser_type = None
18358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    self.show_stdout = False
18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    # When set to True, the browser will use the default profile.  Telemetry
18658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    # will not provide an alternate profile directory.
18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    self.dont_override_profile = False
18858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    self.profile_dir = None
18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    self.profile_type = None
19058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    self._extra_browser_args = set()
19158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    self.extra_wpr_args = []
19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    self.wpr_mode = wpr_modes.WPR_OFF
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self.netsim = None
19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    self.disable_background_networking = True
19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    self.no_proxy_server = False
19758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    self.browser_user_agent_type = None
19858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    self.clear_sytem_cache_for_browser_and_profile_on_start = False
2006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    self.startup_url = 'about:blank'
20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    # Background pages of built-in component extensions can interfere with
2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    # performance measurements.
2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    self.disable_component_extensions_with_background_pages = True
2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
20646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    # Whether to use the new code path for choosing an ephemeral port for
20746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    # DevTools. The bots set this to true. When Chrome 37 reaches stable,
20846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    # remove this setting and the old code path. http://crbug.com/379980
20946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    self.use_devtools_active_port = False
21046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def __repr__(self):
212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return str(sorted(self.__dict__.items()))
213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  @classmethod
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  def AddCommandLineArgs(cls, parser):
216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ############################################################################
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    # Please do not add any more options here without first discussing with    #
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    # a telemetry owner. This is not the right place for platform-specific     #
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    # options.                                                                 #
221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ############################################################################
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
22358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    group = optparse.OptionGroup(parser, 'Browser options')
22458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    profile_choices = profile_types.GetProfileTypes()
22558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    group.add_option('--profile-type',
22658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        dest='profile_type',
22758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        type='choice',
22858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        default='clean',
22958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        choices=profile_choices,
23058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        help=('The user profile to use. A clean profile is used by default. '
23158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)              'Supported values: ' + ', '.join(profile_choices)))
23258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    group.add_option('--profile-dir',
23358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        dest='profile_dir',
23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        help='Profile directory to launch the browser with. '
23558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)             'A clean profile is used by default')
23658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    group.add_option('--extra-browser-args',
23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        dest='extra_browser_args_as_string',
23858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        help='Additional arguments to pass to the browser when it starts')
23958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    group.add_option('--extra-wpr-args',
24058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        dest='extra_wpr_args_as_string',
24158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        help=('Additional arguments to pass to Web Page Replay. '
24258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)              'See third_party/webpagereplay/replay.py for usage.'))
243f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    group.add_option('--netsim', default=None, type='choice',
244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        choices=net_configs.NET_CONFIG_NAMES,
245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        help=('Run benchmark under simulated network conditions. '
246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)              'Will prompt for sudo. Supported values: ' +
247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)              ', '.join(net_configs.NET_CONFIG_NAMES)))
24858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    group.add_option('--show-stdout',
24958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        action='store_true',
25058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        help='When possible, will display the stdout of the process')
25146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    # This hidden option is to be removed, and the older code path deleted,
25246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    # once Chrome 37 reaches Stable. http://crbug.com/379980
25346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    group.add_option('--use-devtools-active-port',
25446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        action='store_true',
25546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        help=optparse.SUPPRESS_HELP)
25658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    parser.add_option_group(group)
25758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    group = optparse.OptionGroup(parser, 'Compatibility options')
2598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    group.add_option('--gtest_output',
2608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        help='Ignored argument for compatibility with runtest.py harness')
2618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    parser.add_option_group(group)
2628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    group = optparse.OptionGroup(parser, 'Synthetic gesture options')
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    synthetic_gesture_source_type_choices = [ 'default', 'mouse', 'touch' ]
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    group.add_option('--synthetic-gesture-source-type',
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        dest='synthetic_gesture_source_type',
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        default='default', type='choice',
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        choices=synthetic_gesture_source_type_choices,
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        help='Specify the source type for synthetic gestures. Note that some ' +
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)             'actions only support a specific source type. ' +
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)             'Supported values: ' +
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)             ', '.join(synthetic_gesture_source_type_choices))
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    parser.add_option_group(group)
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
27658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  def UpdateFromParseResults(self, finder_options):
27758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    """Copies our options from finder_options"""
27858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    browser_options_list = [
279f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        'extra_browser_args_as_string',
280f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        'extra_wpr_args_as_string',
281f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        'netsim',
282f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        'profile_dir',
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        'profile_type',
284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        'show_stdout',
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        'synthetic_gesture_source_type',
28646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        'use_devtools_active_port',
28758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        ]
28858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    for o in browser_options_list:
289d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      a = getattr(finder_options, o, None)
290d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if a is not None:
29158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        setattr(self, o, a)
29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        delattr(finder_options, o)
29358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
29458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    self.browser_type = finder_options.browser_type
29558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
29658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if hasattr(self, 'extra_browser_args_as_string'): # pylint: disable=E1101
29758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      tmp = shlex.split(
29858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        self.extra_browser_args_as_string) # pylint: disable=E1101
29958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      self.AppendExtraBrowserArgs(tmp)
30058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      delattr(self, 'extra_browser_args_as_string')
30158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if hasattr(self, 'extra_wpr_args_as_string'): # pylint: disable=E1101
30258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      tmp = shlex.split(
30358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        self.extra_wpr_args_as_string) # pylint: disable=E1101
30458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      self.extra_wpr_args.extend(tmp)
30558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      delattr(self, 'extra_wpr_args_as_string')
30658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if self.profile_type == 'default':
30758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      self.dont_override_profile = True
30858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
30958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if self.profile_dir and self.profile_type != 'clean':
31046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      logging.critical(
31146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          "It's illegal to specify both --profile-type and --profile-dir.\n"
31246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          "For more information see: http://goo.gl/ngdGD5")
31346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      sys.exit(1)
31458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
3150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    if self.profile_dir and not os.path.isdir(self.profile_dir):
31646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      logging.critical(
31746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          "Directory specified by --profile-dir (%s) doesn't exist "
31846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          "or isn't a directory.\n"
31946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          "For more information see: http://goo.gl/ngdGD5" % self.profile_dir)
32046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      sys.exit(1)
3210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
32258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if not self.profile_dir:
32358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      self.profile_dir = profile_types.GetProfileDir(self.profile_type)
32458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
32568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    # This deferred import is necessary because browser_options is imported in
32668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    # telemetry/telemetry/__init__.py.
32768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    from telemetry.core.backends.chrome import chrome_browser_options
32868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    finder_options.browser_options = (
32968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        chrome_browser_options.CreateChromeBrowserOptions(self))
33068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
33158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  @property
33258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  def extra_browser_args(self):
33358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return self._extra_browser_args
33458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
33558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  def AppendExtraBrowserArgs(self, args):
33658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if isinstance(args, list):
33758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      self._extra_browser_args.update(args)
33858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    else:
33958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      self._extra_browser_args.add(args)
340