Network behaviour & Play data safety
Cefrium embeds a real Chromium engine, and like Chromium it keeps some of its own data current over the network. If you publish on Google Play you have to declare what leaves the device, so here is the complete answer: what the engine contacts, what it provably does not do, how to turn it off, and what that costs you.
What the engine contacts
Besides the pages your app loads, these are the only outbound requests the engine makes on its own:
| What | Where | Default | What it carries |
|---|---|---|---|
| Component updater | update.googleapis.com (HTTPS) |
On | Component ids and versions, the platform, and a random per-component install identifier. No URL, no account, nothing the user typed. |
| Network time | http://clients2.google.com/time/1/current |
Off since 0.9.3 | Nothing identifying. |
The component updater is not telemetry. It is how the engine downloads the data files it depends on to be safe: the certificate revocation list (CRLSet), Certificate Transparency log metadata, the dangerous-download file-type policy, TLS error diagnostics, Trust Token key commitments, First-Party Sets, and the subresource filtering ruleset. It is the mechanism that keeps a shipped app's trust data current between SDK releases.
The time query exists to notice that a device's clock is wrong, so that a certificate which merely looks expired can be diagnosed as a clock problem. It carries no security data, and Android devices normally get the clock from the carrier or NTP already -- so from 0.9.3 Cefrium ships it off, which is a deliberate divergence from upstream Chromium's default. That leaves the component updater as the only request the engine makes on its own.
What it does not do
Each of these was checked on a device by reading the engine's persisted state, not assumed from configuration:
- No usage statistics or metrics upload. Chromium's UMA and UKM reporting is off and no consent is recorded.
- No crash-report upload. The crash reporter is never configured, so it is never started.
- No Chromium field-trial ("variations") seed fetch.
- No Google Cloud Messaging.
- No Safe Browsing store or lookups.
- No Google API keys are compiled into the SDK, so the engine's Google account, sync and optimization-guide backends are inert.
Browsing data -- history, cookies, form data, what the user types -- stays in the on-device profile. Nothing uploads it.
Changing either default
The two requests get opposite defaults because they are not comparable: one is a security feed whose absence degrades the engine silently, the other only improves an error message. So the data feed stays on and you opt out of it, while the time query is off and you opt back in. Set either before the engine initializes, which means before your first browser is created:
// Application.onCreate(), or anywhere before the first CefriumBrowser
Cefrium.setComponentUpdatesEnabled(false); // opt OUT of the security data feed
Cefrium.setNetworkTimeQueriesEnabled(true); // opt back IN to the time query
Called after initialization they are ignored and log a warning. Read the current
state with Cefrium.areComponentUpdatesEnabled() and
Cefrium.areNetworkTimeQueriesEnabled(). Both are implemented with
Chromium's own command-line switches, so they keep working across engine updates.
Available from Cefrium 0.9.3.
Read this before disabling component updates. This is a security trade-off, not just a privacy setting. With component updates off, every data file listed above freezes at the state baked into the SDK version you shipped. In particular certificate revocation data stops being refreshed, so a certificate revoked after your build date will still be accepted by your app.
The failure mode is silent: nothing crashes, nothing logs an error, and no user complains. If you disable it, you are taking on the job of shipping SDK updates promptly, so pin your Cefrium version deliberately and follow releases.
Good reasons to disable it:
- an air-gapped or offline deployment, where the requests cannot succeed anyway;
- a kiosk on a metered or strictly whitelisted network;
- a compliance regime that forbids unattended third-party requests.
"I would rather not talk to Google" on a general-purpose, internet-connected app is not a good enough reason on its own. You would be trading real revocation coverage for a shorter privacy note.
Re-enabling the time query is the opposite case: it costs you one request a day and buys a better error message. Turn it on if your hardware has no dependable clock -- a device with no cellular modem and no NTP reachability, or a kiosk whose RTC has no battery -- where a clock far enough off to break HTTPS is a real support case.
Your Play data safety form
The form asks what your app collects and sends. Data the user types into websites they chose to visit is not your collection: the browser acts on the user's behalf, to third parties the user picked. So web browsing history, form inputs and page content are not declared -- they never leave the device.
What does leave the device by your app's doing is the engine's own maintenance traffic above. The honest declaration is short:
- Device or other IDs -- shared, not collected (you operate no server and never receive it). Purpose: app functionality, and fraud prevention / security / compliance. This is the random per-component install identifier the update check carries.
- Everything else -- not collected.
Two readings are defensible for that identifier: declare it as shared with a third party, or treat it as the embedded engine contacting its own infrastructure. We recommend declaring it. Over-declaring costs you one line in your listing; under-declaring is a policy violation, and this is traffic a reviewer can observe from a packet capture on a fresh install.
If you disable component updates, revisit the answer -- with the data feed off and the time query at its default, the engine makes no requests of its own and there is nothing left to declare.
Cefrium's own browser publishes exactly this, so you can adapt the wording from our privacy policy. Note that page is written for the browser's end users; this guide is the version for you as an integrator.
Verifying it yourself
You do not have to take any of this on trust. The engine records what happened in its own profile, and a server-assigned value on disk is proof that a request was made. On a debuggable build:
adb shell run-as <your.package> cat cache/Local\\ State
Look for updateclientdata.apps (component update checks: the
server-assigned cohortname values can only come from a response) and
network_time.network_time_mapping (the time query). On the 0.9.3
defaults the time mapping never appears at all, and with component updates disabled
too, neither key does. You can also confirm the absences: no
variations_compressed_seed, no metrics
client_id, and an empty ukm.persisted_logs.
Pass the command directly to run-as;
run-as <pkg> sh -c '...' lands in a different SELinux domain and
is denied.
Need this in writing?
If your procurement or compliance process needs a signed statement of a specific release's network behaviour, or a validated configuration for an air-gapped or kiosk deployment kept current with security updates, write to cefrium@proton.me.