Files
onefinity-firmware/scripts/deploy/patch_font_mime.py
muehe 50839718e2 kiosk: chromium 72 mime + flex-gap fixes
Pi's onboard chromium is 72 (Jan 2019). Two issues:

1. Python 3.5's mimetypes doesn't know woff/woff2/ttf, so Tornado
   serves them as application/octet-stream which chromium 72 refuses
   to use as web fonts -> all FA6 icons render as empty boxes. Add
   scripts/deploy/patch_font_mime.py that monkey-patches bbctrl
   Web.py's StaticFileHandler with correct content types. Run
   automatically by deploy-hardware.sh (idempotent).

2. flex-gap landed in chromium 84. Add '> * + *' margin fallbacks
   for the flex containers that show up on Program tab (action-bar,
   action-btn, file-bar, file-btn) and tighten the kiosk-mode
   settings rail so all 14 items fit in 768px height.
2026-05-01 11:16:28 +02:00

103 lines
3.5 KiB
Python

#!/usr/bin/env python3
"""
Patch bbctrl Web.py so font files get the correct MIME type.
Background
----------
The Onefinity controller (Pi 3B running Raspbian stretch) ships Python
3.5, whose ``mimetypes`` module does not recognize ``.woff``, ``.woff2``
or ``.ttf``. Tornado's ``StaticFileHandler`` therefore falls back to
``application/octet-stream`` for those, and Chromium 72 (the Pi's
onboard kiosk browser) refuses to use such payloads as web fonts. The
result is that every FontAwesome icon renders as an empty box on the
kiosk display.
This patch monkey-patches ``StaticFileHandler.get_content_type`` to
emit the right MIME types. It is idempotent: running it twice is a
no-op. Run with ``sudo`` so it can rewrite the egg's Web.py.
Used by:
scripts/deploy/hardware.sh
"""
from __future__ import print_function
import os
import sys
def find_web_py():
"""Return the absolute path to the bbctrl Web.py shipped in the egg."""
base = "/usr/local/lib"
for entry in os.listdir(base):
if not entry.startswith("python"):
continue
candidate_dir = os.path.join(base, entry, "dist-packages")
if not os.path.isdir(candidate_dir):
continue
for sub in os.listdir(candidate_dir):
if sub.startswith("bbctrl-") and sub.endswith(".egg"):
p = os.path.join(candidate_dir, sub, "bbctrl", "Web.py")
if os.path.isfile(p):
return p
return None
OLD_BLOCK = (
"class StaticFileHandler(tornado.web.StaticFileHandler):\n"
" def set_extra_headers(self, path):\n"
" self.set_header('Cache-Control',\n"
" 'no-store, no-cache, must-revalidate, max-age=0')"
)
NEW_BLOCK = (
"class StaticFileHandler(tornado.web.StaticFileHandler):\n"
" # FONT_MIME_FIX: Python 3.5's mimetypes module does not know\n"
" # woff/woff2/ttf, so Tornado serves them as application/octet-\n"
" # stream which Chromium 72 (the Pi's onboard kiosk browser)\n"
" # refuses to use as web fonts. Set explicit types so the FA6\n"
" # icon set actually renders on the kiosk display.\n"
" def get_content_type(self):\n"
" path = self.absolute_path or ''\n"
" if path.endswith('.woff2'): return 'font/woff2'\n"
" if path.endswith('.woff'): return 'font/woff'\n"
" if path.endswith('.ttf'): return 'font/ttf'\n"
" if path.endswith('.otf'): return 'font/otf'\n"
" if path.endswith('.eot'): return 'application/vnd.ms-fontobject'\n"
" return super().get_content_type()\n"
"\n"
" def set_extra_headers(self, path):\n"
" self.set_header('Cache-Control',\n"
" 'no-store, no-cache, must-revalidate, max-age=0')"
)
def main():
target = find_web_py()
if target is None:
print("ERROR: could not locate bbctrl Web.py under /usr/local/lib",
file=sys.stderr)
return 1
with open(target) as f:
src = f.read()
if "FONT_MIME_FIX" in src:
print("font mime: already patched ({})".format(target))
return 0
if OLD_BLOCK not in src:
print("font mime: expected block not found in {} -- skipping".format(target),
file=sys.stderr)
# Don't fail the deploy; just log and continue.
return 0
new_src = src.replace(OLD_BLOCK, NEW_BLOCK, 1)
with open(target, "w") as f:
f.write(new_src)
print("font mime: patched {}".format(target))
return 0
if __name__ == "__main__":
sys.exit(main())