Prevent sharesheet from previewing unowned URIs [RESTRICT AUTOMERGE] (corrected)

This is the corrected cherry-pick of
2a08fce4eb from master.

Bug: 261036568
Test: manually via supplied tool (see bug)
Change-Id: I1ac57c8eb2f509b19c278aacb8e88772095854f7
Merged-In: I83e93c373538460e38ec17f1fd8e39d7aea95c10
This commit is contained in:
Mark Renouf
2023-03-30 21:46:28 -04:00
parent 2864439551
commit 4b0f6503cc

View File

@@ -21,6 +21,7 @@ import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT
import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_PERSONAL; import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_PERSONAL;
import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_WORK; import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_WORK;
import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CROSS_PROFILE_BLOCKED_TITLE; import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CROSS_PROFILE_BLOCKED_TITLE;
import static android.content.ContentProvider.getUserIdFromUri;
import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL; import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL;
import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK; import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK;
@@ -161,6 +162,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors;
/** /**
* The Chooser Activity handles intent resolution specifically for sharing intents - * The Chooser Activity handles intent resolution specifically for sharing intents -
@@ -1395,7 +1397,7 @@ public class ChooserActivity extends ResolverActivity implements
ImageView previewThumbnailView = contentPreviewLayout.findViewById( ImageView previewThumbnailView = contentPreviewLayout.findViewById(
R.id.content_preview_thumbnail); R.id.content_preview_thumbnail);
if (previewThumbnail == null) { if (!validForContentPreview(previewThumbnail)) {
previewThumbnailView.setVisibility(View.GONE); previewThumbnailView.setVisibility(View.GONE);
} else { } else {
mPreviewCoord = new ContentPreviewCoordinator(contentPreviewLayout, false); mPreviewCoord = new ContentPreviewCoordinator(contentPreviewLayout, false);
@@ -1425,6 +1427,10 @@ public class ChooserActivity extends ResolverActivity implements
String action = targetIntent.getAction(); String action = targetIntent.getAction();
if (Intent.ACTION_SEND.equals(action)) { if (Intent.ACTION_SEND.equals(action)) {
Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM); Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM);
if (!validForContentPreview(uri)) {
contentPreviewLayout.setVisibility(View.GONE);
return contentPreviewLayout;
}
imagePreview.findViewById(R.id.content_preview_image_1_large) imagePreview.findViewById(R.id.content_preview_image_1_large)
.setTransitionName(ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME); .setTransitionName(ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
mPreviewCoord.loadUriIntoView(R.id.content_preview_image_1_large, uri, 0); mPreviewCoord.loadUriIntoView(R.id.content_preview_image_1_large, uri, 0);
@@ -1434,7 +1440,7 @@ public class ChooserActivity extends ResolverActivity implements
List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
List<Uri> imageUris = new ArrayList<>(); List<Uri> imageUris = new ArrayList<>();
for (Uri uri : uris) { for (Uri uri : uris) {
if (isImageType(resolver.getType(uri))) { if (validForContentPreview(uri) && isImageType(resolver.getType(uri))) {
imageUris.add(uri); imageUris.add(uri);
} }
} }
@@ -1544,9 +1550,16 @@ public class ChooserActivity extends ResolverActivity implements
String action = targetIntent.getAction(); String action = targetIntent.getAction();
if (Intent.ACTION_SEND.equals(action)) { if (Intent.ACTION_SEND.equals(action)) {
Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM); Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM);
if (!validForContentPreview(uri)) {
contentPreviewLayout.setVisibility(View.GONE);
return contentPreviewLayout;
}
loadFileUriIntoView(uri, contentPreviewLayout); loadFileUriIntoView(uri, contentPreviewLayout);
} else { } else {
List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
uris = uris.stream()
.filter(ChooserActivity::validForContentPreview)
.collect(Collectors.toList());
int uriCount = uris.size(); int uriCount = uris.size();
if (uriCount == 0) { if (uriCount == 0) {
@@ -1605,6 +1618,24 @@ public class ChooserActivity extends ResolverActivity implements
} }
} }
/**
* Indicate if the incoming content URI should be allowed.
*
* @param uri the uri to test
* @return true if the URI is allowed for content preview
*/
private static boolean validForContentPreview(Uri uri) throws SecurityException {
if (uri == null) {
return false;
}
int userId = getUserIdFromUri(uri, UserHandle.USER_CURRENT);
if (userId != UserHandle.USER_CURRENT && userId != UserHandle.myUserId()) {
Log.e(TAG, "dropped invalid content URI belonging to user " + userId);
return false;
}
return true;
}
@VisibleForTesting @VisibleForTesting
protected boolean isImageType(String mimeType) { protected boolean isImageType(String mimeType) {
return mimeType != null && mimeType.startsWith("image/"); return mimeType != null && mimeType.startsWith("image/");