Skip to content

Latest commit

 

History

History
144 lines (112 loc) · 6.25 KB

android.md

File metadata and controls

144 lines (112 loc) · 6.25 KB

Android setup

Status: beta. Firefox for Android needs an Android-specific package and a Tailscale tailnet; report Android issues as bug reports.

Sleeper uses Tailscale Serve as its only mobile-access path. The daemon stays bound to 127.0.0.1; Tailscale supplies HTTPS/WSS and private routing. The mobile setup link carries the daemon bearer only in its URL fragment, which is not sent in the HTTP request; the extension verifies that bearer against the daemon before saving it.

Computer setup

  1. Install Tailscale and sign this computer into your tailnet.

  2. Enable MagicDNS and HTTPS certificates for the tailnet.

  3. Start the Sleeper daemon normally.

  4. Run:

    sleeper mobile setup

Sleeper configures two tailnet-only HTTPS listeners:

  • https://HOSTNAME.ts.net:8790 → daemon HTTP on 127.0.0.1:8790
  • wss://HOSTNAME.ts.net:8789/ws → daemon WebSocket on 127.0.0.1:8789/ws

The command prints a setup URL and, when the optional QR renderer is installed, a terminal QR code. The command changes only Tailscale Serve ports 8789 and 8790; it does not reset unrelated Serve routes.

Phone setup

  1. Install Tailscale on the phone and join the same tailnet.
  2. Install an AMO-signed Android Sleeper package in Firefox for Android. The desktop package requests nativeMessaging, which Android rejects.
  3. Scan the QR code from sleeper mobile setup, or open its setup URL in Firefox.
  4. Sleeper verifies the daemon and opens its connection settings. When replacing an existing pairing, the current daemon stays connected until you approve the proposed endpoint in those settings.

The setup link is a secret: share it only with the intended browser. The extension stores the bearer locally and uses it for authenticated /tabs and WebSocket requests. Tailscale access controls still decide which users and devices can reach the service.

Operations

sleeper mobile status
sleeper mobile disable

status reports the tailnet hostname and current Serve configuration. disable removes only Sleeper's HTTPS listeners on ports 8789 and 8790.

If setup reports that Tailscale is not connected, run tailscale up. If it reports that HTTPS is unavailable, enable MagicDNS and HTTPS certificates in the Tailscale admin console.

Security invariants

  • The daemon must remain loopback-only.
  • Only Tailscale Serve may expose the daemon to another device.
  • Plain LAN HTTP/WS and direct daemon binding are rejected.
  • Setup URLs must use HTTPS, port 8790, and a .ts.net hostname.
  • Pairing succeeds only when the endpoint returns an authenticated /tabs response; a .ts.net page without the setup fragment cannot pair the add-on.

Firefox Nightly Android development iteration

Safety note: web-ext run installs a temporary add-on using the manifest's same ID. It is not safely coexistent with a persistent Sleeper installation: the temporary install may replace that add-on and remove itself on exit. The runner therefore refuses to start unless you explicitly pass --allow-persistent-replacement after backing up or intentionally uninstalling the persistent add-on. This workflow reloads source changes only; it is not a production self-update channel, and add-on storage should be treated as replaceable during the run.

For extension development, use the runner with Mozilla's supported web-ext Android target. First enable Firefox Nightly remote debugging and Android USB or Wi-Fi debugging, then confirm the device is visible to ADB:

npm ci --ignore-scripts
adb devices
scripts/firefox-android-iterate.sh --adb-device SERIAL \
  --allow-persistent-replacement

The script runs:

node_modules/.bin/web-ext run --source-dir TEMP_ANDROID_SOURCE --target firefox-android \
  --adb-device SERIAL --firefox-apk org.mozilla.fenix

The runner generates a temporary Android source directory from extension/, omitting the desktop-only nativeMessaging permission. It mirrors runtime and manifest changes into that directory, which web-ext watches to reload the add-on. The source manifest retains desktop native messaging. The temporary directory is removed when the runner exits.

web-ext run installs the add-on temporarily into Firefox for Android's main browser profile. Because it uses the manifest ID, it can replace the persistent AMO Sleeper add-on with that same ID; when the run exits, the temporary add-on may be removed and the persistent add-on may not be restored. Back up or intentionally uninstall the persistent add-on before using the explicit replacement acknowledgement above. This workflow does not change the production version or provide a self-update channel. Browser profile data outside the add-on is retained, but add-on storage must be treated as replaceable. Keep the debugger and ADB connection alive until cleanup.

When more than one device is connected, --adb-device is mandatory. The package defaults to Nightly (org.mozilla.fenix); set FIREFOX_APK or pass --firefox-apk for another Firefox channel. --dry-run validates device selection and prints the exact command without installing anything:

scripts/firefox-android-iterate.sh --dry-run --adb-device SERIAL

Updates versus development reloads

Firefox does not treat a locally built unsigned XPI as a production update. Persistent add-on updates require a signed package and an update manifest (or distribution through AMO); this repository deliberately has no update_url. For local iteration, web-ext run and its Gecko remote-debugger install/reload protocol are the supported mechanism. Build an Android package for inspection:

python3 scripts/build_packages.py firefox-android extension build/sleeper-android.xpi

This unsigned package is for development. Persistent installation requires AMO signing of the Android package. The existing desktop signing workflow in firefox-signing.md produces a desktop artifact and does not establish Android compatibility.

References: Firefox for Android extension development and the web-ext run command reference.