1#!/usr/bin/env python2 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"""Fetch prebuilt binaries to run PyAuto. 7 8Sets up Chrome and PyAuto binaries using prebuilt binaries from the 9continuous build archives. Works on mac, win, linux (32 & 64 bit). 10 11Examples: 12 On Mac: 13 $ python fetch_prebuilt_pyauto.py -d xcodebuild/Release 14 http://build.chromium.org/f/chromium/continuous/mac/LATEST 15 16 On Win: 17 $ python fetch_prebuilt_pyauto.py -d chrome\Release 18 http://build.chromium.org/f/chromium/continuous/win/LATEST 19""" 20 21from __future__ import print_function 22 23import glob 24import httplib 25import optparse 26import os 27import platform 28import shutil 29import sys 30import urllib 31import urllib2 32import urlparse 33 34import pyauto_utils 35 36 37class FetchPrebuilt(object): 38 """Util class to fetch prebuilt binaries to run PyAuto.""" 39 40 def _ParseArgs(self): 41 parser = optparse.OptionParser() 42 parser.add_option( 43 '-d', '--outdir', type='string', default=None, 44 help='Directory in which to setup. This is typically the directory ' 45 'where the binaries would go when compiled from source.') 46 parser.add_option( 47 '-p', '--platform', type='string', 48 default=pyauto_utils.GetCurrentPlatform(), 49 help='Platform. Valid options: win, mac, linux32, linux64. ' 50 'Default: current platform (%s)' % pyauto_utils.GetCurrentPlatform()) 51 parser.add_option( 52 '-l', '--latest', action='store_true', default=False, 53 help='Download the latest chromium build from commondatastorage. ' 54 '[default=False]') 55 self._options, self._args = parser.parse_args() 56 if self._options.latest: 57 self._url = self._GetLastestDownloadURL(self._options.platform) 58 elif not self._args: 59 print >>sys.stderr, 'Need download url' 60 sys.exit(2) 61 else: 62 self._url = self._args[0] 63 if not self._options.outdir: 64 print >>sys.stderr, 'Need output directory: -d/--outdir' 65 sys.exit(1) 66 self._outdir = self._options.outdir 67 # Chromium continuous build archive has a non-standard format. 68 if 'index.html?path=' in self._url: 69 self._url = self._url.replace('index.html?path=', '') 70 self._url = self._url.rstrip('/') 71 # Determine name of zip. 72 if not self._options.platform.startswith('linux'): 73 self._chrome_zip_name = 'chrome-%s' % {'mac': 'mac', 74 'win': 'win32' 75 }[self._options.platform] 76 else: 77 linux_32_names = ['linux', 'lucid32bit'] 78 linux_64_names = ['linux64', 'lucid64bit'] 79 linux_names = {'linux': linux_32_names + linux_64_names, 80 'linux32': linux_32_names, 81 'linux64': linux_64_names 82 }[self._options.platform] 83 for name in linux_names: 84 zip_name = 'chrome-' + name 85 if pyauto_utils.DoesUrlExist('%s/%s.zip' % (self._url, zip_name)): 86 self._chrome_zip_name = zip_name 87 break 88 else: 89 raise RuntimeError('Could not find chrome zip at ' + self._url) 90 91 # Setup urls to download. 92 self._chrome_zip_url = '%s/%s.zip' % (self._url, self._chrome_zip_name) 93 self._remoting_zip_url = self._url + '/' + 'remoting-webapp.zip' 94 chrome_test_url = '%s/%s.test' % (self._url, self._chrome_zip_name) 95 self._pyautolib_py_url = '%s/pyautolib.py' % chrome_test_url 96 if self._options.platform == 'win': 97 self._pyautolib_so_name = '_pyautolib.pyd' 98 self._chromedriver_name = 'chromedriver.exe' 99 else: 100 self._pyautolib_so_name = '_pyautolib.so' 101 self._chromedriver_name = 'chromedriver' 102 if self._options.platform == 'mac': 103 self._ffmpegsumo_so_name = 'ffmpegsumo.so' 104 self._ffmpegsumo_so_url = chrome_test_url + '/' + self._ffmpegsumo_so_name 105 self._pyautolib_so_url = chrome_test_url + '/' + self._pyautolib_so_name 106 self._chromedriver_url = chrome_test_url + '/' + self._chromedriver_name 107 108 def _GetLastestDownloadURL(self, os_platform): 109 os_type = {'win': 'Win', 110 'mac': 'Mac', 111 'linux': 'Linux', 112 'linux32': 'Linux', 113 'linux64': 'Linux_x64'}[os_platform] 114 if os_type == 'Linux' and platform.architecture()[0] == '64bit': 115 os_type = 'Linux_x64' 116 last_change_url = ('http://commondatastorage.googleapis.com/' 117 'chromium-browser-continuous/%s/LAST_CHANGE' % os_type) 118 response = urllib2.urlopen(last_change_url) 119 last_change = response.read() 120 if not last_change: 121 print >>sys.stderr, ('Unable to get latest from %s' % last_change_url) 122 sys.exit(2) 123 last_change_url = ('http://commondatastorage.googleapis.com/' 124 'chromium-browser-continuous/%s/%s' % (os_type, 125 last_change)) 126 return last_change_url 127 128 def Cleanup(self): 129 """Remove old binaries, if any.""" 130 pass 131 132 def Run(self): 133 self._ParseArgs() 134 if not os.path.isdir(self._outdir): 135 os.makedirs(self._outdir) 136 get_remoting = pyauto_utils.DoesUrlExist(self._remoting_zip_url) 137 138 # Fetch chrome & pyauto binaries 139 print('Fetching', self._chrome_zip_url) 140 chrome_zip = urllib.urlretrieve(self._chrome_zip_url)[0] 141 142 if get_remoting: 143 print('Fetching', self._remoting_zip_url) 144 remoting_zip = urllib.urlretrieve(self._remoting_zip_url)[0] 145 else: 146 print('Warning: %s does not exist.' % self._remoting_zip_url) 147 148 print('Fetching', self._pyautolib_py_url) 149 pyautolib_py = urllib.urlretrieve(self._pyautolib_py_url)[0] 150 151 print('Fetching', self._pyautolib_so_url) 152 pyautolib_so = urllib.urlretrieve(self._pyautolib_so_url)[0] 153 154 if self._options.platform == 'mac': 155 print('Fetching', self._ffmpegsumo_so_url) 156 ffmpegsumo_so = urllib.urlretrieve(self._ffmpegsumo_so_url)[0] 157 158 print('Fetching', self._chromedriver_url) 159 chromedriver = urllib.urlretrieve(self._chromedriver_url)[0] 160 161 chrome_unzip_dir = os.path.join(self._outdir, self._chrome_zip_name) 162 if os.path.exists(chrome_unzip_dir): 163 print('Cleaning', chrome_unzip_dir) 164 pyauto_utils.RemovePath(chrome_unzip_dir) 165 print('Unzipping') 166 pyauto_utils.UnzipFilenameToDir(chrome_zip, self._outdir) 167 if get_remoting: 168 pyauto_utils.UnzipFilenameToDir(remoting_zip, self._outdir) 169 shutil.move(self._outdir + '/remoting-webapp', 170 self._outdir + '/remoting/remoting.webapp') 171 172 # Copy over the binaries to outdir 173 items_to_copy = { 174 pyautolib_py: os.path.join(self._outdir, 'pyautolib.py'), 175 pyautolib_so: os.path.join(self._outdir, self._pyautolib_so_name), 176 chromedriver: os.path.join(self._outdir, self._chromedriver_name) 177 } 178 if self._options.platform == 'mac': 179 items_to_copy[ffmpegsumo_so] = \ 180 os.path.join(self._outdir, self._ffmpegsumo_so_name) 181 182 unzip_dir_contents = glob.glob(os.path.join(chrome_unzip_dir, '*')) 183 for item in unzip_dir_contents: 184 name = os.path.basename(item) 185 items_to_copy[item] = os.path.join(self._outdir, name) 186 187 for src, dest in items_to_copy.iteritems(): 188 pyauto_utils.RemovePath(dest) 189 print('%s ==> %s' % (os.path.basename(src), dest)) 190 shutil.move(src, dest) 191 pyauto_utils.RemovePath(chrome_unzip_dir) 192 193 # Final setup (if any) 194 # Set executable bit on chromedriver binary. 195 if not self._options.platform == 'win': 196 os.chmod(items_to_copy[chromedriver], 0o0700) 197 198 # Create symlink to .framework on Mac 199 if self._options.platform == 'mac': 200 mac_app_name = os.path.basename([x for x in unzip_dir_contents 201 if x.endswith('.app')][0]) 202 os.chdir(self._outdir) 203 framework = glob.glob(os.path.join( 204 mac_app_name, 'Contents', 'Versions', '*', '*.framework'))[0] 205 print(framework) 206 dest = os.path.basename(framework) 207 os.path.lexists(dest) and os.remove(dest) 208 print('Creating symlink "%s"' % dest) 209 os.symlink(framework, dest) 210 211 print('Prepared binaries in "%s"' % self._outdir) 212 return 0 213 214 215if __name__ == '__main__': 216 sys.exit(FetchPrebuilt().Run()) 217