@@ -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 )
0 commit comments