| #!/usr/bin/env python |
| # Copyright 2015 The Native Client Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| """Download the a build of chrome from Google Clound Storage.""" |
| |
| import argparse |
| import logging |
| import os |
| import shutil |
| import sys |
| import zipfile |
| |
| SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) |
| SRC_DIR = os.path.dirname(SCRIPT_DIR) |
| sys.path.insert(0, os.path.join(SRC_DIR, 'lib')) |
| |
| import webports |
| |
| GS_URL = 'http://storage.googleapis.com' |
| CHROME_URL_FORMAT = GS_URL + '/chromium-browser-continuous/%s/%s/%s' |
| CHROME_DOWNLOAD_DIR = os.path.join(webports.paths.OUT_DIR, 'downloaded_chrome') |
| |
| def ChromeDir(arch): |
| """Get the directory to download chrome to.""" |
| return os.path.join(CHROME_DOWNLOAD_DIR, arch) |
| |
| |
| def ChromeArchiveRoot(): |
| if sys.platform == 'win32': |
| return 'chrome-win32' |
| elif sys.platform == 'darwin': |
| return 'chrome-mac' |
| elif sys.platform.startswith('linux'): |
| return 'chrome-linux' |
| else: |
| raise webports.error.Error('Unknown platform: %s' % sys.platform) |
| |
| |
| def ChromeUrl(arch, revision): |
| """Get the URL to download chrome from. |
| |
| Args: |
| arch: Chrome architecture to select i686/x86_64/pnacl. |
| Returns: |
| URL to download a zip file from. |
| """ |
| if sys.platform == 'win32': |
| filename = 'chrome-win32.zip' |
| target = 'Win_x64' |
| elif sys.platform == 'darwin': |
| filename = 'chrome-mac.zip' |
| target = 'Mac' |
| elif sys.platform.startswith('linux'): |
| filename = 'chrome-linux.zip' |
| if arch == 'i686': |
| target = 'Linux' |
| elif arch == 'x86_64' or arch == 'pnacl': |
| # Arbitrarily decide we will use 64-bit Linux for PNaCl. |
| target = 'Linux_x64' |
| else: |
| logging.error('Bad architecture %s' % arch) |
| sys.exit(1) |
| else: |
| logging.error('Unsupported platform %s' % sys.platform) |
| sys.exit(1) |
| return CHROME_URL_FORMAT % (target, revision, filename) |
| |
| |
| def DoDownload(url, destination): |
| """Download chrome. |
| |
| Download chrome to a particular destination, leaving a stamp containing the |
| download URL. Download is skipped if the stamp matches the URL. |
| Args: |
| url: URL to download chrome from. |
| destination: A directory to download chrome to. |
| """ |
| stamp_filename = os.path.join(destination, 'STAMP') |
| # Change this line each time the mods we make to the chrome checkout change |
| # otherwise the modding code will be skipped. |
| stamp_content = 'mods_v2:' + url |
| if os.path.exists(stamp_filename): |
| with open(stamp_filename) as f: |
| if f.read() == stamp_content: |
| logging.info('Skipping chrome download, ' |
| 'chrome in %s is up to date' % destination) |
| return |
| if os.path.exists(destination): |
| logging.info('Deleting old chrome...') |
| shutil.rmtree(destination) |
| |
| logging.info('Creating %s' % destination) |
| os.makedirs(destination) |
| |
| logging.info('Downloading chrome from %s to %s...' % (url, destination)) |
| chrome_zip = os.path.join(webports.paths.CACHE_ROOT, os.path.basename(url)) |
| webports.util.Makedirs(os.path.dirname(chrome_zip)) |
| try: |
| webports.util.DownloadFile(chrome_zip, url) |
| except webports.error.Error as e: |
| logging.error('Unable to download chrome: %s' % str(e)) |
| sys.exit(1) |
| |
| pnacl_url = os.path.join(os.path.dirname(url), 'pnacl.zip') |
| pnacl_zip = os.path.join(webports.paths.CACHE_ROOT, 'pnacl.zip') |
| logging.info('Downloading pnacl component from %s ...' % url) |
| try: |
| webports.util.DownloadFile(pnacl_zip, pnacl_url) |
| except webports.error.Error as e: |
| logging.error('Unable to download chrome: %s' % str(e)) |
| sys.exit(1) |
| |
| logging.info('Extracting %s' % chrome_zip) |
| with zipfile.ZipFile(chrome_zip) as zip_archive: |
| zip_archive.extractall(destination) |
| # Change the executables to be executable. |
| for root, _, files in os.walk(destination): |
| for filename in files: |
| if (filename.startswith('Chromium') or |
| filename in ('chrome-wrapper', 'chrome', 'nacl_helper', |
| 'nacl_helper_bootstrap')): |
| path = os.path.join(root, filename) |
| os.chmod(path, 0755) |
| |
| if sys.platform.startswith('linux'): |
| if '64' in url: |
| libudev0 = '/lib/x86_64-linux-gnu/libudev.so.0' |
| libudev1 = '/lib/x86_64-linux-gnu/libudev.so.1' |
| else: |
| libudev0 = '/lib/i386-linux-gnu/libudev.so.0' |
| libudev1 = '/lib/i386-linux-gnu/libudev.so.1' |
| if os.path.exists(libudev1) and not os.path.exists(libudev0): |
| link = os.path.join(destination, 'chrome-linux', 'libudev.so.0') |
| logging.info('creating link %s' % link) |
| os.symlink(libudev1, link) |
| |
| logging.info('Extracting %s' % pnacl_zip) |
| with zipfile.ZipFile(pnacl_zip) as zip_archive: |
| zip_archive.extractall(destination) |
| |
| chrome_root = os.path.join(destination, ChromeArchiveRoot()) |
| pnacl_root = os.path.join(destination, 'pnacl', 'pnacl') |
| logging.info('Renaming pnacl directory %s -> %s' % (pnacl_root, chrome_root)) |
| os.rename(pnacl_root, os.path.join(chrome_root, 'pnacl')) |
| |
| logging.info('Writing stamp...') |
| with open(stamp_filename, 'w') as fh: |
| fh.write(stamp_content) |
| logging.info('Done.') |
| |
| |
| def DownloadChrome(arch, revision): |
| target_dir = ChromeDir(arch) |
| DoDownload(ChromeUrl(arch, revision), target_dir) |
| return os.path.join(target_dir, ChromeArchiveRoot()) |
| |
| |
| def RunMain(argv): |
| parser = argparse.ArgumentParser(prog='download_chrome', description=__doc__) |
| parser.add_argument('-a', '--arch', default='x86_64', |
| choices=['x86_64', 'i686'], |
| help='Chrome architecture.') |
| logging.basicConfig(format='%(message)s', level=logging.INFO) |
| parser.add_argument('revision') |
| options = parser.parse_args(argv) |
| dirname = DownloadChrome(options.arch, options.revision) |
| logging.info('Chrome %s downloaded to: %s' % (options.revision, dirname)) |
| return 0 |
| |
| |
| def main(argv): |
| try: |
| return RunMain(argv) |
| except KeyboardInterrupt: |
| sys.stderr.write('interrupted\n') |
| return 1 |
| except webports.error.Error as e: |
| if os.environ.get('DEBUG'): |
| raise |
| sys.stderr.write(str(e) + '\n') |
| return 1 |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main(sys.argv[1:])) |