1*c8dee2aaSAndroid Build Coastguard Worker#!/usr/bin/env python 2*c8dee2aaSAndroid Build Coastguard Worker# Copyright (c) 2012 The Chromium Authors. All rights reserved. 3*c8dee2aaSAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 4*c8dee2aaSAndroid Build Coastguard Worker# found in the LICENSE file. 5*c8dee2aaSAndroid Build Coastguard Worker 6*c8dee2aaSAndroid Build Coastguard Worker"""Archives or replays webpages and creates SKPs in a Google Storage location. 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard WorkerTo archive webpages and store SKP files (archives should be rarely updated): 9*c8dee2aaSAndroid Build Coastguard Worker 10*c8dee2aaSAndroid Build Coastguard Workercd skia 11*c8dee2aaSAndroid Build Coastguard Workerpython tools/skp/webpages_playback.py --data_store=gs://your-bucket-name \ 12*c8dee2aaSAndroid Build Coastguard Worker--record --page_sets=all --skia_tools=/home/default/trunk/out/Debug/ \ 13*c8dee2aaSAndroid Build Coastguard Worker--browser_executable=/tmp/chromium/out/Release/chrome 14*c8dee2aaSAndroid Build Coastguard Worker 15*c8dee2aaSAndroid Build Coastguard WorkerThe above command uses Google Storage bucket 'your-bucket-name' to download 16*c8dee2aaSAndroid Build Coastguard Workerneeded files. 17*c8dee2aaSAndroid Build Coastguard Worker 18*c8dee2aaSAndroid Build Coastguard WorkerTo replay archived webpages and re-generate SKP files (should be run whenever 19*c8dee2aaSAndroid Build Coastguard WorkerSkPicture.PICTURE_VERSION changes): 20*c8dee2aaSAndroid Build Coastguard Worker 21*c8dee2aaSAndroid Build Coastguard Workercd skia 22*c8dee2aaSAndroid Build Coastguard Workerpython tools/skp/webpages_playback.py --data_store=gs://your-bucket-name \ 23*c8dee2aaSAndroid Build Coastguard Worker--page_sets=all --skia_tools=/home/default/trunk/out/Debug/ \ 24*c8dee2aaSAndroid Build Coastguard Worker--browser_executable=/tmp/chromium/out/Release/chrome 25*c8dee2aaSAndroid Build Coastguard Worker 26*c8dee2aaSAndroid Build Coastguard Worker 27*c8dee2aaSAndroid Build Coastguard WorkerSpecify the --page_sets flag (default value is 'all') to pick a list of which 28*c8dee2aaSAndroid Build Coastguard Workerwebpages should be archived and/or replayed. Eg: 29*c8dee2aaSAndroid Build Coastguard Worker 30*c8dee2aaSAndroid Build Coastguard Worker--page_sets=tools/skp/page_sets/skia_yahooanswers_desktop.py,\ 31*c8dee2aaSAndroid Build Coastguard Workertools/skp/page_sets/skia_googlecalendar_nexus10.py 32*c8dee2aaSAndroid Build Coastguard Worker 33*c8dee2aaSAndroid Build Coastguard WorkerThe --browser_executable flag should point to the browser binary you want to use 34*c8dee2aaSAndroid Build Coastguard Workerto capture archives and/or capture SKP files. Majority of the time it should be 35*c8dee2aaSAndroid Build Coastguard Workera newly built chrome binary. 36*c8dee2aaSAndroid Build Coastguard Worker 37*c8dee2aaSAndroid Build Coastguard WorkerThe --data_store flag controls where the needed artifacts are downloaded from. 38*c8dee2aaSAndroid Build Coastguard WorkerIt also controls where the generated artifacts, such as recorded webpages and 39*c8dee2aaSAndroid Build Coastguard Workerresulting skp renderings, are uploaded to. URLs with scheme 'gs://' use Google 40*c8dee2aaSAndroid Build Coastguard WorkerStorage. Otherwise use local filesystem. 41*c8dee2aaSAndroid Build Coastguard Worker 42*c8dee2aaSAndroid Build Coastguard WorkerThe --upload=True flag means generated artifacts will be 43*c8dee2aaSAndroid Build Coastguard Workeruploaded or copied to the location specified by --data_store. (default value is 44*c8dee2aaSAndroid Build Coastguard WorkerFalse if not specified). 45*c8dee2aaSAndroid Build Coastguard Worker 46*c8dee2aaSAndroid Build Coastguard WorkerThe --non-interactive flag controls whether the script will prompt the user 47*c8dee2aaSAndroid Build Coastguard Worker(default value is False if not specified). 48*c8dee2aaSAndroid Build Coastguard Worker 49*c8dee2aaSAndroid Build Coastguard WorkerThe --skia_tools flag if specified will allow this script to run 50*c8dee2aaSAndroid Build Coastguard Workerdebugger, render_pictures, and render_pdfs on the captured 51*c8dee2aaSAndroid Build Coastguard WorkerSKP(s). The tools are run after all SKPs are succesfully captured to make sure 52*c8dee2aaSAndroid Build Coastguard Workerthey can be added to the buildbots with no breakages. 53*c8dee2aaSAndroid Build Coastguard Worker""" 54*c8dee2aaSAndroid Build Coastguard Worker 55*c8dee2aaSAndroid Build Coastguard Worker 56*c8dee2aaSAndroid Build Coastguard Workerfrom __future__ import print_function 57*c8dee2aaSAndroid Build Coastguard Workerimport datetime 58*c8dee2aaSAndroid Build Coastguard Workerimport glob 59*c8dee2aaSAndroid Build Coastguard Workerimport optparse 60*c8dee2aaSAndroid Build Coastguard Workerimport os 61*c8dee2aaSAndroid Build Coastguard Workerimport posixpath 62*c8dee2aaSAndroid Build Coastguard Workerimport shutil 63*c8dee2aaSAndroid Build Coastguard Workerimport subprocess 64*c8dee2aaSAndroid Build Coastguard Workerimport sys 65*c8dee2aaSAndroid Build Coastguard Workerimport tempfile 66*c8dee2aaSAndroid Build Coastguard Workerimport time 67*c8dee2aaSAndroid Build Coastguard Workerimport traceback 68*c8dee2aaSAndroid Build Coastguard Worker 69*c8dee2aaSAndroid Build Coastguard Worker 70*c8dee2aaSAndroid Build Coastguard WorkerROOT_PLAYBACK_DIR_NAME = 'playback' 71*c8dee2aaSAndroid Build Coastguard WorkerSKPICTURES_DIR_NAME = 'skps' 72*c8dee2aaSAndroid Build Coastguard Worker 73*c8dee2aaSAndroid Build Coastguard WorkerGS_PREFIX = 'gs://' 74*c8dee2aaSAndroid Build Coastguard Worker 75*c8dee2aaSAndroid Build Coastguard WorkerPARTNERS_GS_BUCKET = 'gs://chrome-partner-telemetry' 76*c8dee2aaSAndroid Build Coastguard Worker 77*c8dee2aaSAndroid Build Coastguard Worker# Local archive and SKP directories. 78*c8dee2aaSAndroid Build Coastguard WorkerLOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR = os.path.join( 79*c8dee2aaSAndroid Build Coastguard Worker os.path.abspath(os.path.dirname(__file__)), 'page_sets', 'data') 80*c8dee2aaSAndroid Build Coastguard WorkerTMP_SKP_DIR = tempfile.mkdtemp() 81*c8dee2aaSAndroid Build Coastguard Worker 82*c8dee2aaSAndroid Build Coastguard Worker# Location of the credentials.json file and the string that represents missing 83*c8dee2aaSAndroid Build Coastguard Worker# passwords. 84*c8dee2aaSAndroid Build Coastguard WorkerCREDENTIALS_FILE_PATH = os.path.join( 85*c8dee2aaSAndroid Build Coastguard Worker os.path.abspath(os.path.dirname(__file__)), 'page_sets', 'data', 86*c8dee2aaSAndroid Build Coastguard Worker 'credentials.json' 87*c8dee2aaSAndroid Build Coastguard Worker) 88*c8dee2aaSAndroid Build Coastguard Worker 89*c8dee2aaSAndroid Build Coastguard Worker# Name of the SKP benchmark 90*c8dee2aaSAndroid Build Coastguard WorkerSKP_BENCHMARK = 'skpicture_printer' 91*c8dee2aaSAndroid Build Coastguard Worker 92*c8dee2aaSAndroid Build Coastguard Worker# The max base name length of Skp files. 93*c8dee2aaSAndroid Build Coastguard WorkerMAX_SKP_BASE_NAME_LEN = 31 94*c8dee2aaSAndroid Build Coastguard Worker 95*c8dee2aaSAndroid Build Coastguard Worker# Dictionary of device to platform prefixes for SKP files. 96*c8dee2aaSAndroid Build Coastguard WorkerDEVICE_TO_PLATFORM_PREFIX = { 97*c8dee2aaSAndroid Build Coastguard Worker 'desktop': 'desk', 98*c8dee2aaSAndroid Build Coastguard Worker 'mobile': 'mobi', 99*c8dee2aaSAndroid Build Coastguard Worker 'tablet': 'tabl' 100*c8dee2aaSAndroid Build Coastguard Worker} 101*c8dee2aaSAndroid Build Coastguard Worker 102*c8dee2aaSAndroid Build Coastguard Worker# How many times the record_wpr binary should be retried. 103*c8dee2aaSAndroid Build Coastguard WorkerRETRY_RECORD_WPR_COUNT = 5 104*c8dee2aaSAndroid Build Coastguard Worker# How many times the run_benchmark binary should be retried. 105*c8dee2aaSAndroid Build Coastguard WorkerRETRY_RUN_MEASUREMENT_COUNT = 3 106*c8dee2aaSAndroid Build Coastguard Worker 107*c8dee2aaSAndroid Build Coastguard Worker# Location of the credentials.json file in Google Storage. 108*c8dee2aaSAndroid Build Coastguard WorkerCREDENTIALS_GS_PATH = 'playback/credentials/credentials.json' 109*c8dee2aaSAndroid Build Coastguard Worker 110*c8dee2aaSAndroid Build Coastguard WorkerX11_DISPLAY = os.getenv('DISPLAY', ':0') 111*c8dee2aaSAndroid Build Coastguard Worker 112*c8dee2aaSAndroid Build Coastguard Worker# Path to Chromium's page sets. 113*c8dee2aaSAndroid Build Coastguard WorkerCHROMIUM_PAGE_SETS_PATH = os.path.join('tools', 'perf', 'page_sets') 114*c8dee2aaSAndroid Build Coastguard Worker 115*c8dee2aaSAndroid Build Coastguard Worker# Dictionary of supported Chromium page sets to their file prefixes. 116*c8dee2aaSAndroid Build Coastguard WorkerCHROMIUM_PAGE_SETS_TO_PREFIX = { 117*c8dee2aaSAndroid Build Coastguard Worker} 118*c8dee2aaSAndroid Build Coastguard Worker 119*c8dee2aaSAndroid Build Coastguard WorkerPAGE_SETS_TO_EXCLUSIONS = { 120*c8dee2aaSAndroid Build Coastguard Worker # See skbug.com/7348 121*c8dee2aaSAndroid Build Coastguard Worker 'key_mobile_sites_smooth.py': '"(digg|worldjournal|twitter|espn)"', 122*c8dee2aaSAndroid Build Coastguard Worker # See skbug.com/7421 123*c8dee2aaSAndroid Build Coastguard Worker 'top_25_smooth.py': '"(mail\.google\.com)"', 124*c8dee2aaSAndroid Build Coastguard Worker} 125*c8dee2aaSAndroid Build Coastguard Worker 126*c8dee2aaSAndroid Build Coastguard Worker 127*c8dee2aaSAndroid Build Coastguard Workerclass InvalidSKPException(Exception): 128*c8dee2aaSAndroid Build Coastguard Worker """Raised when the created SKP is invalid.""" 129*c8dee2aaSAndroid Build Coastguard Worker pass 130*c8dee2aaSAndroid Build Coastguard Worker 131*c8dee2aaSAndroid Build Coastguard Worker 132*c8dee2aaSAndroid Build Coastguard Workerdef remove_prefix(s, prefix): 133*c8dee2aaSAndroid Build Coastguard Worker if s.startswith(prefix): 134*c8dee2aaSAndroid Build Coastguard Worker return s[len(prefix):] 135*c8dee2aaSAndroid Build Coastguard Worker return s 136*c8dee2aaSAndroid Build Coastguard Worker 137*c8dee2aaSAndroid Build Coastguard Worker 138*c8dee2aaSAndroid Build Coastguard Workerclass SkPicturePlayback(object): 139*c8dee2aaSAndroid Build Coastguard Worker """Class that archives or replays webpages and creates SKPs.""" 140*c8dee2aaSAndroid Build Coastguard Worker 141*c8dee2aaSAndroid Build Coastguard Worker def __init__(self, parse_options): 142*c8dee2aaSAndroid Build Coastguard Worker """Constructs a SkPicturePlayback BuildStep instance.""" 143*c8dee2aaSAndroid Build Coastguard Worker assert parse_options.browser_executable, 'Must specify --browser_executable' 144*c8dee2aaSAndroid Build Coastguard Worker self._browser_executable = parse_options.browser_executable 145*c8dee2aaSAndroid Build Coastguard Worker self._browser_args = '--disable-setuid-sandbox --disable-field-trial-config' 146*c8dee2aaSAndroid Build Coastguard Worker if parse_options.browser_extra_args: 147*c8dee2aaSAndroid Build Coastguard Worker self._browser_args = '%s %s' % ( 148*c8dee2aaSAndroid Build Coastguard Worker self._browser_args, parse_options.browser_extra_args) 149*c8dee2aaSAndroid Build Coastguard Worker 150*c8dee2aaSAndroid Build Coastguard Worker self._chrome_page_sets_path = os.path.join(parse_options.chrome_src_path, 151*c8dee2aaSAndroid Build Coastguard Worker CHROMIUM_PAGE_SETS_PATH) 152*c8dee2aaSAndroid Build Coastguard Worker self._all_page_sets_specified = parse_options.page_sets == 'all' 153*c8dee2aaSAndroid Build Coastguard Worker self._page_sets = self._ParsePageSets(parse_options.page_sets) 154*c8dee2aaSAndroid Build Coastguard Worker 155*c8dee2aaSAndroid Build Coastguard Worker self._record = parse_options.record 156*c8dee2aaSAndroid Build Coastguard Worker self._skia_tools = parse_options.skia_tools 157*c8dee2aaSAndroid Build Coastguard Worker self._non_interactive = parse_options.non_interactive 158*c8dee2aaSAndroid Build Coastguard Worker self._upload = parse_options.upload 159*c8dee2aaSAndroid Build Coastguard Worker self._skp_prefix = parse_options.skp_prefix 160*c8dee2aaSAndroid Build Coastguard Worker data_store_location = parse_options.data_store 161*c8dee2aaSAndroid Build Coastguard Worker if data_store_location.startswith(GS_PREFIX): 162*c8dee2aaSAndroid Build Coastguard Worker self.gs = GoogleStorageDataStore(data_store_location) 163*c8dee2aaSAndroid Build Coastguard Worker else: 164*c8dee2aaSAndroid Build Coastguard Worker self.gs = LocalFileSystemDataStore(data_store_location) 165*c8dee2aaSAndroid Build Coastguard Worker self._upload_to_partner_bucket = parse_options.upload_to_partner_bucket 166*c8dee2aaSAndroid Build Coastguard Worker self._alternate_upload_dir = parse_options.alternate_upload_dir 167*c8dee2aaSAndroid Build Coastguard Worker self._telemetry_binaries_dir = os.path.join(parse_options.chrome_src_path, 168*c8dee2aaSAndroid Build Coastguard Worker 'tools', 'perf') 169*c8dee2aaSAndroid Build Coastguard Worker self._catapult_dir = os.path.join(parse_options.chrome_src_path, 170*c8dee2aaSAndroid Build Coastguard Worker 'third_party', 'catapult') 171*c8dee2aaSAndroid Build Coastguard Worker 172*c8dee2aaSAndroid Build Coastguard Worker self._local_skp_dir = os.path.join( 173*c8dee2aaSAndroid Build Coastguard Worker parse_options.output_dir, ROOT_PLAYBACK_DIR_NAME, SKPICTURES_DIR_NAME) 174*c8dee2aaSAndroid Build Coastguard Worker self._local_record_webpages_archive_dir = os.path.join( 175*c8dee2aaSAndroid Build Coastguard Worker parse_options.output_dir, ROOT_PLAYBACK_DIR_NAME, 'webpages_archive') 176*c8dee2aaSAndroid Build Coastguard Worker 177*c8dee2aaSAndroid Build Coastguard Worker # List of SKP files generated by this script. 178*c8dee2aaSAndroid Build Coastguard Worker self._skp_files = [] 179*c8dee2aaSAndroid Build Coastguard Worker 180*c8dee2aaSAndroid Build Coastguard Worker def _ParsePageSets(self, page_sets): 181*c8dee2aaSAndroid Build Coastguard Worker if not page_sets: 182*c8dee2aaSAndroid Build Coastguard Worker raise ValueError('Must specify at least one page_set!') 183*c8dee2aaSAndroid Build Coastguard Worker elif self._all_page_sets_specified: 184*c8dee2aaSAndroid Build Coastguard Worker # Get everything from the page_sets directory. 185*c8dee2aaSAndroid Build Coastguard Worker page_sets_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)), 186*c8dee2aaSAndroid Build Coastguard Worker 'page_sets') 187*c8dee2aaSAndroid Build Coastguard Worker ps = [os.path.join(page_sets_dir, page_set) 188*c8dee2aaSAndroid Build Coastguard Worker for page_set in os.listdir(page_sets_dir) 189*c8dee2aaSAndroid Build Coastguard Worker if not os.path.isdir(os.path.join(page_sets_dir, page_set)) and 190*c8dee2aaSAndroid Build Coastguard Worker page_set.endswith('.py')] 191*c8dee2aaSAndroid Build Coastguard Worker chromium_ps = [ 192*c8dee2aaSAndroid Build Coastguard Worker os.path.join(self._chrome_page_sets_path, cr_page_set) 193*c8dee2aaSAndroid Build Coastguard Worker for cr_page_set in CHROMIUM_PAGE_SETS_TO_PREFIX] 194*c8dee2aaSAndroid Build Coastguard Worker ps.extend(chromium_ps) 195*c8dee2aaSAndroid Build Coastguard Worker elif '*' in page_sets: 196*c8dee2aaSAndroid Build Coastguard Worker # Explode and return the glob. 197*c8dee2aaSAndroid Build Coastguard Worker ps = glob.glob(page_sets) 198*c8dee2aaSAndroid Build Coastguard Worker else: 199*c8dee2aaSAndroid Build Coastguard Worker ps = page_sets.split(',') 200*c8dee2aaSAndroid Build Coastguard Worker ps.sort() 201*c8dee2aaSAndroid Build Coastguard Worker return ps 202*c8dee2aaSAndroid Build Coastguard Worker 203*c8dee2aaSAndroid Build Coastguard Worker def _IsChromiumPageSet(self, page_set): 204*c8dee2aaSAndroid Build Coastguard Worker """Returns true if the specified page set is a Chromium page set.""" 205*c8dee2aaSAndroid Build Coastguard Worker return page_set.startswith(self._chrome_page_sets_path) 206*c8dee2aaSAndroid Build Coastguard Worker 207*c8dee2aaSAndroid Build Coastguard Worker def Run(self): 208*c8dee2aaSAndroid Build Coastguard Worker """Run the SkPicturePlayback BuildStep.""" 209*c8dee2aaSAndroid Build Coastguard Worker 210*c8dee2aaSAndroid Build Coastguard Worker # Download the credentials file if it was not previously downloaded. 211*c8dee2aaSAndroid Build Coastguard Worker if not os.path.isfile(CREDENTIALS_FILE_PATH): 212*c8dee2aaSAndroid Build Coastguard Worker # Download the credentials.json file from Google Storage. 213*c8dee2aaSAndroid Build Coastguard Worker self.gs.download_file(CREDENTIALS_GS_PATH, CREDENTIALS_FILE_PATH) 214*c8dee2aaSAndroid Build Coastguard Worker 215*c8dee2aaSAndroid Build Coastguard Worker if not os.path.isfile(CREDENTIALS_FILE_PATH): 216*c8dee2aaSAndroid Build Coastguard Worker raise Exception("""Could not locate credentials file in the storage. 217*c8dee2aaSAndroid Build Coastguard Worker Please create a credentials file in gs://%s that contains: 218*c8dee2aaSAndroid Build Coastguard Worker { 219*c8dee2aaSAndroid Build Coastguard Worker "google": { 220*c8dee2aaSAndroid Build Coastguard Worker "username": "google_testing_account_username", 221*c8dee2aaSAndroid Build Coastguard Worker "password": "google_testing_account_password" 222*c8dee2aaSAndroid Build Coastguard Worker } 223*c8dee2aaSAndroid Build Coastguard Worker }\n\n""" % CREDENTIALS_GS_PATH) 224*c8dee2aaSAndroid Build Coastguard Worker 225*c8dee2aaSAndroid Build Coastguard Worker # Delete any left over data files in the data directory. 226*c8dee2aaSAndroid Build Coastguard Worker for archive_file in glob.glob( 227*c8dee2aaSAndroid Build Coastguard Worker os.path.join(LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR, 'skia_*')): 228*c8dee2aaSAndroid Build Coastguard Worker os.remove(archive_file) 229*c8dee2aaSAndroid Build Coastguard Worker 230*c8dee2aaSAndroid Build Coastguard Worker # Create the required local storage directories. 231*c8dee2aaSAndroid Build Coastguard Worker self._CreateLocalStorageDirs() 232*c8dee2aaSAndroid Build Coastguard Worker 233*c8dee2aaSAndroid Build Coastguard Worker # Start the timer. 234*c8dee2aaSAndroid Build Coastguard Worker start_time = time.time() 235*c8dee2aaSAndroid Build Coastguard Worker 236*c8dee2aaSAndroid Build Coastguard Worker # Loop through all page_sets. 237*c8dee2aaSAndroid Build Coastguard Worker for page_set in self._page_sets: 238*c8dee2aaSAndroid Build Coastguard Worker if os.path.basename(page_set) == '__init__.py': 239*c8dee2aaSAndroid Build Coastguard Worker continue 240*c8dee2aaSAndroid Build Coastguard Worker page_set_basename = os.path.basename(page_set).split('.')[0] 241*c8dee2aaSAndroid Build Coastguard Worker page_set_json_name = page_set_basename + '.json' 242*c8dee2aaSAndroid Build Coastguard Worker wpr_data_file_glob = ( 243*c8dee2aaSAndroid Build Coastguard Worker page_set.split(os.path.sep)[-1].split('.')[0] + '_*.wprgo') 244*c8dee2aaSAndroid Build Coastguard Worker page_set_dir = os.path.dirname(page_set) 245*c8dee2aaSAndroid Build Coastguard Worker 246*c8dee2aaSAndroid Build Coastguard Worker if self._IsChromiumPageSet(page_set): 247*c8dee2aaSAndroid Build Coastguard Worker print('Using Chromium\'s captured archives for Chromium\'s page sets.') 248*c8dee2aaSAndroid Build Coastguard Worker elif self._record: 249*c8dee2aaSAndroid Build Coastguard Worker # Create an archive of the specified webpages if '--record=True' is 250*c8dee2aaSAndroid Build Coastguard Worker # specified. 251*c8dee2aaSAndroid Build Coastguard Worker record_wpr_cmd = ( 252*c8dee2aaSAndroid Build Coastguard Worker 'PYTHONPATH=%s:%s:$PYTHONPATH' % (page_set_dir, self._catapult_dir), 253*c8dee2aaSAndroid Build Coastguard Worker 'DISPLAY=%s' % X11_DISPLAY, 254*c8dee2aaSAndroid Build Coastguard Worker os.path.join(self._telemetry_binaries_dir, 'record_wpr'), 255*c8dee2aaSAndroid Build Coastguard Worker '--extra-browser-args="%s"' % self._browser_args, 256*c8dee2aaSAndroid Build Coastguard Worker '--browser=exact', 257*c8dee2aaSAndroid Build Coastguard Worker '--browser-executable=%s' % self._browser_executable, 258*c8dee2aaSAndroid Build Coastguard Worker '%s_page_set' % page_set_basename, 259*c8dee2aaSAndroid Build Coastguard Worker '--page-set-base-dir=%s' % page_set_dir 260*c8dee2aaSAndroid Build Coastguard Worker ) 261*c8dee2aaSAndroid Build Coastguard Worker for _ in range(RETRY_RECORD_WPR_COUNT): 262*c8dee2aaSAndroid Build Coastguard Worker try: 263*c8dee2aaSAndroid Build Coastguard Worker subprocess.check_call(' '.join(record_wpr_cmd), shell=True) 264*c8dee2aaSAndroid Build Coastguard Worker 265*c8dee2aaSAndroid Build Coastguard Worker # Copy over the created archive into the local webpages archive 266*c8dee2aaSAndroid Build Coastguard Worker # directory. 267*c8dee2aaSAndroid Build Coastguard Worker for wpr_data_file in glob.glob(os.path.join( 268*c8dee2aaSAndroid Build Coastguard Worker LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR, wpr_data_file_glob)): 269*c8dee2aaSAndroid Build Coastguard Worker shutil.copy( 270*c8dee2aaSAndroid Build Coastguard Worker os.path.join(LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR, wpr_data_file), 271*c8dee2aaSAndroid Build Coastguard Worker self._local_record_webpages_archive_dir) 272*c8dee2aaSAndroid Build Coastguard Worker shutil.copy( 273*c8dee2aaSAndroid Build Coastguard Worker os.path.join(LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR, 274*c8dee2aaSAndroid Build Coastguard Worker page_set_json_name), 275*c8dee2aaSAndroid Build Coastguard Worker self._local_record_webpages_archive_dir) 276*c8dee2aaSAndroid Build Coastguard Worker 277*c8dee2aaSAndroid Build Coastguard Worker # Break out of the retry loop since there were no errors. 278*c8dee2aaSAndroid Build Coastguard Worker break 279*c8dee2aaSAndroid Build Coastguard Worker except Exception: 280*c8dee2aaSAndroid Build Coastguard Worker # There was a failure continue with the loop. 281*c8dee2aaSAndroid Build Coastguard Worker traceback.print_exc() 282*c8dee2aaSAndroid Build Coastguard Worker else: 283*c8dee2aaSAndroid Build Coastguard Worker # If we get here then record_wpr did not succeed and thus did not 284*c8dee2aaSAndroid Build Coastguard Worker # break out of the loop. 285*c8dee2aaSAndroid Build Coastguard Worker raise Exception('record_wpr failed for page_set: %s' % page_set) 286*c8dee2aaSAndroid Build Coastguard Worker 287*c8dee2aaSAndroid Build Coastguard Worker else: 288*c8dee2aaSAndroid Build Coastguard Worker # Get the webpages archive so that it can be replayed. 289*c8dee2aaSAndroid Build Coastguard Worker self._DownloadWebpagesArchive(wpr_data_file_glob, page_set_json_name) 290*c8dee2aaSAndroid Build Coastguard Worker 291*c8dee2aaSAndroid Build Coastguard Worker run_benchmark_cmd = [ 292*c8dee2aaSAndroid Build Coastguard Worker 'PYTHONPATH=%s:%s:$PYTHONPATH' % (page_set_dir, self._catapult_dir), 293*c8dee2aaSAndroid Build Coastguard Worker 'DISPLAY=%s' % X11_DISPLAY, 294*c8dee2aaSAndroid Build Coastguard Worker 'timeout', '1800', 295*c8dee2aaSAndroid Build Coastguard Worker os.path.join(self._telemetry_binaries_dir, 'run_benchmark'), 296*c8dee2aaSAndroid Build Coastguard Worker '--extra-browser-args="%s"' % self._browser_args, 297*c8dee2aaSAndroid Build Coastguard Worker '--browser=exact', 298*c8dee2aaSAndroid Build Coastguard Worker '--browser-executable=%s' % self._browser_executable, 299*c8dee2aaSAndroid Build Coastguard Worker SKP_BENCHMARK, 300*c8dee2aaSAndroid Build Coastguard Worker '--page-set-name=%s' % page_set_basename, 301*c8dee2aaSAndroid Build Coastguard Worker '--page-set-base-dir=%s' % page_set_dir, 302*c8dee2aaSAndroid Build Coastguard Worker '--skp-outdir=%s' % TMP_SKP_DIR, 303*c8dee2aaSAndroid Build Coastguard Worker '--also-run-disabled-tests', 304*c8dee2aaSAndroid Build Coastguard Worker ] 305*c8dee2aaSAndroid Build Coastguard Worker 306*c8dee2aaSAndroid Build Coastguard Worker exclusions = PAGE_SETS_TO_EXCLUSIONS.get(os.path.basename(page_set)) 307*c8dee2aaSAndroid Build Coastguard Worker if exclusions: 308*c8dee2aaSAndroid Build Coastguard Worker run_benchmark_cmd.append('--story-filter-exclude=' + exclusions) 309*c8dee2aaSAndroid Build Coastguard Worker 310*c8dee2aaSAndroid Build Coastguard Worker for _ in range(RETRY_RUN_MEASUREMENT_COUNT): 311*c8dee2aaSAndroid Build Coastguard Worker try: 312*c8dee2aaSAndroid Build Coastguard Worker print('\n\n=======Capturing SKP of %s=======\n\n' % page_set) 313*c8dee2aaSAndroid Build Coastguard Worker subprocess.check_call(' '.join(run_benchmark_cmd), shell=True) 314*c8dee2aaSAndroid Build Coastguard Worker except subprocess.CalledProcessError: 315*c8dee2aaSAndroid Build Coastguard Worker # There was a failure continue with the loop. 316*c8dee2aaSAndroid Build Coastguard Worker traceback.print_exc() 317*c8dee2aaSAndroid Build Coastguard Worker print('\n\n=======Retrying %s=======\n\n' % page_set) 318*c8dee2aaSAndroid Build Coastguard Worker time.sleep(10) 319*c8dee2aaSAndroid Build Coastguard Worker continue 320*c8dee2aaSAndroid Build Coastguard Worker 321*c8dee2aaSAndroid Build Coastguard Worker try: 322*c8dee2aaSAndroid Build Coastguard Worker # Rename generated SKP files into more descriptive names. 323*c8dee2aaSAndroid Build Coastguard Worker self._RenameSkpFiles(page_set) 324*c8dee2aaSAndroid Build Coastguard Worker except InvalidSKPException: 325*c8dee2aaSAndroid Build Coastguard Worker # There was a failure continue with the loop. 326*c8dee2aaSAndroid Build Coastguard Worker traceback.print_exc() 327*c8dee2aaSAndroid Build Coastguard Worker print('\n\n=======Retrying %s=======\n\n' % page_set) 328*c8dee2aaSAndroid Build Coastguard Worker time.sleep(10) 329*c8dee2aaSAndroid Build Coastguard Worker continue 330*c8dee2aaSAndroid Build Coastguard Worker 331*c8dee2aaSAndroid Build Coastguard Worker # Break out of the retry loop since there were no errors. 332*c8dee2aaSAndroid Build Coastguard Worker break 333*c8dee2aaSAndroid Build Coastguard Worker else: 334*c8dee2aaSAndroid Build Coastguard Worker # If we get here then run_benchmark did not succeed and thus did not 335*c8dee2aaSAndroid Build Coastguard Worker # break out of the loop. 336*c8dee2aaSAndroid Build Coastguard Worker raise Exception('run_benchmark failed for page_set: %s' % page_set) 337*c8dee2aaSAndroid Build Coastguard Worker 338*c8dee2aaSAndroid Build Coastguard Worker print('\n\n=======Capturing SKP files took %s seconds=======\n\n' % ( 339*c8dee2aaSAndroid Build Coastguard Worker time.time() - start_time)) 340*c8dee2aaSAndroid Build Coastguard Worker 341*c8dee2aaSAndroid Build Coastguard Worker if self._skia_tools: 342*c8dee2aaSAndroid Build Coastguard Worker render_pictures_cmd = [ 343*c8dee2aaSAndroid Build Coastguard Worker os.path.join(self._skia_tools, 'render_pictures'), 344*c8dee2aaSAndroid Build Coastguard Worker '-r', self._local_skp_dir 345*c8dee2aaSAndroid Build Coastguard Worker ] 346*c8dee2aaSAndroid Build Coastguard Worker render_pdfs_cmd = [ 347*c8dee2aaSAndroid Build Coastguard Worker os.path.join(self._skia_tools, 'render_pdfs'), 348*c8dee2aaSAndroid Build Coastguard Worker '-r', self._local_skp_dir 349*c8dee2aaSAndroid Build Coastguard Worker ] 350*c8dee2aaSAndroid Build Coastguard Worker 351*c8dee2aaSAndroid Build Coastguard Worker for tools_cmd in (render_pictures_cmd, render_pdfs_cmd): 352*c8dee2aaSAndroid Build Coastguard Worker print('\n\n=======Running %s=======' % ' '.join(tools_cmd)) 353*c8dee2aaSAndroid Build Coastguard Worker subprocess.check_call(tools_cmd) 354*c8dee2aaSAndroid Build Coastguard Worker 355*c8dee2aaSAndroid Build Coastguard Worker if not self._non_interactive: 356*c8dee2aaSAndroid Build Coastguard Worker print('\n\n=======Running debugger=======') 357*c8dee2aaSAndroid Build Coastguard Worker os.system('%s %s' % (os.path.join(self._skia_tools, 'debugger'), 358*c8dee2aaSAndroid Build Coastguard Worker self._local_skp_dir)) 359*c8dee2aaSAndroid Build Coastguard Worker 360*c8dee2aaSAndroid Build Coastguard Worker print('\n\n') 361*c8dee2aaSAndroid Build Coastguard Worker 362*c8dee2aaSAndroid Build Coastguard Worker if self._upload: 363*c8dee2aaSAndroid Build Coastguard Worker print('\n\n=======Uploading to %s=======\n\n' % self.gs.target_type()) 364*c8dee2aaSAndroid Build Coastguard Worker # Copy the directory structure in the root directory into Google Storage. 365*c8dee2aaSAndroid Build Coastguard Worker dest_dir_name = ROOT_PLAYBACK_DIR_NAME 366*c8dee2aaSAndroid Build Coastguard Worker if self._alternate_upload_dir: 367*c8dee2aaSAndroid Build Coastguard Worker dest_dir_name = self._alternate_upload_dir 368*c8dee2aaSAndroid Build Coastguard Worker 369*c8dee2aaSAndroid Build Coastguard Worker self.gs.upload_dir_contents( 370*c8dee2aaSAndroid Build Coastguard Worker self._local_skp_dir, dest_dir=dest_dir_name) 371*c8dee2aaSAndroid Build Coastguard Worker 372*c8dee2aaSAndroid Build Coastguard Worker print('\n\n=======New SKPs have been uploaded to %s =======\n\n' % 373*c8dee2aaSAndroid Build Coastguard Worker posixpath.join(self.gs.target_name(), dest_dir_name, 374*c8dee2aaSAndroid Build Coastguard Worker SKPICTURES_DIR_NAME)) 375*c8dee2aaSAndroid Build Coastguard Worker 376*c8dee2aaSAndroid Build Coastguard Worker else: 377*c8dee2aaSAndroid Build Coastguard Worker print('\n\n=======Not Uploading to %s=======\n\n' % self.gs.target_type()) 378*c8dee2aaSAndroid Build Coastguard Worker print('Generated resources are available in %s\n\n' % self._local_skp_dir) 379*c8dee2aaSAndroid Build Coastguard Worker 380*c8dee2aaSAndroid Build Coastguard Worker if self._upload_to_partner_bucket: 381*c8dee2aaSAndroid Build Coastguard Worker print('\n\n=======Uploading to Partner bucket %s =======\n\n' % 382*c8dee2aaSAndroid Build Coastguard Worker PARTNERS_GS_BUCKET) 383*c8dee2aaSAndroid Build Coastguard Worker partner_gs = GoogleStorageDataStore(PARTNERS_GS_BUCKET) 384*c8dee2aaSAndroid Build Coastguard Worker timestamp = datetime.datetime.utcnow().strftime('%Y-%m-%d') 385*c8dee2aaSAndroid Build Coastguard Worker upload_dir = posixpath.join(SKPICTURES_DIR_NAME, timestamp) 386*c8dee2aaSAndroid Build Coastguard Worker try: 387*c8dee2aaSAndroid Build Coastguard Worker partner_gs.delete_path(upload_dir) 388*c8dee2aaSAndroid Build Coastguard Worker except subprocess.CalledProcessError: 389*c8dee2aaSAndroid Build Coastguard Worker print('Cannot delete %s because it does not exist yet.' % upload_dir) 390*c8dee2aaSAndroid Build Coastguard Worker print('Uploading %s to %s' % (self._local_skp_dir, upload_dir)) 391*c8dee2aaSAndroid Build Coastguard Worker partner_gs.upload_dir_contents(self._local_skp_dir, upload_dir) 392*c8dee2aaSAndroid Build Coastguard Worker print('\n\n=======New SKPs have been uploaded to %s =======\n\n' % 393*c8dee2aaSAndroid Build Coastguard Worker posixpath.join(partner_gs.target_name(), upload_dir)) 394*c8dee2aaSAndroid Build Coastguard Worker 395*c8dee2aaSAndroid Build Coastguard Worker return 0 396*c8dee2aaSAndroid Build Coastguard Worker 397*c8dee2aaSAndroid Build Coastguard Worker def _GetSkiaSkpFileName(self, page_set): 398*c8dee2aaSAndroid Build Coastguard Worker """Returns the SKP file name for Skia page sets.""" 399*c8dee2aaSAndroid Build Coastguard Worker # /path/to/skia_yahooanswers_desktop.py -> skia_yahooanswers_desktop.py 400*c8dee2aaSAndroid Build Coastguard Worker ps_filename = os.path.basename(page_set) 401*c8dee2aaSAndroid Build Coastguard Worker # skia_yahooanswers_desktop.py -> skia_yahooanswers_desktop 402*c8dee2aaSAndroid Build Coastguard Worker ps_basename, _ = os.path.splitext(ps_filename) 403*c8dee2aaSAndroid Build Coastguard Worker # skia_yahooanswers_desktop -> skia, yahooanswers, desktop 404*c8dee2aaSAndroid Build Coastguard Worker _, page_name, device = ps_basename.split('_') 405*c8dee2aaSAndroid Build Coastguard Worker basename = '%s_%s' % (DEVICE_TO_PLATFORM_PREFIX[device], page_name) 406*c8dee2aaSAndroid Build Coastguard Worker return basename[:MAX_SKP_BASE_NAME_LEN] + '.skp' 407*c8dee2aaSAndroid Build Coastguard Worker 408*c8dee2aaSAndroid Build Coastguard Worker def _GetChromiumSkpFileName(self, page_set, site): 409*c8dee2aaSAndroid Build Coastguard Worker """Returns the SKP file name for Chromium page sets.""" 410*c8dee2aaSAndroid Build Coastguard Worker # /path/to/http___mobile_news_sandbox_pt0 -> http___mobile_news_sandbox_pt0 411*c8dee2aaSAndroid Build Coastguard Worker _, webpage = os.path.split(site) 412*c8dee2aaSAndroid Build Coastguard Worker # http___mobile_news_sandbox_pt0 -> mobile_news_sandbox_pt0 413*c8dee2aaSAndroid Build Coastguard Worker for prefix in ('http___', 'https___', 'www_'): 414*c8dee2aaSAndroid Build Coastguard Worker if webpage.startswith(prefix): 415*c8dee2aaSAndroid Build Coastguard Worker webpage = webpage[len(prefix):] 416*c8dee2aaSAndroid Build Coastguard Worker # /path/to/skia_yahooanswers_desktop.py -> skia_yahooanswers_desktop.py 417*c8dee2aaSAndroid Build Coastguard Worker ps_filename = os.path.basename(page_set) 418*c8dee2aaSAndroid Build Coastguard Worker # http___mobile_news_sandbox -> pagesetprefix_http___mobile_news_sandbox 419*c8dee2aaSAndroid Build Coastguard Worker basename = '%s_%s' % (CHROMIUM_PAGE_SETS_TO_PREFIX[ps_filename], webpage) 420*c8dee2aaSAndroid Build Coastguard Worker return basename[:MAX_SKP_BASE_NAME_LEN] + '.skp' 421*c8dee2aaSAndroid Build Coastguard Worker 422*c8dee2aaSAndroid Build Coastguard Worker def _RenameSkpFiles(self, page_set): 423*c8dee2aaSAndroid Build Coastguard Worker """Rename generated SKP files into more descriptive names. 424*c8dee2aaSAndroid Build Coastguard Worker 425*c8dee2aaSAndroid Build Coastguard Worker Look into the subdirectory of TMP_SKP_DIR and find the most interesting 426*c8dee2aaSAndroid Build Coastguard Worker .skp in there to be this page_set's representative .skp. 427*c8dee2aaSAndroid Build Coastguard Worker 428*c8dee2aaSAndroid Build Coastguard Worker Throws InvalidSKPException if the chosen .skp is less than 1KB. This 429*c8dee2aaSAndroid Build Coastguard Worker typically happens when there is a 404 or a redirect loop. Anything greater 430*c8dee2aaSAndroid Build Coastguard Worker than 1KB seems to have captured at least some useful information. 431*c8dee2aaSAndroid Build Coastguard Worker """ 432*c8dee2aaSAndroid Build Coastguard Worker subdirs = glob.glob(os.path.join(TMP_SKP_DIR, '*')) 433*c8dee2aaSAndroid Build Coastguard Worker for site in subdirs: 434*c8dee2aaSAndroid Build Coastguard Worker if self._IsChromiumPageSet(page_set): 435*c8dee2aaSAndroid Build Coastguard Worker filename = self._GetChromiumSkpFileName(page_set, site) 436*c8dee2aaSAndroid Build Coastguard Worker else: 437*c8dee2aaSAndroid Build Coastguard Worker filename = self._GetSkiaSkpFileName(page_set) 438*c8dee2aaSAndroid Build Coastguard Worker filename = filename.lower() 439*c8dee2aaSAndroid Build Coastguard Worker 440*c8dee2aaSAndroid Build Coastguard Worker if self._skp_prefix: 441*c8dee2aaSAndroid Build Coastguard Worker filename = '%s%s' % (self._skp_prefix, filename) 442*c8dee2aaSAndroid Build Coastguard Worker 443*c8dee2aaSAndroid Build Coastguard Worker # We choose the largest .skp as the most likely to be interesting. 444*c8dee2aaSAndroid Build Coastguard Worker largest_skp = max(glob.glob(os.path.join(site, '*.skp')), 445*c8dee2aaSAndroid Build Coastguard Worker key=lambda path: os.stat(path).st_size) 446*c8dee2aaSAndroid Build Coastguard Worker dest = os.path.join(self._local_skp_dir, filename) 447*c8dee2aaSAndroid Build Coastguard Worker print('Moving', largest_skp, 'to', dest) 448*c8dee2aaSAndroid Build Coastguard Worker shutil.move(largest_skp, dest) 449*c8dee2aaSAndroid Build Coastguard Worker self._skp_files.append(filename) 450*c8dee2aaSAndroid Build Coastguard Worker shutil.rmtree(site) 451*c8dee2aaSAndroid Build Coastguard Worker skp_size = os.path.getsize(dest) 452*c8dee2aaSAndroid Build Coastguard Worker if skp_size < 1024: 453*c8dee2aaSAndroid Build Coastguard Worker raise InvalidSKPException( 454*c8dee2aaSAndroid Build Coastguard Worker 'Size of %s is only %d. Something is wrong.' % (dest, skp_size)) 455*c8dee2aaSAndroid Build Coastguard Worker 456*c8dee2aaSAndroid Build Coastguard Worker 457*c8dee2aaSAndroid Build Coastguard Worker def _CreateLocalStorageDirs(self): 458*c8dee2aaSAndroid Build Coastguard Worker """Creates required local storage directories for this script.""" 459*c8dee2aaSAndroid Build Coastguard Worker for d in (self._local_record_webpages_archive_dir, 460*c8dee2aaSAndroid Build Coastguard Worker self._local_skp_dir): 461*c8dee2aaSAndroid Build Coastguard Worker if os.path.exists(d): 462*c8dee2aaSAndroid Build Coastguard Worker shutil.rmtree(d) 463*c8dee2aaSAndroid Build Coastguard Worker os.makedirs(d) 464*c8dee2aaSAndroid Build Coastguard Worker 465*c8dee2aaSAndroid Build Coastguard Worker def _DownloadWebpagesArchive(self, wpr_data_file, page_set_json_name): 466*c8dee2aaSAndroid Build Coastguard Worker """Downloads the webpages archive and its required page set from GS.""" 467*c8dee2aaSAndroid Build Coastguard Worker wpr_source = posixpath.join(ROOT_PLAYBACK_DIR_NAME, 'webpages_archive', 468*c8dee2aaSAndroid Build Coastguard Worker wpr_data_file) 469*c8dee2aaSAndroid Build Coastguard Worker page_set_source = posixpath.join(ROOT_PLAYBACK_DIR_NAME, 470*c8dee2aaSAndroid Build Coastguard Worker 'webpages_archive', 471*c8dee2aaSAndroid Build Coastguard Worker page_set_json_name) 472*c8dee2aaSAndroid Build Coastguard Worker gs = self.gs 473*c8dee2aaSAndroid Build Coastguard Worker if (gs.does_storage_object_exist(wpr_source) and 474*c8dee2aaSAndroid Build Coastguard Worker gs.does_storage_object_exist(page_set_source)): 475*c8dee2aaSAndroid Build Coastguard Worker gs.download_file(wpr_source, LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR) 476*c8dee2aaSAndroid Build Coastguard Worker gs.download_file(page_set_source, 477*c8dee2aaSAndroid Build Coastguard Worker os.path.join(LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR, 478*c8dee2aaSAndroid Build Coastguard Worker page_set_json_name)) 479*c8dee2aaSAndroid Build Coastguard Worker else: 480*c8dee2aaSAndroid Build Coastguard Worker raise Exception('%s and %s do not exist in %s!' % (gs.target_type(), 481*c8dee2aaSAndroid Build Coastguard Worker wpr_source, page_set_source)) 482*c8dee2aaSAndroid Build Coastguard Worker 483*c8dee2aaSAndroid Build Coastguard Workerclass DataStore: 484*c8dee2aaSAndroid Build Coastguard Worker """An abstract base class for uploading recordings to a data storage. 485*c8dee2aaSAndroid Build Coastguard Worker The interface emulates the google storage api.""" 486*c8dee2aaSAndroid Build Coastguard Worker def target_name(self): 487*c8dee2aaSAndroid Build Coastguard Worker raise NotImplementedError() 488*c8dee2aaSAndroid Build Coastguard Worker def target_type(self): 489*c8dee2aaSAndroid Build Coastguard Worker raise NotImplementedError() 490*c8dee2aaSAndroid Build Coastguard Worker def does_storage_object_exist(self, name): 491*c8dee2aaSAndroid Build Coastguard Worker raise NotImplementedError() 492*c8dee2aaSAndroid Build Coastguard Worker def download_file(self, name, local_path): 493*c8dee2aaSAndroid Build Coastguard Worker raise NotImplementedError() 494*c8dee2aaSAndroid Build Coastguard Worker def upload_dir_contents(self, source_dir, dest_dir): 495*c8dee2aaSAndroid Build Coastguard Worker raise NotImplementedError() 496*c8dee2aaSAndroid Build Coastguard Worker 497*c8dee2aaSAndroid Build Coastguard Worker 498*c8dee2aaSAndroid Build Coastguard Workerclass GoogleStorageDataStore(DataStore): 499*c8dee2aaSAndroid Build Coastguard Worker def __init__(self, data_store_url): 500*c8dee2aaSAndroid Build Coastguard Worker self._url = data_store_url.rstrip('/') 501*c8dee2aaSAndroid Build Coastguard Worker 502*c8dee2aaSAndroid Build Coastguard Worker def target_name(self): 503*c8dee2aaSAndroid Build Coastguard Worker return self._url 504*c8dee2aaSAndroid Build Coastguard Worker 505*c8dee2aaSAndroid Build Coastguard Worker def target_type(self): 506*c8dee2aaSAndroid Build Coastguard Worker return 'Google Storage' 507*c8dee2aaSAndroid Build Coastguard Worker 508*c8dee2aaSAndroid Build Coastguard Worker def does_storage_object_exist(self, name): 509*c8dee2aaSAndroid Build Coastguard Worker try: 510*c8dee2aaSAndroid Build Coastguard Worker output = subprocess.check_output([ 511*c8dee2aaSAndroid Build Coastguard Worker 'gsutil', 'ls', '/'.join((self._url, name))]) 512*c8dee2aaSAndroid Build Coastguard Worker except subprocess.CalledProcessError: 513*c8dee2aaSAndroid Build Coastguard Worker return False 514*c8dee2aaSAndroid Build Coastguard Worker if len(output.splitlines()) != 1: 515*c8dee2aaSAndroid Build Coastguard Worker return False 516*c8dee2aaSAndroid Build Coastguard Worker return True 517*c8dee2aaSAndroid Build Coastguard Worker 518*c8dee2aaSAndroid Build Coastguard Worker def delete_path(self, path): 519*c8dee2aaSAndroid Build Coastguard Worker subprocess.check_call(['gsutil', 'rm', '-r', '/'.join((self._url, path))]) 520*c8dee2aaSAndroid Build Coastguard Worker 521*c8dee2aaSAndroid Build Coastguard Worker def download_file(self, name, local_path): 522*c8dee2aaSAndroid Build Coastguard Worker subprocess.check_call([ 523*c8dee2aaSAndroid Build Coastguard Worker 'gsutil', 'cp', '/'.join((self._url, name)), local_path]) 524*c8dee2aaSAndroid Build Coastguard Worker 525*c8dee2aaSAndroid Build Coastguard Worker def upload_dir_contents(self, source_dir, dest_dir): 526*c8dee2aaSAndroid Build Coastguard Worker subprocess.check_call([ 527*c8dee2aaSAndroid Build Coastguard Worker 'gsutil', 'cp', '-r', source_dir, '/'.join((self._url, dest_dir))]) 528*c8dee2aaSAndroid Build Coastguard Worker 529*c8dee2aaSAndroid Build Coastguard Worker 530*c8dee2aaSAndroid Build Coastguard Workerclass LocalFileSystemDataStore(DataStore): 531*c8dee2aaSAndroid Build Coastguard Worker def __init__(self, data_store_location): 532*c8dee2aaSAndroid Build Coastguard Worker self._base_dir = data_store_location 533*c8dee2aaSAndroid Build Coastguard Worker def target_name(self): 534*c8dee2aaSAndroid Build Coastguard Worker return self._base_dir 535*c8dee2aaSAndroid Build Coastguard Worker def target_type(self): 536*c8dee2aaSAndroid Build Coastguard Worker return self._base_dir 537*c8dee2aaSAndroid Build Coastguard Worker def does_storage_object_exist(self, name): 538*c8dee2aaSAndroid Build Coastguard Worker return os.path.isfile(os.path.join(self._base_dir, name)) 539*c8dee2aaSAndroid Build Coastguard Worker def delete_path(self, path): 540*c8dee2aaSAndroid Build Coastguard Worker shutil.rmtree(path) 541*c8dee2aaSAndroid Build Coastguard Worker def download_file(self, name, local_path): 542*c8dee2aaSAndroid Build Coastguard Worker shutil.copyfile(os.path.join(self._base_dir, name), local_path) 543*c8dee2aaSAndroid Build Coastguard Worker def upload_dir_contents(self, source_dir, dest_dir): 544*c8dee2aaSAndroid Build Coastguard Worker def copytree(source_dir, dest_dir): 545*c8dee2aaSAndroid Build Coastguard Worker if not os.path.exists(dest_dir): 546*c8dee2aaSAndroid Build Coastguard Worker os.makedirs(dest_dir) 547*c8dee2aaSAndroid Build Coastguard Worker for item in os.listdir(source_dir): 548*c8dee2aaSAndroid Build Coastguard Worker source = os.path.join(source_dir, item) 549*c8dee2aaSAndroid Build Coastguard Worker dest = os.path.join(dest_dir, item) 550*c8dee2aaSAndroid Build Coastguard Worker if os.path.isdir(source): 551*c8dee2aaSAndroid Build Coastguard Worker copytree(source, dest) 552*c8dee2aaSAndroid Build Coastguard Worker else: 553*c8dee2aaSAndroid Build Coastguard Worker shutil.copy2(source, dest) 554*c8dee2aaSAndroid Build Coastguard Worker copytree(source_dir, os.path.join(self._base_dir, dest_dir)) 555*c8dee2aaSAndroid Build Coastguard Worker 556*c8dee2aaSAndroid Build Coastguard Workerif '__main__' == __name__: 557*c8dee2aaSAndroid Build Coastguard Worker option_parser = optparse.OptionParser() 558*c8dee2aaSAndroid Build Coastguard Worker option_parser.add_option( 559*c8dee2aaSAndroid Build Coastguard Worker '', '--page_sets', 560*c8dee2aaSAndroid Build Coastguard Worker help='Specifies the page sets to use to archive. Supports globs.', 561*c8dee2aaSAndroid Build Coastguard Worker default='all') 562*c8dee2aaSAndroid Build Coastguard Worker option_parser.add_option( 563*c8dee2aaSAndroid Build Coastguard Worker '', '--record', action='store_true', 564*c8dee2aaSAndroid Build Coastguard Worker help='Specifies whether a new website archive should be created.', 565*c8dee2aaSAndroid Build Coastguard Worker default=False) 566*c8dee2aaSAndroid Build Coastguard Worker option_parser.add_option( 567*c8dee2aaSAndroid Build Coastguard Worker '', '--skia_tools', 568*c8dee2aaSAndroid Build Coastguard Worker help=('Path to compiled Skia executable tools. ' 569*c8dee2aaSAndroid Build Coastguard Worker 'render_pictures/render_pdfs is run on the set ' 570*c8dee2aaSAndroid Build Coastguard Worker 'after all SKPs are captured. If the script is run without ' 571*c8dee2aaSAndroid Build Coastguard Worker '--non-interactive then the debugger is also run at the end. Debug ' 572*c8dee2aaSAndroid Build Coastguard Worker 'builds are recommended because they seem to catch more failures ' 573*c8dee2aaSAndroid Build Coastguard Worker 'than Release builds.'), 574*c8dee2aaSAndroid Build Coastguard Worker default=None) 575*c8dee2aaSAndroid Build Coastguard Worker option_parser.add_option( 576*c8dee2aaSAndroid Build Coastguard Worker '', '--upload', action='store_true', 577*c8dee2aaSAndroid Build Coastguard Worker help=('Uploads to Google Storage or copies to local filesystem storage ' 578*c8dee2aaSAndroid Build Coastguard Worker ' if this is True.'), 579*c8dee2aaSAndroid Build Coastguard Worker default=False) 580*c8dee2aaSAndroid Build Coastguard Worker option_parser.add_option( 581*c8dee2aaSAndroid Build Coastguard Worker '', '--upload_to_partner_bucket', action='store_true', 582*c8dee2aaSAndroid Build Coastguard Worker help=('Uploads SKPs to the chrome-partner-telemetry Google Storage ' 583*c8dee2aaSAndroid Build Coastguard Worker 'bucket if true.'), 584*c8dee2aaSAndroid Build Coastguard Worker default=False) 585*c8dee2aaSAndroid Build Coastguard Worker option_parser.add_option( 586*c8dee2aaSAndroid Build Coastguard Worker '', '--data_store', 587*c8dee2aaSAndroid Build Coastguard Worker help=('The location of the file storage to use to download and upload ' 588*c8dee2aaSAndroid Build Coastguard Worker 'files. Can be \'gs://<bucket>\' for Google Storage, or ' 589*c8dee2aaSAndroid Build Coastguard Worker 'a directory for local filesystem storage'), 590*c8dee2aaSAndroid Build Coastguard Worker default='gs://skia-skps') 591*c8dee2aaSAndroid Build Coastguard Worker option_parser.add_option( 592*c8dee2aaSAndroid Build Coastguard Worker '', '--alternate_upload_dir', 593*c8dee2aaSAndroid Build Coastguard Worker help= ('Uploads to a different directory in Google Storage or local ' 594*c8dee2aaSAndroid Build Coastguard Worker 'storage if this flag is specified'), 595*c8dee2aaSAndroid Build Coastguard Worker default=None) 596*c8dee2aaSAndroid Build Coastguard Worker option_parser.add_option( 597*c8dee2aaSAndroid Build Coastguard Worker '', '--output_dir', 598*c8dee2aaSAndroid Build Coastguard Worker help=('Temporary directory where SKPs and webpage archives will be ' 599*c8dee2aaSAndroid Build Coastguard Worker 'outputted to.'), 600*c8dee2aaSAndroid Build Coastguard Worker default=tempfile.gettempdir()) 601*c8dee2aaSAndroid Build Coastguard Worker option_parser.add_option( 602*c8dee2aaSAndroid Build Coastguard Worker '', '--browser_executable', 603*c8dee2aaSAndroid Build Coastguard Worker help='The exact browser executable to run.', 604*c8dee2aaSAndroid Build Coastguard Worker default=None) 605*c8dee2aaSAndroid Build Coastguard Worker option_parser.add_option( 606*c8dee2aaSAndroid Build Coastguard Worker '', '--browser_extra_args', 607*c8dee2aaSAndroid Build Coastguard Worker help='Additional arguments to pass to the browser.', 608*c8dee2aaSAndroid Build Coastguard Worker default=None) 609*c8dee2aaSAndroid Build Coastguard Worker option_parser.add_option( 610*c8dee2aaSAndroid Build Coastguard Worker '', '--chrome_src_path', 611*c8dee2aaSAndroid Build Coastguard Worker help='Path to the chromium src directory.', 612*c8dee2aaSAndroid Build Coastguard Worker default=None) 613*c8dee2aaSAndroid Build Coastguard Worker option_parser.add_option( 614*c8dee2aaSAndroid Build Coastguard Worker '', '--non-interactive', action='store_true', 615*c8dee2aaSAndroid Build Coastguard Worker help='Runs the script without any prompts. If this flag is specified and ' 616*c8dee2aaSAndroid Build Coastguard Worker '--skia_tools is specified then the debugger is not run.', 617*c8dee2aaSAndroid Build Coastguard Worker default=False) 618*c8dee2aaSAndroid Build Coastguard Worker option_parser.add_option( 619*c8dee2aaSAndroid Build Coastguard Worker '', '--skp_prefix', 620*c8dee2aaSAndroid Build Coastguard Worker help='Prefix to add to the names of generated SKPs.', 621*c8dee2aaSAndroid Build Coastguard Worker default=None) 622*c8dee2aaSAndroid Build Coastguard Worker options, unused_args = option_parser.parse_args() 623*c8dee2aaSAndroid Build Coastguard Worker 624*c8dee2aaSAndroid Build Coastguard Worker playback = SkPicturePlayback(options) 625*c8dee2aaSAndroid Build Coastguard Worker sys.exit(playback.Run()) 626