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

Commit 48086605 authored by Shafik Nassar's avatar Shafik Nassar Committed by Android (Google) Code Review
Browse files

Merge "Mitigate Intent Capturing vulnerability"

parents b88c7977 69df9632
Loading
Loading
Loading
Loading
+96 −22
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@ public class ResolverActivity extends Activity {
    private AbsListView mAdapterView;
    private Button mAlwaysButton;
    private Button mOnceButton;
    private Button mSettingsButton;
    private View mProfileView;
    private int mIconDpi;
    private int mLastSelected = AbsListView.INVALID_POSITION;
@@ -112,6 +113,7 @@ public class ResolverActivity extends Activity {
    private String mReferrerPackage;
    private CharSequence mTitle;
    private int mDefaultTitleResId;
    private boolean mUseLayoutForBrowsables;

    // Whether or not this activity supports choosing a default handler for the intent.
    private boolean mSupportsAlwaysUseOption;
@@ -192,6 +194,12 @@ public class ResolverActivity extends Activity {
                com.android.internal.R.string.whichHomeApplicationNamed,
                com.android.internal.R.string.whichHomeApplicationLabel);

        // SpR.id.buttonecial titles for BROWSABLE components
        public static final int BROWSABLE_TITLE_RES =
                com.android.internal.R.string.whichGiveAccessToApplication;
        public static final int BROWSABLE_NAMED_TITLE_RES =
                com.android.internal.R.string.whichGiveAccessToApplicationNamed;

        public final String action;
        public final int titleRes;
        public final int namedTitleRes;
@@ -283,7 +291,6 @@ public class ResolverActivity extends Activity {
        mPackageMonitor.register(this, getMainLooper(), false);
        mRegistered = true;
        mReferrerPackage = getReferrerPackageName();
        mSupportsAlwaysUseOption = supportsAlwaysUseOption;

        final ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        mIconDpi = am.getLauncherLargeIconDensity();
@@ -293,6 +300,14 @@ public class ResolverActivity extends Activity {
        mTitle = title;
        mDefaultTitleResId = defaultTitleRes;

        mUseLayoutForBrowsables = getTargetIntent() == null
                ? false
                : getTargetIntent().hasCategory(Intent.CATEGORY_BROWSABLE);

        // We don't want to support Always Use if browsable layout is being used,
        // as to mitigate Intent Capturing vulnerability
        mSupportsAlwaysUseOption = supportsAlwaysUseOption && !mUseLayoutForBrowsables;

        mIconFactory = IconDrawableFactory.newInstance(this, true);
        if (configureContentView(mIntents, initialIntents, rList)) {
            return;
@@ -448,13 +463,23 @@ public class ResolverActivity extends Activity {
        mSafeForwardingMode = safeForwarding;
    }

    protected CharSequence getTitleForAction(String action, int defaultTitleRes) {
        final ActionTitle title = mResolvingHome ? ActionTitle.HOME : ActionTitle.forAction(action);
    protected CharSequence getTitleForAction(Intent intent, int defaultTitleRes) {
        final ActionTitle title = mResolvingHome
                ? ActionTitle.HOME
                : ActionTitle.forAction(intent.getAction());

        // While there may already be a filtered item, we can only use it in the title if the list
        // is already sorted and all information relevant to it is already in the list.
        final boolean named = mAdapter.getFilteredPosition() >= 0;
        if (title == ActionTitle.DEFAULT && defaultTitleRes != 0) {
            return getString(defaultTitleRes);
        } else if (intent.hasCategory(Intent.CATEGORY_BROWSABLE)) {
            // If the Intent is BROWSABLE then we need to warn the user that
            // they're giving access for the activity to open URLs from this specific host
            return named
                    ? getString(ActionTitle.BROWSABLE_NAMED_TITLE_RES, intent.getData().getHost(),
                    mAdapter.getFilteredItem().getDisplayLabel())
                    : getString(ActionTitle.BROWSABLE_TITLE_RES, intent.getData().getHost());
        } else {
            return named
                    ? getString(title.namedTitleRes, mAdapter.getFilteredItem().getDisplayLabel())
@@ -555,7 +580,7 @@ public class ResolverActivity extends Activity {
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        resetAlwaysOrOnceButtonBar();
        resetButtonBar();
    }

    private boolean hasManagedProfile() {
@@ -607,11 +632,23 @@ public class ResolverActivity extends Activity {

    public void onButtonClick(View v) {
        final int id = v.getId();
        startSelected(mAdapter.hasFilteredItem() ?
                        mAdapter.getFilteredPosition():
                        mAdapterView.getCheckedItemPosition(),
                id == R.id.button_always,
                !mAdapter.hasFilteredItem());
        int which = mAdapter.hasFilteredItem()
                ? mAdapter.getFilteredPosition()
                : mAdapterView.getCheckedItemPosition();
        boolean hasIndexBeenFiltered = !mAdapter.hasFilteredItem();
        if (id == R.id.button_app_settings) {
            showSettingsForSelected(which, hasIndexBeenFiltered);
        } else {
            startSelected(which, id == R.id.button_always, hasIndexBeenFiltered);
        }
    }

    private void showSettingsForSelected(int which, boolean hasIndexBeenFiltered) {
        ResolveInfo ri = mAdapter.resolveInfoForPosition(which, hasIndexBeenFiltered);
        Intent in = new Intent().setAction(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS)
                .setData(Uri.fromParts("package", ri.activityInfo.packageName, null))
                .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
        startActivity(in);
    }

    public void startSelected(int which, boolean always, boolean hasIndexBeenFiltered) {
@@ -995,7 +1032,7 @@ public class ResolverActivity extends Activity {
        adapterView.setOnItemClickListener(listener);
        adapterView.setOnItemLongClickListener(listener);

        if (mSupportsAlwaysUseOption) {
        if (mSupportsAlwaysUseOption || mUseLayoutForBrowsables) {
            listView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
        }

@@ -1017,7 +1054,7 @@ public class ResolverActivity extends Activity {

        CharSequence title = mTitle != null
                ? mTitle
                : getTitleForAction(getTargetIntent().getAction(), mDefaultTitleResId);
                : getTitleForAction(getTargetIntent(), mDefaultTitleResId);

        if (!TextUtils.isEmpty(title)) {
            final TextView titleView = findViewById(R.id.title);
@@ -1051,18 +1088,49 @@ public class ResolverActivity extends Activity {
        }
    }

    public void resetAlwaysOrOnceButtonBar() {
        if (mSupportsAlwaysUseOption) {
    private void resetButtonBar() {
        if (!mSupportsAlwaysUseOption && !mUseLayoutForBrowsables) {
            return;
        }
        final ViewGroup buttonLayout = findViewById(R.id.button_bar);
        if (buttonLayout != null) {
            buttonLayout.setVisibility(View.VISIBLE);
                mAlwaysButton = (Button) buttonLayout.findViewById(R.id.button_always);
            mOnceButton = (Button) buttonLayout.findViewById(R.id.button_once);
            mSettingsButton = (Button) buttonLayout.findViewById(R.id.button_app_settings);
            mAlwaysButton = (Button) buttonLayout.findViewById(R.id.button_always);

            if (mUseLayoutForBrowsables) {
                resetSettingsOrOnceButtonBar();
            } else {
                resetAlwaysOrOnceButtonBar();
            }
        } else {
            Log.e(TAG, "Layout unexpectedly does not have a button bar");
        }
    }

    private void resetSettingsOrOnceButtonBar() {
        //unsetting always button
        mAlwaysButton.setVisibility(View.GONE);

        // When the items load in, if an item was already selected,
        // enable the buttons
        if (mAdapterView != null
                && mAdapterView.getCheckedItemPosition() != ListView.INVALID_POSITION) {
            mSettingsButton.setEnabled(true);
            mOnceButton.setEnabled(true);
        }
    }

    private void resetAlwaysOrOnceButtonBar() {
        // This check needs to be made because layout with default
        // doesn't have a settings button
        if (mSettingsButton != null) {
            //unsetting always button
            mSettingsButton.setVisibility(View.GONE);
            mSettingsButton = null;
        }

        if (useLayoutWithDefault()
                && mAdapter.getFilteredPosition() != ListView.INVALID_POSITION) {
            setAlwaysButtonEnabled(true, mAdapter.getFilteredPosition(), false);
@@ -1625,7 +1693,7 @@ public class ResolverActivity extends Activity {
                    @Override
                    public void run() {
                        setTitleAndIcon();
                        resetAlwaysOrOnceButtonBar();
                        resetButtonBar();
                        onListRebuilt();
                        mPostListReadyRunnable = null;
                    }
@@ -1986,8 +2054,14 @@ public class ResolverActivity extends Activity {
            final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION;
            if (!useLayoutWithDefault()
                    && (!hasValidSelection || mLastSelected != checkedPos)
                    && mAlwaysButton != null) {
                    && (mAlwaysButton != null || mSettingsButton != null)) {
                if (mSettingsButton != null) {
                    // this implies that the layout for browsables is being used
                    mSettingsButton.setEnabled(true);
                } else {
                    // this implies that mAlwaysButton != null
                    setAlwaysButtonEnabled(hasValidSelection, checkedPos, true);
                }
                mOnceButton.setEnabled(hasValidSelection);
                if (hasValidSelection) {
                    mAdapterView.smoothScrollToPosition(checkedPos);
+12 −0
Original line number Diff line number Diff line
@@ -129,6 +129,18 @@
            android:enabled="false"
            android:text="@string/activity_resolver_use_always"
            android:onClick="onButtonClick" />

        <Button
            android:id="@+id/button_app_settings"
            android:layout_width="wrap_content"
            android:layout_gravity="end"
            android:maxLines="2"
            android:minHeight="@dimen/alert_dialog_button_bar_height"
            style="?attr/buttonBarPositiveButtonStyle"
            android:layout_height="wrap_content"
            android:enabled="false"
            android:text="@string/activity_resolver_app_settings"
            android:onClick="onButtonClick" />
    </LinearLayout>

</com.android.internal.widget.ResolverDrawerLayout>
+12 −0
Original line number Diff line number Diff line
@@ -3066,6 +3066,14 @@
    <string name="whichViewApplicationNamed">Open with %1$s</string>
    <!-- Label for a link to a intent resolver dialog to view something -->
    <string name="whichViewApplicationLabel">Open</string>
    <!-- Title of intent resolver dialog when selecting a viewer application that opens URI
         [CHAR LIMIT=128]. -->
    <string name="whichGiveAccessToApplication">Give access to open <xliff:g id="host" example="mail.google.com">%1$s</xliff:g> links with</string>
    <!-- Title of intent resolver dialog when selecting a viewer application that opens URI
         and a previously used application is known [CHAR LIMIT=128]. -->
    <string name="whichGiveAccessToApplicationNamed">Give access to open <xliff:g id="host" example="mail.google.com">%1$s</xliff:g> links with <xliff:g id="application" example="Gmail">%2$s</xliff:g></string>
    <!-- Label for a link to an intent resolver dialog to open URI [CHAR LIMIT=16] -->
    <string name="whichGiveAccessToApplicationLabel">Give access</string>
    <!-- Title of intent resolver dialog when selecting an editor application to run. -->
    <string name="whichEditApplication">Edit with</string>
    <!-- Title of intent resolver dialog when selecting an editor application to run
@@ -4156,6 +4164,10 @@
         from the activity resolver to use just this once. [CHAR LIMIT=25] -->
    <string name="activity_resolver_use_once">Just once</string>

    <!-- Title for a button to choose to go to
          'Open by Default' app settings. [CHAR LIMIT=25] -->
    <string name="activity_resolver_app_settings">Settings</string>

    <!-- Text for the toast that is shown when the user clicks on a launcher that
         doesn't support the work profile. [CHAR LIMIT=100] -->
    <string name="activity_resolver_work_profiles_support">%1$s doesn\'t support work profile</string>
+5 −0
Original line number Diff line number Diff line
@@ -2144,6 +2144,7 @@
  <java-symbol type="id" name="resolver_list" />
  <java-symbol type="id" name="button_once" />
  <java-symbol type="id" name="button_always" />
  <java-symbol type="id" name="button_app_settings" />
  <java-symbol type="integer" name="config_globalActionsKeyTimeout" />
  <java-symbol type="integer" name="config_maxResolverActivityColumns" />
  <java-symbol type="array" name="config_notificationSignalExtractors" />
@@ -2499,11 +2500,15 @@
  <java-symbol type="bool" name="config_use_voip_mode_for_ims" />
  <java-symbol type="attr" name="touchscreenBlocksFocus" />
  <java-symbol type="layout" name="resolver_list_with_default" />
  <java-symbol type="string" name="activity_resolver_app_settings" />
  <java-symbol type="string" name="whichApplicationNamed" />
  <java-symbol type="string" name="whichApplicationLabel" />
  <java-symbol type="string" name="whichViewApplication" />
  <java-symbol type="string" name="whichViewApplicationNamed" />
  <java-symbol type="string" name="whichViewApplicationLabel" />
  <java-symbol type="string" name="whichGiveAccessToApplication" />
  <java-symbol type="string" name="whichGiveAccessToApplicationNamed" />
  <java-symbol type="string" name="whichGiveAccessToApplicationLabel" />
  <java-symbol type="string" name="whichEditApplication" />
  <java-symbol type="string" name="whichEditApplicationNamed" />
  <java-symbol type="string" name="whichEditApplicationLabel" />