From a8e5deec3393e94c9a3a18fb9d617a3184e82de0 Mon Sep 17 00:00:00 2001 From: AKolenda Date: Tue, 20 Oct 2026 15:34:21 -0600 Subject: [PATCH] Ignore opaque URIs in calendar deep links MainActivity is exported, so an explicit intent can deliver any URI. Uri.getQueryParameter throws on opaque URIs such as solidtime:calendar, which crashed the activity. Return no calendar date for them instead. --- .../ui/navigation/CalendarDeepLink.kt | 17 ++++++---- .../ui/navigation/CalendarDeepLinkUriTest.kt | 31 +++++++++++++++++++ 2 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 app/src/test/java/dev/tricked/solidverdant/ui/navigation/CalendarDeepLinkUriTest.kt diff --git a/app/src/main/java/dev/tricked/solidverdant/ui/navigation/CalendarDeepLink.kt b/app/src/main/java/dev/tricked/solidverdant/ui/navigation/CalendarDeepLink.kt index a5152ced..54dcc39e 100644 --- a/app/src/main/java/dev/tricked/solidverdant/ui/navigation/CalendarDeepLink.kt +++ b/app/src/main/java/dev/tricked/solidverdant/ui/navigation/CalendarDeepLink.kt @@ -16,12 +16,17 @@ private const val CALENDAR_DATE_QUERY = "date" private const val LOCAL_DATE_LENGTH = 10 /** Resolve a calendar date from the public app-link contract without accepting malformed input. */ -internal fun calendarDateFromUri(uri: Uri): LocalDate? = parseCalendarDateDeepLink( - scheme = uri.scheme, - host = uri.host, - path = uri.path, - queryDate = uri.getQueryParameter(CALENDAR_DATE_QUERY), -) +internal fun calendarDateFromUri(uri: Uri): LocalDate? { + // The activity is exported, so explicit intents can carry any URI. Query accessors throw on + // opaque URIs such as `solidtime:calendar`, which would otherwise crash the activity. + if (!uri.isHierarchical) return null + return parseCalendarDateDeepLink( + scheme = uri.scheme, + host = uri.host, + path = uri.path, + queryDate = uri.getQueryParameter(CALENDAR_DATE_QUERY), + ) +} /** * Pure parser seam for JVM tests. Both `solidtime://calendar?date=yyyy-MM-dd` and diff --git a/app/src/test/java/dev/tricked/solidverdant/ui/navigation/CalendarDeepLinkUriTest.kt b/app/src/test/java/dev/tricked/solidverdant/ui/navigation/CalendarDeepLinkUriTest.kt new file mode 100644 index 00000000..ba5ae79d --- /dev/null +++ b/app/src/test/java/dev/tricked/solidverdant/ui/navigation/CalendarDeepLinkUriTest.kt @@ -0,0 +1,31 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package dev.tricked.solidverdant.ui.navigation + +import android.net.Uri +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import java.time.LocalDate + +@RunWith(RobolectricTestRunner::class) +class CalendarDeepLinkUriTest { + + @Test + fun resolvesHierarchicalCalendarLinks() { + assertEquals(LocalDate.of(2026, 8, 11), calendarDateFromUri(Uri.parse("solidtime://calendar?date=2026-08-11"))) + assertEquals(LocalDate.of(2026, 8, 11), calendarDateFromUri(Uri.parse("solidtime://calendar/2026-08-11"))) + } + + @Test + fun ignoresOpaqueUrisInsteadOfThrowing() { + assertNull(calendarDateFromUri(Uri.parse("solidtime:calendar?date=2026-08-11"))) + assertNull(calendarDateFromUri(Uri.parse("mailto:someone@example.com"))) + } +}