Merge "Resolver - Improve flow for Intent URL handling" into qt-dev

This commit is contained in:
Matt Pietal
2019-06-28 12:02:04 +00:00
committed by Android (Google) Code Review
4 changed files with 90 additions and 79 deletions

View File

@@ -29,7 +29,6 @@ import android.app.ActivityThread;
import android.app.VoiceInteractor.PickOptionRequest;
import android.app.VoiceInteractor.PickOptionRequest.Option;
import android.app.VoiceInteractor.Prompt;
import android.app.role.RoleManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -111,7 +110,6 @@ public class ResolverActivity extends Activity {
protected AbsListView mAdapterView;
private Button mAlwaysButton;
private Button mOnceButton;
private Button mSettingsButton;
protected View mProfileView;
private int mIconDpi;
private int mLastSelected = AbsListView.INVALID_POSITION;
@@ -146,6 +144,10 @@ public class ResolverActivity extends Activity {
/** See {@link #setRetainInOnStop}. */
private boolean mRetainInOnStop;
private static final String EXTRA_SHOW_FRAGMENT_ARGS = ":settings:show_fragment_args";
private static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key";
private static final String OPEN_LINKS_COMPONENT_KEY = "app_link_state";
private final PackageMonitor mPackageMonitor = createPackageMonitor();
/**
@@ -196,9 +198,13 @@ public class ResolverActivity extends Activity {
// titles for layout that deals with http(s) intents
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;
com.android.internal.R.string.whichOpenLinksWith;
public static final int BROWSABLE_HOST_TITLE_RES =
com.android.internal.R.string.whichOpenHostLinksWith;
public static final int BROWSABLE_HOST_APP_TITLE_RES =
com.android.internal.R.string.whichOpenHostLinksWithApp;
public static final int BROWSABLE_APP_TITLE_RES =
com.android.internal.R.string.whichOpenLinksWithApp;
public final String action;
public final int titleRes;
@@ -322,9 +328,7 @@ public class ResolverActivity extends Activity {
? false
: isHttpSchemeAndViewAction(getTargetIntent());
// We don't want to support Always Use if browsable layout is being used,
// as to mitigate Intent Capturing vulnerability
mSupportsAlwaysUseOption = supportsAlwaysUseOption && !mUseLayoutForBrowsables;
mSupportsAlwaysUseOption = supportsAlwaysUseOption;
if (configureContentView(mIntents, initialIntents, rList)) {
return;
@@ -554,10 +558,21 @@ public class ResolverActivity extends Activity {
} else if (isHttpSchemeAndViewAction(intent)) {
// If the Intent's scheme is http(s) 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());
String dialogTitle = null;
if (named && !mUseLayoutForBrowsables) {
dialogTitle = getString(ActionTitle.BROWSABLE_APP_TITLE_RES,
mAdapter.getFilteredItem().getDisplayLabel());
} else if (named && mUseLayoutForBrowsables) {
dialogTitle = getString(ActionTitle.BROWSABLE_HOST_APP_TITLE_RES,
intent.getData().getHost(),
mAdapter.getFilteredItem().getDisplayLabel());
} else if (mAdapter.areAllTargetsBrowsers()) {
dialogTitle = getString(ActionTitle.BROWSABLE_TITLE_RES);
} else {
dialogTitle = getString(ActionTitle.BROWSABLE_HOST_TITLE_RES,
intent.getData().getHost());
}
return dialogTitle;
} else {
return named
? getString(title.namedTitleRes, mAdapter.getFilteredItem().getDisplayLabel())
@@ -856,6 +871,13 @@ public class ResolverActivity extends Activity {
} else {
enabled = true;
}
if (mUseLayoutForBrowsables && !ri.handleAllWebDataURI) {
mAlwaysButton.setText(getResources()
.getString(R.string.activity_resolver_set_always));
} else {
mAlwaysButton.setText(getResources()
.getString(R.string.activity_resolver_use_always));
}
}
mAlwaysButton.setEnabled(enabled);
}
@@ -866,26 +888,29 @@ public class ResolverActivity extends Activity {
? mAdapter.getFilteredPosition()
: mAdapterView.getCheckedItemPosition();
boolean hasIndexBeenFiltered = !mAdapter.hasFilteredItem();
if (id == R.id.button_app_settings) {
showSettingsForSelected(which, hasIndexBeenFiltered);
ResolveInfo ri = mAdapter.resolveInfoForPosition(which, hasIndexBeenFiltered);
if (!ri.handleAllWebDataURI && id == R.id.button_always) {
showSettingsForSelected(ri);
} else {
startSelected(which, id == R.id.button_always, hasIndexBeenFiltered);
}
}
private void showSettingsForSelected(int which, boolean hasIndexBeenFiltered) {
ResolveInfo ri = mAdapter.resolveInfoForPosition(which, hasIndexBeenFiltered);
private void showSettingsForSelected(ResolveInfo ri) {
Intent intent = new Intent();
// For browsers, we open the Default Browser page
final String packageName = ri.activityInfo.packageName;
Bundle showFragmentArgs = new Bundle();
showFragmentArgs.putString(EXTRA_FRAGMENT_ARG_KEY, OPEN_LINKS_COMPONENT_KEY);
showFragmentArgs.putString("package", packageName);
// For regular apps, we open the Open by Default page
if (ri.handleAllWebDataURI) {
intent.setAction(Intent.ACTION_MANAGE_DEFAULT_APP)
.putExtra(Intent.EXTRA_ROLE_NAME, RoleManager.ROLE_BROWSER);
} else {
intent.setAction(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS)
.setData(Uri.fromParts("package", ri.activityInfo.packageName, null))
.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
}
intent.setAction(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS)
.setData(Uri.fromParts("package", packageName, null))
.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
.putExtra(EXTRA_FRAGMENT_ARG_KEY, OPEN_LINKS_COMPONENT_KEY)
.putExtra(EXTRA_SHOW_FRAGMENT_ARGS, showFragmentArgs);
startActivity(intent);
}
@@ -1332,41 +1357,15 @@ public class ResolverActivity extends Activity {
R.dimen.resolver_button_bar_spacing) + inset);
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();
}
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);
@@ -1626,6 +1625,7 @@ public class ResolverActivity extends Activity {
private DisplayResolveInfo mOtherProfile;
private ResolverListController mResolverListController;
private int mPlaceholderCount;
private boolean mAllTargetsAreBrowsers = false;
protected final LayoutInflater mInflater;
@@ -1700,6 +1700,14 @@ public class ResolverActivity extends Activity {
mResolverListController.updateChooserCounts(packageName, userId, action);
}
/**
* @return true if all items in the display list are defined as browsers by
* ResolveInfo.handleAllWebDataURI
*/
public boolean areAllTargetsBrowsers() {
return mAllTargetsAreBrowsers;
}
/**
* Rebuild the list of resolvers. In some cases some parts will need some asynchronous work
* to complete.
@@ -1712,6 +1720,7 @@ public class ResolverActivity extends Activity {
mOtherProfile = null;
mLastChosen = null;
mLastChosenPosition = -1;
mAllTargetsAreBrowsers = false;
mDisplayList.clear();
if (mBaseResolveList != null) {
currentResolveList = mUnfilteredResolveList = new ArrayList<>();
@@ -1812,6 +1821,8 @@ public class ResolverActivity extends Activity {
private void processSortedList(List<ResolvedComponentInfo> sortedComponents) {
int N;
if (sortedComponents != null && (N = sortedComponents.size()) != 0) {
mAllTargetsAreBrowsers = mUseLayoutForBrowsables;
// First put the initial items at the top.
if (mInitialIntents != null) {
for (int i = 0; i < mInitialIntents.length; i++) {
@@ -1841,6 +1852,8 @@ public class ResolverActivity extends Activity {
ri.noResourceId = true;
ri.icon = 0;
}
mAllTargetsAreBrowsers &= ri.handleAllWebDataURI;
addResolveInfo(new DisplayResolveInfo(ii, ri,
ri.loadLabel(getPackageManager()), null, ii));
}
@@ -1850,6 +1863,8 @@ public class ResolverActivity extends Activity {
for (ResolvedComponentInfo rci : sortedComponents) {
final ResolveInfo ri = rci.getResolveInfoAt(0);
if (ri != null) {
mAllTargetsAreBrowsers &= ri.handleAllWebDataURI;
ResolveInfoPresentationGetter pg = makePresentationGetter(ri);
addResolveInfoWithAlternates(rci, pg.getSubLabel(), pg.getLabel());
}
@@ -2152,14 +2167,8 @@ public class ResolverActivity extends Activity {
final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION;
if (!useLayoutWithDefault()
&& (!hasValidSelection || mLastSelected != checkedPos)
&& (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);
}
&& mAlwaysButton != null) {
setAlwaysButtonEnabled(hasValidSelection, checkedPos, true);
mOnceButton.setEnabled(hasValidSelection);
if (hasValidSelection) {
mAdapterView.smoothScrollToPosition(checkedPos);

View File

@@ -129,18 +129,6 @@
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>

View File

@@ -3074,12 +3074,20 @@
<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
<!-- Title of intent resolver dialog when selecting a browser/application that opens specific URIs
[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>
<string name="whichOpenHostLinksWith">Open <xliff:g id="host" example="mail.google.com">%1$s</xliff:g> links with</string>
<!-- Title of intent resolver dialog when selecting a browser that opens URI
[CHAR LIMIT=128]. -->
<string name="whichOpenLinksWith">Open links with</string>
<!-- Title of intent resolver dialog when defaulting to a specific browser that opens URI
[CHAR LIMIT=128]. -->
<string name="whichOpenLinksWithApp">Open links with <xliff:g id="application" example="Chrome">%1$s</xliff:g></string>
<!-- Title of intent resolver dialog when defaulting to a specific browser that opens URI
[CHAR LIMIT=128]. -->
<string name="whichOpenHostLinksWithApp">Open <xliff:g id="host" example="mail.google.com">%1$s</xliff:g> links with <xliff:g id="application" example="Chrome">%2$s</xliff:g></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=18] -->
<string name="whichGiveAccessToApplicationLabel">Give access</string>
<!-- Title of intent resolver dialog when selecting an editor application to run. -->
@@ -4211,6 +4219,10 @@
as the default in the activity resolver. [CHAR LIMIT=25] -->
<string name="activity_resolver_use_always">Always</string>
<!-- Title for a button to choose the currently selected activity
as the default in the activity resolver. [CHAR LIMIT=50] -->
<string name="activity_resolver_set_always">Set to always open</string>
<!-- Title for a button to choose the currently selected activity
from the activity resolver to use just this once. [CHAR LIMIT=25] -->
<string name="activity_resolver_use_once">Just once</string>

View File

@@ -2238,7 +2238,6 @@
<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_screenshotChordKeyTimeout" />
<java-symbol type="integer" name="config_maxResolverActivityColumns" />
@@ -2623,14 +2622,17 @@
<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="activity_resolver_set_always" />
<java-symbol type="string" name="activity_resolver_use_always" />
<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="whichOpenHostLinksWith" />
<java-symbol type="string" name="whichOpenHostLinksWithApp" />
<java-symbol type="string" name="whichOpenLinksWith" />
<java-symbol type="string" name="whichOpenLinksWithApp" />
<java-symbol type="string" name="whichGiveAccessToApplicationLabel" />
<java-symbol type="string" name="whichEditApplication" />
<java-symbol type="string" name="whichEditApplicationNamed" />