iOS: iPX opens with no connection (#435)

A WKWebView runs no service worker unless the app lists its domains
in WKAppBoundDomains and the web view limits itself to them. So the
Info.plist lists ipodderx.sdf1.net, with Cloudflare Access's
(rays-sdf1.cloudflareaccess.com) and Authentik's (authentik.sdf1.net)
hosts so signing in still works. For a server in that list the web
view is made app-bound and #389's worker runs: the page and its lists
open offline from the second launch, since the first only installs the
worker.

The costs:
- Navigation elsewhere is refused, and the failure looked like the
  server being down. decidePolicyFor sends such links to Safari.
- With the key present, WebKit cuts the bridge for any server not in
  the list. That server then gets the page with its own audio, not
  the phone's player.

The web view is made again when the server changes, since being
app-bound is fixed when it is made.

A debug build adds localhost through a build script, so the simulator
can test against a page served on the Mac; the release archive's plist
was checked to have only the three. Tested in the simulator: opened
twice online, the server stopped, relaunched, and the page came up from
the worker. With the bridge still up on the app-bound host, the
phone's player played.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Ray Slakinski
2026-11-08 17:08:27 -05:00
parent cf0dad7380
commit b455c1ec8c
5 changed files with 76 additions and 6 deletions

View File

@@ -25,7 +25,7 @@ targets:
properties:
CFBundleDisplayName: iPX
CFBundleShortVersionString: $(MARKETING_VERSION)
CFBundleVersion: "8"
CFBundleVersion: "9"
# Playing on with the screen locked. A plist key, not a signed entitlement, so it works on
# a free personal team; CarPlay's own dashboard app is an entitlement Apple has to grant.
UIBackgroundModes: [audio, fetch]
@@ -48,12 +48,30 @@ targets:
# Plain HTTP only for a server on your own network (192.168.1.130:8099); the tunnel is HTTPS.
NSAppTransportSecurity:
NSAllowsLocalNetworking: true
# The page's service worker runs only for these, so iPX opens offline only at them
# (#435): the server, and Cloudflare Access and Authentik, where its sign-in goes. Ten at
# most, and a server not here loses the bridge (WebViewController.makeWebView).
WKAppBoundDomains:
- ipodderx.sdf1.net
- rays-sdf1.cloudflareaccess.com
- authentik.sdf1.net
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: net.sdf1.ipx
MARKETING_VERSION: "0.1.0"
DEVELOPMENT_TEAM: 8743L8D729
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
# The script below writes into the built Info.plist, which the sandbox would refuse.
ENABLE_USER_SCRIPT_SANDBOXING: NO
postBuildScripts:
# A debug build is app-bound to localhost too, so the simulator can test the service
# worker against a page served on the Mac (#435). Never in a release.
- name: App-bound localhost (debug)
basedOnDependencyAnalysis: false
script: |
if [ "$CONFIGURATION" = Debug ]; then
/usr/libexec/PlistBuddy -c "Add :WKAppBoundDomains: string localhost" "$TARGET_BUILD_DIR/$INFOPLIST_PATH"
fi
iPXTests:
type: bundle.unit-test