Commit 6713b986 authored by Michael Thiessen's avatar Michael Thiessen Committed by Commit Bot

Delete unused UrlUtilities#validateIntentUrl

The downstream usage of this function has been removed, so we can
delete it.

Bug: 783819
Change-Id: I41309bdb93b7f0fde005cd313494f06c209cfa30
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2062581Reviewed-by: default avatarYaron Friedman <yfriedman@chromium.org>
Commit-Queue: Michael Thiessen <mthiesse@chromium.org>
Cr-Commit-Position: refs/heads/master@{#742818}
parent 7115044c
...@@ -47,74 +47,6 @@ public class UrlUtilitiesUnitTest { ...@@ -47,74 +47,6 @@ public class UrlUtilitiesUnitTest {
Assert.assertFalse(UrlUtilities.isHttpOrHttps("")); Assert.assertFalse(UrlUtilities.isHttpOrHttps(""));
} }
@CalledByNativeJavaTest
public void testValidateIntentUrl() {
// Valid action, hostname, and (empty) path.
Assert.assertTrue(UrlUtilities.validateIntentUrl(
"intent://10010#Intent;scheme=tel;action=com.google.android.apps."
+ "authenticator.AUTHENTICATE;end"));
// Valid package, scheme, hostname, and path.
Assert.assertTrue(UrlUtilities.validateIntentUrl(
"intent://scan/#Intent;package=com.google.zxing.client.android;"
+ "scheme=zxing;end;"));
// Valid package, scheme, component, hostname, and path.
Assert.assertTrue(UrlUtilities.validateIntentUrl(
"intent://wump-hey.example.com/#Intent;package=com.example.wump;"
+ "scheme=yow;component=com.example.PUMPKIN;end;"));
// Valid package, scheme, action, hostname, and path.
Assert.assertTrue(UrlUtilities.validateIntentUrl(
"intent://wump-hey.example.com/#Intent;package=com.example.wump;"
+ "scheme=eeek;action=frighten_children;end;"));
// Valid package, component, String extra, hostname, and path.
Assert.assertTrue(UrlUtilities.validateIntentUrl(
"intent://testing/#Intent;package=cybergoat.noodle.crumpet;"
+ "component=wump.noodle/Crumpet;S.goat=leg;end"));
// Valid package, component, int extra (with URL-encoded key), String
// extra, hostname, and path.
Assert.assertTrue(UrlUtilities.validateIntentUrl(
"intent://testing/#Intent;package=cybergoat.noodle.crumpet;"
+ "component=wump.noodle/Crumpet;i.pumpkinCount%3D=42;"
+ "S.goat=leg;end"));
// Android's Intent.toUri does not generate URLs like this, but
// Google Authenticator does, and we must handle them.
Assert.assertTrue(UrlUtilities.validateIntentUrl(
"intent:#Intent;action=com.google.android.apps.chrome."
+ "TEST_AUTHENTICATOR;category=android.intent.category."
+ "BROWSABLE;S.inputData=cancelled;end"));
// null does not have a valid intent scheme.
Assert.assertFalse(UrlUtilities.validateIntentUrl(null));
// The empty string does not have a valid intent scheme.
Assert.assertFalse(UrlUtilities.validateIntentUrl(""));
// A whitespace string does not have a valid intent scheme.
Assert.assertFalse(UrlUtilities.validateIntentUrl(" "));
// Junk after end.
Assert.assertFalse(UrlUtilities.validateIntentUrl(
"intent://10010#Intent;scheme=tel;action=com.google.android.apps."
+ "authenticator.AUTHENTICATE;end','*');"
+ "alert(document.cookie);//"));
// component appears twice.
Assert.assertFalse(UrlUtilities.validateIntentUrl(
"intent://wump-hey.example.com/#Intent;package=com.example.wump;"
+ "scheme=yow;component=com.example.PUMPKIN;"
+ "component=com.example.AVOCADO;end;"));
// scheme contains illegal character.
Assert.assertFalse(UrlUtilities.validateIntentUrl(
"intent://wump-hey.example.com/#Intent;package=com.example.wump;"
+ "scheme=hello+goodbye;component=com.example.PUMPKIN;end;"));
// category contains illegal character.
Assert.assertFalse(UrlUtilities.validateIntentUrl(
"intent://wump-hey.example.com/#Intent;package=com.example.wump;"
+ "category=42%_by_volume;end"));
// Incorrectly URL-encoded.
Assert.assertFalse(UrlUtilities.validateIntentUrl(
"intent://testing/#Intent;package=cybergoat.noodle.crumpet;"
+ "component=wump.noodle/Crumpet;i.pumpkinCount%%3D=42;"
+ "S.goat=&leg;end"));
}
@CalledByNativeJavaTest @CalledByNativeJavaTest
public void testStripPath() { public void testStripPath() {
Assert.assertEquals("https://example.com:9000", Assert.assertEquals("https://example.com:9000",
......
...@@ -11,18 +11,11 @@ import androidx.annotation.NonNull; ...@@ -11,18 +11,11 @@ import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import org.chromium.base.CollectionUtil; import org.chromium.base.CollectionUtil;
import org.chromium.base.Log;
import org.chromium.base.annotations.NativeMethods; import org.chromium.base.annotations.NativeMethods;
import org.chromium.content_public.common.ContentUrlConstants; import org.chromium.content_public.common.ContentUrlConstants;
import org.chromium.url.GURL; import org.chromium.url.GURL;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.util.HashSet; import java.util.HashSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** /**
* Utilities for working with URIs (and URLs). These methods may be used in security-sensitive * Utilities for working with URIs (and URLs). These methods may be used in security-sensitive
...@@ -42,12 +35,6 @@ public class UrlUtilities { ...@@ -42,12 +35,6 @@ public class UrlUtilities {
CollectionUtil.newHashSet(UrlConstants.CHROME_SCHEME, UrlConstants.CHROME_NATIVE_SCHEME, CollectionUtil.newHashSet(UrlConstants.CHROME_SCHEME, UrlConstants.CHROME_NATIVE_SCHEME,
ContentUrlConstants.ABOUT_SCHEME); ContentUrlConstants.ABOUT_SCHEME);
// Patterns used in validateIntentUrl.
private static final Pattern DNS_HOSTNAME_PATTERN = Pattern.compile("^[\\w\\.-]*$");
private static final Pattern JAVA_PACKAGE_NAME_PATTERN = Pattern.compile("^[\\w\\.-]*$");
private static final Pattern ANDROID_COMPONENT_NAME_PATTERN = Pattern.compile("^[\\w\\./-]*$");
private static final Pattern URL_SCHEME_PATTERN = Pattern.compile("^[a-zA-Z]+$");
private static final String TEL_URL_PREFIX = "tel:"; private static final String TEL_URL_PREFIX = "tel:";
/** /**
...@@ -188,149 +175,6 @@ public class UrlUtilities { ...@@ -188,149 +175,6 @@ public class UrlUtilities {
return UrlUtilitiesJni.get().urlsFragmentsDiffer(url, url2); return UrlUtilitiesJni.get().urlsFragmentsDiffer(url, url2);
} }
/**
* @param url An Android intent:// URL to validate.
*/
@VisibleForTesting
public static boolean validateIntentUrl(String url) {
if (url == null) {
Log.d(TAG, "url was null");
return false;
}
URI parsed;
try {
parsed = new URI(url);
} catch (URISyntaxException e) {
// It may be that we received a URI of the form "intent:#Intent...",
// which e.g. Google Authenticator produces. Work around that
// specific case.
if (url.indexOf("intent:#Intent;") == 0) {
return validateIntentUrl(url.replace("intent:#Intent;", "intent://foo/#Intent;"));
}
Log.d(TAG, "Could not parse url '%s': %s", url, e.toString());
return false;
}
String scheme = parsed.getScheme();
if (scheme == null || !scheme.equals("intent")) {
Log.d(TAG, "scheme was not 'intent'");
return false;
}
String hostname = parsed.getHost();
if (hostname == null) {
Log.d(TAG, "hostname was null for '%s'", url);
return false;
}
Matcher m = DNS_HOSTNAME_PATTERN.matcher(hostname);
if (!m.matches()) {
Log.d(TAG, "hostname did not match DNS_HOSTNAME_PATTERN");
return false;
}
String path = parsed.getPath();
if (path == null || (!path.isEmpty() && !path.equals("/"))) {
Log.d(TAG, "path was null or not \"/\"");
return false;
}
// We need to get the raw, unparsed, un-URL-decoded fragment.
// parsed.getFragment() returns a URL-decoded fragment, which can
// interfere with lexing and parsing Intent extras correctly. Therefore,
// we handle the fragment "manually", but first assert that it
// URL-decodes correctly.
int fragmentStart = url.indexOf('#');
if (fragmentStart == -1 || fragmentStart == url.length() - 1) {
Log.d(TAG, "Could not find '#'");
return false;
}
String fragment = url.substring(url.indexOf('#') + 1);
try {
String f = parsed.getFragment();
if (f == null) {
Log.d(TAG, "Could not get fragment from parsed URL");
return false;
}
if (!URLDecoder.decode(fragment, "UTF-8").equals(f)) {
Log.d(TAG, "Parsed fragment does not equal lexed fragment");
return false;
}
} catch (UnsupportedEncodingException e) {
Log.d(TAG, e.toString());
return false;
}
// Now lex and parse the correctly-encoded fragment.
String[] parts = fragment.split(";");
if (parts.length < 3 || !parts[0].equals("Intent")
|| !parts[parts.length - 1].equals("end")) {
Log.d(TAG, "Invalid fragment (not enough parts, lacking Intent, or lacking end)");
return false;
}
boolean seenPackage = false;
boolean seenAction = false;
boolean seenCategory = false;
boolean seenComponent = false;
boolean seenScheme = false;
for (int i = 1; i < parts.length - 1; ++i) {
// This is OK *only* because no valid package, action, category,
// component, or scheme contains (unencoded) "=".
String[] pair = parts[i].split("=");
if (2 != pair.length) {
Log.d(TAG, "Invalid key=value pair '%s'", parts[i]);
return false;
}
m = JAVA_PACKAGE_NAME_PATTERN.matcher(pair[1]);
if (pair[0].equals("package")) {
if (seenPackage || !m.matches()) {
Log.d(TAG, "Invalid package '%s'", pair[1]);
return false;
}
seenPackage = true;
} else if (pair[0].equals("action")) {
if (seenAction || !m.matches()) {
Log.d(TAG, "Invalid action '%s'", pair[1]);
return false;
}
seenAction = true;
} else if (pair[0].equals("category")) {
if (seenCategory || !m.matches()) {
Log.d(TAG, "Invalid category '%s'", pair[1]);
return false;
}
seenCategory = true;
} else if (pair[0].equals("component")) {
Matcher componentMatcher = ANDROID_COMPONENT_NAME_PATTERN.matcher(pair[1]);
if (seenComponent || !componentMatcher.matches()) {
Log.d(TAG, "Invalid component '%s'", pair[1]);
return false;
}
seenComponent = true;
} else if (pair[0].equals("scheme")) {
if (seenScheme) return false;
Matcher schemeMatcher = URL_SCHEME_PATTERN.matcher(pair[1]);
if (!schemeMatcher.matches()) {
Log.d(TAG, "Invalid scheme '%s'", pair[1]);
return false;
}
seenScheme = true;
} else {
// Assume we are seeing an Intent Extra. Up above, we ensured
// that the #Intent... fragment was correctly URL-encoded;
// beyond that, there is no further validation we can do. Extras
// are blobs to us.
continue;
}
}
return true;
}
/** /**
* @param url An HTTP or HTTPS URL. * @param url An HTTP or HTTPS URL.
* @return The URL without path and query. * @return The URL without path and query.
......
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