Backed out changeset f594e6f00208 (bug 1940883) for causing crashes in bug 1941164.
[gecko.git] / dom / media / tools / checkGmpBalrog.py
blob3731c89cbea7ada1fc89a6e89112827d7c582f75
1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 import argparse
6 import hashlib
7 import re
8 from datetime import datetime
9 from urllib.parse import urlparse
10 from xml.etree import ElementTree
12 import requests
15 def check_hash(plugin, url, valid_urls):
16 if url in valid_urls:
17 return
18 valid_urls[url] = True
20 response = requests.get(url)
21 response.raise_for_status()
23 if "hashValue" in plugin.attrib:
24 hashValue = hashlib.sha512(response.content).hexdigest()
25 if hashValue != plugin.attrib["hashValue"]:
26 raise Exception(
27 "Given hash {} and calculated hash {} differ",
28 plugin.attrib["hashValue"],
29 hashValue,
31 if "size" in plugin.attrib:
32 size = len(response.content)
33 if size != int(plugin.attrib["size"]):
34 raise Exception(
35 "Given size {} and calculated size {} differ",
36 int(plugin.attrib["size"]),
37 size,
41 def fetch_balrog_xml(
42 url_base: str, plugin_id, version: str, buildid: str, channels, targets, checkHash
43 ) -> str:
44 url = "{url_base}/{version}/{buildid}/{target}/en-US/{channel}/default/default/default/update.xml"
45 valid_urls = {}
46 results = {}
47 for channel in channels:
48 results[channel] = {}
49 for target in targets:
50 balrog_url = url.format_map(
52 "url_base": url_base,
53 "buildid": buildid,
54 "channel": channel,
55 "version": version,
56 "target": target,
60 response = requests.get(balrog_url)
61 response.raise_for_status()
63 plugin_urls = []
64 tree = ElementTree.fromstring(response.content)
65 for plugin in tree.findall("./addons/addon"):
66 if not "id" in plugin.attrib:
67 continue
68 if plugin.attrib["id"] != plugin_id:
69 continue
70 if "URL" in plugin.attrib:
71 if checkHash:
72 check_hash(plugin, plugin.attrib["URL"], valid_urls)
73 plugin_urls.append(plugin.attrib["URL"])
74 for mirror in plugin.findall("./mirror"):
75 if "URL" in mirror.attrib:
76 if checkHash:
77 check_hash(plugin, plugin.attrib["URL"], valid_urls)
78 plugin_urls.append(mirror.attrib["URL"])
80 results[channel][target] = plugin_urls
82 matching_channels = {}
83 for channel in channels:
84 matching_channels[channel] = [channel]
85 for other_channel in channels:
86 if (
87 channel == other_channel
88 or channel not in results
89 or other_channel not in results
91 continue
92 if results[channel] == results[other_channel]:
93 matching_channels[channel].append(other_channel)
94 del results[other_channel]
96 for channel in results:
97 print(", ".join(matching_channels[channel]))
98 for target in targets:
99 print("\t{}".format(target))
100 for url in results[channel][target]:
101 print("\t\t{}".format(url))
104 def main():
105 examples = """examples:
106 python dom/media/tools/checkGmpBalrog.py widevine 133.0
107 python dom/media/tools/checkGmpBalrog.py widevine 133.0 --target Darwin_aarch64-gcc3 Darwin_x86_64-gcc3
108 python dom/media/tools/checkGmpBalrog.py --url http://localhost:8080 openh264 125.0
109 python dom/media/tools/checkGmpBalrog.py widevine_l1 115.14.0 --staging --channel nightly beta"""
111 parser = argparse.ArgumentParser(
112 description="Check Balrog XML for GMP plugin updates",
113 epilog=examples,
114 formatter_class=argparse.RawDescriptionHelpFormatter,
116 parser.add_argument(
117 "plugin",
118 help="which plugin: openh264, widevine, widevine_l1",
120 parser.add_argument("version", help="version of Firefox")
121 parser.add_argument(
122 "--channel", action="extend", nargs="+", help="check specific channel(s)"
124 parser.add_argument(
125 "--list-channels", action="store_true", help="list the supported channels"
127 parser.add_argument(
128 "--target", action="extend", nargs="+", help="check specific target(s)"
130 parser.add_argument(
131 "--list-targets", action="store_true", help="list the supported targets"
133 parser.add_argument("--buildid", help="override generated build ID to be specific")
134 parser.add_argument(
135 "--url", help="override base URL from which to fetch the balrog configuration"
137 parser.add_argument(
138 "--staging",
139 action="store_true",
140 help="using the balrog staging URL instead of production",
142 parser.add_argument(
143 "--checkHash",
144 action="store_true",
145 help="download plugins and validate the size/hash",
147 args = parser.parse_args()
149 valid_channels = ["esr", "release", "beta", "nightly", "nightlytest"]
150 if args.list_channels:
151 for channel in valid_channels:
152 print(channel)
153 return
154 if args.channel is not None:
155 for channel in args.channel:
156 if channel not in valid_channels:
157 parser.error("`%s` is invalid, see --list-channels" % channel)
158 return
159 channels = args.channel
160 else:
161 channels = valid_channels
163 valid_targets = [
164 "Darwin_aarch64-gcc3",
165 "Darwin_x86_64-gcc3",
166 "Linux_aarch64-gcc3",
167 "Linux_x86-gcc3",
168 "Linux_x86_64-gcc3",
169 "WINNT_aarch64-msvc-aarch64",
170 "WINNT_x86-msvc",
171 "WINNT_x86_64-msvc",
173 valid_aliases = [
174 "Linux_x86_64-gcc3-asan",
175 "WINNT_x86-msvc-x64",
176 "WINNT_x86-msvc-x86",
177 "WINNT_x86_64-msvc-x64",
178 "WINNT_x86_64-msvc-x64-asan",
180 if args.list_targets:
181 for target in valid_targets:
182 print(target)
183 for target in valid_aliases:
184 print("%s (alias)" % target)
185 return
186 if args.target is not None:
187 for target in args.target:
188 if target not in valid_targets and target not in valid_aliases:
189 parser.error("`%s` is invalid, see --list-targets" % target)
190 return
191 targets = args.target
192 else:
193 targets = valid_targets
195 if args.buildid is not None:
196 if not re.match(r"^\d{14}$", args.buildid):
197 parser.error("`%s` is invalid, build id must be 14 digits")
198 return
199 buildid = args.buildid
201 else:
202 buildid = datetime.today().strftime("%y%m%d%H%M%S")
204 url_base = "https://aus5.mozilla.org"
205 if args.staging:
206 url_base = "https://stage.balrog.nonprod.cloudops.mozgcp.net"
207 if args.url is not None:
208 url_base = args.url
209 if url_base[-1] == "/":
210 url_base = url_base[:-1]
211 url_base += "/update/3/GMP"
213 parsed_url = urlparse(url_base)
214 if parsed_url.scheme not in ("http", "https"):
215 parser.error("expected http(s) scheme, got `%s`" % parsed_url.scheme)
216 return
217 if parsed_url.path != "/update/3/GMP":
218 parser.error("expected url path of `/update/3/GMP`, got `%s`" % parsed_url.path)
219 return
221 if args.plugin == "openh264":
222 plugin = "gmp-gmpopenh264"
223 elif args.plugin == "widevine":
224 plugin = "gmp-widevinecdm"
225 elif args.plugin == "widevine_l1":
226 plugin = "gmp-widevinecdm-l1"
227 else:
228 parser.error("plugin not recognized")
229 return
231 if not re.match(r"^\d+\.\d+(\.\d+)?$", args.version):
232 parser.error("version must be of the form ###.###(.###)")
233 return
235 fetch_balrog_xml(
236 url_base, plugin, args.version, buildid, channels, targets, args.checkHash
240 main()