diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-10-17 13:29:25 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-10-17 13:29:25 +0200 |
| commit | 165847da1ca3c3be627b5968bc77e9a11b3385cb (patch) | |
| tree | 603329a801d1304fdba833c1a8f4cd8c4ce4e7c6 /packages/meshbay-hub/tests | |
| parent | a1d18a2957d167444c6fc6c2e4ec8628509a7009 (diff) | |
| download | meshbay-165847da1ca3c3be627b5968bc77e9a11b3385cb.tar.gz | |
feat(android): ask for the local network when a group opens
Android 17 makes it a permission for an application targeting SDK 37.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub/tests')
| -rw-r--r-- | packages/meshbay-hub/tests/test_android_shell.py | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/packages/meshbay-hub/tests/test_android_shell.py b/packages/meshbay-hub/tests/test_android_shell.py index 520fa7e7..cba4b320 100644 --- a/packages/meshbay-hub/tests/test_android_shell.py +++ b/packages/meshbay-hub/tests/test_android_shell.py @@ -137,7 +137,8 @@ def test_the_shim_offers_desktop_channels_and_native_answers_each(): native = set() for path in (SRC / "bridge" / "Channels.kt", SRC / "bridge" / "KeyChannels.kt", SRC / "cast" / "CastChannels.kt", SRC / "notify" / "PushChannels.kt", - SRC / "photos" / "PhotoChannels.kt", SRC / "phonesync" / "Destination.kt"): + SRC / "photos" / "PhotoChannels.kt", SRC / "phonesync" / "Destination.kt", + SRC / "shell" / "LocalNetwork.kt"): native |= set(re.findall(r'^\s*"([\w:-]+)" ->', _read(path), flags=re.M)) # Contacts and the calendar share one class, its channels named by a prefix. docs = set(re.findall(r'^\s*"([\w-]+)" ->', _read(SRC / "phonesync" / "DocChannels.kt"), flags=re.M)) @@ -151,10 +152,11 @@ def test_the_shim_offers_desktop_channels_and_native_answers_each(): assert shim, "no channel found in the shim" # A phone has a push distributor to talk to and a camera roll and an # address book to back up, and a desktop has none of them; those families are the ones the desktop lacks - # rather than the ones it shares. + # rather than the ones it shares. Nor does a desktop ask before reaching the + # local network (Android 17). phone_only = {c for c in shim if c.startswith(("push:", "photosync:", "phonesync:", "contactsync:", "calendarsync:", "drivesync:", - "wasync:"))} + "wasync:", "lan:"))} assert any(c.startswith("push:") for c in phone_only), "the push channels are gone" assert any(c.startswith("photosync:") for c in phone_only), "the backup channels are gone" assert shim - phone_only <= preload, f"channels the desktop does not have: {shim - preload}" @@ -236,6 +238,31 @@ def test_a_notification_is_drawn_only_when_it_opened_and_leads_inside_the_page() assert 'location.hash = ${JSONObject.quote(link)}' in activity +def test_the_local_network_is_asked_for_when_a_group_opens(): + """Android 17 makes the local network a permission for an application that + targets it, and the node is usually on the phone's Wi-Fi: without it the + group opens on mobile data and not at home. The page's WebRTC carries this + application's permission. Asked when a group is first opened, never at + start, and only by an application that targets 37: before that the + permission comes with INTERNET and asking for it is what Android says not + to do.""" + manifest = _read(APP / "src" / "main" / "AndroidManifest.xml") + assert "android.permission.ACCESS_LOCAL_NETWORK" in manifest + target = int(re.search(r"targetSdk = (\d+)", _read(APP / "build.gradle.kts")).group(1)) + assert target >= 37, "the permission is declared by an application that does not target 37" + activity = _read(SRC / "MainActivity.kt") + on_create = activity.split("override fun onCreate(", 1)[1].split("\n override fun ", 1)[0] + assert "requestPermissions" not in on_create + assert "lan.deliverPermission(requestCode)" in activity + lan = _read(SRC / "shell" / "LocalNetwork.kt") + assert "ACCESS_LOCAL_NETWORK" in lan and "ACTION_APPLICATION_DETAILS_SETTINGS" in lan + from spa_source import STATIC + page = _read(STATIC / "group-page.js") + asked = page.split("platform.localNetwork.available && !lanAsked", 1) + assert len(asked) == 2 and "platform.localNetwork.request()" in asked[1][:200] + assert "lanAsked = true" in asked[1][:200] + + def test_no_backup_carries_the_keys_away(): manifest = _read(APP / "src" / "main" / "AndroidManifest.xml") assert 'android:allowBackup="false"' in manifest |