| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- import os
- import configparser
- import shutil
- from typing import Optional
- from time import sleep
- from argparse import ArgumentParser
- from subprocess import run, Popen
- from sys import stderr, stdout
- from yaml import load, SafeLoader
- from marionette_driver.addons import Addons
- from marionette_driver.marionette import Marionette
- from marionette_driver.geckoinstance import DesktopInstance
- from mozprofile import FirefoxProfile
- def shell_execute(cmd: str, env: Optional[dict] = None):
- if env is None:
- env = {}
- run(cmd, env=env, stdout=stdout, stderr=stderr, shell=True)
- def profile_list() -> list:
- result = []
- ini = configparser.ConfigParser()
- ini.read(os.path.expanduser("~/.mozilla/firefox/profiles.ini"))
- for _, values in ini.items():
- for key, value in values.items():
- if key != "path":
- continue
- result.append(value)
- return list(set(result))
- def profile_create(name_1: str):
- shell_execute(f"/usr/bin/firefox --createprofile {name_1} -headless")
- def profile_configure(name_1: str, name_2: str):
- cwd = os.path.dirname(os.path.realpath(__file__))
- # Read config
- config = {}
- with open(f"{cwd}/profiles/{name_1}.yaml", "rt", encoding="utf-8") as handle:
- config = load(handle, Loader=SafeLoader)
- # Install signed addons first
- # Start firefox
- profile = FirefoxProfile(name_1)
- firefox = DesktopInstance(
- host="127.0.0.1",
- port=2828,
- bin="/usr/bin/firefox",
- app_args=["-remote-allow-system-access"],
- profile=profile,
- headless=1,
- )
- firefox.start()
- # Init marionette
- marionette = Marionette()
- marionette.start_session()
- # Install addons
- addons = Addons(marionette)
- for addon in config["addons"]:
- addons.install(f"{cwd}/addons/{addon['id']}-{addon['version']}.xpi")
- firefox.close()
- # Set prefs
- with open(f"{cwd}/{name_1}/user.js", "wt", encoding="utf-8") as handle:
- for key, value in config["prefs"].items():
- if type(value) == str:
- value = f'"{value}"'
- elif type(value) == bool:
- value = 'true' if value else 'false'
- else:
- value = value
- handle.write(f'user_pref("{key}", {value});\n')
- # Install profile
- from_path = f"{cwd}/{name_1}"
- to_path = os.path.expanduser(f"~/.mozilla/firefox/{name_2}")
- if os.path.exists(to_path):
- shutil.rmtree(to_path)
- shutil.copytree(from_path, to_path, dirs_exist_ok=True)
- shutil.rmtree(from_path)
- def profile_init(name_1: str):
- proc = Popen(f"/usr/bin/firefox -p {name_1} -headless", shell=True)
- sleep(5) # TODO: investigate why firefox take a time to apply extensions
- proc.kill()
- def profile_patch(name_2: str):
- cwd = os.path.dirname(os.path.realpath(__file__))
- # Patch profile
- from_path = f"{cwd}/patches/search.json.mozlz4"
- to_path = os.path.expanduser(f"~/.mozilla/firefox/{name_2}/search.json.mozlz4")
- shutil.copy(from_path, to_path)
- def main():
- parser = ArgumentParser()
- parser.add_argument("--configs", type=str, nargs="*", required=True)
- args = parser.parse_args()
- try:
- shutil.rmtree(os.path.expanduser("~/.mozilla"))
- except:
- pass
- names_1 = []
- for config in args.configs:
- names_1.append(config)
- for name_1 in names_1:
- profile_create(name_1)
- sleep(1) # Prevent profile hash collision
- names_2 = profile_list()
- mapping = {}
- for name_1 in names_1:
- for name_2 in names_2:
- if name_1 in name_2:
- mapping[name_1] = name_2
- break
- for name_1, name_2 in mapping.items():
- profile_configure(name_1, name_2)
- profile_init(name_1) # TODO: remove this workaround
- # profile_patch(name_2) # TODO: patching not working for now, dynamic patching needed
- if __name__ == "__main__":
- try:
- main()
- except Exception as e:
- print(e)
|