filters the unique notification uris from the link handling

- fixes malformed url errors appearing for uri we only create to force uniqueness in the notifications
This commit is contained in:
Adam Brown 2021-10-22 18:29:53 +01:00
parent 0d1382ab01
commit 06b3cc3f4b
3 changed files with 53 additions and 22 deletions

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2021 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.core.extensions
import android.net.Uri
const val IGNORED_SCHEMA = "ignored"
fun Uri.isIgnored() = scheme == IGNORED_SCHEMA
fun createIgnoredUri(path: String): Uri = Uri.parse("$IGNORED_SCHEMA://$path")

View File

@ -47,6 +47,7 @@ import androidx.core.graphics.drawable.IconCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import im.vector.app.BuildConfig import im.vector.app.BuildConfig
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.extensions.createIgnoredUri
import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.StringProvider
import im.vector.app.core.services.CallService import im.vector.app.core.services.CallService
import im.vector.app.core.utils.startNotificationChannelSettingsIntent import im.vector.app.core.utils.startNotificationChannelSettingsIntent
@ -317,7 +318,7 @@ class NotificationUtils @Inject constructor(private val context: Context,
mode = VectorCallActivity.INCOMING_RINGING mode = VectorCallActivity.INCOMING_RINGING
).apply { ).apply {
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
data = Uri.parse("foobar://${call.callId}") data = createIgnoredUri(call.callId)
} }
val contentPendingIntent = PendingIntent.getActivity(context, System.currentTimeMillis().toInt(), contentIntent, 0) val contentPendingIntent = PendingIntent.getActivity(context, System.currentTimeMillis().toInt(), contentIntent, 0)
@ -378,7 +379,7 @@ class NotificationUtils @Inject constructor(private val context: Context,
call = call, call = call,
mode = null).apply { mode = null).apply {
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
data = Uri.parse("foobar://$call.callId") data = createIgnoredUri(call.callId)
} }
val contentPendingIntent = PendingIntent.getActivity(context, System.currentTimeMillis().toInt(), contentIntent, 0) val contentPendingIntent = PendingIntent.getActivity(context, System.currentTimeMillis().toInt(), contentIntent, 0)
@ -584,7 +585,7 @@ class NotificationUtils @Inject constructor(private val context: Context,
// Mark room as read // Mark room as read
val markRoomReadIntent = Intent(context, NotificationBroadcastReceiver::class.java) val markRoomReadIntent = Intent(context, NotificationBroadcastReceiver::class.java)
markRoomReadIntent.action = MARK_ROOM_READ_ACTION markRoomReadIntent.action = MARK_ROOM_READ_ACTION
markRoomReadIntent.data = Uri.parse("foobar://${roomInfo.roomId}") markRoomReadIntent.data = createIgnoredUri(roomInfo.roomId)
markRoomReadIntent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomInfo.roomId) markRoomReadIntent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomInfo.roomId)
val markRoomReadPendingIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt(), markRoomReadIntent, val markRoomReadPendingIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt(), markRoomReadIntent,
PendingIntent.FLAG_UPDATE_CURRENT) PendingIntent.FLAG_UPDATE_CURRENT)
@ -652,7 +653,7 @@ class NotificationUtils @Inject constructor(private val context: Context,
// offer to type a quick reject button // offer to type a quick reject button
val rejectIntent = Intent(context, NotificationBroadcastReceiver::class.java) val rejectIntent = Intent(context, NotificationBroadcastReceiver::class.java)
rejectIntent.action = REJECT_ACTION rejectIntent.action = REJECT_ACTION
rejectIntent.data = Uri.parse("foobar://$roomId&$matrixId") rejectIntent.data = createIgnoredUri("$roomId&$matrixId")
rejectIntent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomId) rejectIntent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomId)
val rejectIntentPendingIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt(), rejectIntent, val rejectIntentPendingIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt(), rejectIntent,
PendingIntent.FLAG_UPDATE_CURRENT) PendingIntent.FLAG_UPDATE_CURRENT)
@ -665,7 +666,7 @@ class NotificationUtils @Inject constructor(private val context: Context,
// offer to type a quick accept button // offer to type a quick accept button
val joinIntent = Intent(context, NotificationBroadcastReceiver::class.java) val joinIntent = Intent(context, NotificationBroadcastReceiver::class.java)
joinIntent.action = JOIN_ACTION joinIntent.action = JOIN_ACTION
joinIntent.data = Uri.parse("foobar://$roomId&$matrixId") joinIntent.data = createIgnoredUri("$roomId&$matrixId")
joinIntent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomId) joinIntent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomId)
val joinIntentPendingIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt(), joinIntent, val joinIntentPendingIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt(), joinIntent,
PendingIntent.FLAG_UPDATE_CURRENT) PendingIntent.FLAG_UPDATE_CURRENT)
@ -677,7 +678,7 @@ class NotificationUtils @Inject constructor(private val context: Context,
val contentIntent = HomeActivity.newIntent(context, inviteNotificationRoomId = inviteNotifiableEvent.roomId) val contentIntent = HomeActivity.newIntent(context, inviteNotificationRoomId = inviteNotifiableEvent.roomId)
contentIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP contentIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
// pending intent get reused by system, this will mess up the extra params, so put unique info to avoid that // pending intent get reused by system, this will mess up the extra params, so put unique info to avoid that
contentIntent.data = Uri.parse("foobar://" + inviteNotifiableEvent.eventId) contentIntent.data = createIgnoredUri(inviteNotifiableEvent.eventId)
setContentIntent(PendingIntent.getActivity(context, 0, contentIntent, 0)) setContentIntent(PendingIntent.getActivity(context, 0, contentIntent, 0))
if (inviteNotifiableEvent.noisy) { if (inviteNotifiableEvent.noisy) {
@ -716,7 +717,7 @@ class NotificationUtils @Inject constructor(private val context: Context,
val contentIntent = HomeActivity.newIntent(context) val contentIntent = HomeActivity.newIntent(context)
contentIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP contentIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
// pending intent get reused by system, this will mess up the extra params, so put unique info to avoid that // pending intent get reused by system, this will mess up the extra params, so put unique info to avoid that
contentIntent.data = Uri.parse("foobar://" + simpleNotifiableEvent.eventId) contentIntent.data = createIgnoredUri(simpleNotifiableEvent.eventId)
setContentIntent(PendingIntent.getActivity(context, 0, contentIntent, 0)) setContentIntent(PendingIntent.getActivity(context, 0, contentIntent, 0))
if (simpleNotifiableEvent.noisy) { if (simpleNotifiableEvent.noisy) {
@ -738,7 +739,7 @@ class NotificationUtils @Inject constructor(private val context: Context,
val roomIntentTap = RoomDetailActivity.newIntent(context, RoomDetailArgs(roomId)) val roomIntentTap = RoomDetailActivity.newIntent(context, RoomDetailArgs(roomId))
roomIntentTap.action = TAP_TO_VIEW_ACTION roomIntentTap.action = TAP_TO_VIEW_ACTION
// pending intent get reused by system, this will mess up the extra params, so put unique info to avoid that // pending intent get reused by system, this will mess up the extra params, so put unique info to avoid that
roomIntentTap.data = Uri.parse("foobar://openRoom?$roomId") roomIntentTap.data = createIgnoredUri("openRoom?$roomId")
// Recreate the back stack // Recreate the back stack
return TaskStackBuilder.create(context) return TaskStackBuilder.create(context)
@ -750,7 +751,7 @@ class NotificationUtils @Inject constructor(private val context: Context,
private fun buildOpenHomePendingIntentForSummary(): PendingIntent { private fun buildOpenHomePendingIntentForSummary(): PendingIntent {
val intent = HomeActivity.newIntent(context, clearNotification = true) val intent = HomeActivity.newIntent(context, clearNotification = true)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
intent.data = Uri.parse("foobar://tapSummary") intent.data = createIgnoredUri("tapSummary")
return PendingIntent.getActivity(context, Random.nextInt(1000), intent, PendingIntent.FLAG_UPDATE_CURRENT) return PendingIntent.getActivity(context, Random.nextInt(1000), intent, PendingIntent.FLAG_UPDATE_CURRENT)
} }
@ -766,7 +767,7 @@ class NotificationUtils @Inject constructor(private val context: Context,
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent = Intent(context, NotificationBroadcastReceiver::class.java) intent = Intent(context, NotificationBroadcastReceiver::class.java)
intent.action = SMART_REPLY_ACTION intent.action = SMART_REPLY_ACTION
intent.data = Uri.parse("foobar://$roomId") intent.data = createIgnoredUri(roomId)
intent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomId) intent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomId)
return PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt(), intent, return PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt(), intent,
PendingIntent.FLAG_UPDATE_CURRENT) PendingIntent.FLAG_UPDATE_CURRENT)
@ -781,7 +782,7 @@ class NotificationUtils @Inject constructor(private val context: Context,
// the action must be unique else the parameters are ignored // the action must be unique else the parameters are ignored
quickReplyIntent.action = QUICK_LAUNCH_ACTION quickReplyIntent.action = QUICK_LAUNCH_ACTION
quickReplyIntent.data = Uri.parse("foobar://$roomId") quickReplyIntent.data = _root_ide_package_.im.vector.app.core.extensions.createIgnoredUri($roomId")
return PendingIntent.getActivity(context, 0, quickReplyIntent, 0) return PendingIntent.getActivity(context, 0, quickReplyIntent, 0)
} }
*/ */
@ -835,7 +836,7 @@ class NotificationUtils @Inject constructor(private val context: Context,
private fun getDismissSummaryPendingIntent(): PendingIntent { private fun getDismissSummaryPendingIntent(): PendingIntent {
val intent = Intent(context, NotificationBroadcastReceiver::class.java) val intent = Intent(context, NotificationBroadcastReceiver::class.java)
intent.action = DISMISS_SUMMARY_ACTION intent.action = DISMISS_SUMMARY_ACTION
intent.data = Uri.parse("foobar://deleteSummary") intent.data = createIgnoredUri("deleteSummary")
return PendingIntent.getBroadcast(context.applicationContext, return PendingIntent.getBroadcast(context.applicationContext,
0, intent, PendingIntent.FLAG_UPDATE_CURRENT) 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
} }

View File

@ -20,6 +20,7 @@ import android.content.Context
import android.net.Uri import android.net.Uri
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.extensions.isIgnored
import im.vector.app.core.utils.toast import im.vector.app.core.utils.toast
import im.vector.app.features.navigation.Navigator import im.vector.app.features.navigation.Navigator
import im.vector.app.features.roomdirectory.roompreview.RoomPreviewData import im.vector.app.features.roomdirectory.roompreview.RoomPreviewData
@ -53,15 +54,19 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
navigationInterceptor: NavigationInterceptor? = null, navigationInterceptor: NavigationInterceptor? = null,
buildTask: Boolean = false buildTask: Boolean = false
): Boolean { ): Boolean {
if (deepLink == null || !isPermalinkSupported(context, deepLink.toString())) { return when {
return false deepLink == null -> false
} deepLink.isIgnored() -> true
return tryOrNull { !isPermalinkSupported(context, deepLink.toString()) -> false
withContext(Dispatchers.Default) { else -> {
val permalinkData = PermalinkParser.parse(deepLink) tryOrNull {
handlePermalink(permalinkData, deepLink, context, navigationInterceptor, buildTask) withContext(Dispatchers.Default) {
val permalinkData = PermalinkParser.parse(deepLink)
handlePermalink(permalinkData, deepLink, context, navigationInterceptor, buildTask)
}
} ?: false
} }
} ?: false }
} }
private suspend fun handlePermalink( private suspend fun handlePermalink(
@ -115,8 +120,8 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
private fun isPermalinkSupported(context: Context, url: String): Boolean { private fun isPermalinkSupported(context: Context, url: String): Boolean {
return url.startsWith(PermalinkService.MATRIX_TO_URL_BASE) || return url.startsWith(PermalinkService.MATRIX_TO_URL_BASE) ||
context.resources.getStringArray(R.array.permalink_supported_hosts).any { context.resources.getStringArray(R.array.permalink_supported_hosts).any {
url.startsWith(it) url.startsWith(it)
} }
} }
private suspend fun PermalinkData.RoomLink.getRoomId(): String? { private suspend fun PermalinkData.RoomLink.getRoomId(): String? {