mirror of
https://github.com/steveseguin/caption-local.git
synced 2026-10-10 10:09:31 +00:00
75 lines
4.3 KiB
Python
75 lines
4.3 KiB
Python
"""Controlled HTTPS-origin preview; assets intercepted locally, no public publishing."""
|
|
import json
|
|
from pathlib import Path
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
import urllib.request
|
|
from urllib.parse import urlsplit
|
|
from playwright.sync_api import sync_playwright
|
|
from browser_support import browser_options
|
|
from browser_capture_connection import TOKEN, ROOT
|
|
from service_test_support import require_free_port
|
|
|
|
require_free_port(8778)
|
|
child=subprocess.Popen([sys.executable,'scripts/browser_capture_connection.py','--serve-https'],
|
|
creationflags=getattr(subprocess,'CREATE_NO_WINDOW',0))
|
|
report={'scope':'Intercepted HTTPS-origin page assets with real loopback HTTP requests and fake inference; not a deployed HTTPS site', 'scenarios':[]}
|
|
try:
|
|
for _ in range(100):
|
|
try:
|
|
urllib.request.urlopen('http://127.0.0.1:8778/capture-local.html',timeout=1).close(); break
|
|
except OSError: time.sleep(.1)
|
|
with sync_playwright() as p:
|
|
browser=p.chromium.launch(**browser_options(),headless=True,args=[
|
|
'--use-fake-device-for-media-stream',f'--use-file-for-fake-audio-capture={ROOT/"samples/jfk.wav"}'])
|
|
report['browser_version']=browser.version
|
|
for permission in ('denied','granted'):
|
|
context=browser.new_context(permissions=['microphone'])
|
|
page=context.new_page(); cdp=context.new_cdp_session(page)
|
|
context_id=cdp.send('Target.getTargetInfo')['targetInfo']['browserContextId']
|
|
cdp.send('Browser.setPermission',{'permission':{'name':'loopback-network'},
|
|
'setting':permission,'origin':'https://caption.ninja','browserContextId':context_id})
|
|
failures=[]
|
|
console=[]
|
|
page.on('console',lambda message: console.append(message.text) if message.type=='error' else None)
|
|
page.on('requestfailed',lambda request: failures.append({'url':request.url,'error':request.failure}))
|
|
def route(request):
|
|
url=request.request.url
|
|
if url.startswith('http://127.0.0.1:8778/'):
|
|
request.continue_(); return
|
|
if url.startswith('https://caption.ninja/'):
|
|
relative=urlsplit(url).path.lstrip('/')
|
|
source=(ROOT/'samples/captionninja'/relative).resolve()
|
|
base=(ROOT/'samples/captionninja').resolve()
|
|
if source.is_relative_to(base) and source.is_file():
|
|
request.fulfill(path=str(source),content_type='text/html' if source.suffix=='.html' else 'application/javascript'); return
|
|
request.abort()
|
|
context.route('**/*',route)
|
|
context.route_web_socket('**/*',lambda socket:socket.close())
|
|
page.goto('https://caption.ninja/capture-local.html')
|
|
page.fill('#endpoint','http://127.0.0.1:8778');page.fill('#connectionToken',TOKEN);page.click('#connect')
|
|
page.wait_for_function('() => !connection.checking')
|
|
ready=not page.locator('#start').is_disabled()
|
|
scenario={'permission':permission,'ready':ready,'request_failures':failures,'console':console}
|
|
report['scenarios'].append(scenario)
|
|
if ready:
|
|
page.click('#start')
|
|
try:
|
|
page.wait_for_function('() => transcript.length > 0',timeout=30000)
|
|
except Exception:
|
|
scenario['capture_state']=page.evaluate('({running,starting,failed,error:$("error").textContent})')
|
|
raise
|
|
page.click('#stop');page.wait_for_function('() => !processing && !running && !stopping && !pending',timeout=20000)
|
|
scenario['capture_drained']=page.evaluate('!failed && buffer.length <= 8000')
|
|
context.close()
|
|
browser.close()
|
|
report['passed']=not report['scenarios'][0]['ready'] and report['scenarios'][1].get('capture_drained',False)
|
|
except Exception as exc:
|
|
report['error']=repr(exc);report['passed']=False
|
|
finally:
|
|
child.terminate();child.wait(timeout=15)
|
|
output=ROOT/'evidence/gpu-validation/https-preview.json';output.parent.mkdir(parents=True,exist_ok=True)
|
|
output.write_text(json.dumps(report,indent=2)+'\n',encoding='utf-8');print(json.dumps(report,indent=2))
|
|
if not report['passed']: raise SystemExit('HTTPS preview validation incomplete; evidence retained')
|