From f74448a1b262941da712a6e0db923d1cf4d1006e Mon Sep 17 00:00:00 2001 From: Dave Page Date: Thu, 25 Apr 2019 09:38:52 +0100 Subject: [PATCH] Add a script for installing the required Chromedriver version. --- tools/get_chromedriver.py | 204 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 tools/get_chromedriver.py diff --git a/tools/get_chromedriver.py b/tools/get_chromedriver.py new file mode 100644 index 000000000..0a5630609 --- /dev/null +++ b/tools/get_chromedriver.py @@ -0,0 +1,204 @@ +# -*- coding: utf-8 -*- + +########################################################################## +# +# pgAdmin 4 - PostgreSQL Tools +# +# Copyright (C) 2013 - 2019, The pgAdmin Development Team +# This software is released under the PostgreSQL Licence +# +########################################################################## + +# Get the correct version of chromedriver for the version of Chrome on the +# machine and save it to the specified location. + +import argparse +import os +import platform +import subprocess +import sys +import urllib.request +import zipfile + + +def read_command_line(): + """Read the command line arguments. + + Returns: + ArgumentParser: The parsed arguments object + """ + parser = argparse.ArgumentParser( + description='Get the correct version of chromedriver for the ' + 'specified Chrome installation and save it.') + if platform.system() != 'Windows': + parser.add_argument("chrome", metavar="CHROME", + help="the Chrome executable") + parser.add_argument("directory", metavar="DIRECTORY", + help="the directory in which to save chromedriver") + + args = parser.parse_args() + + return args + + +def get_chrome_version(args): + """Get the Chrome version number. + + Args: + args: The parsed arguments object + Returns: + The Chrome version number + """ + if platform.system() == 'Windows': + # On Windows we need to examine the resource section of the binary + import winreg + + def _read_registry(root, key, value): + try: + hkey = winreg.OpenKey(root, key) + except Exception as e: + return None + try: + (val, typ) = winreg.QueryValueEx(hkey, value) + except Exception as e: + winreg.CloseKey(hkey) + return None + + winreg.CloseKey(hkey) + return val + + key = r'SOFTWARE\Google\Chrome\BLBeacon' + version_str = _read_registry(winreg.HKEY_CURRENT_USER, key, 'Version') + + # On a 64b host, look for a 32b installation + if not version_str: + key = r'SOFTWARE\Wow6432Node\Google\Chrome\BLBeacon' + version_str = _read_registry(winreg.HKEY_CURRENT_USER, key, + 'Version') + + if not version_str: + print('The Chrome version could not be read from the registry.') + sys.exit(1) + + chrome_version = '.'.join(version_str.split()[-1].split('.')[:-1]) + else: + # On Linux/Mac we run the Chrome executable with the --version flag, + # then parse the output. + try: + result = subprocess.run([args.chrome, '--version'], + stdout=subprocess.PIPE) + except FileNotFoundError as e: + print('The specified Chrome executable could not be found.') + sys.exit(1) + + version_str = result.stdout.decode("utf-8").strip() + # Check for 'Chrom' not 'Chrome' in case the user is using Chromium. + if "Chrom" not in version_str: + print('The specified Chrome executable output an unexpected ' + 'version string: {}.'.format(version_str)) + sys.exit(1) + + chrome_version = '.'.join(version_str.split()[-1].split('.')[:-1]) + + if chrome_version.count('.') != 2: + print('The specified Chrome executable output an unexpected ' + 'version string: {}.'.format(version_str)) + sys.exit(1) + + return chrome_version + + +def get_chromedriver_version(chrome_version): + """Get the required chromedriver version number. + + Args: + chrome_version: The chrome version number + Returns: + The chromedriver version number + """ + url = 'https://chromedriver.storage.googleapis.com/LATEST_RELEASE_{}' \ + .format(chrome_version) + + try: + fp = urllib.request.urlopen(url) + except urllib.error.URLError as e: + print('The chromedriver catalog URL could not be accessed: {}' + .format(e)) + sys.exit(1) + + version = fp.read().decode("utf-8").strip() + fp.close() + + return version + + +def get_system(): + """Get the system name as known to chromedriver + + Returns: + The system name + """ + if platform.system() == 'Darwin': + return 'mac64' + elif platform.system() == 'Linux': + return 'linux64' + elif platform.system() == 'Windows': + return 'win32' + else: + print("Unknown or unsupported operating system: {}" + .format(platform.system())) + sys.exit(1) + + +"""The core structure of the app.""" + +# Read the command line options +args = read_command_line() + +chrome_version = get_chrome_version(args) + +# Check the directory exists +if not os.path.isdir(args.directory): + print('The specified output directory could not be accessed.') + sys.exit(1) + +chromedriver_version = get_chromedriver_version(chrome_version) + +system = get_system() + +url = 'https://chromedriver.storage.googleapis.com/{}/chromedriver_{}.zip' \ + .format(chromedriver_version, system) + +print('Downloading chromedriver v{} for Chrome v{} on {}...' + .format(chromedriver_version, chrome_version, system)) + +try: + file, headers = urllib.request.urlretrieve(url) +except urllib.error.URLError as e: + print('The chromedriver download URL could not be accessed: {}' + .format(e)) + sys.exit(1) + +# Unzip chromedriver +print('Extracting chromedriver...') + +found = False +fp = open(file, 'rb') +z = zipfile.ZipFile(fp) +for name in z.namelist(): + if (system == 'win32' and name == 'chromedriver.exe') or \ + (system != 'win32' and name == 'chromedriver'): + z.extract(name, args.directory) + found = True +fp.close() + +if not found: + print("chromedriver could not be found in the downloaded archive: {}" + .format(file)) + sys.exit(1) + +# Set the permissions +if system == 'mac64' or system == 'linux64': + os.chmod(os.path.join(args.directory, 'chromedriver'), 0o755) + +print('Chromedriver downloaded to: {}'.format(args.directory))