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