Skip to content

Commit 920ae61

Browse files
committed
Download and install OpenH264 GMP plugin when installing Firefox
This patch adds a step to download the public OpenH264 GMP plugin from the Cisco CDN during Firefox installation . The correct version is parsed from openh264.json, which is downloaded for the corresponding revision from the Firefox github. The plugin is extracted into the correct folder structure "gmp-gmpopenh264/{version}" inside "browsers/{channel}". In Firefox.setup_kwargs, the presence of this folder is detected and used to set the environment variable MOZ_GMP_PATH down the line. This makes OpenH264 available to WebRTC tests, allowing those reliant on H264 to pass.
1 parent 6066618 commit 920ae61

File tree

2 files changed

+92
-1
lines changed

2 files changed

+92
-1
lines changed

tools/wpt/browser.py

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,16 @@ class Firefox(Browser):
452452
"nightly": "Firefox Nightly.app"
453453
}
454454

455+
openh264_platform = {
456+
("linux", "x86_64"): "Linux_x86_64-gcc3",
457+
("linux", "x86"): "Linux_x86-gcc3",
458+
("linux", "aarch64"): "Linux_aarch64-gcc3",
459+
("win", "AMD64"): "WINNT_x86_64-msvc",
460+
("win", "x86"): "WINNT_x86-msvc",
461+
("macos", "x86_64"): "Darwin_x86_64-gcc3",
462+
("macos", "arm64"): "Darwin_aarch64-gcc3",
463+
}
464+
455465
def platform_string_geckodriver(self):
456466
if self.platform is None:
457467
raise ValueError("Unable to construct a valid Geckodriver package name for current platform")
@@ -529,7 +539,74 @@ def install(self, dest=None, channel="nightly"):
529539
raise
530540

531541
os.remove(installer_path)
532-
return self.find_binary_path(dest)
542+
binary = self.find_binary_path(dest)
543+
self.install_openh264(binary_dir=dest, binary=binary, channel=channel)
544+
return binary
545+
546+
def install_openh264(self, binary_dir, binary, channel="nightly"):
547+
import hashlib
548+
import io
549+
550+
platform_key = self.openh264_platform.get((self.platform, uname.machine))
551+
if platform_key is None:
552+
self.logger.warning("OpenH264: unsupported platform %s %s, skipping" % (self.platform, uname.machine))
553+
return None
554+
555+
prefs = FirefoxPrefs(self.logger)
556+
version, channel_, rev = prefs.get_version_and_channel(binary) if binary else (None, channel, None)
557+
ref = prefs.get_git_ref(version, channel_ if channel is None else channel, rev)
558+
559+
self.logger.info("Downloading openh264.json from git ref %s" % ref)
560+
try:
561+
openh264_json = json.loads(
562+
get_file_github("mozilla-firefox/firefox", ref, "toolkit/content/gmp-sources/openh264.json"))
563+
except Exception as e:
564+
self.logger.warning("Failed to download openh264.json: %s" % e)
565+
return None
566+
567+
version = openh264_json["vendors"]["gmp-gmpopenh264"]["version"]
568+
if version is None:
569+
self.logger.warning("OpenH264: no entry for version in openh264.json")
570+
return None
571+
572+
openh264_dir = os.path.join(binary_dir, "gmp-gmpopenh264", version)
573+
if os.path.isdir(openh264_dir):
574+
self.logger.info("Using cached OpenH264 plugin from %s" % openh264_dir)
575+
return openh264_dir
576+
577+
platforms = openh264_json["vendors"]["gmp-gmpopenh264"]["platforms"]
578+
platform_data = platforms.get(platform_key)
579+
if platform_data is None:
580+
self.logger.warning("OpenH264: no entry for platform %s in openh264.json" % platform_key)
581+
return None
582+
if "alias" in platform_data:
583+
platform_data = platforms.get(platform_data["alias"])
584+
if platform_data is None:
585+
self.logger.warning("OpenH264: alias target missing in openh264.json")
586+
return None
587+
588+
file_url = platform_data["fileUrl"]
589+
expected_hash = platform_data["hashValue"]
590+
hash_function = openh264_json.get("hashFunction", "sha512")
591+
592+
self.logger.info("Downloading OpenH264 plugin from %s" % file_url)
593+
try:
594+
resp = get(file_url)
595+
except Exception as e:
596+
self.logger.warning("Failed to download OpenH264 plugin: %s" % e)
597+
return None
598+
599+
data = resp.content
600+
actual_hash = getattr(hashlib, hash_function)(data).hexdigest()
601+
if actual_hash != expected_hash:
602+
self.logger.warning(
603+
"OpenH264 hash mismatch: expected %s, got %s" % (expected_hash, actual_hash))
604+
return None
605+
606+
os.makedirs(openh264_dir, exist_ok=True)
607+
unzip(io.BytesIO(data), dest=openh264_dir)
608+
self.logger.info("OpenH264 plugin installed to %s" % openh264_dir)
609+
return openh264_dir
533610

534611
def install_prefs(self, binary, dest=None, channel=None):
535612
return FirefoxPrefs(self.logger).install_prefs(binary, dest, channel)

tools/wpt/run.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,20 @@ def setup_kwargs(self, kwargs):
335335
# Allow WebRTC tests to call getUserMedia.
336336
kwargs["extra_prefs"].append("media.navigator.streams.fake=true")
337337

338+
if kwargs.get("gmp_path") is None and kwargs["browser_channel"] is not None:
339+
openh264_dir = os.path.join(
340+
self.browser._get_browser_binary_dir(self.venv.path, kwargs["browser_channel"]),
341+
"gmp-gmpopenh264")
342+
if os.path.isdir(openh264_dir):
343+
dirs = os.listdir(openh264_dir)
344+
openh264_dir = os.path.join(openh264_dir, dirs[0]) if dirs else None
345+
if len(dirs) > 1:
346+
logger.warning("More than one version of OpenH264 found. Using %s" % dirs[0])
347+
if os.path.isdir(openh264_dir):
348+
logger.info("Using OpenH264 plugin in %s" % openh264_dir)
349+
kwargs["gmp_path"] = openh264_dir
350+
else:
351+
logger.warning("OpenH264 is not installed. Some tests may fail.")
338352

339353
class FirefoxAndroid(BrowserSetup):
340354
name = "firefox_android"

0 commit comments

Comments
 (0)