Skip to content

Instantly share code, notes, and snippets.

@cryzed
Created August 4, 2018 22:47
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cryzed/29e6ff9fbf92281f8c3bded50de68836 to your computer and use it in GitHub Desktop.
Save cryzed/29e6ff9fbf92281f8c3bded50de68836 to your computer and use it in GitHub Desktop.
import argparse
import json
import os
import posixpath
import shutil
import subprocess
import tempfile
import requests
EXTENSIONS_PATH = os.path.expanduser('~/.config/chromium/Default/Extensions')
LOCAL_STATE_PATH = os.path.expanduser('~/.config/chromium/Local State')
MANIFEST_PATH_TEMPLATE = os.path.expanduser('~/.config/chromium/Default/Extensions/{id}/{version}/manifest.json')
# https://ungoogled-software.github.io/ungoogled-chromium-wiki/faq#can-i-install-extensions-from-the-chrome-webstore
CRX_URL_TEMPLATE = 'https://clients2.google.com/service/update2/crx?response=redirect&prodversion={version}&x=id%3D{id}%26installsource%3Dondemand%26uc'
argument_parser = argparse.ArgumentParser()
# Chromium 67.0.3396.87 Arch Linux
def get_installed_chromium_version():
with open(LOCAL_STATE_PATH, 'rb') as file:
data = json.load(file)
return data['startup_metric']['last_startup_version']
def get_extension_ids():
ids = set(os.listdir(EXTENSIONS_PATH))
return ids - {'Temp'}
def get_installed_version(extension_id):
versions = os.listdir(os.path.join(EXTENSIONS_PATH, extension_id))
return sorted(versions, reverse=True)[0]
def check_for_update(chromium_version, extension_id, installed_version):
crx_url = CRX_URL_TEMPLATE.format(version=chromium_version, id=extension_id)
response = requests.get(crx_url, allow_redirects=False, stream=True)
location = response.headers['Location']
filename = posixpath.basename(location)
version = os.path.splitext(filename)[0].replace('extension_', '', 1)
if version.replace('_', '.') != installed_version.replace('_', '.'):
return version, location
def install_update(crx_path):
executable = shutil.which('chromium')
subprocess.run([executable, crx_path], stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
def load_manifest(extension_id, version):
path = MANIFEST_PATH_TEMPLATE.format(id=extension_id, version=version)
with open(path, 'rb') as file:
return json.load(file)
def main(arguments):
chromium_version = get_installed_chromium_version()
chromium_major_version = '.'.join(chromium_version.split('.', 2)[:-1])
print(f'Detected Chromium version: {chromium_version} (Major: {chromium_major_version})')
for extension_id in get_extension_ids():
extension_version = get_installed_version(extension_id)
manifest = load_manifest(extension_id, extension_version)
print(f'Checking updates for extension {manifest["name"]!r} ({extension_id}) v{manifest["version"]}...')
update = check_for_update(chromium_major_version, extension_id, extension_version)
if not update:
continue
version, url = update
print(f'Downloading update {version}: {url}...')
fd, path = tempfile.mkstemp('.crx')
response = requests.get(url)
with os.fdopen(fd, 'wb') as file:
file.write(response.content)
print('Installing update...')
install_update(path)
if __name__ == '__main__':
arguments = argument_parser.parse_args()
argument_parser.exit(main(arguments))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment