widevine-cdm: refactor x86_64-linux to use official sources, add update script

fmbearmf 450c540f eac25e9e

+168 -8
+1
pkgs/by-name/wi/widevine-cdm/package.nix
··· 5 5 }: 6 6 7 7 let 8 + # TODO: update aarch64 to use crx3 8 9 targets = lib.genAttrs [ 9 10 "aarch64-linux" 10 11 "x86_64-linux"
+148
pkgs/by-name/wi/widevine-cdm/update-x86_64.py
··· 1 + #! /usr/bin/env nix-shell 2 + #! nix-shell -i python3 -p python3 3 + 4 + from __future__ import annotations 5 + import sys, os, json, base64, re, subprocess, shutil, argparse, urllib.request, time 6 + from typing import Dict, Optional, Tuple 7 + 8 + DEFAULT_JSON = "https://raw.githubusercontent.com/mozilla/gecko-dev/master/toolkit/content/gmp-sources/widevinecdm.json" 9 + ARCH_PATTERNS = { 10 + "linux_x86_64": ["Linux_x86_64-gcc3", "Linux_x86_64", "linux_x86_64"], # trying to predict the future rn... 11 + "linux_aarch64": ["Linux_aarch64-gcc3", "Linux_aarch64", "linux_aarch64"] 12 + } 13 + 14 + def fetch_json(url: str) -> dict: 15 + with urllib.request.urlopen(url) as r: 16 + return json.load(r) 17 + 18 + def hex_to_sri(hexstr: str) -> str: 19 + b = bytes.fromhex(hexstr) 20 + return "sha512-" + base64.b64encode(b).decode() 21 + 22 + def find_widevine_vendor(data: dict) -> dict: 23 + vendors = data.get("vendors") or {} 24 + for key, value in vendors.items(): 25 + if "gmp-widevinecdm" in key.lower(): 26 + return value 27 + 28 + raise SystemExit("ERR: couldn't find a widevine vendor entry in JSON !") 29 + 30 + def judge_platforms(platforms: dict, patterns) -> Optional[Tuple[str, dict]]: 31 + for plkey, plvalue in platforms.items(): 32 + if plvalue.get("alias"): 33 + continue 34 + 35 + low = plkey.lower() 36 + for pat in patterns: 37 + if pat.lower() in low: 38 + return plkey, plvalue 39 + 40 + return None 41 + 42 + def normalize_fileurl(entry: dict) -> Optional[str]: 43 + if entry.get("fileUrl"): 44 + return entry["fileUrl"] 45 + 46 + m = entry.get("mirrorUrls") 47 + if isinstance(m, list) and m: 48 + return m[0] 49 + 50 + return None 51 + 52 + def extract_ver_from_url(url: str) -> Optional[str]: 53 + m = re.search(r'[_-](\d+\.\d+\.\d+\.\d+)[_-]', url) 54 + if m: 55 + return m.group(1) 56 + m = re.search(r'(\d+\.\d+\.\d+\.\d+)', url) 57 + return m.group(1) if m else None 58 + 59 + def build_entry(pkey: str, pentry: dict) -> dict: 60 + url = normalize_fileurl(pentry) 61 + hv = pentry.get("hashValue") 62 + 63 + if not url or not hv: 64 + raise SystemExit(f"ERR: platform {pkey} is missing a file URL or hash !") 65 + 66 + sri = hex_to_sri(hv) 67 + version = extract_ver_from_url(url) 68 + return {"platform_key": pkey, "url": url, "hashValue": hv, "sri": sri, "version": version} 69 + 70 + 71 + 72 + def main(): 73 + ap = argparse.ArgumentParser() 74 + ap.add_argument("--json-url", default="https://raw.githubusercontent.com/mozilla-firefox/firefox/refs/heads/main/toolkit/content/gmp-sources/widevinecdm.json") 75 + args = ap.parse_args() 76 + 77 + print(f"# fetching {args.json_url} !", file=sys.stderr) 78 + data = fetch_json(args.json_url) 79 + vendor = find_widevine_vendor(data) 80 + platforms = vendor.get("platforms") or {} # should never be null but moz could forseeably delete it 81 + if not platforms: 82 + raise SystemExit("ERR: no widevine platforms !") 83 + 84 + results = {} 85 + for arch, patterns in ARCH_PATTERNS.items(): 86 + found = judge_platforms(platforms, patterns) 87 + if not found: 88 + print(f"# WARN: no platform for {arch}. skipping !", file=sys.stderr) 89 + continue 90 + pkey, pentry = found 91 + print(f"# found {arch} --> {pkey}", file=sys.stderr) 92 + entry = build_entry(pkey, pentry) 93 + results[arch] = entry 94 + 95 + if not results: 96 + raise SystemExit("ERR: no linux platform entries !") 97 + 98 + linux_x64 = results["linux_x86_64"] 99 + 100 + try: 101 + with open("x86_64-linux.nix", "w") as f: 102 + f.write(f"""{{ 103 + lib, 104 + stdenv, 105 + fetchurl, 106 + go-crx3, 107 + }}: 108 + 109 + stdenv.mkDerivation (finalAttrs: {{ 110 + # Generated by update.py (don't edit this file manually) 111 + pname = "widevine-cdm"; 112 + version = "{linux_x64["version"]}"; 113 + 114 + src = fetchurl {{ 115 + url = "{linux_x64["url"]}"; 116 + hash = "{linux_x64["sri"]}"; 117 + }}; 118 + 119 + nativeBuildInputs = [ go-crx3 ]; 120 + 121 + unpackPhase = '' 122 + unpackDir="src" 123 + cp "$src" "$unpackDir".crx # go-crx3 doesn't like .crx3 extensions 124 + crx3 unpack "$unpackDir".crx 125 + 126 + cd "$unpackDir" 127 + ''; 128 + 129 + installPhase = '' 130 + runHook preInstall 131 + 132 + install -vD manifest.json $out/share/google/chrome/WidevineCdm/manifest.json 133 + install -vD LICENSE $out/share/google/chrome/WidevineCdm/LICENSE.txt 134 + install -vD _platform_specific/linux_x64/libwidevinecdm.so $out/share/google/chrome/WidevineCdm/_platform_specific/linux_x64/libwidevinecdm.so 135 + 136 + runHook postInstall 137 + ''; 138 + 139 + meta = import ./meta.nix lib; 140 + passthru.updateScript = ./update-x86_64.py; 141 + }})""") 142 + 143 + except Exception as e: 144 + print("failed to write x86_64-linux.nix: ", e, file=sys.stderr) 145 + 146 + 147 + if __name__ == "__main__": 148 + main()
+19 -8
pkgs/by-name/wi/widevine-cdm/x86_64-linux.nix
··· 1 1 { 2 2 lib, 3 3 stdenv, 4 - fetchzip, 4 + fetchurl, 5 + go-crx3, 5 6 }: 6 7 7 8 stdenv.mkDerivation (finalAttrs: { 9 + # Generated by update.py (don't edit this file manually) 8 10 pname = "widevine-cdm"; 9 11 version = "4.10.2891.0"; 10 12 11 - src = fetchzip { 12 - # The download 404s 13 - url = "https://web.archive.org/web/20250725071306/https://dl.google.com/widevine-cdm/4.10.2891.0-linux-x64.zip"; 14 - hash = "sha256-ZO6FmqJUnB9VEJ7caJt58ym8eB3/fDATri3iOWCULRI="; 15 - stripRoot = false; 13 + src = fetchurl { 14 + url = "https://edgedl.me.gvt1.com/edgedl/release2/chrome_component/aclxnidwwkj5di3vduduj2gqpgpq_4.10.2891.0/oimompecagnajdejgnnjijobebaeigek_4.10.2891.0_linux_b4hin3q5s66ws2322cyyfp35lu.crx3"; 15 + hash = "sha512-8S/4FRQQmQAO9wJ7QGJg8KUVxUQgm5/oEl6l9N2/WGAdMCIqxBoBPrCkPadrpwQUpK0WYX2fIZ8Zzfx3lNm8lA=="; 16 16 }; 17 17 18 + nativeBuildInputs = [ go-crx3 ]; 19 + 20 + unpackPhase = '' 21 + unpackDir="src" 22 + cp "$src" "$unpackDir".crx # go-crx3 doesn't like .crx3 extensions 23 + crx3 unpack "$unpackDir".crx 24 + 25 + cd "$unpackDir" 26 + ''; 27 + 18 28 installPhase = '' 19 29 runHook preInstall 20 30 21 31 install -vD manifest.json $out/share/google/chrome/WidevineCdm/manifest.json 22 - install -vD LICENSE.txt $out/share/google/chrome/WidevineCdm/LICENSE.txt 23 - install -vD libwidevinecdm.so $out/share/google/chrome/WidevineCdm/_platform_specific/linux_x64/libwidevinecdm.so 32 + install -vD LICENSE $out/share/google/chrome/WidevineCdm/LICENSE.txt 33 + install -vD _platform_specific/linux_x64/libwidevinecdm.so $out/share/google/chrome/WidevineCdm/_platform_specific/linux_x64/libwidevinecdm.so 24 34 25 35 runHook postInstall 26 36 ''; 27 37 28 38 meta = import ./meta.nix lib; 39 + passthru.updateScript = ./update-x86_64.py; 29 40 })