From 16e67edb366ad9a65d67b473ecc52a2d9e22f060 Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Thu, 10 Nov 2016 00:40:56 -0800 Subject: [PATCH] Fix up content URI for different users Currently Commit Content API work only when the content URI provided by the IME is accessible to the target application. This is non-trivial if the target application is running as a different user (profile) and it is actually a possible scenario when managed profile is enabled. This CL takes care of such a situation, by fixing up the content URI when and only when InputContentInfo#getContentUri() is called from a different user than the owner of the content URI. This CL also makes it clear that we currently do not support content URIs that already have embedded user IDs. Since IActivityManager#grantUriPermissionFromOwner() does not support such URIs, we should have had a special handling for such a case, which will be addressed in a subsequent CL. Bug: 32427307 Bug: 32778718 Test: Made sure that Commit Content API works as expected on a managed profile created by https://github.com/googlesamples/android-testdpc Change-Id: I19d87fc19beea248f49b59ec5a5711b95bcbb466 --- .../view/inputmethod/InputContentInfo.java | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/core/java/android/view/inputmethod/InputContentInfo.java b/core/java/android/view/inputmethod/InputContentInfo.java index b39705e0b1fa6..001f6534c7619 100644 --- a/core/java/android/view/inputmethod/InputContentInfo.java +++ b/core/java/android/view/inputmethod/InputContentInfo.java @@ -18,11 +18,14 @@ package android.view.inputmethod; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.content.ClipDescription; +import android.content.ContentProvider; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; +import android.os.UserHandle; import com.android.internal.inputmethod.IInputContentUriToken; @@ -33,8 +36,21 @@ import java.security.InvalidParameterException; */ public final class InputContentInfo implements Parcelable { + /** + * The content URI that never has a user ID embedded by + * {@link ContentProvider#maybeAddUserId(Uri, int)}. + */ @NonNull private final Uri mContentUri; + /** + * The user ID to which {@link #mContentUri} belongs to. This is always determined based on + * the process ID when the constructor is called. + * + *

CAUTION: If you received {@link InputContentInfo} from a different process, there is no + * guarantee that this value is correct and valid. Never use this for any security purpose

+ */ + @UserIdInt + private final int mContentUriOwnerUserId; @NonNull private final ClipDescription mDescription; @Nullable @@ -73,6 +89,7 @@ public final class InputContentInfo implements Parcelable { @Nullable Uri linkUri) { validateInternal(contentUri, description, linkUri, true /* throwException */); mContentUri = contentUri; + mContentUriOwnerUserId = UserHandle.myUserId(); mDescription = description; mLinkUri = linkUri; } @@ -121,6 +138,13 @@ public final class InputContentInfo implements Parcelable { } return false; } + if (ContentProvider.uriHasUserId(contentUri)) { + if (throwException) { + throw new InvalidParameterException( + "contentUri with a user ID is not currently supported"); + } + return false; + } if (linkUri != null) { final String scheme = linkUri.getScheme(); if (scheme == null || @@ -139,7 +163,14 @@ public final class InputContentInfo implements Parcelable { * @return Content URI with which the content can be obtained. */ @NonNull - public Uri getContentUri() { return mContentUri; } + public Uri getContentUri() { + // Fix up the content URI when and only when the caller's user ID does not match the owner's + // user ID. + if (mContentUriOwnerUserId != UserHandle.myUserId()) { + return ContentProvider.maybeAddUserId(mContentUri, mContentUriOwnerUserId); + } + return mContentUri; + } /** * @return {@link ClipDescription} object that contains the metadata of {@code #getContentUri()} @@ -203,6 +234,7 @@ public final class InputContentInfo implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { Uri.writeToParcel(dest, mContentUri); + dest.writeInt(mContentUriOwnerUserId); mDescription.writeToParcel(dest, flags); Uri.writeToParcel(dest, mLinkUri); if (mUriToken != null) { @@ -215,6 +247,7 @@ public final class InputContentInfo implements Parcelable { private InputContentInfo(@NonNull Parcel source) { mContentUri = Uri.CREATOR.createFromParcel(source); + mContentUriOwnerUserId = source.readInt(); mDescription = ClipDescription.CREATOR.createFromParcel(source); mLinkUri = Uri.CREATOR.createFromParcel(source); if (source.readInt() == 1) {