diff --git a/main.js b/main.js index aa73190..f2af83d 100644 --- a/main.js +++ b/main.js @@ -40,6 +40,61 @@ const DEFAULT_CONFIG = { apps: [], proxy: { host: '127.0.0.1', port: '7890' }, t let blockerPromise = null; let cachedTrustedDomains = DEFAULT_TRUSTED_DOMAINS; +// chrome.* spoof: injected via executeJavaScript on every page's dom-ready. +// Goal is to look like real Chrome to JS-based "embedded browser" detectors +// (Google login, etc.). Cannot fix TLS-fingerprint detection — that's server-side. +const CHROME_SPOOF_JS = `(function(){ + try { + if (!window.chrome) window.chrome = {}; + var c = window.chrome; + if (!c.app) c.app = { + isInstalled: false, + InstallState: { DISABLED: 'disabled', INSTALLED: 'installed', NOT_INSTALLED: 'not_installed' }, + RunningState: { CANNOT_RUN: 'cannot_run', READY_TO_RUN: 'ready_to_run', RUNNING: 'running' }, + getDetails: function(){ return null; }, + getIsInstalled: function(){ return false; }, + runningState: function(){ return 'cannot_run'; } + }; + if (!c.runtime) c.runtime = { + PlatformOs: { MAC:'mac', WIN:'win', ANDROID:'android', CROS:'cros', LINUX:'linux', OPENBSD:'openbsd' }, + PlatformArch: { ARM:'arm', X86_32:'x86-32', X86_64:'x86-64' }, + PlatformNaclArch: { ARM:'arm', X86_32:'x86-32', X86_64:'x86-64' }, + RequestUpdateCheckStatus: { NO_UPDATE:'no_update', THROTTLED:'throttled', UPDATE_AVAILABLE:'update_available' }, + OnInstalledReason: { CHROME_UPDATE:'chrome_update', INSTALL:'install', SHARED_MODULE_UPDATE:'shared_module_update', UPDATE:'update' }, + OnRestartRequiredReason: { APP_UPDATE:'app_update', OS_UPDATE:'os_update', PERIODIC:'periodic' }, + sendMessage: function(){}, + connect: function(){ + return { + postMessage: function(){}, disconnect: function(){}, + onDisconnect: { addListener: function(){}, removeListener: function(){} }, + onMessage: { addListener: function(){}, removeListener: function(){} } + }; + } + }; + if (!c.csi) c.csi = function(){ return { startE: Date.now()-1000, onloadT: Date.now()-500, pageT: 1000, tran: 15 }; }; + if (!c.loadTimes) c.loadTimes = function(){ + var t = performance.timing; + return { + commitLoadTime: t.responseStart/1000, connectionInfo: 'http/1.1', + finishDocumentLoadTime: t.domContentLoadedEventEnd/1000, + finishLoadTime: (t.loadEventEnd/1000) || 0, + firstPaintAfterLoadTime: 0, firstPaintTime: t.responseEnd/1000, + navigationType: 'Other', npnNegotiatedProtocol: 'h2', + requestTime: t.requestStart/1000, startLoadTime: t.fetchStart/1000, + wasAlternateProtocolAvailable: false, wasFetchedViaSpdy: true, wasNpnNegotiated: true + }; + }; + // navigator.permissions.query: Notification permission must agree with Notification.permission + if (navigator.permissions && navigator.permissions.query) { + var origQuery = navigator.permissions.query.bind(navigator.permissions); + navigator.permissions.query = function(p){ + if (p && p.name === 'notifications') return Promise.resolve({ state: Notification.permission, onchange: null }); + return origQuery(p); + }; + } + } catch (_) {} +})();`; + function loadTrustedDomainsFromDisk() { try { if (fs.existsSync(CONFIG_PATH)) { @@ -608,6 +663,17 @@ ipcMain.on('create-view', async (_event, name, url, imageUrl, _zoom, useProxy) = view.setBounds(getViewBounds()); attachDevToolsShortcut(view.webContents); + // Experimental: spoof chrome.* JS objects on every page so Google's + // "embedded browser" detector sees a real-Chrome-shaped global. Runs on + // dom-ready which is AFTER scripts, so detection scripts that ran + // there have already seen the un-spoofed environment — this fix only + // helps if Google's gate is re-checked on form submit / later events. + // TLS fingerprint (JA3) is server-side and unaffected; if Google flags us + // there, no client-side spoof helps. Best-effort attempt only. + view.webContents.on('dom-ready', () => { + view.webContents.executeJavaScript(CHROME_SPOOF_JS).catch(() => {}); + }); + view.webContents.on('did-finish-load', () => { removeLoader(); addChild(view); diff --git a/package.json b/package.json index dd24b07..9502ef6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ESH-Media", - "version": "1.0.9", + "version": "1.0.10", "private": true, "main": "main.js", "scripts": {