Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a74e729f authored by Vladislav Kaznacheev's avatar Vladislav Kaznacheev Committed by Android (Google) Code Review
Browse files

Merge "Fix SecurityException in Editor.onDrop"

parents 05a7dfc4 c14df8e7
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -17,11 +17,14 @@
package android.content;

import static android.content.ContentProvider.maybeAddUserId;

import android.content.pm.PackageManager;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Process;
import android.os.StrictMode;
import android.text.Html;
import android.text.Spannable;
@@ -462,7 +465,12 @@ public class ClipData implements Parcelable {
                // Check to see what data representations the content
                // provider supports.  We would like HTML text, but if that
                // is not possible we'll live with plan text.
                String[] types = context.getContentResolver().getStreamTypes(mUri, "text/*");
                String[] types = null;
                try {
                    types = context.getContentResolver().getStreamTypes(mUri, "text/*");
                } catch (SecurityException e) {
                    // No read permission for mUri, assume empty stream types list.
                }
                boolean hasHtml = false;
                boolean hasText = false;
                if (types != null) {
+21 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.view;

import android.app.ActivityManagerNative;
import android.os.IBinder;
import android.os.RemoteException;
import com.android.internal.view.IDropPermissions;
@@ -41,6 +42,8 @@ public final class DropPermissions {

    private final IDropPermissions mDropPermissions;

    private IBinder mPermissionOwnerToken;

    private final CloseGuard mCloseGuard = CloseGuard.get();

    /**
@@ -79,12 +82,30 @@ public final class DropPermissions {
        return true;
    }

    /**
     * Take the permissions. Must call {@link #release} explicitly.
     * @return True if permissions are successfully taken.
     * @hide
     */
    public boolean takeTransient() {
        try {
            mPermissionOwnerToken = ActivityManagerNative.getDefault().
                    newUriPermissionOwner("drop");
            mDropPermissions.takeTransient(mPermissionOwnerToken);
        } catch (RemoteException e) {
            return false;
        }
        mCloseGuard.open("release");
        return true;
    }

    /**
     * Revoke permissions explicitly.
     */
    public void release() {
        try {
            mDropPermissions.release();
            mPermissionOwnerToken = null;
        } catch (RemoteException e) {
        }
        mCloseGuard.close();
+19 −5
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ import android.view.ActionMode.Callback;
import android.view.ContextMenu;
import android.view.DisplayListCanvas;
import android.view.DragEvent;
import android.view.DropPermissions;
import android.view.Gravity;
import android.view.InputDevice;
import android.view.LayoutInflater;
@@ -2298,12 +2299,25 @@ public class Editor {

    void onDrop(DragEvent event) {
        StringBuilder content = new StringBuilder("");

        final DropPermissions dropPermissions = DropPermissions.obtain(event);
        if (dropPermissions != null) {
            dropPermissions.takeTransient();
        }

        try {
            ClipData clipData = event.getClipData();
            final int itemCount = clipData.getItemCount();
            for (int i=0; i < itemCount; i++) {
                Item item = clipData.getItemAt(i);
                content.append(item.coerceToStyledText(mTextView.getContext()));
            }
        }
        finally {
            if (dropPermissions != null) {
                dropPermissions.release();
            }
        }

        final int offset = mTextView.getOffsetForPosition(event.getX(), event.getY());

+1 −0
Original line number Diff line number Diff line
@@ -24,5 +24,6 @@ import android.os.IBinder;
 */
interface IDropPermissions {
    void take(IBinder activityToken);
    void takeTransient(IBinder permissionOwnerToken);
    void release();
}
+42 −11
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ import com.android.internal.view.IDropPermissions;

import java.util.ArrayList;

class DropPermissionsHandler extends IDropPermissions.Stub {
class DropPermissionsHandler extends IDropPermissions.Stub implements IBinder.DeathRecipient {

    private final int mSourceUid;
    private final String mTargetPackage;
@@ -38,6 +38,7 @@ class DropPermissionsHandler extends IDropPermissions.Stub {
    private final ArrayList<Uri> mUris = new ArrayList<Uri>();

    private IBinder mActivityToken = null;
    private IBinder mPermissionOwnerToken = null;

    DropPermissionsHandler(ClipData clipData, int sourceUid, String targetPackage, int mode,
            int sourceUserId, int targetUserId) {
@@ -52,7 +53,7 @@ class DropPermissionsHandler extends IDropPermissions.Stub {

    @Override
    public void take(IBinder activityToken) throws RemoteException {
        if (mActivityToken != null) {
        if (mActivityToken != null || mPermissionOwnerToken != null) {
            return;
        }
        mActivityToken = activityToken;
@@ -61,6 +62,10 @@ class DropPermissionsHandler extends IDropPermissions.Stub {
        IBinder permissionOwner = ActivityManagerNative.getDefault().
                getUriPermissionOwnerForActivity(mActivityToken);

        doTake(permissionOwner);
    }

    private void doTake(IBinder permissionOwner) throws RemoteException {
        long origId = Binder.clearCallingIdentity();
        try {
            for (int i = 0; i < mUris.size(); i++) {
@@ -73,13 +78,25 @@ class DropPermissionsHandler extends IDropPermissions.Stub {
        }
    }

    @Override
    public void takeTransient(IBinder permissionOwnerToken) throws RemoteException {
        if (mActivityToken != null || mPermissionOwnerToken != null) {
            return;
        }
        mPermissionOwnerToken = permissionOwnerToken;
        mPermissionOwnerToken.linkToDeath(this, 0);

        doTake(mPermissionOwnerToken);
    }

    @Override
    public void release() throws RemoteException {
        if (mActivityToken == null) {
        if (mActivityToken == null && mPermissionOwnerToken == null) {
            return;
        }

        IBinder permissionOwner = null;
        if (mActivityToken != null) {
            try {
                permissionOwner = ActivityManagerNative.getDefault().
                        getUriPermissionOwnerForActivity(mActivityToken);
@@ -89,10 +106,24 @@ class DropPermissionsHandler extends IDropPermissions.Stub {
            } finally {
                mActivityToken = null;
            }
        } else {
            permissionOwner = mPermissionOwnerToken;
            mPermissionOwnerToken.unlinkToDeath(this, 0);
            mPermissionOwnerToken = null;
        }

        for (int i = 0; i < mUris.size(); ++i) {
            ActivityManagerNative.getDefault().revokeUriPermissionFromOwner(
                    permissionOwner, mUris.get(i), mMode, mSourceUserId);
        }
    }

    @Override
    public void binderDied() {
        try {
            release();
        } catch (RemoteException e) {
            // Cannot happen, local call.
        }
    }
}