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/.
8 from datetime
import datetime
9 from urllib
.parse
import urlparse
10 from xml
.etree
import ElementTree
15 def check_hash(plugin
, url
, valid_urls
):
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"]:
27 "Given hash {} and calculated hash {} differ",
28 plugin
.attrib
["hashValue"],
31 if "size" in plugin
.attrib
:
32 size
= len(response
.content
)
33 if size
!= int(plugin
.attrib
["size"]):
35 "Given size {} and calculated size {} differ",
36 int(plugin
.attrib
["size"]),
42 url_base
: str, plugin_id
, version
: str, buildid
: str, channels
, targets
, checkHash
44 url
= "{url_base}/{version}/{buildid}/{target}/en-US/{channel}/default/default/default/update.xml"
47 for channel
in channels
:
49 for target
in targets
:
50 balrog_url
= url
.format_map(
60 response
= requests
.get(balrog_url
)
61 response
.raise_for_status()
64 tree
= ElementTree
.fromstring(response
.content
)
65 for plugin
in tree
.findall("./addons/addon"):
66 if not "id" in plugin
.attrib
:
68 if plugin
.attrib
["id"] != plugin_id
:
70 if "URL" in plugin
.attrib
:
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
:
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
:
87 channel
== other_channel
88 or channel
not in results
89 or other_channel
not in results
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
))
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",
114 formatter_class
=argparse
.RawDescriptionHelpFormatter
,
118 help="which plugin: openh264, widevine, widevine_l1",
120 parser
.add_argument("version", help="version of Firefox")
122 "--channel", action
="extend", nargs
="+", help="check specific channel(s)"
125 "--list-channels", action
="store_true", help="list the supported channels"
128 "--target", action
="extend", nargs
="+", help="check specific target(s)"
131 "--list-targets", action
="store_true", help="list the supported targets"
133 parser
.add_argument("--buildid", help="override generated build ID to be specific")
135 "--url", help="override base URL from which to fetch the balrog configuration"
140 help="using the balrog staging URL instead of production",
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
:
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
)
159 channels
= args
.channel
161 channels
= valid_channels
164 "Darwin_aarch64-gcc3",
165 "Darwin_x86_64-gcc3",
166 "Linux_aarch64-gcc3",
169 "WINNT_aarch64-msvc-aarch64",
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
:
183 for target
in valid_aliases
:
184 print("%s (alias)" % target
)
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
)
191 targets
= args
.target
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")
199 buildid
= args
.buildid
202 buildid
= datetime
.today().strftime("%y%m%d%H%M%S")
204 url_base
= "https://aus5.mozilla.org"
206 url_base
= "https://stage.balrog.nonprod.cloudops.mozgcp.net"
207 if args
.url
is not None:
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
)
217 if parsed_url
.path
!= "/update/3/GMP":
218 parser
.error("expected url path of `/update/3/GMP`, got `%s`" % parsed_url
.path
)
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"
228 parser
.error("plugin not recognized")
231 if not re
.match(r
"^\d+\.\d+(\.\d+)?$", args
.version
):
232 parser
.error("version must be of the form ###.###(.###)")
236 url_base
, plugin
, args
.version
, buildid
, channels
, targets
, args
.checkHash