summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
authorNikita Dubrovsky <dubrovsky@google.com>2021-03-04 16:25:53 -0800
committerNikita Dubrovsky <dubrovsky@google.com>2021-03-25 09:37:21 -0700
commit10646dff7e625aa1de718a692a1bb35c7670a3ca (patch)
treec0f8ed9793942e424d6a88328bcc81f3154a50f6 /core/java
parent4b7b90e79182805dd52fb0b779a0b4ab08983ab0 (diff)
OnReceiveContentListener: Handle IME insertion permissions release
For content insertion from the IME, the platform currently assumes that it can automatically revoke URI permissions (via InputContentUriTokenHandler.finalize) any time after the InputContentInfo instance is garbage collected and InputContentInfo.releasePermission() has not been called explicitly. This can cause permissions to be revoked before the receiving code has had a chance to read the content when using OnReceiveContentListener, since we did not keep a reference to InputContentInfo. This change does the following: * Sets the InputContentInfo instance in the ContentInfo payload passed to OnReceiveContentListener. * Exposes a hidden API on ContentInfo to allow system features to proactively release permissions for sources that allow this (IME and drag-and-drop). * Updates notifications direct-reply code to proactively release permissions as soon as they are no longer needed. Bug: 183643556 Test: Manual Change-Id: I1cbc55d53804810a3cd4b6b97c197f4dd2d7d8e6
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/view/ContentInfo.java53
-rw-r--r--core/java/android/view/View.java6
-rw-r--r--core/java/android/view/inputmethod/BaseInputConnection.java4
-rw-r--r--core/java/android/widget/Editor.java4
4 files changed, 61 insertions, 6 deletions
diff --git a/core/java/android/view/ContentInfo.java b/core/java/android/view/ContentInfo.java
index 547bc9d49380..b55d9b3a1913 100644
--- a/core/java/android/view/ContentInfo.java
+++ b/core/java/android/view/ContentInfo.java
@@ -26,6 +26,7 @@ import android.content.ClipDescription;
import android.net.Uri;
import android.os.Bundle;
import android.util.Pair;
+import android.view.inputmethod.InputContentInfo;
import com.android.internal.util.Preconditions;
@@ -141,6 +142,10 @@ public final class ContentInfo {
private final Uri mLinkUri;
@Nullable
private final Bundle mExtras;
+ @Nullable
+ private final InputContentInfo mInputContentInfo;
+ @Nullable
+ private final DragAndDropPermissions mDragAndDropPermissions;
private ContentInfo(Builder b) {
this.mClip = Objects.requireNonNull(b.mClip);
@@ -149,6 +154,23 @@ public final class ContentInfo {
this.mFlags = Preconditions.checkFlagsArgument(b.mFlags, FLAG_CONVERT_TO_PLAIN_TEXT);
this.mLinkUri = b.mLinkUri;
this.mExtras = b.mExtras;
+ this.mInputContentInfo = b.mInputContentInfo;
+ this.mDragAndDropPermissions = b.mDragAndDropPermissions;
+ }
+
+ /**
+ * If the content came from a source that supports proactive release of URI permissions
+ * (e.g. IME), releases permissions; otherwise a no-op.
+ *
+ * @hide
+ */
+ public void releasePermissions() {
+ if (mInputContentInfo != null) {
+ mInputContentInfo.releasePermission();
+ }
+ if (mDragAndDropPermissions != null) {
+ mDragAndDropPermissions.release();
+ }
}
@NonNull
@@ -275,6 +297,10 @@ public final class ContentInfo {
private Uri mLinkUri;
@Nullable
private Bundle mExtras;
+ @Nullable
+ private InputContentInfo mInputContentInfo;
+ @Nullable
+ private DragAndDropPermissions mDragAndDropPermissions;
/**
* Creates a new builder initialized with the data from the given builder.
@@ -285,6 +311,8 @@ public final class ContentInfo {
mFlags = other.mFlags;
mLinkUri = other.mLinkUri;
mExtras = other.mExtras;
+ mInputContentInfo = other.mInputContentInfo;
+ mDragAndDropPermissions = other.mDragAndDropPermissions;
}
/**
@@ -355,6 +383,31 @@ public final class ContentInfo {
}
/**
+ * Set the {@link InputContentInfo} object if the content is coming from the IME. This can
+ * be used for proactive cleanup of permissions.
+ *
+ * @hide
+ */
+ @NonNull
+ public Builder setInputContentInfo(@Nullable InputContentInfo inputContentInfo) {
+ mInputContentInfo = inputContentInfo;
+ return this;
+ }
+
+ /**
+ * Set the {@link DragAndDropPermissions} object if the content is coming via drag-and-drop.
+ * This can be used for proactive cleanup of permissions.
+ *
+ * @hide
+ */
+ @NonNull
+ public Builder setDragAndDropPermissions(@Nullable DragAndDropPermissions permissions) {
+ mDragAndDropPermissions = permissions;
+ return this;
+ }
+
+
+ /**
* @return A new {@link ContentInfo} instance with the data from this builder.
*/
@NonNull
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7455b8bc3cf3..41112d8f3443 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -26794,8 +26794,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (permissions != null) {
permissions.takeTransient();
}
- final ContentInfo payload = new ContentInfo.Builder(
- event.getClipData(), SOURCE_DRAG_AND_DROP).build();
+ final ContentInfo payload =
+ new ContentInfo.Builder(event.getClipData(), SOURCE_DRAG_AND_DROP)
+ .setDragAndDropPermissions(permissions)
+ .build();
ContentInfo remainingPayload = performReceiveContent(payload);
// Return true unless none of the payload was consumed.
return remainingPayload != payload;
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index 37220fe6870b..163ae37b5de2 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -954,10 +954,10 @@ public class BaseInputConnection implements InputConnection {
}
final ClipData clip = new ClipData(inputContentInfo.getDescription(),
new ClipData.Item(inputContentInfo.getContentUri()));
- final ContentInfo payload =
- new ContentInfo.Builder(clip, SOURCE_INPUT_METHOD)
+ final ContentInfo payload = new ContentInfo.Builder(clip, SOURCE_INPUT_METHOD)
.setLinkUri(inputContentInfo.getLinkUri())
.setExtras(opts)
+ .setInputContentInfo(inputContentInfo)
.build();
return mTargetView.performReceiveContent(payload) == null;
}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index bcbfe37c6904..4a9c2d6c3487 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -2888,8 +2888,8 @@ public class Editor {
final int originalLength = mTextView.getText().length();
Selection.setSelection((Spannable) mTextView.getText(), offset);
final ClipData clip = event.getClipData();
- final ContentInfo payload =
- new ContentInfo.Builder(clip, SOURCE_DRAG_AND_DROP)
+ final ContentInfo payload = new ContentInfo.Builder(clip, SOURCE_DRAG_AND_DROP)
+ .setDragAndDropPermissions(permissions)
.build();
mTextView.performReceiveContent(payload);
if (dragDropIntoItself) {