Commit 7f160bf8 authored by huangxueqing's avatar huangxueqing Committed by Commit Bot

Reland "Ignore Intent filters with wildcard hosts when handling links."

This is a reland of 6d48958d

Don't check acceptable scheme links since UrlUtilities.isAcceptedScheme()
was native function, libchrome.so had not loaded when handle intent.

Original change's description:
> Ignore Intent filters with wildcard hosts when handling links.
>
> If the Android device has a package installed that declares
> an Intent filter with `android:host="*"`, Chrome will launch
> the Intent picker UX whenever a person taps a link.
> This is a poor user experience. (Using `android:host="*"`
> arguably doesn't make much sense; normally, Intent filters
> would use `*` to match subdomains such as *.google.com.) Thus,
> skip Intent filters with such wildcard hosts when handling
> acceptable scheme links.
>
> R=dtrainor@chromium.org
>
> Bug: 841133
> Change-Id: I3cb14309ed53e0bd623ed0da59af6635391a8718
> Reviewed-on: https://chromium-review.googlesource.com/1053847
> Reviewed-by: Michael Thiessen <mthiesse@chromium.org>
> Reviewed-by: Chris Palmer <palmer@chromium.org>
> Reviewed-by: Maria Khomenko <mariakhomenko@chromium.org>
> Commit-Queue: Michael Thiessen <mthiesse@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#564487}

Bug: 841133
Change-Id: Id2fd7f7364eb6c70280b29a1f71783a2ee89747b
Reviewed-on: https://chromium-review.googlesource.com/1096554Reviewed-by: default avatarYaron Friedman <yfriedman@chromium.org>
Reviewed-by: default avatarChris Palmer <palmer@chromium.org>
Reviewed-by: default avatarMaria Khomenko <mariakhomenko@chromium.org>
Commit-Queue: Yaron Friedman <yfriedman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#574155}
parent 0d0514d9
...@@ -42,7 +42,7 @@ interface ExternalNavigationDelegate { ...@@ -42,7 +42,7 @@ interface ExternalNavigationDelegate {
* Returns the number of specialized intent handlers in {@params infos}. Specialized intent * Returns the number of specialized intent handlers in {@params infos}. Specialized intent
* handlers are intent handlers which handle only a few URLs (e.g. google maps or youtube). * handlers are intent handlers which handle only a few URLs (e.g. google maps or youtube).
*/ */
int countSpecializedHandlers(List<ResolveInfo> infos); int countSpecializedHandlers(List<ResolveInfo> infos, Intent intent);
/** /**
* Returns the package name of the first valid WebAPK in {@link infos}. * Returns the package name of the first valid WebAPK in {@link infos}.
......
...@@ -59,6 +59,7 @@ import org.chromium.ui.base.WindowAndroid; ...@@ -59,6 +59,7 @@ import org.chromium.ui.base.WindowAndroid;
import org.chromium.webapk.lib.client.WebApkValidator; import org.chromium.webapk.lib.client.WebApkValidator;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
/** /**
...@@ -266,32 +267,20 @@ public class ExternalNavigationDelegateImpl implements ExternalNavigationDelegat ...@@ -266,32 +267,20 @@ public class ExternalNavigationDelegateImpl implements ExternalNavigationDelegat
} }
@Override @Override
public int countSpecializedHandlers(List<ResolveInfo> infos) { public int countSpecializedHandlers(List<ResolveInfo> infos, Intent intent) {
return getSpecializedHandlersWithFilter(infos, null).size(); return getSpecializedHandlersWithFilter(infos, null, intent).size();
} }
@VisibleForTesting @VisibleForTesting
public static ArrayList<String> getSpecializedHandlersWithFilter( public static ArrayList<String> getSpecializedHandlersWithFilter(
List<ResolveInfo> infos, String filterPackageName) { List<ResolveInfo> infos, String filterPackageName, Intent intent) {
ArrayList<String> result = new ArrayList<>(); ArrayList<String> result = new ArrayList<>();
if (infos == null) { if (infos == null) {
return result; return result;
} }
for (ResolveInfo info : infos) { for (ResolveInfo info : infos) {
IntentFilter filter = info.filter; if (!matchResolveInfoExceptWildCardHost(info, filterPackageName, intent)) {
if (filter == null) {
// Error on the side of classifying ResolveInfo as generic.
continue;
}
if (filter.countDataAuthorities() == 0 && filter.countDataPaths() == 0) {
// Don't count generic handlers.
continue;
}
if (!TextUtils.isEmpty(filterPackageName)
&& (info.activityInfo == null
|| !info.activityInfo.packageName.equals(filterPackageName))) {
continue; continue;
} }
...@@ -309,6 +298,39 @@ public class ExternalNavigationDelegateImpl implements ExternalNavigationDelegat ...@@ -309,6 +298,39 @@ public class ExternalNavigationDelegateImpl implements ExternalNavigationDelegat
return result; return result;
} }
private static boolean matchResolveInfoExceptWildCardHost(
ResolveInfo info, String filterPackageName, Intent intent) {
IntentFilter intentFilter = info.filter;
if (intentFilter == null) {
// Error on the side of classifying ResolveInfo as generic.
return false;
}
if (intentFilter.countDataAuthorities() == 0 && intentFilter.countDataPaths() == 0) {
// Don't count generic handlers.
return false;
}
if (intent != null) {
boolean isWildCardHost = false;
Iterator<IntentFilter.AuthorityEntry> it = intentFilter.authoritiesIterator();
while (it != null && it.hasNext()) {
IntentFilter.AuthorityEntry entry = it.next();
if ("*".equals(entry.getHost())) {
isWildCardHost = true;
break;
}
}
if (isWildCardHost) {
return false;
}
}
if (!TextUtils.isEmpty(filterPackageName)
&& (info.activityInfo == null
|| !info.activityInfo.packageName.equals(filterPackageName))) {
return false;
}
return true;
}
/** /**
* Check whether the given package is a specialized handler for the given intent * Check whether the given package is a specialized handler for the given intent
* *
...@@ -322,7 +344,7 @@ public class ExternalNavigationDelegateImpl implements ExternalNavigationDelegat ...@@ -322,7 +344,7 @@ public class ExternalNavigationDelegateImpl implements ExternalNavigationDelegat
try { try {
List<ResolveInfo> handlers = context.getPackageManager().queryIntentActivities( List<ResolveInfo> handlers = context.getPackageManager().queryIntentActivities(
intent, PackageManager.GET_RESOLVED_FILTER); intent, PackageManager.GET_RESOLVED_FILTER);
return getSpecializedHandlersWithFilter(handlers, packageName).size() > 0; return getSpecializedHandlersWithFilter(handlers, packageName, intent).size() > 0;
} catch (RuntimeException e) { } catch (RuntimeException e) {
IntentUtils.logTransactionTooLargeOrRethrow(e, intent); IntentUtils.logTransactionTooLargeOrRethrow(e, intent);
} }
...@@ -594,7 +616,7 @@ public class ExternalNavigationDelegateImpl implements ExternalNavigationDelegat ...@@ -594,7 +616,7 @@ public class ExternalNavigationDelegateImpl implements ExternalNavigationDelegat
@Override @Override
public void maybeRecordAppHandlersInIntent(Intent intent, List<ResolveInfo> infos) { public void maybeRecordAppHandlersInIntent(Intent intent, List<ResolveInfo> infos) {
intent.putExtra(IntentHandler.EXTRA_EXTERNAL_NAV_PACKAGES, intent.putExtra(IntentHandler.EXTRA_EXTERNAL_NAV_PACKAGES,
getSpecializedHandlersWithFilter(infos, null)); getSpecializedHandlersWithFilter(infos, null, intent));
} }
@Override @Override
......
...@@ -455,7 +455,7 @@ public class ExternalNavigationHandler { ...@@ -455,7 +455,7 @@ public class ExternalNavigationHandler {
// handlers. If webkit can't handle it internally, we need to call // handlers. If webkit can't handle it internally, we need to call
// startActivityIfNeeded or startActivity. // startActivityIfNeeded or startActivity.
if (!isExternalProtocol) { if (!isExternalProtocol) {
if (mDelegate.countSpecializedHandlers(resolvingInfos) == 0) { if (mDelegate.countSpecializedHandlers(resolvingInfos, intent) == 0) {
if (incomingIntentRedirect if (incomingIntentRedirect
&& mDelegate.maybeLaunchInstantApp( && mDelegate.maybeLaunchInstantApp(
params.getUrl(), params.getReferrerUrl(), true)) { params.getUrl(), params.getReferrerUrl(), true)) {
...@@ -595,7 +595,7 @@ public class ExternalNavigationHandler { ...@@ -595,7 +595,7 @@ public class ExternalNavigationHandler {
} }
if (targetWebApkPackageName != null if (targetWebApkPackageName != null
&& mDelegate.countSpecializedHandlers(resolvingInfos) == 1) { && mDelegate.countSpecializedHandlers(resolvingInfos, null) == 1) {
intent.setPackage(targetWebApkPackageName); intent.setPackage(targetWebApkPackageName);
} }
...@@ -776,7 +776,8 @@ public class ExternalNavigationHandler { ...@@ -776,7 +776,8 @@ public class ExternalNavigationHandler {
} catch (URISyntaxException ex) { } catch (URISyntaxException ex) {
return false; return false;
} }
return ExternalNavigationDelegateImpl.getSpecializedHandlersWithFilter(handlers, appId) return ExternalNavigationDelegateImpl
.getSpecializedHandlersWithFilter(handlers, appId, null)
.size() .size()
> 0; > 0;
} }
......
...@@ -83,7 +83,7 @@ public class WebappTabDelegate extends TabDelegate { ...@@ -83,7 +83,7 @@ public class WebappTabDelegate extends TabDelegate {
boolean foundSpecializedHandler = false; boolean foundSpecializedHandler = false;
for (String result : ExternalNavigationDelegateImpl.getSpecializedHandlersWithFilter( for (String result : ExternalNavigationDelegateImpl.getSpecializedHandlersWithFilter(
handlers, null)) { handlers, null, null)) {
if (result.equals(mApkPackageName)) { if (result.equals(mApkPackageName)) {
// Current webapk matches, don't intercept so that we can launch a cct. See // Current webapk matches, don't intercept so that we can launch a cct. See
// http://crbug.com/831806 for more context. // http://crbug.com/831806 for more context.
......
...@@ -4,9 +4,12 @@ ...@@ -4,9 +4,12 @@
package org.chromium.chrome.browser.externalnav; package org.chromium.chrome.browser.externalnav;
import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Build;
import android.support.test.filters.SmallTest; import android.support.test.filters.SmallTest;
import org.junit.Assert; import org.junit.Assert;
...@@ -47,7 +50,7 @@ public class ExternalNavigationDelegateImplTest { ...@@ -47,7 +50,7 @@ public class ExternalNavigationDelegateImplTest {
List<ResolveInfo> resolveInfos = new ArrayList<ResolveInfo>(); List<ResolveInfo> resolveInfos = new ArrayList<ResolveInfo>();
Assert.assertEquals(0, Assert.assertEquals(0,
ExternalNavigationDelegateImpl ExternalNavigationDelegateImpl
.getSpecializedHandlersWithFilter(resolveInfos, packageName) .getSpecializedHandlersWithFilter(resolveInfos, packageName, null)
.size()); .size());
} }
...@@ -60,7 +63,7 @@ public class ExternalNavigationDelegateImplTest { ...@@ -60,7 +63,7 @@ public class ExternalNavigationDelegateImplTest {
List<ResolveInfo> resolveInfos = makeResolveInfos(info); List<ResolveInfo> resolveInfos = makeResolveInfos(info);
Assert.assertEquals(0, Assert.assertEquals(0,
ExternalNavigationDelegateImpl ExternalNavigationDelegateImpl
.getSpecializedHandlersWithFilter(resolveInfos, packageName) .getSpecializedHandlersWithFilter(resolveInfos, packageName, null)
.size()); .size());
} }
...@@ -74,7 +77,7 @@ public class ExternalNavigationDelegateImplTest { ...@@ -74,7 +77,7 @@ public class ExternalNavigationDelegateImplTest {
List<ResolveInfo> resolveInfos = makeResolveInfos(info); List<ResolveInfo> resolveInfos = makeResolveInfos(info);
Assert.assertEquals(1, Assert.assertEquals(1,
ExternalNavigationDelegateImpl ExternalNavigationDelegateImpl
.getSpecializedHandlersWithFilter(resolveInfos, packageName) .getSpecializedHandlersWithFilter(resolveInfos, packageName, null)
.size()); .size());
} }
...@@ -88,7 +91,49 @@ public class ExternalNavigationDelegateImplTest { ...@@ -88,7 +91,49 @@ public class ExternalNavigationDelegateImplTest {
List<ResolveInfo> resolveInfos = makeResolveInfos(info); List<ResolveInfo> resolveInfos = makeResolveInfos(info);
Assert.assertEquals(1, Assert.assertEquals(1,
ExternalNavigationDelegateImpl ExternalNavigationDelegateImpl
.getSpecializedHandlersWithFilter(resolveInfos, packageName) .getSpecializedHandlersWithFilter(resolveInfos, packageName, null)
.size());
}
@Test
@SmallTest
public void testIsPackageSpecializedHandler_WithAuthority_Wildcard_Host() {
String packageName = "";
ResolveInfo info = new ResolveInfo();
info.filter = new IntentFilter();
info.filter.addDataAuthority("*", null);
List<ResolveInfo> resolveInfos = makeResolveInfos(info);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.google.com"));
Assert.assertEquals(0,
ExternalNavigationDelegateImpl
.getSpecializedHandlersWithFilter(resolveInfos, packageName, intent)
.size());
Intent intentWildcardHost =
new Intent(Intent.ACTION_VIEW, Uri.parse("https://*.google.com"));
Assert.assertEquals(0,
ExternalNavigationDelegateImpl
.getSpecializedHandlersWithFilter(
resolveInfos, packageName, intentWildcardHost)
.size());
ResolveInfo infoWildcardSubDomain = new ResolveInfo();
infoWildcardSubDomain.filter = new IntentFilter();
infoWildcardSubDomain.filter.addDataAuthority("http://*.google.com", "80");
List<ResolveInfo> resolveInfosWildcardSubDomain = makeResolveInfos(infoWildcardSubDomain);
Intent intentSubDomain1 = new Intent(Intent.ACTION_VIEW, Uri.parse("https://google.com"));
Assert.assertEquals(1,
ExternalNavigationDelegateImpl
.getSpecializedHandlersWithFilter(
resolveInfosWildcardSubDomain, packageName, intentSubDomain1)
.size());
Intent intentSubDomain2 =
new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com"));
Assert.assertEquals(1,
ExternalNavigationDelegateImpl
.getSpecializedHandlersWithFilter(
resolveInfosWildcardSubDomain, packageName, intentSubDomain2)
.size()); .size());
} }
...@@ -104,7 +149,7 @@ public class ExternalNavigationDelegateImplTest { ...@@ -104,7 +149,7 @@ public class ExternalNavigationDelegateImplTest {
List<ResolveInfo> resolveInfos = makeResolveInfos(info); List<ResolveInfo> resolveInfos = makeResolveInfos(info);
Assert.assertEquals(1, Assert.assertEquals(1,
ExternalNavigationDelegateImpl ExternalNavigationDelegateImpl
.getSpecializedHandlersWithFilter(resolveInfos, packageName) .getSpecializedHandlersWithFilter(resolveInfos, packageName, null)
.size()); .size());
} }
...@@ -120,7 +165,7 @@ public class ExternalNavigationDelegateImplTest { ...@@ -120,7 +165,7 @@ public class ExternalNavigationDelegateImplTest {
List<ResolveInfo> resolveInfos = makeResolveInfos(info); List<ResolveInfo> resolveInfos = makeResolveInfos(info);
Assert.assertEquals(0, Assert.assertEquals(0,
ExternalNavigationDelegateImpl ExternalNavigationDelegateImpl
.getSpecializedHandlersWithFilter(resolveInfos, packageName) .getSpecializedHandlersWithFilter(resolveInfos, packageName, null)
.size()); .size());
} }
...@@ -132,13 +177,19 @@ public class ExternalNavigationDelegateImplTest { ...@@ -132,13 +177,19 @@ public class ExternalNavigationDelegateImplTest {
info.filter = new IntentFilter(); info.filter = new IntentFilter();
info.filter.addDataPath("somepath", 2); info.filter.addDataPath("somepath", 2);
info.activityInfo = new ActivityInfo(); info.activityInfo = new ActivityInfo();
// See InstantAppsHandler.isInstantAppResolveInfo
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
info.isInstantAppAvailable = true;
} else {
info.activityInfo.name = InstantAppsHandler.EPHEMERAL_INSTALLER_CLASS; info.activityInfo.name = InstantAppsHandler.EPHEMERAL_INSTALLER_CLASS;
}
info.activityInfo.packageName = "com.google.android.gms"; info.activityInfo.packageName = "com.google.android.gms";
List<ResolveInfo> resolveInfos = makeResolveInfos(info); List<ResolveInfo> resolveInfos = makeResolveInfos(info);
// Ephemeral resolver is not counted as a specialized handler. // Ephemeral resolver is not counted as a specialized handler.
Assert.assertEquals(0, Assert.assertEquals(0,
ExternalNavigationDelegateImpl ExternalNavigationDelegateImpl
.getSpecializedHandlersWithFilter(resolveInfos, packageName) .getSpecializedHandlersWithFilter(resolveInfos, packageName, null)
.size()); .size());
} }
......
...@@ -1564,7 +1564,7 @@ public class ExternalNavigationHandlerTest { ...@@ -1564,7 +1564,7 @@ public class ExternalNavigationHandlerTest {
} }
@Override @Override
public int countSpecializedHandlers(List<ResolveInfo> infos) { public int countSpecializedHandlers(List<ResolveInfo> infos, Intent intent) {
int count = 0; int count = 0;
List<IntentActivity> matchingIntentActivities = findMatchingIntentActivities(infos); List<IntentActivity> matchingIntentActivities = findMatchingIntentActivities(infos);
for (IntentActivity intentActivity : matchingIntentActivities) { for (IntentActivity intentActivity : matchingIntentActivities) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment