Home | History | Annotate | Download | only in pyautolib
      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