|
| 1 | +/** |
| 2 | + * The user agent the browser resource presents to sites. |
| 3 | + * |
| 4 | + * Electron's default string carries two tokens no browser sends — |
| 5 | + * `Sim/<version>` and `Electron/<version>`. Chromium's own token sits right |
| 6 | + * beside them, but that does not save it: the detection libraries sites gate on |
| 7 | + * test for Electron BEFORE Chrome (bowser matches `/electron/i` several |
| 8 | + * descriptors ahead of its Chrome one, ua-parser-js reports `Electron` as the |
| 9 | + * browser name), so the browser reads as "Electron", which is on nobody's |
| 10 | + * supported list. Ashby warns "Ashby does not support this browser"; stricter |
| 11 | + * sites refuse to render at all. |
| 12 | + * |
| 13 | + * Reporting stock Chrome is accurate rather than a disguise — the engine is the |
| 14 | + * Chromium build the token already names, and Electron's user-agent client |
| 15 | + * hints (`Sec-CH-UA`, `navigator.userAgentData`) only ever carried a Chromium |
| 16 | + * brand, so dropping the token makes the header and the hints agree instead of |
| 17 | + * contradicting each other. |
| 18 | + */ |
| 19 | +import { app } from 'electron' |
| 20 | + |
| 21 | +/** Platform token, then the Chromium major version, in the order a Chromium user agent lists them. */ |
| 22 | +const CHROMIUM_USER_AGENT = /^Mozilla\/5\.0 \(([^)]*)\).* Chrome\/(\d+)\./ |
| 23 | + |
| 24 | +/** |
| 25 | + * Rebuilds the default user agent as the string Chrome itself sends. Chrome's |
| 26 | + * user-agent reduction fixes the desktop form at |
| 27 | + * `Mozilla/5.0 (<platform>) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/<major>.0.0.0 Safari/537.36`, |
| 28 | + * so keeping the platform token and the Chromium major version — and zeroing |
| 29 | + * the rest — reproduces it exactly, with no room left for an application or |
| 30 | + * Electron token. A string that is not a Chromium user agent is returned |
| 31 | + * unchanged rather than replaced with a guess. |
| 32 | + */ |
| 33 | +export function stockChromeUserAgent(defaultUserAgent: string): string { |
| 34 | + const match = defaultUserAgent.match(CHROMIUM_USER_AGENT) |
| 35 | + if (!match) return defaultUserAgent |
| 36 | + const [, platform, chromeMajor] = match |
| 37 | + return `Mozilla/5.0 (${platform}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${chromeMajor}.0.0.0 Safari/537.36` |
| 38 | +} |
| 39 | + |
| 40 | +/** |
| 41 | + * Derived from the string Electron would otherwise have sent, so the reported |
| 42 | + * Chromium version tracks whatever Chromium the app actually ships. |
| 43 | + */ |
| 44 | +export function browserUserAgent(): string { |
| 45 | + return stockChromeUserAgent(app.userAgentFallback) |
| 46 | +} |
0 commit comments