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

Commit 965db179 authored by Nan Wu's avatar Nan Wu
Browse files

Do not block intetn in a top level ClipData from being launched

If an app that supports drag-and-drop and its drop target performs
launching the intent passed through the ClipData, the intent is
blocked due to missing creator token error. The root cause is the
ClipData.Item.getIntent() method calls maybeMarkAsMissingCreatorToken
even if the ClipData is a top level object passed to the application.
In such case, the ClipData won't go through the collect keys and
add creator token to the intent. But it will be marked as missing
creator token when being launched. To fix it, follow the example of
how we handle intent's extra bundle. Only clipData inside an intent
would be marked as need token verification. And if it is not marked,
do not call maybeMarkAsMissingCreatorToken in Item.getIntent()

Bug: 388879274
Test: ActivityManagerServiceTest#testCanLaunchClipDataIntent
Flag: EXEMPT bug fix
Change-Id: I88a904c96e0cf646dd25070bc12fbc344967feb3
parent a270408a
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -221,6 +221,12 @@ public class ClipData implements Parcelable {
        // if the data is obtained from {@link #copyForTransferWithActivityInfo}
        private ActivityInfo mActivityInfo;

        private boolean mTokenVerificationEnabled;

        void setTokenVerificationEnabled() {
            mTokenVerificationEnabled = true;
        }

        /**
         * A builder for a ClipData Item.
         */
@@ -398,7 +404,9 @@ public class ClipData implements Parcelable {
         * Retrieve the raw Intent contained in this Item.
         */
        public Intent getIntent() {
            if (mTokenVerificationEnabled) {
                Intent.maybeMarkAsMissingCreatorToken(mIntent);
            }
            return mIntent;
        }

@@ -1353,6 +1361,12 @@ public class ClipData implements Parcelable {
        }
    }

    void setTokenVerificationEnabled() {
        for (int i = 0; i < mItems.size(); ++i) {
            mItems.get(i).setTokenVerificationEnabled();
        }
    }

    @Override
    public int describeContents() {
        return 0;
+6 −0
Original line number Diff line number Diff line
@@ -12506,6 +12506,9 @@ public class Intent implements Parcelable, Cloneable {
        if (intent.mExtras != null) {
            intent.mExtras.enableTokenVerification();
        }
        if (intent.mClipData != null) {
            intent.mClipData.setTokenVerificationEnabled();
        }
    };
    /** @hide */
@@ -12517,6 +12520,9 @@ public class Intent implements Parcelable, Cloneable {
            // mark trusted creator token present.
            mExtras.enableTokenVerification();
        }
        if (mClipData != null) {
            mClipData.setTokenVerificationEnabled();
        }
    }
    /** @hide */
+12 −0
Original line number Diff line number Diff line
@@ -1454,6 +1454,18 @@ public class ActivityManagerServiceTest {
        assertThat(tokenForFullIntent.getKeyFields()).isEqualTo(tokenForCloneIntent.getKeyFields());
    }

    @Test
    public void testCanLaunchClipDataIntent() {
        ClipData clipData = ClipData.newIntent("test", new Intent("test"));
        clipData.prepareToLeaveProcess(true);
        // skip mimicking sending clipData to another app because it will just be parceled and
        // un-parceled.
        Intent intent = clipData.getItemAt(0).getIntent();
        // default intent redirect protection won't block an intent nested in a top level ClipData.
        assertThat(intent.getExtendedFlags()
                & Intent.EXTENDED_FLAG_MISSING_CREATOR_OR_INVALID_TOKEN).isEqualTo(0);
    }

    private void verifyWaitingForNetworkStateUpdate(long curProcStateSeq,
            long lastNetworkUpdatedProcStateSeq,
            final long procStateSeqToWait, boolean expectWait) throws Exception {