Strip embedded userId from shared URIs
When screenshot saving images, the userId is explicitly attached to
the resulting URI to support cross-profile actions. This is only
necessary for internal operations and does not need to be present
in the resulting share intent which is already scoped to the target
user.
Bug: 291706486
Test: On pixel, set R.string.config_systemImageEditor to
'com.google.android.apps.photos/.editor.intents.EditActivity'
take screenshot, share, edit -> verify Photos opens
Change-Id: If417620c1aa4a4fc3a4d291a1384e7aff137af5c
This commit is contained in:
@@ -19,6 +19,7 @@ package com.android.systemui.screenshot
|
||||
import android.content.ClipData
|
||||
import android.content.ClipDescription
|
||||
import android.content.ComponentName
|
||||
import android.content.ContentProvider
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
@@ -36,7 +37,9 @@ object ActionIntentCreator {
|
||||
fun createShareWithText(uri: Uri, extraText: String): Intent =
|
||||
createShare(uri, text = extraText)
|
||||
|
||||
private fun createShare(uri: Uri, subject: String? = null, text: String? = null): Intent {
|
||||
private fun createShare(rawUri: Uri, subject: String? = null, text: String? = null): Intent {
|
||||
val uri = uriWithoutUserId(rawUri)
|
||||
|
||||
// Create a share intent, this will always go through the chooser activity first
|
||||
// which should not trigger auto-enter PiP
|
||||
val sharingIntent =
|
||||
@@ -68,7 +71,8 @@ object ActionIntentCreator {
|
||||
* @return an ACTION_EDIT intent for the given URI, directed to config_screenshotEditor if
|
||||
* available.
|
||||
*/
|
||||
fun createEditIntent(uri: Uri, context: Context): Intent {
|
||||
fun createEdit(rawUri: Uri, context: Context): Intent {
|
||||
val uri = uriWithoutUserId(rawUri)
|
||||
val editIntent = Intent(Intent.ACTION_EDIT)
|
||||
|
||||
val editor = context.getString(R.string.config_screenshotEditor)
|
||||
@@ -84,3 +88,12 @@ object ActionIntentCreator {
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* URIs here are passed only via Intent which are sent to the target user via Intent. Because of
|
||||
* this, the userId component can be removed to prevent compatibility issues when an app attempts
|
||||
* valid a URI containing a userId within the authority.
|
||||
*/
|
||||
private fun uriWithoutUserId(uri: Uri): Uri {
|
||||
return ContentProvider.getUriWithoutUserId(uri)
|
||||
}
|
||||
|
||||
@@ -334,7 +334,7 @@ public class LongScreenshotActivity extends Activity {
|
||||
if (mScreenshotUserHandle != Process.myUserHandle()) {
|
||||
// TODO: Fix transition for work profile. Omitting it in the meantime.
|
||||
mActionExecutor.launchIntentAsync(
|
||||
ActionIntentCreator.INSTANCE.createEditIntent(uri, this),
|
||||
ActionIntentCreator.INSTANCE.createEdit(uri, this),
|
||||
null,
|
||||
mScreenshotUserHandle, false);
|
||||
} else {
|
||||
|
||||
@@ -815,7 +815,7 @@ public class ScreenshotView extends FrameLayout implements
|
||||
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_EDIT_TAPPED, 0, mPackageName);
|
||||
prepareSharedTransition();
|
||||
mActionExecutor.launchIntentAsync(
|
||||
ActionIntentCreator.INSTANCE.createEditIntent(imageData.uri, mContext),
|
||||
ActionIntentCreator.INSTANCE.createEdit(imageData.uri, mContext),
|
||||
imageData.editTransition.get().bundle,
|
||||
imageData.owner, true);
|
||||
});
|
||||
@@ -823,7 +823,7 @@ public class ScreenshotView extends FrameLayout implements
|
||||
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_PREVIEW_TAPPED, 0, mPackageName);
|
||||
prepareSharedTransition();
|
||||
mActionExecutor.launchIntentAsync(
|
||||
ActionIntentCreator.INSTANCE.createEditIntent(imageData.uri, mContext),
|
||||
ActionIntentCreator.INSTANCE.createEdit(imageData.uri, mContext),
|
||||
imageData.editTransition.get().bundle,
|
||||
imageData.owner, true);
|
||||
});
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.mockito.Mockito.`when` as whenever
|
||||
class ActionIntentCreatorTest : SysuiTestCase() {
|
||||
|
||||
@Test
|
||||
fun testCreateShareIntent() {
|
||||
fun testCreateShare() {
|
||||
val uri = Uri.parse("content://fake")
|
||||
|
||||
val output = ActionIntentCreator.createShare(uri)
|
||||
@@ -59,7 +59,17 @@ class ActionIntentCreatorTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCreateShareIntentWithSubject() {
|
||||
fun testCreateShare_embeddedUserIdRemoved() {
|
||||
val uri = Uri.parse("content://555@fake")
|
||||
|
||||
val output = ActionIntentCreator.createShare(uri)
|
||||
|
||||
assertThat(output.getParcelableExtra(Intent.EXTRA_INTENT, Intent::class.java))
|
||||
.hasData(Uri.parse("content://fake"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCreateShareWithSubject() {
|
||||
val uri = Uri.parse("content://fake")
|
||||
val subject = "Example subject"
|
||||
|
||||
@@ -83,7 +93,7 @@ class ActionIntentCreatorTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCreateShareIntentWithExtraText() {
|
||||
fun testCreateShareWithText() {
|
||||
val uri = Uri.parse("content://fake")
|
||||
val extraText = "Extra text"
|
||||
|
||||
@@ -107,13 +117,13 @@ class ActionIntentCreatorTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCreateEditIntent() {
|
||||
fun testCreateEdit() {
|
||||
val uri = Uri.parse("content://fake")
|
||||
val context = mock<Context>()
|
||||
|
||||
whenever(context.getString(eq(R.string.config_screenshotEditor))).thenReturn("")
|
||||
|
||||
val output = ActionIntentCreator.createEditIntent(uri, context)
|
||||
val output = ActionIntentCreator.createEdit(uri, context)
|
||||
|
||||
assertThat(output).hasAction(Intent.ACTION_EDIT)
|
||||
assertThat(output).hasData(uri)
|
||||
@@ -129,7 +139,18 @@ class ActionIntentCreatorTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCreateEditIntent_withEditor() {
|
||||
fun testCreateEdit_embeddedUserIdRemoved() {
|
||||
val uri = Uri.parse("content://555@fake")
|
||||
val context = mock<Context>()
|
||||
whenever(context.getString(eq(R.string.config_screenshotEditor))).thenReturn("")
|
||||
|
||||
val output = ActionIntentCreator.createEdit(uri, context)
|
||||
|
||||
assertThat(output).hasData(Uri.parse("content://fake"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCreateEdit_withEditor() {
|
||||
val uri = Uri.parse("content://fake")
|
||||
val context = mock<Context>()
|
||||
val component = ComponentName("com.android.foo", "com.android.foo.Something")
|
||||
@@ -137,7 +158,7 @@ class ActionIntentCreatorTest : SysuiTestCase() {
|
||||
whenever(context.getString(eq(R.string.config_screenshotEditor)))
|
||||
.thenReturn(component.flattenToString())
|
||||
|
||||
val output = ActionIntentCreator.createEditIntent(uri, context)
|
||||
val output = ActionIntentCreator.createEdit(uri, context)
|
||||
|
||||
assertThat(output).hasComponent(component)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user