The request pipeline
Qt WebEngine lets an application inspect every network request before Chromium sends it. JBrowser uses two
QWebEngineUrlRequestInterceptors, both in services/privacy.py, and both
delegate their decisions to PrivacyService:
page request
│
▼
ProfileInterceptor (one per space) rewrite(): developer host → redirect
│ tracking parameters → redirect to the clean URL
│ http → https (HTTPS-first) → redirect
│ otherwise: add DNT: 1 and Sec-GPC: 1 headers
▼
PageInterceptor (one per card) should_block(): block, and count it on the card
│ (a WebSocket request is noted for the memory saver)
▼
Chromium's network service
Qt calls the profile interceptor first, then the page's own. Both run on the UI thread for every request, so they
must be fast and must never raise: each wraps its work in try/except and logs failures.
rewrite(): redirects#
In order, the first rule that applies wins:
- Developer hosts. A request to a mapped name (
app.test) is redirected to its local target (http://127.0.0.1:3000), keeping the path and query. See networking. - Link cleaning (
privacy.strip_tracking, on by default). For top-level and frameGETnavigations,strip_tracking()removes known tracking parameters:utm_*,fbclid,gclid,msclkid,mc_eidand about 40 more, plus site-specific ones such as YouTube'ssior Amazon'sref_. Allowed sites are skipped. - HTTPS-first (
privacy.https_upgrade, off by default). A main-framehttp://navigation to a public host is redirected tohttps://. If the site bounces back to http within 4 seconds, or the https version fails to load or has a certificate error, JBrowser opens the original http page instead, shows a "not encrypted" warning, and doesn't try that host again this session.
If nothing redirects, the interceptor adds DNT: 1 (privacy.dnt) and Sec-GPC: 1 (privacy.gpc).
should_block(): blocking#
- Main-frame navigations and local hosts are never blocked here.
- Threats: sub-resources and frames from known phishing or malware hosts are always blocked.
- With
privacy.block_trackersoff, stop here. - When the first party is on
privacy.allowlist, nothing is blocked. - Third-party requests to a domain on the blocklist (the built-in list plus the whole-domain rules extracted from the downloaded lists) are blocked, as are a few built-in path rules.
This version blocks by domain only. URL-pattern rules, exceptions and element hiding came with the filter engine in 1.5.0.
A blocked request increments tab.blocked, which the shield button in the address pill shows.
Cookies#
Each profile's cookie store has a filter, PrivacyService.allow_cookie(). With
privacy.block_third_party_cookies on (the default), third-party cookies are refused, except:
- on sites where protection is switched off (the allowed list).
Adding a rule#
- Something that changes the URL: add it to
rewrite(), keep it cheap, and returnNonequickly for the common case. - Something that blocks: put it in
should_block()at the right place in the order above, and make sure it can't block main-frame navigations. - Always test with a page that makes many requests (a news site) and watch the log for exceptions.