From c449f727866a9edeb2f83ddd102868ff91fec0ce Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Fri, 10 Apr 2026 16:17:41 -0400 Subject: [PATCH] Allow internal shares as long as they originate from our process. --- .../securesms/mediapreview/MediaPreviewV2Fragment.kt | 7 +++++++ .../securesms/sharing/v2/ShareActivity.kt | 8 ++++++-- .../securesms/sharing/v2/ShareRepository.kt | 4 ++-- .../securesms/sharing/v2/UnresolvedShareData.kt | 4 ++-- .../securesms/stories/dialogs/StoryContextMenu.kt | 11 ++++++++++- 5 files changed, 27 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediapreview/MediaPreviewV2Fragment.kt b/app/src/main/java/org/thoughtcrime/securesms/mediapreview/MediaPreviewV2Fragment.kt index 36fa4c1345..c83b9ec812 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediapreview/MediaPreviewV2Fragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/mediapreview/MediaPreviewV2Fragment.kt @@ -2,10 +2,12 @@ package org.thoughtcrime.securesms.mediapreview import android.annotation.SuppressLint import android.content.ActivityNotFoundException +import android.content.ComponentName import android.content.Context import android.content.Intent import android.graphics.PorterDuff import android.graphics.PorterDuffColorFilter +import android.os.Build import android.os.Bundle import android.text.Annotation import android.text.SpannableString @@ -67,6 +69,7 @@ import org.thoughtcrime.securesms.mediapreview.mediarail.MediaRailAdapter.ImageL import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionActivity import org.thoughtcrime.securesms.mms.PartAuthority import org.thoughtcrime.securesms.recipients.Recipient +import org.thoughtcrime.securesms.sharing.v2.ShareActivity import org.thoughtcrime.securesms.util.ContextUtil import org.thoughtcrime.securesms.util.DateUtils import org.thoughtcrime.securesms.util.Debouncer @@ -578,6 +581,10 @@ class MediaPreviewV2Fragment : .createChooserIntent() .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + if (Build.VERSION.SDK_INT < 34) { + shareIntent.putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, arrayOf(ComponentName(requireContext(), ShareActivity::class.java))) + } + try { startActivity(shareIntent) } catch (e: ActivityNotFoundException) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/sharing/v2/ShareActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/sharing/v2/ShareActivity.kt index a53e6ba5b0..016525f178 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/sharing/v2/ShareActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/sharing/v2/ShareActivity.kt @@ -4,7 +4,9 @@ import android.app.Activity import android.content.Context import android.content.Intent import android.net.Uri +import android.os.Build import android.os.Bundle +import android.os.Process import android.view.ViewGroup import android.widget.Toast import androidx.activity.result.ActivityResultLauncher @@ -194,12 +196,14 @@ class ShareActivity : PassphraseRequiredActivity(), MultiselectForwardFragment.C override fun getDialogBackgroundColor(): Int = ContextCompat.getColor(this, R.color.signal_background_primary) private fun getUnresolvedShareData(): Result { + val isInternalShare = Build.VERSION.SDK_INT >= 34 && getLaunchedFromUid() == Process.myUid() + return when (intent.action) { Intent.ACTION_SEND_MULTIPLE if intent.hasExtra(Intent.EXTRA_STREAM) -> { intent.getParcelableArrayListExtraCompat(Intent.EXTRA_STREAM, Uri::class.java)?.let { uris -> val text: CharSequence? = intent.getCharSequenceArrayListExtra(Intent.EXTRA_TEXT) ?.let { textExtras -> combineTextExtras(textExtras) } - Result.success(UnresolvedShareData.ExternalMultiShare(uris, text)) + Result.success(UnresolvedShareData.ExternalMultiShare(uris, text, isInternalShare)) } ?: Result.failure(IntentError.SEND_MULTIPLE_STREAM) } @@ -215,7 +219,7 @@ class ShareActivity : PassphraseRequiredActivity(), MultiselectForwardFragment.C extractSingleExtraTextFromIntent(IntentError.SEND_STREAM) } else { val text: CharSequence? = if (intent.hasExtra(Intent.EXTRA_TEXT)) intent.getCharSequenceExtra(Intent.EXTRA_TEXT) else null - Result.success(UnresolvedShareData.ExternalSingleShare(uri, intent.type, text)) + Result.success(UnresolvedShareData.ExternalSingleShare(uri, intent.type, text, isInternalShare)) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/sharing/v2/ShareRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/sharing/v2/ShareRepository.kt index 6a382062a5..f85018ca83 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/sharing/v2/ShareRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/sharing/v2/ShareRepository.kt @@ -32,7 +32,7 @@ class ShareRepository(context: Context) { @WorkerThread @Throws(IOException::class) private fun resolve(multiShareExternal: UnresolvedShareData.ExternalSingleShare): ResolvedShareData { - if (!UriUtil.isValidExternalUri(appContext, multiShareExternal.uri)) { + if (!multiShareExternal.isInternalShare && !UriUtil.isValidExternalUri(appContext, multiShareExternal.uri)) { return ResolvedShareData.Failure } @@ -70,7 +70,7 @@ class ShareRepository(context: Context) { @WorkerThread private fun resolve(externalMultiShare: UnresolvedShareData.ExternalMultiShare): ResolvedShareData { val mimeTypes: Map = externalMultiShare.uris - .filter { UriUtil.isValidExternalUri(appContext, it) } + .filter { externalMultiShare.isInternalShare || UriUtil.isValidExternalUri(appContext, it) } .associateWith { uri -> getMimeType(appContext, uri, null) } .filterValues { MediaUtil.isImageType(it) || MediaUtil.isVideoType(it) diff --git a/app/src/main/java/org/thoughtcrime/securesms/sharing/v2/UnresolvedShareData.kt b/app/src/main/java/org/thoughtcrime/securesms/sharing/v2/UnresolvedShareData.kt index fbbc14fb3c..2735af2698 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/sharing/v2/UnresolvedShareData.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/sharing/v2/UnresolvedShareData.kt @@ -3,7 +3,7 @@ package org.thoughtcrime.securesms.sharing.v2 import android.net.Uri sealed class UnresolvedShareData { - data class ExternalMultiShare(val uris: List, val text: CharSequence?) : UnresolvedShareData() - data class ExternalSingleShare(val uri: Uri, val mimeType: String?, val text: CharSequence?) : UnresolvedShareData() + data class ExternalMultiShare(val uris: List, val text: CharSequence?, val isInternalShare: Boolean = false) : UnresolvedShareData() + data class ExternalSingleShare(val uri: Uri, val mimeType: String?, val text: CharSequence?, val isInternalShare: Boolean = false) : UnresolvedShareData() data class ExternalPrimitiveShare(val text: CharSequence) : UnresolvedShareData() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/stories/dialogs/StoryContextMenu.kt b/app/src/main/java/org/thoughtcrime/securesms/stories/dialogs/StoryContextMenu.kt index 3b7a3ae88d..74d398c001 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/stories/dialogs/StoryContextMenu.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/stories/dialogs/StoryContextMenu.kt @@ -1,9 +1,11 @@ package org.thoughtcrime.securesms.stories.dialogs import android.content.ActivityNotFoundException +import android.content.ComponentName import android.content.Context import android.content.Intent import android.net.Uri +import android.os.Build import android.view.View import android.view.ViewGroup import android.widget.Toast @@ -26,6 +28,7 @@ import org.thoughtcrime.securesms.database.model.MessageRecord import org.thoughtcrime.securesms.database.model.MmsMessageRecord import org.thoughtcrime.securesms.database.model.databaseprotos.StoryTextPost import org.thoughtcrime.securesms.providers.BlobProvider +import org.thoughtcrime.securesms.sharing.v2.ShareActivity import org.thoughtcrime.securesms.stories.StoryTextPostModel import org.thoughtcrime.securesms.stories.landing.StoriesLandingItem import org.thoughtcrime.securesms.stories.viewer.page.StoryPost @@ -118,11 +121,17 @@ object StoryContextMenu { } else { val attachment: Attachment = messageRecord.slideDeck.firstSlide!!.asAttachment() - ShareCompat.IntentBuilder(fragment.requireContext()) + val chooserIntent = ShareCompat.IntentBuilder(fragment.requireContext()) .setStream(attachment.publicUri) .setType(attachment.contentType) .createChooserIntent() .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + + if (Build.VERSION.SDK_INT < 34) { + chooserIntent.putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, arrayOf(ComponentName(fragment.requireContext(), ShareActivity::class.java))) + } + + chooserIntent } try {