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 8 Sets up Chrome and PyAuto binaries using prebuilt binaries from the 9 continuous build archives. Works on mac, win, linux (32 & 64 bit). 10 11 Examples: 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 21 import glob 22 import httplib 23 import optparse 24 import os 25 import platform 26 import shutil 27 import sys 28 import urllib 29 import urllib2 30 import urlparse 31 32 import pyauto_utils 33 34 35 class 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 213 if __name__ == '__main__': 214 sys.exit(FetchPrebuilt().Run()) 215