blob: f8b1fc3b4f20122f3e24fb952b7871754917893a [file] [log] [blame]
#!/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:]))