1 # Copyright 2012 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.
12 from telemetry.core import browser_finder
13 from telemetry.core import profile_types
14 from telemetry.core import util
15 from telemetry.core import wpr_modes
16 from telemetry.core.platform.profiler import profiler_finder
18 util.AddDirToPythonPath(
19 util.GetChromiumSrcDir(), 'third_party', 'webpagereplay')
20 import net_configs # pylint: disable=F0401
23 class BrowserFinderOptions(optparse.Values):
24 """Options to be used for discovering a browser."""
26 def __init__(self, browser_type=None):
27 optparse.Values.__init__(self)
29 self.browser_type = browser_type
30 self.browser_executable = None
31 self.chrome_root = None
32 self.android_device = None
33 self.cros_ssh_identity = None
35 self.extensions_to_load = []
37 # If set, copy the generated profile to this path on exit.
38 self.output_profile_path = None
40 self.cros_remote = None
45 self.browser_options = BrowserOptions()
46 self.output_file = None
48 self.android_rndis = False
49 self.no_performance_mode = False
52 return str(sorted(self.__dict__.items()))
55 return copy.deepcopy(self)
57 def CreateParser(self, *args, **kwargs):
58 parser = optparse.OptionParser(*args, **kwargs)
61 group = optparse.OptionGroup(parser, 'Which browser to use')
62 group.add_option('--browser',
65 help='Browser type to run, '
66 'in order of priority. Supported values: list,%s' %
67 ','.join(browser_finder.FindAllBrowserTypes(self)))
68 group.add_option('--browser-executable',
69 dest='browser_executable',
70 help='The exact browser to run.')
71 group.add_option('--chrome-root',
73 help='Where to look for chrome builds.'
74 'Defaults to searching parent dirs by default.')
75 group.add_option('--device',
76 dest='android_device',
77 help='The android device ID to use'
78 'If not specified, only 0 or 1 connected devices are supported.')
79 group.add_option('--target-arch',
81 help='The target architecture of the browser. Options available are: '
82 'x64, x86_64, arm, arm64 and mips. '
83 'Defaults to the default architecture of the platform if omitted.')
87 help='The IP address of a remote ChromeOS device to use.')
89 testing_rsa = os.path.join(
90 util.GetChromiumSrcDir(),
91 'third_party', 'chromite', 'ssh_keys', 'testing_rsa')
92 if os.path.exists(testing_rsa):
93 identity = testing_rsa
94 group.add_option('--identity',
95 dest='cros_ssh_identity',
97 help='The identity file to use when ssh\'ing into the ChromeOS device')
98 parser.add_option_group(group)
101 group = optparse.OptionGroup(parser, 'When things go wrong')
102 profiler_choices = profiler_finder.GetAllAvailableProfilers()
104 '--profiler', default=None, type='choice',
105 choices=profiler_choices,
106 help='Record profiling data using this tool. Supported values: ' +
107 ', '.join(profiler_choices))
109 '--interactive', dest='interactive', action='store_true',
110 help='Let the user interact with the page; the actions specified for '
111 'the page are not run.')
113 '-v', '--verbose', action='count', dest='verbosity',
114 help='Increase verbosity level (repeat as needed)')
115 group.add_option('--print-bootstrap-deps',
117 help='Output bootstrap deps list.')
118 group.add_option('--disable-crash-service',
119 dest='disable_crash_service',
122 help='Whether to disable crash service. NOTE: this flag '
123 'is added temporarily for crbug.com/424024, and will be '
124 'deprecated as soon as the bug is marked fixed.')
125 parser.add_option_group(group)
128 group = optparse.OptionGroup(parser, 'Platform options')
129 group.add_option('--no-performance-mode', action='store_true',
130 help='Some platforms run on "full performance mode" where the '
131 'test is executed at maximum CPU speed in order to minimize noise '
132 '(specially important for dashboards / continuous builds). '
133 'This option prevents Telemetry from tweaking such platform settings.')
134 group.add_option('--android-rndis', dest='android_rndis', default=False,
135 action='store_true', help='Use RNDIS forwarding on Android.')
136 group.add_option('--no-android-rndis', dest='android_rndis',
137 action='store_false', help='Do not use RNDIS forwarding on Android.'
139 parser.add_option_group(group)
142 self.browser_options.AddCommandLineArgs(parser)
144 real_parse = parser.parse_args
145 def ParseArgs(args=None):
146 defaults = parser.get_default_values()
147 for k, v in defaults.__dict__.items():
148 if k in self.__dict__ and self.__dict__[k] != None:
151 ret = real_parse(args, self) # pylint: disable=E1121
153 if self.verbosity >= 2:
154 logging.getLogger().setLevel(logging.DEBUG)
156 logging.getLogger().setLevel(logging.INFO)
158 logging.getLogger().setLevel(logging.WARNING)
160 if self.browser_executable and not self.browser_type:
161 self.browser_type = 'exact'
162 if self.browser_type == 'list':
164 types = browser_finder.GetAllAvailableBrowserTypes(self)
165 except browser_finder.BrowserFinderException, ex:
166 sys.stderr.write('ERROR: ' + str(ex))
168 sys.stdout.write('Available browsers:\n')
169 sys.stdout.write(' %s\n' % '\n '.join(types))
172 # Parse browser options.
173 self.browser_options.UpdateFromParseResults(self)
176 parser.parse_args = ParseArgs
179 def AppendExtraBrowserArgs(self, args):
180 self.browser_options.AppendExtraBrowserArgs(args)
182 def MergeDefaultValues(self, defaults):
183 for k, v in defaults.__dict__.items():
184 self.ensure_value(k, v)
186 class BrowserOptions(object):
187 """Options to be used for launching a browser."""
189 self.browser_type = None
190 self.show_stdout = False
192 # When set to True, the browser will use the default profile. Telemetry
193 # will not provide an alternate profile directory.
194 self.dont_override_profile = False
195 self.profile_dir = None
196 self.profile_type = None
197 self._extra_browser_args = set()
198 self.extra_wpr_args = []
199 self.wpr_mode = wpr_modes.WPR_OFF
202 self.disable_background_networking = True
203 self.no_proxy_server = False
204 self.browser_user_agent_type = None
206 self.clear_sytem_cache_for_browser_and_profile_on_start = False
207 self.startup_url = 'about:blank'
209 # Background pages of built-in component extensions can interfere with
210 # performance measurements.
211 self.disable_component_extensions_with_background_pages = True
213 # Whether to use the new code path for choosing an ephemeral port for
214 # DevTools. The bots set this to true. When Chrome 37 reaches stable,
215 # remove this setting and the old code path. http://crbug.com/379980
216 self.use_devtools_active_port = False
219 return str(sorted(self.__dict__.items()))
222 def AddCommandLineArgs(cls, parser):
224 ############################################################################
225 # Please do not add any more options here without first discussing with #
226 # a telemetry owner. This is not the right place for platform-specific #
228 ############################################################################
230 group = optparse.OptionGroup(parser, 'Browser options')
231 profile_choices = profile_types.GetProfileTypes()
232 group.add_option('--profile-type',
236 choices=profile_choices,
237 help=('The user profile to use. A clean profile is used by default. '
238 'Supported values: ' + ', '.join(profile_choices)))
239 group.add_option('--profile-dir',
241 help='Profile directory to launch the browser with. '
242 'A clean profile is used by default')
243 group.add_option('--extra-browser-args',
244 dest='extra_browser_args_as_string',
245 help='Additional arguments to pass to the browser when it starts')
246 group.add_option('--extra-wpr-args',
247 dest='extra_wpr_args_as_string',
248 help=('Additional arguments to pass to Web Page Replay. '
249 'See third_party/webpagereplay/replay.py for usage.'))
250 group.add_option('--netsim', default=None, type='choice',
251 choices=net_configs.NET_CONFIG_NAMES,
252 help=('Run benchmark under simulated network conditions. '
253 'Will prompt for sudo. Supported values: ' +
254 ', '.join(net_configs.NET_CONFIG_NAMES)))
255 group.add_option('--show-stdout',
257 help='When possible, will display the stdout of the process')
258 # This hidden option is to be removed, and the older code path deleted,
259 # once Chrome 37 reaches Stable. http://crbug.com/379980
260 group.add_option('--use-devtools-active-port',
262 help=optparse.SUPPRESS_HELP)
263 parser.add_option_group(group)
265 group = optparse.OptionGroup(parser, 'Compatibility options')
266 group.add_option('--gtest_output',
267 help='Ignored argument for compatibility with runtest.py harness')
268 parser.add_option_group(group)
270 group = optparse.OptionGroup(parser, 'Synthetic gesture options')
271 synthetic_gesture_source_type_choices = [ 'default', 'mouse', 'touch' ]
272 group.add_option('--synthetic-gesture-source-type',
273 dest='synthetic_gesture_source_type',
274 default='default', type='choice',
275 choices=synthetic_gesture_source_type_choices,
276 help='Specify the source type for synthetic gestures. Note that some ' +
277 'actions only support a specific source type. ' +
278 'Supported values: ' +
279 ', '.join(synthetic_gesture_source_type_choices))
280 parser.add_option_group(group)
283 def UpdateFromParseResults(self, finder_options):
284 """Copies our options from finder_options"""
285 browser_options_list = [
286 'disable_crash_service',
287 'extra_browser_args_as_string',
288 'extra_wpr_args_as_string',
293 'synthetic_gesture_source_type',
294 'use_devtools_active_port',
296 for o in browser_options_list:
297 a = getattr(finder_options, o, None)
300 delattr(finder_options, o)
302 self.browser_type = finder_options.browser_type
304 if hasattr(self, 'extra_browser_args_as_string'): # pylint: disable=E1101
306 self.extra_browser_args_as_string) # pylint: disable=E1101
307 self.AppendExtraBrowserArgs(tmp)
308 delattr(self, 'extra_browser_args_as_string')
309 if hasattr(self, 'extra_wpr_args_as_string'): # pylint: disable=E1101
311 self.extra_wpr_args_as_string) # pylint: disable=E1101
312 self.extra_wpr_args.extend(tmp)
313 delattr(self, 'extra_wpr_args_as_string')
314 if self.profile_type == 'default':
315 self.dont_override_profile = True
317 if self.profile_dir and self.profile_type != 'clean':
319 "It's illegal to specify both --profile-type and --profile-dir.\n"
320 "For more information see: http://goo.gl/ngdGD5")
323 if self.profile_dir and not os.path.isdir(self.profile_dir):
325 "Directory specified by --profile-dir (%s) doesn't exist "
326 "or isn't a directory.\n"
327 "For more information see: http://goo.gl/ngdGD5" % self.profile_dir)
330 if not self.profile_dir:
331 self.profile_dir = profile_types.GetProfileDir(self.profile_type)
333 # This deferred import is necessary because browser_options is imported in
334 # telemetry/telemetry/__init__.py.
335 from telemetry.core.backends.chrome import chrome_browser_options
336 finder_options.browser_options = (
337 chrome_browser_options.CreateChromeBrowserOptions(self))
340 def extra_browser_args(self):
341 return self._extra_browser_args
343 def AppendExtraBrowserArgs(self, args):
344 if isinstance(args, list):
345 self._extra_browser_args.update(args)
347 self._extra_browser_args.add(args)