1.0.1 ("trusted-domains OAuth popups") changed setWindowOpenHandler to
return action:'allow' with overrideBrowserWindowOptions for trusted
domains (Google, Yandex, etc.), opening a real Electron BrowserWindow
as popup. The reasoning was that OAuth flows need window.opener +
postMessage. That's correct for some flows but wrong for YouTube-style
login, which uses straight redirect.
Worse: Google specifically detects popup-style embedded browsers
(Electron BrowserWindow has distinct fingerprint vs real Chrome popup)
and blocks them with "Возможно, этот браузер небезопасны". The user
reported this stopped working after 1.0.0 — that's why.
Restore the 1.0.0 behavior for trusted domains: deny the popup and call
view.webContents.loadURL(newUrl) in the same view. The OAuth flow now
happens as a normal in-place navigation: YouTube → accounts.google.com
→ (user logs in) → redirect back to YouTube. No popup, no fingerprint
mismatch. The only UX loss is the popup window aesthetic; behavior is
functionally identical and matches what worked in 1.0.0.
Untrusted cross-domain still asks for confirmation, same-origin popups
still navigate in-place — unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cliqz/adblocker-electron registers its preload at session level via
session.setPreloads([...preloads, PRELOAD_PATH]) inside
enableBlockingInSession. That preload injects inline <script> elements
via doc.createElement('script') + script.appendChild(textNode) +
parent.appendChild(script). On modern strict-CSP sites this breaks:
- Trusted Types (YouTube, Gmail): "An HTMLScriptElement was directly
modified and will not be executed" — 52+ console errors.
- Nonce-required CSP (kinogo via Cloudflare): "Refused to execute inline
script ... script-src 'nonce-...'" — competing with Cloudflare's
challenge JS, likely the proximate cause of the 403 we see on kinogo
(CF treats the broken page as bot).
Remove the cliqz preload from each session immediately after
enableBlockingInSession. The network/CSP/blockers attached via
webRequest hooks remain active — only the script-injection layer for
anti-anti-adblock scriptlets is lost, which is a niche feature that
breaks more sites than it fixes.
The 1.0.7 Blink TrustedDOMTypes disable stays (defense in depth, no
cost). The 1.0.6 CSP-header strip stays removed (adblocker overwrites
the webRequest listener anyway).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The 1.0.6 fix (strip require-trusted-types-for from CSP via
onHeadersReceived) didn't take effect: cliqz/adblocker calls
session.webRequest.onHeadersReceived during enableBlockingInSession,
overwriting our hook (Electron permits only one listener per session).
Replace with engine-level kill switch:
app.commandLine.appendSwitch('disable-blink-features', 'TrustedDOMTypes')
Makes the entire Trusted Types runtime feature inert, so
require-trusted-types-for CSP becomes a no-op site-wide. Safe in this
kiosk/single-user context; only relaxes one security boundary that
sites use to harden against XSS via adblocker-style script injection —
which is exactly what we need to neutralize for cliqz's anti-anti-adblock
scriptlets on YouTube.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
YouTube response sends Content-Security-Policy: require-trusted-types-for
'script' which blocks the cliqz adblocker's inline-script injection used
to neutralize YT's anti-adblock detection (52 "HTMLScriptElement was
directly modified and will not be executed" console errors).
Strip require-trusted-types-for and trusted-types directives from CSP
and CSP-Report-Only headers for youtube.com / youtu.be / google.com /
gmail.com (and subdomains) via onHeadersReceived on all 3 sessions.
Other CSP directives stay intact so site-level security boundaries hold.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Sec-CH-UA / Sec-CH-UA-Mobile / Sec-CH-UA-Platform header overrides on
every request in 1.0.4 broke page rendering (all views white). Reverted
to image-Referer-only behavior from 1.0.3. The Google "embedded browser"
fix in 1.0.4 came primarily from the adblock whitelist (which IS kept)
— Sec-CH-UA spoofing was the suspect for the regression.
- Ctrl+Shift+I and F12 now open DevTools on the main shell and on every
in-app browser view. Always-on so kiosk machines can be debugged
without leaving kiosk mode.
- Restore session sequenced (await 150ms between tabs) to avoid concurrent
create-view races where multiple setLoader/addChild interleaved.
- Update banner now shows error state with a "Повторить" button instead
of hiding it, so install-update failures are visible to the user.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two-part fix for Google login "Возможно, этот браузер небезопасны" error:
1. The adblocker was eating Google integrity-check resources (gstatic,
google-analytics, googletagmanager — flagged by EasyPrivacy). Add @@
whitelist filters for Google, Yandex, Microsoft, Apple, Facebook,
GitHub, VK, Mail.ru ecosystems. Also switch from non-existent
addFilters() to updateFromDiff({added}) — previous TMDB whitelist was
silently failing in a then().catch() and never applied. Adblock cache
bumped to v3 so the new filters take effect.
2. Sec-CH-UA client-hints branding was leaking Electron app name as the
browser brand. Override sec-ch-ua, sec-ch-ua-mobile, sec-ch-ua-platform
headers via webRequest.onBeforeSendHeaders on all 3 sessions so
embedded-browser detectors see real-Chrome brand list.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- electron-updater wired with Gitea API discovery: setFeedURL dynamically
per release (Gitea 1.24.7 lacks /releases/latest/download/ shortcut).
Differential download via .blockmap saves ~70 MB per patch. Renderer
banner shows states: available → downloading X% → ready. User clicks
"Установить и перезапустить" → quitAndInstall replaces files + relaunches.
- Multi-select filters per user spec: genres AND (TMDB with_genres comma-
joined), countries OR (pipe-joined into with_origin_country /
with_original_language), years OR (fan-out one request per year, merge
by id since TMDB has no discrete-year OR). Rating stays single threshold.
- Session persistence: openedSession {tabs, activeName} saved to config
on tab create/show/hide/remove/in-app navigation, plus before-quit.
Restored after did-finish-load via ipcMain.emit('create-view',...) per
tab. Survives auto-update relaunch — bring user back to the same page.
- electron-builder publish config (generic provider) so latest.yml is
generated during build.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- main.js: app.userAgentFallback cleaned of Electron/X.X and ESH-Media/X.X
tokens at startup; applied to default/proxy/direct sessions. Google's
accounts page blocked Electron UA with "Поддержка JavaScript отключена".
- Header.tsx: subscribe currentUrl to updateWebButtons (already fired on
each in-app navigation). Bookmark star now updates as user clicks
between movies inside the same opened site, not only on app switch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- main.js: trusted-domains list with default Google/Yandex/GitHub/etc.;
cross-domain confirmation skipped for trusted; setWindowOpenHandler
returns action:'allow' for trusted so OAuth popups work (postMessage
back to opener, popup self-closes). Fixes YouTube/Google login reset.
- main.js: get-page-meta IPC extracts og:image / twitter:image / JSON-LD
image from current view; HDRezka also tries .b-sidecover img for hi-res.
- Header: bookmark button pulls og:image as poster and the page's title;
duplicate detection switched from hostname to full URL so multiple
movies from same site can coexist.
- BookmarksBar: site icon rendered next to source domain when distinct
from poster; img onerror falls back to placeholder.
- Settings: trusted domains chip list with add/remove/reset.
- Updater: proper semver compare (only show if latest > current),
direct installer URL detection per platform, hourly re-check.
Bookmark schema gains optional siteIcon; existing bookmarks remain valid.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>