Skip to content

Commit

Permalink
Permalink: Merge LinkHandlerActivity with PermalinkHandlerActivity
Browse files Browse the repository at this point in the history
Also convert links to matrix.to before permalink parsing
  • Loading branch information
Frenaud14 committed Sep 16, 2021
1 parent d63fca0 commit 3968131
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 206 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright 2020 The Matrix.org Foundation C.I.C.
*
* 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 org.matrix.android.sdk.api.session.permalinks

import android.net.Uri

/**
* Mapping of an input URI to a matrix.to compliant URI.
*/
object MatrixToMapper {

/**
* Try to convert a URL from an element web instance or from a client permalink to a matrix.to url.
* Examples:
* - https://riot.im/develop/#/room/#element-android:matrix.org -> https://matrix.to/#/#element-android:matrix.org
* - https://app.element.io/#/room/#element-android:matrix.org -> https://matrix.to/#/#element-android:matrix.org
* - https://www.example.org/#/room/#element-android:matrix.org -> https://matrix.to/#/#element-android:matrix.org
* - element://room/#element-android:matrix.org -> https://matrix.to/#/#element-android:matrix.org
*/
fun map(uri: Uri): Uri? {
val uriString = uri.toString()

return when {
// URL is already a matrix.to
uriString.startsWith(PermalinkService.MATRIX_TO_URL_BASE) -> uri
// Web or client url
SUPPORTED_PATHS.any { it in uriString } -> {
val path = SUPPORTED_PATHS.first { it in uriString }
Uri.parse(PermalinkService.MATRIX_TO_URL_BASE + uriString.substringAfter(path))
}
// Element custom scheme
uriString.startsWith(PermalinkService.MATRIX_TO_CUSTOM_SCHEME_URL_BASE) -> {
val permalinkId = when {
uriString.startsWith(USER_LINK_PREFIX) -> uriString.substring(USER_LINK_PREFIX.length)
uriString.startsWith(ROOM_LINK_PREFIX) -> uriString.substring(ROOM_LINK_PREFIX.length)
else -> null
}
Uri.parse(PermalinkService.MATRIX_TO_URL_BASE + permalinkId)
}
// URL is not supported
else -> null
}
}

private const val ROOM_LINK_PREFIX = "${PermalinkService.MATRIX_TO_CUSTOM_SCHEME_URL_BASE}room/"
private const val USER_LINK_PREFIX = "${PermalinkService.MATRIX_TO_CUSTOM_SCHEME_URL_BASE}user/"

private val SUPPORTED_PATHS = listOf(
"/#/room/",
"/#/user/",
"/#/group/"
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import java.net.URLDecoder
* This class turns a uri to a [PermalinkData]
* element-based domains (e.g. https://app.element.io/#/user/@chagai95:matrix.org) permalinks
* or matrix.to permalinks (e.g. https://matrix.to/#/@chagai95:matrix.org)
* or client permalinks (e.g. https://www.example.com/#/user/@chagai95:matrix.org)
*/
object PermalinkParser {

Expand All @@ -42,12 +43,14 @@ object PermalinkParser {
* https://github.com/matrix-org/matrix-doc/blob/master/proposals/1704-matrix.to-permalinks.md
*/
fun parse(uri: Uri): PermalinkData {
if (!uri.toString().startsWith(PermalinkService.MATRIX_TO_URL_BASE)) {
return PermalinkData.FallbackLink(uri)
}
// the client or element-based domain permalinks (e.g. https://app.element.io/#/user/@chagai95:matrix.org) don't have the
// mxid in the first param (like matrix.to does - https://matrix.to/#/@chagai95:matrix.org) but rather in the second after /user/ so /user/mxid
// so convert URI to matrix.to to simplify parsing process
val matrixToUri = MatrixToMapper.map(uri) ?: return PermalinkData.FallbackLink(uri)

// We can't use uri.fragment as it is decoding to early and it will break the parsing
// of parameters that represents url (like signurl)
val fragment = uri.toString().substringAfter("#") // uri.fragment
val fragment = matrixToUri.toString().substringAfter("#") // uri.fragment
if (fragment.isNullOrEmpty()) {
return PermalinkData.FallbackLink(uri)
}
Expand All @@ -61,20 +64,14 @@ object PermalinkParser {
.map { URLDecoder.decode(it, "UTF-8") }
.take(2)

// the element-based domain permalinks (e.g. https://app.element.io/#/user/@chagai95:matrix.org) don't have the
// mxid in the first param (like matrix.to does - https://matrix.to/#/@chagai95:matrix.org) but rather in the second after /user/ so /user/mxid
var identifier = params.getOrNull(0)
if (identifier.equals("user")) {
identifier = params.getOrNull(1)
}

val identifier = params.getOrNull(0)
val extraParameter = params.getOrNull(1)
return when {
identifier.isNullOrEmpty() -> PermalinkData.FallbackLink(uri)
MatrixPatterns.isUserId(identifier) -> PermalinkData.UserLink(userId = identifier)
MatrixPatterns.isGroupId(identifier) -> PermalinkData.GroupLink(groupId = identifier)
MatrixPatterns.isRoomId(identifier) -> {
handleRoomIdCase(fragment, identifier, uri, extraParameter, viaQueryParameters)
handleRoomIdCase(fragment, identifier, matrixToUri, extraParameter, viaQueryParameters)
}
MatrixPatterns.isRoomAlias(identifier) -> {
PermalinkData.RoomLink(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ interface PermalinkService {

companion object {
const val MATRIX_TO_URL_BASE = "https://matrix.to/#/"
const val MATRIX_TO_CUSTOM_SCHEME_URL_BASE = "element://"
}

/**
Expand Down
57 changes: 31 additions & 26 deletions vector/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,9 @@
<activity android:name=".features.createdirect.CreateDirectRoomActivity" />
<activity android:name=".features.invite.InviteUsersToRoomActivity" />
<activity android:name=".features.webview.VectorWebViewActivity" />
<activity android:name=".features.link.LinkHandlerActivity">
<activity
android:name=".features.link.LinkHandlerActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />

Expand All @@ -196,6 +198,30 @@
</intent-filter>
</activity>

<activity-alias
android:name=".features.permalink.PermalinkHandlerActivity"
android:exported="true"
android:launchMode="singleTask"
android:targetActivity=".features.link.LinkHandlerActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="matrix.to" />
<data
android:host="user"
android:scheme="element" />
<data
android:host="room"
android:scheme="element" />

</intent-filter>
</activity-alias>

<activity
android:name=".features.share.IncomingShareActivity"
android:parentActivityName=".features.home.HomeActivity">
Expand Down Expand Up @@ -230,27 +256,6 @@
<activity
android:name=".features.signout.soft.SoftLogoutActivity"
android:windowSoftInputMode="adjustResize" />
<activity
android:name=".features.permalink.PermalinkHandlerActivity"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="matrix.to" />
<data
android:host="user"
android:scheme="element" />
<data
android:host="room"
android:scheme="element" />

</intent-filter>
</activity>

<activity
android:name=".features.roommemberprofile.RoomMemberProfileActivity"
Expand All @@ -271,12 +276,12 @@
android:name=".features.attachments.preview.AttachmentsPreviewActivity"
android:theme="@style/Theme.Vector.Black.AttachmentsPreview" />
<activity
android:supportsPictureInPicture="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:name=".features.call.VectorCallActivity"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:taskAffinity=".features.call.VectorCallActivity"
android:excludeFromRecents="true" />
android:supportsPictureInPicture="true"
android:taskAffinity=".features.call.VectorCallActivity" />
<!-- PIP Support https://developer.android.com/guide/topics/ui/picture-in-picture -->
<activity
android:name=".features.call.conference.VectorJitsiActivity"
Expand Down
2 changes: 0 additions & 2 deletions vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ import im.vector.app.features.matrixto.MatrixToBottomSheet
import im.vector.app.features.media.BigImageViewerActivity
import im.vector.app.features.media.VectorAttachmentViewerActivity
import im.vector.app.features.navigation.Navigator
import im.vector.app.features.permalink.PermalinkHandlerActivity
import im.vector.app.features.pin.PinLocker
import im.vector.app.features.qrcode.QrCodeScannerActivity
import im.vector.app.features.rageshake.BugReportActivity
Expand Down Expand Up @@ -153,7 +152,6 @@ interface ScreenComponent {
fun inject(activity: CreateDirectRoomActivity)
fun inject(activity: IncomingShareActivity)
fun inject(activity: SoftLogoutActivity)
fun inject(activity: PermalinkHandlerActivity)
fun inject(activity: QrCodeScannerActivity)
fun inject(activity: DebugMenuActivity)
fun inject(activity: SharedSecureStorageActivity)
Expand Down
27 changes: 5 additions & 22 deletions vector/src/main/java/im/vector/app/features/home/HomeActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -264,35 +264,22 @@ class HomeActivity :
}

private fun handleIntent(intent: Intent?) {
intent?.dataString?.let { deepLink ->
val resolvedLink = when {
deepLink.startsWith(PermalinkService.MATRIX_TO_URL_BASE) -> deepLink
deepLink.startsWith(MATRIX_TO_CUSTOM_SCHEME_URL_BASE) -> {
// This is a bit ugly, but for now just convert to matrix.to link for compatibility
when {
deepLink.startsWith(USER_LINK_PREFIX) -> deepLink.substring(USER_LINK_PREFIX.length)
deepLink.startsWith(ROOM_LINK_PREFIX) -> deepLink.substring(ROOM_LINK_PREFIX.length)
else -> null
}?.let {
activeSessionHolder.getSafeActiveSession()?.permalinkService()?.createPermalink(it)
}
}
else -> return@let
}

intent?.data?.let { deeplink ->
permalinkHandler.launch(
context = this,
deepLink = resolvedLink,
deepLink = deeplink,
navigationInterceptor = this,
buildTask = true
)
// .delay(500, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe { isHandled ->
if (!isHandled) {
val isMatrixToLink = deeplink.toString().startsWith(PermalinkService.MATRIX_TO_URL_BASE)
|| deeplink.toString().startsWith(PermalinkService.MATRIX_TO_CUSTOM_SCHEME_URL_BASE)
MaterialAlertDialogBuilder(this)
.setTitle(R.string.dialog_title_error)
.setMessage(R.string.permalink_malformed)
.setMessage(if (isMatrixToLink) R.string.permalink_malformed else R.string.universal_link_malformed)
.setPositiveButton(R.string.ok, null)
.show()
}
Expand Down Expand Up @@ -559,10 +546,6 @@ class HomeActivity :
putExtra(MvRx.KEY_ARG, args)
}
}

private const val MATRIX_TO_CUSTOM_SCHEME_URL_BASE = "element://"
private const val ROOM_LINK_PREFIX = "${MATRIX_TO_CUSTOM_SCHEME_URL_BASE}room/"
private const val USER_LINK_PREFIX = "${MATRIX_TO_CUSTOM_SCHEME_URL_BASE}user/"
}

override fun create(initialState: ActiveSpaceViewState) = promoteRestrictedViewModelFactory.create(initialState)
Expand Down
Loading

0 comments on commit 3968131

Please sign in to comment.