mirror of
https://forge.fsky.io/oneflux/omegafox.git
synced 2026-02-10 06:22:03 -08:00
- `camoufox test` will no longer highlight the cursor by default - Fixed launch_options blocking async - WebGL database cleanup & added ability to query all possible vendor/renderer pairs
108 lines
3.6 KiB
Python
108 lines
3.6 KiB
Python
import sqlite3
|
|
from pathlib import Path
|
|
from typing import Dict, List, Optional, Tuple
|
|
|
|
import numpy as np
|
|
import orjson
|
|
|
|
from camoufox.pkgman import OS_ARCH_MATRIX
|
|
|
|
# Get database path relative to this file
|
|
DB_PATH = Path(__file__).parent / 'webgl_data.db'
|
|
|
|
|
|
def sample_webgl(
|
|
os: str, vendor: Optional[str] = None, renderer: Optional[str] = None
|
|
) -> Dict[str, str]:
|
|
"""
|
|
Sample a random WebGL vendor/renderer combination and its data based on OS probabilities.
|
|
Optionally use a specific vendor/renderer pair.
|
|
|
|
Args:
|
|
os: Operating system ('win', 'mac', or 'lin')
|
|
vendor: Optional specific vendor to use
|
|
renderer: Optional specific renderer to use (requires vendor to be set)
|
|
|
|
Returns:
|
|
Dict containing WebGL data including vendor, renderer and additional parameters
|
|
|
|
Raises:
|
|
ValueError: If invalid OS provided or no data found for OS/vendor/renderer
|
|
"""
|
|
# Check that the OS is valid (avoid SQL injection)
|
|
if os not in OS_ARCH_MATRIX:
|
|
raise ValueError(f'Invalid OS: {os}. Must be one of: win, mac, lin')
|
|
|
|
# Connect to database
|
|
conn = sqlite3.connect(DB_PATH)
|
|
cursor = conn.cursor()
|
|
|
|
if vendor and renderer:
|
|
# Get specific vendor/renderer pair and verify it exists for this OS
|
|
cursor.execute(
|
|
f'SELECT vendor, renderer, data, {os} FROM webgl_fingerprints ' # nosec
|
|
'WHERE vendor = ? AND renderer = ?',
|
|
(vendor, renderer),
|
|
)
|
|
result = cursor.fetchone()
|
|
|
|
if not result:
|
|
raise ValueError(f'No WebGL data found for vendor "{vendor}" and renderer "{renderer}"')
|
|
|
|
if result[3] <= 0: # Check OS-specific probability
|
|
# Get a list of possible (vendor, renderer) pairs for this OS
|
|
cursor.execute(
|
|
f'SELECT DISTINCT vendor, renderer FROM webgl_fingerprints WHERE {os} > 0' # nosec
|
|
)
|
|
possible_pairs = cursor.fetchall()
|
|
raise ValueError(
|
|
f'Vendor "{vendor}" and renderer "{renderer}" combination not valid for {os.title()}.\n'
|
|
f'Possible pairs: {", ".join(str(pair) for pair in possible_pairs)}'
|
|
)
|
|
|
|
conn.close()
|
|
return orjson.loads(result[2])
|
|
|
|
# Get all vendor/renderer pairs and their probabilities for this OS
|
|
cursor.execute(
|
|
f'SELECT vendor, renderer, data, {os} FROM webgl_fingerprints WHERE {os} > 0' # nosec
|
|
)
|
|
results = cursor.fetchall()
|
|
conn.close()
|
|
|
|
if not results:
|
|
raise ValueError(f'No WebGL data found for OS: {os}')
|
|
|
|
# Split into separate arrays
|
|
_, _, data_strs, probs = map(list, zip(*results))
|
|
|
|
# Convert probabilities to numpy array and normalize
|
|
probs_array = np.array(probs, dtype=np.float64)
|
|
probs_array = probs_array / probs_array.sum()
|
|
|
|
# Sample based on probabilities
|
|
idx = np.random.choice(len(probs_array), p=probs_array)
|
|
|
|
# Parse the JSON data string
|
|
return orjson.loads(data_strs[idx])
|
|
|
|
|
|
def get_possible_pairs() -> Dict[str, List[Tuple[str, str]]]:
|
|
"""
|
|
Get all possible (vendor, renderer) pairs for all OS, where the probability is greater than 0.
|
|
"""
|
|
# Connect to database
|
|
conn = sqlite3.connect(DB_PATH)
|
|
cursor = conn.cursor()
|
|
|
|
# Get all vendor/renderer pairs for each OS where probability > 0
|
|
result: Dict[str, List[Tuple[str, str]]] = {}
|
|
for os_type in OS_ARCH_MATRIX:
|
|
cursor.execute(
|
|
'SELECT DISTINCT vendor, renderer FROM webgl_fingerprints '
|
|
f'WHERE {os_type} > 0 ORDER BY {os_type} DESC', # nosec
|
|
)
|
|
result[os_type] = cursor.fetchall()
|
|
|
|
conn.close()
|
|
return result
|