1 # Copyright (c) 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 repeat_options
15 from telemetry.core import util
16 from telemetry.core import wpr_modes
17 from telemetry.core.platform.profiler import profiler_finder
20 class BrowserFinderOptions(optparse.Values):
21 """Options to be used for discovering a browser."""
23 def __init__(self, browser_type=None):
24 optparse.Values.__init__(self)
26 self.browser_type = browser_type
27 self.browser_executable = None
28 self.chrome_root = None
29 self.android_device = None
30 self.cros_ssh_identity = None
32 self.extensions_to_load = []
34 # If set, copy the generated profile to this path on exit.
35 self.output_profile_path = None
37 self.cros_remote = None
42 self.page_filter = None
43 self.page_filter_exclude = None
45 self.repeat_options = repeat_options.RepeatOptions()
46 self.browser_options = BrowserOptions()
47 self.output_file = None
48 self.skip_navigate_on_repeat = False
50 self.android_rndis = False
53 return copy.deepcopy(self)
55 def CreateParser(self, *args, **kwargs):
56 parser = optparse.OptionParser(*args, **kwargs)
59 group = optparse.OptionGroup(parser, 'Which browser to use')
60 group.add_option('--browser',
63 help='Browser type to run, '
64 'in order of priority. Supported values: list,%s' %
65 browser_finder.ALL_BROWSER_TYPES)
66 group.add_option('--browser-executable',
67 dest='browser_executable',
68 help='The exact browser to run.')
69 group.add_option('--chrome-root',
71 help='Where to look for chrome builds.'
72 'Defaults to searching parent dirs by default.')
73 group.add_option('--device',
74 dest='android_device',
75 help='The android device ID to use'
76 'If not specified, only 0 or 1 connected devcies are supported.')
80 help='The IP address of a remote ChromeOS device to use.')
82 testing_rsa = os.path.join(
83 util.GetChromiumSrcDir(),
84 'third_party', 'chromite', 'ssh_keys', 'testing_rsa')
85 if os.path.exists(testing_rsa):
86 identity = testing_rsa
87 group.add_option('--identity',
88 dest='cros_ssh_identity',
90 help='The identity file to use when ssh\'ing into the ChromeOS device')
91 parser.add_option_group(group)
94 group = optparse.OptionGroup(parser, 'Page set options')
95 group.add_option('--pageset-shuffle', action='store_true',
96 dest='pageset_shuffle',
97 help='Shuffle the order of pages within a pageset.')
98 group.add_option('--pageset-shuffle-order-file',
99 dest='pageset_shuffle_order_file', default=None,
100 help='Filename of an output of a previously run test on the current ' +
101 'pageset. The tests will run in the same order again, overriding ' +
102 'what is specified by --page-repeat and --pageset-repeat.')
103 parser.add_option_group(group)
105 group = optparse.OptionGroup(parser, 'Web Page Replay options')
106 group.add_option('--allow-live-sites',
107 dest='allow_live_sites', action='store_true',
108 help='Run against live sites if the Web Page Replay archives don\'t '
109 'exist. Without this flag, the test will just fail instead '
110 'of running against live sites.')
111 parser.add_option_group(group)
114 group = optparse.OptionGroup(parser, 'When things go wrong')
115 profiler_choices = profiler_finder.GetAllAvailableProfilers()
117 '--profiler', default=None, type='choice',
118 choices=profiler_choices,
119 help=('Record profiling data using this tool. Supported values: ' +
120 ', '.join(profiler_choices)))
122 '-v', '--verbose', action='count', dest='verbosity',
123 help='Increase verbosity level (repeat as needed)')
124 group.add_option('--print-bootstrap-deps',
126 help='Output bootstrap deps list.')
127 parser.add_option_group(group)
130 group = optparse.OptionGroup(parser, 'Platform options')
131 group.add_option('--no-performance-mode', action='store_true',
132 help='Some platforms run on "full performance mode" where the '
133 'test is executed at maximum CPU speed in order to minimize noise '
134 '(specially important for dashboards / continuous builds). '
135 'This option prevents Telemetry from tweaking such platform settings.')
136 group.add_option('--android-rndis', dest='android_rndis', default=False,
137 action='store_true', help='Use RNDIS forwarding on Android.')
138 group.add_option('--no-android-rndis', dest='android_rndis',
139 action='store_false', help='Do not use RNDIS forwarding on Android.'
141 parser.add_option_group(group)
144 self.repeat_options.AddCommandLineOptions(parser)
147 self.browser_options.AddCommandLineOptions(parser)
149 real_parse = parser.parse_args
150 def ParseArgs(args=None):
151 defaults = parser.get_default_values()
152 for k, v in defaults.__dict__.items():
153 if k in self.__dict__ and self.__dict__[k] != None:
156 ret = real_parse(args, self) # pylint: disable=E1121
158 if self.verbosity >= 2:
159 logging.getLogger().setLevel(logging.DEBUG)
161 logging.getLogger().setLevel(logging.INFO)
163 logging.getLogger().setLevel(logging.WARNING)
165 if self.browser_executable and not self.browser_type:
166 self.browser_type = 'exact'
167 if self.browser_type == 'list':
169 types = browser_finder.GetAllAvailableBrowserTypes(self)
170 except browser_finder.BrowserFinderException, ex:
171 sys.stderr.write('ERROR: ' + str(ex))
173 sys.stdout.write('Available browsers:\n')
174 sys.stdout.write(' %s\n' % '\n '.join(types))
177 # Parse repeat options.
178 self.repeat_options.UpdateFromParseResults(self, parser)
180 # Parse browser options.
181 self.browser_options.UpdateFromParseResults(self)
184 parser.parse_args = ParseArgs
187 def AppendExtraBrowserArgs(self, args):
188 self.browser_options.AppendExtraBrowserArgs(args)
190 def MergeDefaultValues(self, defaults):
191 for k, v in defaults.__dict__.items():
192 self.ensure_value(k, v)
194 class BrowserOptions(object):
195 """Options to be used for launching a browser."""
197 self.browser_type = None
198 self.show_stdout = False
200 # When set to True, the browser will use the default profile. Telemetry
201 # will not provide an alternate profile directory.
202 self.dont_override_profile = False
203 self.profile_dir = None
204 self.profile_type = None
205 self._extra_browser_args = set()
206 self.extra_wpr_args = []
207 self.wpr_mode = wpr_modes.WPR_OFF
209 self.no_proxy_server = False
210 self.browser_user_agent_type = None
212 self.clear_sytem_cache_for_browser_and_profile_on_start = False
213 self.startup_url = None
215 self.keep_test_server_ports = False
217 # Background pages of built-in component extensions can interfere with
218 # performance measurements.
219 self.disable_component_extensions_with_background_pages = True
221 def AddCommandLineOptions(self, parser):
222 group = optparse.OptionGroup(parser, 'Browser options')
223 profile_choices = profile_types.GetProfileTypes()
224 group.add_option('--profile-type',
228 choices=profile_choices,
229 help=('The user profile to use. A clean profile is used by default. '
230 'Supported values: ' + ', '.join(profile_choices)))
231 group.add_option('--profile-dir',
233 help='Profile directory to launch the browser with. '
234 'A clean profile is used by default')
235 group.add_option('--extra-browser-args',
236 dest='extra_browser_args_as_string',
237 help='Additional arguments to pass to the browser when it starts')
238 group.add_option('--extra-wpr-args',
239 dest='extra_wpr_args_as_string',
240 help=('Additional arguments to pass to Web Page Replay. '
241 'See third_party/webpagereplay/replay.py for usage.'))
242 group.add_option('--show-stdout',
244 help='When possible, will display the stdout of the process')
245 parser.add_option_group(group)
247 # Android options. TODO(achuith): Move to AndroidBrowserOptions.
248 group = optparse.OptionGroup(parser, 'Android options')
249 group.add_option('--keep_test_server_ports',
251 help='Indicates the test server ports must be kept. When this is run '
252 'via a sharder the test server ports should be kept and should '
254 parser.add_option_group(group)
256 group = optparse.OptionGroup(parser, 'Compatibility options')
257 group.add_option('--gtest_output',
258 help='Ignored argument for compatibility with runtest.py harness')
259 parser.add_option_group(group)
262 def UpdateFromParseResults(self, finder_options):
263 """Copies our options from finder_options"""
264 browser_options_list = [
265 'profile_type', 'profile_dir',
266 'extra_browser_args_as_string', 'extra_wpr_args_as_string',
269 for o in browser_options_list:
270 a = getattr(finder_options, o, None)
273 delattr(finder_options, o)
275 self.browser_type = finder_options.browser_type
277 if hasattr(self, 'extra_browser_args_as_string'): # pylint: disable=E1101
279 self.extra_browser_args_as_string) # pylint: disable=E1101
280 self.AppendExtraBrowserArgs(tmp)
281 delattr(self, 'extra_browser_args_as_string')
282 if hasattr(self, 'extra_wpr_args_as_string'): # pylint: disable=E1101
284 self.extra_wpr_args_as_string) # pylint: disable=E1101
285 self.extra_wpr_args.extend(tmp)
286 delattr(self, 'extra_wpr_args_as_string')
287 if self.profile_type == 'default':
288 self.dont_override_profile = True
290 if self.profile_dir and self.profile_type != 'clean':
291 raise Exception("It's illegal to specify both --profile-type and"
294 if self.profile_dir and not os.path.isdir(self.profile_dir):
295 raise Exception("Directory specified by --profile-dir (%s) doesn't"
296 " exist or isn't a directory." % (self.profile_dir))
298 if not self.profile_dir:
299 self.profile_dir = profile_types.GetProfileDir(self.profile_type)
301 # This deferred import is necessary because browser_options is imported in
302 # telemetry/telemetry/__init__.py.
303 from telemetry.core.backends.chrome import chrome_browser_options
304 finder_options.browser_options = (
305 chrome_browser_options.CreateChromeBrowserOptions(self))
308 def extra_browser_args(self):
309 return self._extra_browser_args
311 def AppendExtraBrowserArgs(self, args):
312 if isinstance(args, list):
313 self._extra_browser_args.update(args)
315 self._extra_browser_args.add(args)