Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 82f7fa7545 | |||
| b5e1296a7a | |||
| e80704c534 | |||
| c9c9e1171b |
67
main.js
67
main.js
@@ -6,6 +6,16 @@ const cheerio = require('cheerio');
|
||||
const { ElectronBlocker, adsAndTrackingLists } = require('@cliqz/adblocker-electron');
|
||||
const { autoUpdater } = require('electron-updater');
|
||||
|
||||
// Disable Trusted Types CSP enforcement engine-wide.
|
||||
// YouTube sends `Content-Security-Policy: require-trusted-types-for 'script'`,
|
||||
// which blocks the cliqz adblocker's scriptlet injection (it uses plain
|
||||
// `script.text = ...`) → 52+ console errors and broken anti-adblock neutralizers.
|
||||
// Stripping the CSP header via webRequest doesn't work — the adblocker's own
|
||||
// onHeadersReceived hook overwrites ours (Electron allows only one listener
|
||||
// per session). Disabling the Blink feature is the cleanest fix; safe in a
|
||||
// kiosk single-user context.
|
||||
app.commandLine.appendSwitch('disable-blink-features', 'TrustedDOMTypes');
|
||||
|
||||
const CONFIG_PATH = path.join(os.homedir(), '.ESH-Media.json');
|
||||
const BLOCKER_CACHE_PATH = path.join(os.homedir(), '.ESH-Media-adblock-v3.bin');
|
||||
const DEFAULT_TRUSTED_DOMAINS = [
|
||||
@@ -101,7 +111,27 @@ function getBlocker() {
|
||||
|
||||
function enableBlockingInSession(sess) {
|
||||
getBlocker()
|
||||
.then(b => { b.enableBlockingInSession(sess); console.log('[adblock] enabled for session'); })
|
||||
.then(b => {
|
||||
b.enableBlockingInSession(sess);
|
||||
// Remove the cliqz preload script that the blocker just registered on this
|
||||
// session. The preload injects inline <script> elements (via createTextNode +
|
||||
// appendChild) to neutralize anti-adblock scripts, but:
|
||||
// • Strict-CSP sites (kinogo via Cloudflare, etc.) reject inline scripts
|
||||
// without a matching nonce → "Refused to execute inline script".
|
||||
// • Trusted-Types sites (YouTube, Gmail) reject `script.appendChild(text)`
|
||||
// → "HTMLScriptElement was directly modified" (52 errors).
|
||||
// We keep the adblocker's network blocking and CSP filtering (via the still-
|
||||
// attached webRequest hooks), losing only the niche scriptlet/cosmetic-DOM
|
||||
// injection layer that breaks more sites than it helps.
|
||||
const before = sess.getPreloads();
|
||||
const after = before.filter(p => !/adblocker-electron-preload/i.test(p));
|
||||
if (after.length !== before.length) {
|
||||
sess.setPreloads(after);
|
||||
console.log('[adblock] enabled for session (preload script disabled)');
|
||||
} else {
|
||||
console.log('[adblock] enabled for session');
|
||||
}
|
||||
})
|
||||
.catch(e => console.warn('[adblock] failed to enable:', e.message));
|
||||
}
|
||||
|
||||
@@ -629,37 +659,30 @@ ipcMain.on('create-view', async (_event, name, url, imageUrl, _zoom, useProxy) =
|
||||
trackNavigation(newUrl);
|
||||
});
|
||||
view.webContents.on('will-redirect', (_e, u) => trackNavigation(u));
|
||||
view.webContents.setWindowOpenHandler(({ url: newUrl, frameName, features }) => {
|
||||
view.webContents.setWindowOpenHandler(({ url: newUrl }) => {
|
||||
let newHostname = '';
|
||||
try { newHostname = new URL(newUrl).hostname; } catch (_) {}
|
||||
|
||||
// Trusted domain → open as real popup BrowserWindow with same session.
|
||||
// This is what OAuth flows need: window.opener.postMessage() works,
|
||||
// popup can close itself when done, parent stays on the original page.
|
||||
// Trusted domain (Google, Yandex, etc.) → navigate IN-PLACE, no popup.
|
||||
// 1.0.1 tried opening a real popup BrowserWindow here for OAuth postMessage
|
||||
// flows — turns out Google specifically detects popup-style embedded
|
||||
// browsers and blocks OAuth ("Возможно, этот браузер небезопасны").
|
||||
// YouTube-style login uses standard redirect flow, so in-place navigation
|
||||
// works AND avoids the popup fingerprint. 1.0.0 behavior, restored.
|
||||
if (newHostname && isTrustedDomain(newHostname)) {
|
||||
return {
|
||||
action: 'allow',
|
||||
overrideBrowserWindowOptions: {
|
||||
width: 520, height: 640,
|
||||
parent: mainWindow,
|
||||
autoHideMenuBar: true,
|
||||
webPreferences: {
|
||||
session: view.webContents.session,
|
||||
contextIsolation: true,
|
||||
nodeIntegration: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
trackNavigation(newUrl);
|
||||
view.webContents.loadURL(newUrl);
|
||||
return { action: 'deny' };
|
||||
}
|
||||
|
||||
// Untrusted cross-domain → ask the user (original behavior).
|
||||
// Untrusted cross-domain → ask the user.
|
||||
if (origHostname && newHostname && newHostname !== origHostname) {
|
||||
pendingNavigate = { view, url: newUrl };
|
||||
setConfirm(`Перейти на "${newHostname}"?`, 'navigate-confirmed');
|
||||
return { action: 'deny' };
|
||||
}
|
||||
|
||||
// Same-origin popup → just navigate the current view.
|
||||
// Same-origin popup → navigate the current view.
|
||||
trackNavigation(newUrl);
|
||||
view.webContents.loadURL(newUrl);
|
||||
return { action: 'deny' };
|
||||
@@ -1228,6 +1251,10 @@ app.whenReady().then(async () => {
|
||||
}
|
||||
);
|
||||
|
||||
// (Trusted Types now handled engine-wide via --disable-blink-features
|
||||
// command-line switch at file top. webRequest.onHeadersReceived strip
|
||||
// was tried in 1.0.6 but the cliqz adblocker overwrites the listener.)
|
||||
|
||||
// Apply proxy from config before blocker tries to download filter lists
|
||||
loadTrustedDomainsFromDisk();
|
||||
try {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ESH-Media",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.9",
|
||||
"private": true,
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
|
||||
Reference in New Issue
Block a user