"""Probes Firefox's web-platform support by loading a page that reports back. Usage: python3 tools/probe_firefox.py Launches headless Firefox against a local page whose script POSTs its feature detection results back to this server, then prints them. """ import http.server import json import os import shutil import subprocess import threading PORT = 8766 # Snap-confined Firefox cannot see /tmp, so the profile lives next to the repo. ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) PROFILE = os.path.join(ROOT, 'tmp-ffprof-probe') USER_JS = ''' user_pref("browser.shell.checkDefaultBrowser", false); user_pref("browser.startup.homepage_override.mstone", "ignore"); user_pref("datareporting.policy.dataSubmissionEnabled", false); user_pref("toolkit.telemetry.enabled", false); user_pref("app.update.auto", false); ''' PAGE = """
""" report = {} done = threading.Event() class Handler(http.server.BaseHTTPRequestHandler): def do_GET(self): if self.path == '/manifest.webmanifest': body = json.dumps({ "name": "Probe", "short_name": "Probe", "start_url": "./", "display": "standalone", "icons": [{"src": "/icon.png", "sizes": "192x192", "type": "image/png"}], }).encode() self.send_response(200) self.send_header('Content-Type', 'application/manifest+json') self.send_header('Content-Length', str(len(body))) self.end_headers() self.wfile.write(body) return body = PAGE.encode() self.send_response(200) self.send_header('Content-Type', 'text/html') self.send_header('Content-Length', str(len(body))) self.end_headers() self.wfile.write(body) def do_POST(self): length = int(self.headers.get('Content-Length', 0)) report.update(json.loads(self.rfile.read(length) or b'{}')) self.send_response(204) self.end_headers() done.set() def log_message(self, *args): pass def main(): server = http.server.ThreadingHTTPServer(('127.0.0.1', PORT), Handler) threading.Thread(target=server.serve_forever, daemon=True).start() shutil.rmtree(PROFILE, ignore_errors=True) os.makedirs(PROFILE, exist_ok=True) with open(os.path.join(PROFILE, 'user.js'), 'w') as fh: fh.write(USER_JS) proc = subprocess.Popen( ['firefox', '--headless', '--no-remote', '--new-instance', '--profile', PROFILE, f'http://127.0.0.1:{PORT}/'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, ) ok = done.wait(timeout=30) proc.terminate() try: proc.wait(timeout=10) except subprocess.TimeoutExpired: proc.kill() server.shutdown() shutil.rmtree(PROFILE, ignore_errors=True) if not ok: print('probe: no report received (Firefox did not run the page)') return print(json.dumps(report, indent=2, sort_keys=True)) if __name__ == '__main__': main()