blob: a3bff696da3c7d1bd3f8ad099f561d9543d8f115 [file] [log] [blame]
borenetdc89ca52014-10-17 07:37:05 -07001#!/usr/bin/env python
2# Copyright (c) 2012 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Archives or replays webpages and creates SKPs in a Google Storage location.
7
8To archive webpages and store SKP files (archives should be rarely updated):
9
kkinnunenfcf35c52014-12-03 05:51:24 -080010cd skia
kkinnunenb4ee7ea2015-03-31 00:18:26 -070011python tools/skp/webpages_playback.py --data_store=gs://rmistry --record \
borenetdc89ca52014-10-17 07:37:05 -070012--page_sets=all --skia_tools=/home/default/trunk/out/Debug/ \
13--browser_executable=/tmp/chromium/out/Release/chrome
14
kkinnunenb4ee7ea2015-03-31 00:18:26 -070015The above command uses Google Storage bucket 'rmistry' to download needed files.
borenetdc89ca52014-10-17 07:37:05 -070016
17To replay archived webpages and re-generate SKP files (should be run whenever
18SkPicture.PICTURE_VERSION changes):
19
kkinnunenfcf35c52014-12-03 05:51:24 -080020cd skia
kkinnunenb4ee7ea2015-03-31 00:18:26 -070021python tools/skp/webpages_playback.py --data_store=gs://rmistry \
borenetdc89ca52014-10-17 07:37:05 -070022--page_sets=all --skia_tools=/home/default/trunk/out/Debug/ \
23--browser_executable=/tmp/chromium/out/Release/chrome
24
25
26Specify the --page_sets flag (default value is 'all') to pick a list of which
27webpages should be archived and/or replayed. Eg:
28
kkinnunenfcf35c52014-12-03 05:51:24 -080029--page_sets=tools/skp/page_sets/skia_yahooanswers_desktop.py,\
30tools/skp/page_sets/skia_googlecalendar_nexus10.py
borenetdc89ca52014-10-17 07:37:05 -070031
32The --browser_executable flag should point to the browser binary you want to use
33to capture archives and/or capture SKP files. Majority of the time it should be
34a newly built chrome binary.
35
kkinnunenb4ee7ea2015-03-31 00:18:26 -070036The --data_store flag controls where the needed artifacts, such as
37credential files, are downloaded from. It also controls where the
38generated artifacts, such as recorded webpages and resulting skp renderings,
39are uploaded to. URLs with scheme 'gs://' use Google Storage. Otherwise
40use local filesystem.
41
42The --upload=True flag means generated artifacts will be
43uploaded or copied to the location specified by --data_store. (default value is
44False if not specified).
borenetdc89ca52014-10-17 07:37:05 -070045
46The --non-interactive flag controls whether the script will prompt the user
47(default value is False if not specified).
48
49The --skia_tools flag if specified will allow this script to run
50debugger, render_pictures, and render_pdfs on the captured
51SKP(s). The tools are run after all SKPs are succesfully captured to make sure
52they can be added to the buildbots with no breakages.
borenetdc89ca52014-10-17 07:37:05 -070053"""
54
55import glob
56import optparse
57import os
58import posixpath
59import shutil
60import subprocess
61import sys
62import tempfile
63import time
64import traceback
65
66sys.path.insert(0, os.getcwd())
67
68from common.py.utils import gs_utils
69from common.py.utils import shell_utils
70
71ROOT_PLAYBACK_DIR_NAME = 'playback'
72SKPICTURES_DIR_NAME = 'skps'
73
74
75# Local archive and SKP directories.
76LOCAL_PLAYBACK_ROOT_DIR = os.path.join(
77 tempfile.gettempdir(), ROOT_PLAYBACK_DIR_NAME)
78LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR = os.path.join(
79 os.path.abspath(os.path.dirname(__file__)), 'page_sets', 'data')
80TMP_SKP_DIR = tempfile.mkdtemp()
81
rmistryf802f322014-10-22 05:04:43 -070082# Location of the credentials.json file and the string that represents missing
83# passwords.
84CREDENTIALS_FILE_PATH = os.path.join(
85 os.path.abspath(os.path.dirname(__file__)), 'page_sets', 'data',
86 'credentials.json'
87)
88
borenetdc89ca52014-10-17 07:37:05 -070089# Name of the SKP benchmark
90SKP_BENCHMARK = 'skpicture_printer'
91
92# The max base name length of Skp files.
93MAX_SKP_BASE_NAME_LEN = 31
94
95# Dictionary of device to platform prefixes for SKP files.
96DEVICE_TO_PLATFORM_PREFIX = {
97 'desktop': 'desk',
98 'galaxynexus': 'mobi',
99 'nexus10': 'tabl'
100}
101
102# How many times the record_wpr binary should be retried.
103RETRY_RECORD_WPR_COUNT = 5
borenet78399152014-10-17 12:15:46 -0700104# How many times the run_benchmark binary should be retried.
borenetdc89ca52014-10-17 07:37:05 -0700105RETRY_RUN_MEASUREMENT_COUNT = 5
106
rmistryf802f322014-10-22 05:04:43 -0700107# Location of the credentials.json file in Google Storage.
108CREDENTIALS_GS_PATH = '/playback/credentials/credentials.json'
109
borenetdc89ca52014-10-17 07:37:05 -0700110X11_DISPLAY = os.getenv('DISPLAY', ':0')
111
112GS_PREDEFINED_ACL = gs_utils.GSUtils.PredefinedACL.PRIVATE
113GS_FINE_GRAINED_ACL_LIST = [
114 (gs_utils.GSUtils.IdType.GROUP_BY_DOMAIN, 'google.com',
115 gs_utils.GSUtils.Permission.READ),
116]
117
kkinnunene75d2d22014-12-03 04:38:46 -0800118def remove_prefix(s, prefix):
119 if s.startswith(prefix):
120 return s[len(prefix):]
121 return s
borenetdc89ca52014-10-17 07:37:05 -0700122
123class SkPicturePlayback(object):
124 """Class that archives or replays webpages and creates SKPs."""
125
126 def __init__(self, parse_options):
127 """Constructs a SkPicturePlayback BuildStep instance."""
128 assert parse_options.browser_executable, 'Must specify --browser_executable'
129 self._browser_executable = parse_options.browser_executable
130
131 self._all_page_sets_specified = parse_options.page_sets == 'all'
132 self._page_sets = self._ParsePageSets(parse_options.page_sets)
133
borenetdc89ca52014-10-17 07:37:05 -0700134 self._record = parse_options.record
135 self._skia_tools = parse_options.skia_tools
136 self._non_interactive = parse_options.non_interactive
kkinnunenb4ee7ea2015-03-31 00:18:26 -0700137 self._upload = parse_options.upload
138 data_store_location = parse_options.data_store
139 if data_store_location.startswith(gs_utils.GS_PREFIX):
140 self.gs = GoogleStorageDataStore(data_store_location)
141 else:
142 self.gs = LocalFileSystemDataStore(data_store_location)
borenetdc89ca52014-10-17 07:37:05 -0700143 self._alternate_upload_dir = parse_options.alternate_upload_dir
borenetdc89ca52014-10-17 07:37:05 -0700144 self._telemetry_binaries_dir = os.path.join(parse_options.chrome_src_path,
145 'tools', 'perf')
146
147 self._local_skp_dir = os.path.join(
148 parse_options.output_dir, ROOT_PLAYBACK_DIR_NAME, SKPICTURES_DIR_NAME)
149 self._local_record_webpages_archive_dir = os.path.join(
150 parse_options.output_dir, ROOT_PLAYBACK_DIR_NAME, 'webpages_archive')
151
152 # List of SKP files generated by this script.
153 self._skp_files = []
154
155 def _ParsePageSets(self, page_sets):
156 if not page_sets:
157 raise ValueError('Must specify at least one page_set!')
158 elif self._all_page_sets_specified:
159 # Get everything from the page_sets directory.
160 page_sets_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)),
161 'page_sets')
162 ps = [os.path.join(page_sets_dir, page_set)
163 for page_set in os.listdir(page_sets_dir)
164 if not os.path.isdir(os.path.join(page_sets_dir, page_set)) and
165 page_set.endswith('.py')]
166 elif '*' in page_sets:
167 # Explode and return the glob.
168 ps = glob.glob(page_sets)
169 else:
170 ps = page_sets.split(',')
171 ps.sort()
172 return ps
173
174 def Run(self):
175 """Run the SkPicturePlayback BuildStep."""
176
rmistryf802f322014-10-22 05:04:43 -0700177 # Download the credentials file if it was not previously downloaded.
kkinnunenb4ee7ea2015-03-31 00:18:26 -0700178 if not os.path.isfile(CREDENTIALS_FILE_PATH):
179 # Download the credentials.json file from Google Storage.
180 self.gs.download_file(CREDENTIALS_GS_PATH, CREDENTIALS_FILE_PATH)
181
182 if not os.path.isfile(CREDENTIALS_FILE_PATH):
183 print """\n\nCould not locate credentials file in the storage.
184 Please create a %s file that contains:
rmistryf802f322014-10-22 05:04:43 -0700185 {
186 "google": {
187 "username": "google_testing_account_username",
188 "password": "google_testing_account_password"
189 },
190 "facebook": {
191 "username": "facebook_testing_account_username",
192 "password": "facebook_testing_account_password"
193 }
194 }\n\n""" % CREDENTIALS_FILE_PATH
195 raw_input("Please press a key when you are ready to proceed...")
rmistryf802f322014-10-22 05:04:43 -0700196
borenetdc89ca52014-10-17 07:37:05 -0700197 # Delete any left over data files in the data directory.
198 for archive_file in glob.glob(
199 os.path.join(LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR, 'skia_*')):
200 os.remove(archive_file)
201
202 # Delete the local root directory if it already exists.
203 if os.path.exists(LOCAL_PLAYBACK_ROOT_DIR):
204 shutil.rmtree(LOCAL_PLAYBACK_ROOT_DIR)
205
206 # Create the required local storage directories.
207 self._CreateLocalStorageDirs()
208
209 # Start the timer.
210 start_time = time.time()
211
212 # Loop through all page_sets.
213 for page_set in self._page_sets:
214
rmistry7620bf02014-10-27 06:42:11 -0700215 page_set_basename = os.path.basename(page_set).split('.')[0]
216 page_set_json_name = page_set_basename + '.json'
borenetdc89ca52014-10-17 07:37:05 -0700217 wpr_data_file = page_set.split(os.path.sep)[-1].split('.')[0] + '_000.wpr'
rmistry7620bf02014-10-27 06:42:11 -0700218 page_set_dir = os.path.dirname(page_set)
borenetdc89ca52014-10-17 07:37:05 -0700219
220 if self._record:
221 # Create an archive of the specified webpages if '--record=True' is
222 # specified.
223 record_wpr_cmd = (
rmistry7620bf02014-10-27 06:42:11 -0700224 'PYTHONPATH=%s:$PYTHONPATH' % page_set_dir,
borenetdc89ca52014-10-17 07:37:05 -0700225 'DISPLAY=%s' % X11_DISPLAY,
226 os.path.join(self._telemetry_binaries_dir, 'record_wpr'),
227 '--extra-browser-args=--disable-setuid-sandbox',
228 '--browser=exact',
229 '--browser-executable=%s' % self._browser_executable,
rmistry7620bf02014-10-27 06:42:11 -0700230 '%s_page_set' % page_set_basename,
231 '--page-set-base-dir=%s' % page_set_dir
borenetdc89ca52014-10-17 07:37:05 -0700232 )
233 for _ in range(RETRY_RECORD_WPR_COUNT):
rmistry0ec28af2014-10-28 14:25:17 -0700234 try:
235 shell_utils.run(' '.join(record_wpr_cmd), shell=True)
kkinnunenf9310fe2015-03-29 22:33:16 -0700236
237 # Move over the created archive into the local webpages archive
238 # directory.
239 shutil.move(
240 os.path.join(LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR, wpr_data_file),
241 self._local_record_webpages_archive_dir)
242 shutil.move(
243 os.path.join(LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR,
244 page_set_json_name),
245 self._local_record_webpages_archive_dir)
246
borenetdc89ca52014-10-17 07:37:05 -0700247 # Break out of the retry loop since there were no errors.
248 break
rmistry0ec28af2014-10-28 14:25:17 -0700249 except Exception:
250 # There was a failure continue with the loop.
251 traceback.print_exc()
borenetdc89ca52014-10-17 07:37:05 -0700252 else:
253 # If we get here then record_wpr did not succeed and thus did not
254 # break out of the loop.
255 raise Exception('record_wpr failed for page_set: %s' % page_set)
256
257 else:
kkinnunenb4ee7ea2015-03-31 00:18:26 -0700258 # Get the webpages archive so that it can be replayed.
259 self._DownloadWebpagesArchive(wpr_data_file, page_set_json_name)
borenetdc89ca52014-10-17 07:37:05 -0700260
borenet78399152014-10-17 12:15:46 -0700261 run_benchmark_cmd = (
rmistryf802f322014-10-22 05:04:43 -0700262 'PYTHONPATH=%s:$PYTHONPATH' % page_set_dir,
borenetdc89ca52014-10-17 07:37:05 -0700263 'DISPLAY=%s' % X11_DISPLAY,
264 'timeout', '300',
borenet78399152014-10-17 12:15:46 -0700265 os.path.join(self._telemetry_binaries_dir, 'run_benchmark'),
borenetdc89ca52014-10-17 07:37:05 -0700266 '--extra-browser-args=--disable-setuid-sandbox',
267 '--browser=exact',
268 '--browser-executable=%s' % self._browser_executable,
269 SKP_BENCHMARK,
rmistry7620bf02014-10-27 06:42:11 -0700270 '--page-set-name=%s' % page_set_basename,
rmistryf802f322014-10-22 05:04:43 -0700271 '--page-set-base-dir=%s' % page_set_dir,
272 '--skp-outdir=%s' % TMP_SKP_DIR,
273 '--also-run-disabled-tests'
borenetdc89ca52014-10-17 07:37:05 -0700274 )
borenetdc89ca52014-10-17 07:37:05 -0700275
276 for _ in range(RETRY_RUN_MEASUREMENT_COUNT):
277 try:
278 print '\n\n=======Capturing SKP of %s=======\n\n' % page_set
borenet78399152014-10-17 12:15:46 -0700279 shell_utils.run(' '.join(run_benchmark_cmd), shell=True)
borenetdc89ca52014-10-17 07:37:05 -0700280 except shell_utils.CommandFailedException:
281 # skpicture_printer sometimes fails with AssertionError but the
282 # captured SKP is still valid. This is a known issue.
283 pass
284
borenetdc89ca52014-10-17 07:37:05 -0700285 # Rename generated SKP files into more descriptive names.
286 try:
287 self._RenameSkpFiles(page_set)
288 # Break out of the retry loop since there were no errors.
289 break
290 except Exception:
291 # There was a failure continue with the loop.
292 traceback.print_exc()
293 print '\n\n=======Retrying %s=======\n\n' % page_set
294 time.sleep(10)
295 else:
borenet78399152014-10-17 12:15:46 -0700296 # If we get here then run_benchmark did not succeed and thus did not
borenetdc89ca52014-10-17 07:37:05 -0700297 # break out of the loop.
borenet78399152014-10-17 12:15:46 -0700298 raise Exception('run_benchmark failed for page_set: %s' % page_set)
borenetdc89ca52014-10-17 07:37:05 -0700299
borenetdc89ca52014-10-17 07:37:05 -0700300 print '\n\n=======Capturing SKP files took %s seconds=======\n\n' % (
301 time.time() - start_time)
302
303 if self._skia_tools:
304 render_pictures_cmd = [
305 os.path.join(self._skia_tools, 'render_pictures'),
306 '-r', self._local_skp_dir
307 ]
308 render_pdfs_cmd = [
309 os.path.join(self._skia_tools, 'render_pdfs'),
kkinnunen3a6aa862014-12-03 04:22:06 -0800310 '-r', self._local_skp_dir
borenetdc89ca52014-10-17 07:37:05 -0700311 ]
312
313 for tools_cmd in (render_pictures_cmd, render_pdfs_cmd):
314 print '\n\n=======Running %s=======' % ' '.join(tools_cmd)
315 proc = subprocess.Popen(tools_cmd)
rmistry0ec28af2014-10-28 14:25:17 -0700316 (code, _) = shell_utils.log_process_after_completion(proc, echo=False)
borenetdc89ca52014-10-17 07:37:05 -0700317 if code != 0:
318 raise Exception('%s failed!' % ' '.join(tools_cmd))
319
320 if not self._non_interactive:
321 print '\n\n=======Running debugger======='
322 os.system('%s %s' % (os.path.join(self._skia_tools, 'debugger'),
kkinnunen960fb502014-12-03 06:18:12 -0800323 self._local_skp_dir))
borenetdc89ca52014-10-17 07:37:05 -0700324
325 print '\n\n'
326
kkinnunenb4ee7ea2015-03-31 00:18:26 -0700327 if self._upload:
328 print '\n\n=======Uploading to %s=======\n\n' % self.gs.target_type()
borenetdc89ca52014-10-17 07:37:05 -0700329 # Copy the directory structure in the root directory into Google Storage.
330 dest_dir_name = ROOT_PLAYBACK_DIR_NAME
331 if self._alternate_upload_dir:
332 dest_dir_name = self._alternate_upload_dir
333
kkinnunenb4ee7ea2015-03-31 00:18:26 -0700334 self.gs.upload_dir_contents(
335 LOCAL_PLAYBACK_ROOT_DIR, dest_dir_name,
borenetdc89ca52014-10-17 07:37:05 -0700336 upload_if=gs_utils.GSUtils.UploadIf.IF_MODIFIED,
337 predefined_acl=GS_PREDEFINED_ACL,
338 fine_grained_acl_list=GS_FINE_GRAINED_ACL_LIST)
339
340 print '\n\n=======New SKPs have been uploaded to %s =======\n\n' % (
kkinnunenb4ee7ea2015-03-31 00:18:26 -0700341 posixpath.join(self.gs.target_name(), dest_dir_name,
342 SKPICTURES_DIR_NAME))
borenetdc89ca52014-10-17 07:37:05 -0700343 else:
kkinnunenb4ee7ea2015-03-31 00:18:26 -0700344 print '\n\n=======Not Uploading to %s=======\n\n' % self.gs.target_type()
borenetdc89ca52014-10-17 07:37:05 -0700345 print 'Generated resources are available in %s\n\n' % (
346 LOCAL_PLAYBACK_ROOT_DIR)
347
348 return 0
349
350 def _RenameSkpFiles(self, page_set):
351 """Rename generated SKP files into more descriptive names.
352
353 Look into the subdirectory of TMP_SKP_DIR and find the most interesting
354 .skp in there to be this page_set's representative .skp.
355 """
356 # Here's where we're assuming there's one page per pageset.
357 # If there were more than one, we'd overwrite filename below.
358
359 # /path/to/skia_yahooanswers_desktop.json -> skia_yahooanswers_desktop.json
360 _, ps_filename = os.path.split(page_set)
361 # skia_yahooanswers_desktop.json -> skia_yahooanswers_desktop
362 ps_basename, _ = os.path.splitext(ps_filename)
363 # skia_yahooanswers_desktop -> skia, yahooanswers, desktop
364 _, page_name, device = ps_basename.split('_')
365
366 basename = '%s_%s' % (DEVICE_TO_PLATFORM_PREFIX[device], page_name)
367 filename = basename[:MAX_SKP_BASE_NAME_LEN] + '.skp'
368
369 subdirs = glob.glob(os.path.join(TMP_SKP_DIR, '*'))
370 assert len(subdirs) == 1
371 for site in subdirs:
372 # We choose the largest .skp as the most likely to be interesting.
373 largest_skp = max(glob.glob(os.path.join(site, '*.skp')),
374 key=lambda path: os.stat(path).st_size)
375 dest = os.path.join(self._local_skp_dir, filename)
376 print 'Moving', largest_skp, 'to', dest
377 shutil.move(largest_skp, dest)
378 self._skp_files.append(filename)
379 shutil.rmtree(site)
380
381 def _CreateLocalStorageDirs(self):
382 """Creates required local storage directories for this script."""
383 for d in (self._local_record_webpages_archive_dir,
384 self._local_skp_dir):
385 if os.path.exists(d):
386 shutil.rmtree(d)
387 os.makedirs(d)
388
rmistry7620bf02014-10-27 06:42:11 -0700389 def _DownloadWebpagesArchive(self, wpr_data_file, page_set_json_name):
borenetdc89ca52014-10-17 07:37:05 -0700390 """Downloads the webpages archive and its required page set from GS."""
391 wpr_source = posixpath.join(ROOT_PLAYBACK_DIR_NAME, 'webpages_archive',
392 wpr_data_file)
393 page_set_source = posixpath.join(ROOT_PLAYBACK_DIR_NAME,
394 'webpages_archive',
rmistry7620bf02014-10-27 06:42:11 -0700395 page_set_json_name)
kkinnunenb4ee7ea2015-03-31 00:18:26 -0700396 gs = self.gs
397 if (gs.does_storage_object_exist(wpr_source) and
398 gs.does_storage_object_exist(page_set_source)):
399 gs.download_file(wpr_source,
borenetdc89ca52014-10-17 07:37:05 -0700400 os.path.join(LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR,
401 wpr_data_file))
kkinnunenb4ee7ea2015-03-31 00:18:26 -0700402 gs.download_file(page_set_source,
borenetdc89ca52014-10-17 07:37:05 -0700403 os.path.join(LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR,
rmistry7620bf02014-10-27 06:42:11 -0700404 page_set_json_name))
borenetdc89ca52014-10-17 07:37:05 -0700405 else:
kkinnunenb4ee7ea2015-03-31 00:18:26 -0700406 raise Exception('%s and %s do not exist in %s!' % (gs.target_type(),
407 wpr_source, page_set_source))
borenetdc89ca52014-10-17 07:37:05 -0700408
kkinnunenb4ee7ea2015-03-31 00:18:26 -0700409class DataStore:
410 """An abstract base class for uploading recordings to a data storage.
411 The interface emulates the google storage api."""
412 def target_name(self):
413 raise NotImplementedError()
414 def target_type(self):
415 raise NotImplementedError()
416 def does_storage_object_exist(self, *args):
417 raise NotImplementedError()
418 def download_file(self, *args):
419 raise NotImplementedError()
420 def upload_dir_contents(self, source_dir, **kwargs):
421 raise NotImplementedError()
422
423class GoogleStorageDataStore(DataStore):
424 def __init__(self, data_store_url):
425 self._data_store_url = data_store_url
426 self._bucket = remove_prefix(self._data_store_url.lstrip(),
427 gs_utils.GS_PREFIX)
428 self.gs = gs_utils.GSUtils()
429 def target_name(self):
430 return self._data_store_url
431 def target_type(self):
432 return 'Google Storage'
433 def does_storage_object_exist(self, *args):
434 return self.gs.does_storage_object_exist(self._bucket, *args)
435 def download_file(self, *args):
436 self.gs.download_file(self._bucket, *args)
437 def upload_dir_contents(self, source_dir, **kwargs):
438 self.gs.upload_dir_contents(source_dir, self._bucket, **kwargs)
439
440class LocalFileSystemDataStore(DataStore):
441 def __init__(self, data_store_location):
442 self._base_dir = data_store_location
443 def target_name(self):
444 return self._base_dir
445 def target_type(self):
446 return self._base_dir
447 def does_storage_object_exist(self, name, *args):
448 return os.path.isfile(os.path.join(self._base_dir, name))
449 def download_file(self, name, local_path, *args):
450 shutil.copyfile(os.path.join(self._base_dir, name), local_path)
451 def upload_dir_contents(self, source_dir, dest_dir, **kwargs):
452 def copytree(source_dir, dest_dir):
453 if not os.path.exists(dest_dir):
454 os.makedirs(dest_dir)
455 for item in os.listdir(source_dir):
456 source = os.path.join(source_dir, item)
457 dest = os.path.join(dest_dir, item)
458 if os.path.isdir(source):
459 copytree(source, dest)
460 else:
461 shutil.copy2(source, dest)
462 copytree(source_dir, os.path.join(self._base_dir, dest_dir))
borenetdc89ca52014-10-17 07:37:05 -0700463
464if '__main__' == __name__:
465 option_parser = optparse.OptionParser()
466 option_parser.add_option(
467 '', '--page_sets',
468 help='Specifies the page sets to use to archive. Supports globs.',
469 default='all')
470 option_parser.add_option(
borenetdc89ca52014-10-17 07:37:05 -0700471 '', '--record', action='store_true',
472 help='Specifies whether a new website archive should be created.',
473 default=False)
474 option_parser.add_option(
borenetdc89ca52014-10-17 07:37:05 -0700475 '', '--skia_tools',
476 help=('Path to compiled Skia executable tools. '
477 'render_pictures/render_pdfs is run on the set '
478 'after all SKPs are captured. If the script is run without '
479 '--non-interactive then the debugger is also run at the end. Debug '
480 'builds are recommended because they seem to catch more failures '
481 'than Release builds.'),
482 default=None)
483 option_parser.add_option(
kkinnunenb4ee7ea2015-03-31 00:18:26 -0700484 '', '--upload', action='store_true',
485 help=('Uploads to Google Storage or copies to local filesystem storage '
486 ' if this is True.'),
borenetdc89ca52014-10-17 07:37:05 -0700487 default=False)
488 option_parser.add_option(
kkinnunenb4ee7ea2015-03-31 00:18:26 -0700489 '', '--data_store',
490 help=('The location of the file storage to use to download and upload '
491 'files. Can be \'gs://<bucket>\' for Google Storage, or '
492 'a directory for local filesystem storage'),
493 default='gs://chromium-skia-gm')
494 option_parser.add_option(
borenetdc89ca52014-10-17 07:37:05 -0700495 '', '--alternate_upload_dir',
kkinnunenb4ee7ea2015-03-31 00:18:26 -0700496 help= ('Uploads to a different directory in Google Storage or local '
497 'storage if this flag is specified'),
borenetdc89ca52014-10-17 07:37:05 -0700498 default=None)
499 option_parser.add_option(
500 '', '--output_dir',
kkinnunenb4ee7ea2015-03-31 00:18:26 -0700501 help=('Temporary directory where SKPs and webpage archives will be '
502 'outputted to.'),
borenetdc89ca52014-10-17 07:37:05 -0700503 default=tempfile.gettempdir())
504 option_parser.add_option(
505 '', '--browser_executable',
506 help='The exact browser executable to run.',
507 default=None)
508 option_parser.add_option(
509 '', '--chrome_src_path',
510 help='Path to the chromium src directory.',
511 default=None)
512 option_parser.add_option(
513 '', '--non-interactive', action='store_true',
514 help='Runs the script without any prompts. If this flag is specified and '
515 '--skia_tools is specified then the debugger is not run.',
516 default=False)
517 options, unused_args = option_parser.parse_args()
518
519 playback = SkPicturePlayback(options)
520 sys.exit(playback.Run())