Loading core/java/android/net/Uri.java +17 −19 Original line number Original line Diff line number Diff line Loading @@ -874,10 +874,11 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { } } static Uri readFrom(Parcel parcel) { static Uri readFrom(Parcel parcel) { final StringUri stringUri = new StringUri(parcel.readString8()); return new OpaqueUri( return new OpaqueUri( parcel.readString8(), stringUri.parseScheme(), Part.readFrom(parcel), stringUri.getSsp(), Part.readFrom(parcel) stringUri.getFragmentPart() ); ); } } Loading @@ -887,9 +888,7 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { public void writeToParcel(Parcel parcel, int flags) { public void writeToParcel(Parcel parcel, int flags) { parcel.writeInt(TYPE_ID); parcel.writeInt(TYPE_ID); parcel.writeString8(scheme); parcel.writeString8(toString()); ssp.writeTo(parcel); fragment.writeTo(parcel); } } public boolean isHierarchical() { public boolean isHierarchical() { Loading Loading @@ -1188,22 +1187,25 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { Part query, Part fragment) { Part query, Part fragment) { this.scheme = scheme; this.scheme = scheme; this.authority = Part.nonNull(authority); this.authority = Part.nonNull(authority); this.path = path == null ? PathPart.NULL : path; this.path = generatePath(path); this.query = Part.nonNull(query); this.query = Part.nonNull(query); this.fragment = Part.nonNull(fragment); this.fragment = Part.nonNull(fragment); } } static Uri readFrom(Parcel parcel) { private PathPart generatePath(PathPart originalPath) { final String scheme = parcel.readString8(); final Part authority = Part.readFrom(parcel); // In RFC3986 the path should be determined based on whether there is a scheme or // In RFC3986 the path should be determined based on whether there is a scheme or // authority present (https://www.rfc-editor.org/rfc/rfc3986.html#section-3.3). // authority present (https://www.rfc-editor.org/rfc/rfc3986.html#section-3.3). final boolean hasSchemeOrAuthority = final boolean hasSchemeOrAuthority = (scheme != null && scheme.length() > 0) || !authority.isEmpty(); (scheme != null && scheme.length() > 0) || !authority.isEmpty(); final PathPart path = PathPart.readFrom(hasSchemeOrAuthority, parcel); final PathPart newPath = hasSchemeOrAuthority ? PathPart.makeAbsolute(originalPath) final Part query = Part.readFrom(parcel); : originalPath; final Part fragment = Part.readFrom(parcel); return newPath == null ? PathPart.NULL : newPath; return new HierarchicalUri(scheme, authority, path, query, fragment); } static Uri readFrom(Parcel parcel) { final StringUri stringUri = new StringUri(parcel.readString8()); return new HierarchicalUri(stringUri.getScheme(), stringUri.getAuthorityPart(), stringUri.getPathPart(), stringUri.getQueryPart(), stringUri.getFragmentPart()); } } public int describeContents() { public int describeContents() { Loading @@ -1212,11 +1214,7 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { public void writeToParcel(Parcel parcel, int flags) { public void writeToParcel(Parcel parcel, int flags) { parcel.writeInt(TYPE_ID); parcel.writeInt(TYPE_ID); parcel.writeString8(scheme); parcel.writeString8(toString()); authority.writeTo(parcel); path.writeTo(parcel); query.writeTo(parcel); fragment.writeTo(parcel); } } public boolean isHierarchical() { public boolean isHierarchical() { Loading core/tests/coretests/src/android/net/UriTest.java +60 −56 Original line number Original line Diff line number Diff line Loading @@ -25,8 +25,6 @@ import junit.framework.TestCase; import java.io.File; import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Arrays; import java.util.Iterator; import java.util.Iterator; import java.util.List; import java.util.List; Loading Loading @@ -852,84 +850,90 @@ public class UriTest extends TestCase { return (Uri) hierarchicalUriConstructor.newInstance("https", authority, path, null, null); return (Uri) hierarchicalUriConstructor.newInstance("https", authority, path, null, null); } } /** Attempting to unparcel a legacy parcel format of Uri.{,Path}Part should fail. */ private Uri buildUriFromParts(boolean argumentsEncoded, public void testUnparcelLegacyPart_fails() throws Exception { assertUnparcelLegacyPart_fails(Class.forName("android.net.Uri$Part")); assertUnparcelLegacyPart_fails(Class.forName("android.net.Uri$PathPart")); } private static void assertUnparcelLegacyPart_fails(Class partClass) throws Exception { Parcel parcel = Parcel.obtain(); parcel.writeInt(0 /* BOTH */); parcel.writeString("encoded"); parcel.writeString("decoded"); parcel.setDataPosition(0); Method readFromMethod = partClass.getDeclaredMethod("readFrom", Parcel.class); readFromMethod.setAccessible(true); try { readFromMethod.invoke(null, parcel); fail(); } catch (InvocationTargetException expected) { Throwable targetException = expected.getTargetException(); // Check that the exception was thrown for the correct reason. assertEquals("Unknown representation: 0", targetException.getMessage()); } finally { parcel.recycle(); } } private Uri buildUriFromRawParcel(boolean argumentsEncoded, String scheme, String scheme, String authority, String authority, String path, String path, String query, String query, String fragment) { String fragment) { // Representation value (from AbstractPart.REPRESENTATION_{ENCODED,DECODED}). final Uri.Builder builder = new Uri.Builder(); final int representation = argumentsEncoded ? 1 : 2; builder.scheme(scheme); Parcel parcel = Parcel.obtain(); if (argumentsEncoded) { try { builder.encodedAuthority(authority); parcel.writeInt(3); // hierarchical builder.encodedPath(path); parcel.writeString8(scheme); builder.encodedQuery(query); parcel.writeInt(representation); builder.encodedFragment(fragment); parcel.writeString8(authority); } else { parcel.writeInt(representation); builder.authority(authority); parcel.writeString8(path); builder.path(path); parcel.writeInt(representation); builder.query(query); parcel.writeString8(query); builder.fragment(fragment); parcel.writeInt(representation); parcel.writeString8(fragment); parcel.setDataPosition(0); return Uri.CREATOR.createFromParcel(parcel); } finally { parcel.recycle(); } } return builder.build(); } } public void testUnparcelMalformedPath() { public void testUnparcelMalformedPath() { // Regression tests for b/171966843. // Regression tests for b/171966843. // Test cases with arguments encoded (covering testing `scheme` * `authority` options). // Test cases with arguments encoded (covering testing `scheme` * `authority` options). Uri uri0 = buildUriFromRawParcel(true, "https", "google.com", "@evil.com", null, null); Uri uri0 = buildUriFromParts(true, "https", "google.com", "@evil.com", null, null); assertEquals("https://google.com/@evil.com", uri0.toString()); assertEquals("https://google.com/@evil.com", uri0.toString()); Uri uri1 = buildUriFromRawParcel(true, null, "google.com", "@evil.com", "name=spark", "x"); Uri uri1 = buildUriFromParts(true, null, "google.com", "@evil.com", "name=spark", "x"); assertEquals("//google.com/@evil.com?name=spark#x", uri1.toString()); assertEquals("//google.com/@evil.com?name=spark#x", uri1.toString()); Uri uri2 = buildUriFromRawParcel(true, "http:", null, "@evil.com", null, null); Uri uri2 = buildUriFromParts(true, "http:", null, "@evil.com", null, null); assertEquals("http::/@evil.com", uri2.toString()); assertEquals("http::/@evil.com", uri2.toString()); Uri uri3 = buildUriFromRawParcel(true, null, null, "@evil.com", null, null); Uri uri3 = buildUriFromParts(true, null, null, "@evil.com", null, null); assertEquals("@evil.com", uri3.toString()); assertEquals("@evil.com", uri3.toString()); // Test cases with arguments not encoded (covering testing `scheme` * `authority` options). // Test cases with arguments not encoded (covering testing `scheme` * `authority` options). Uri uriA = buildUriFromRawParcel(false, "https", "google.com", "@evil.com", null, null); Uri uriA = buildUriFromParts(false, "https", "google.com", "@evil.com", null, null); assertEquals("https://google.com/%40evil.com", uriA.toString()); assertEquals("https://google.com/%40evil.com", uriA.toString()); Uri uriB = buildUriFromRawParcel(false, null, "google.com", "@evil.com", null, null); Uri uriB = buildUriFromParts(false, null, "google.com", "@evil.com", null, null); assertEquals("//google.com/%40evil.com", uriB.toString()); assertEquals("//google.com/%40evil.com", uriB.toString()); Uri uriC = buildUriFromRawParcel(false, "http:", null, "@evil.com", null, null); Uri uriC = buildUriFromParts(false, "http:", null, "@evil.com", null, null); assertEquals("http::/%40evil.com", uriC.toString()); assertEquals("http::/%40evil.com", uriC.toString()); Uri uriD = buildUriFromRawParcel(false, null, null, "@evil.com", "name=spark", "y"); Uri uriD = buildUriFromParts(false, null, null, "@evil.com", "name=spark", "y"); assertEquals("%40evil.com?name%3Dspark#y", uriD.toString()); assertEquals("%40evil.com?name%3Dspark#y", uriD.toString()); } } public void testParsedUriFromStringEquality() { Uri uri = buildUriFromParts( true, "https", "google.com", "@evil.com", null, null); assertEquals(uri, Uri.parse(uri.toString())); Uri uri2 = buildUriFromParts( true, "content://evil.authority?foo=", "safe.authority", "@evil.com", null, null); assertEquals(uri2, Uri.parse(uri2.toString())); Uri uri3 = buildUriFromParts( false, "content://evil.authority?foo=", "safe.authority", "@evil.com", null, null); assertEquals(uri3, Uri.parse(uri3.toString())); } public void testParceledUrisAreEqual() { Uri opaqueUri = Uri.fromParts("fake://uri#", "ssp", "fragment"); Parcel parcel = Parcel.obtain(); try { opaqueUri.writeToParcel(parcel, 0); parcel.setDataPosition(0); Uri postParcelUri = Uri.CREATOR.createFromParcel(parcel); Uri parsedUri = Uri.parse(postParcelUri.toString()); assertEquals(parsedUri.getScheme(), postParcelUri.getScheme()); } finally { parcel.recycle(); } Uri hierarchicalUri = new Uri.Builder().scheme("fake://uri#").authority("auth").build(); parcel = Parcel.obtain(); try { hierarchicalUri.writeToParcel(parcel, 0); parcel.setDataPosition(0); Uri postParcelUri = Uri.CREATOR.createFromParcel(parcel); Uri parsedUri = Uri.parse(postParcelUri.toString()); assertEquals(parsedUri.getScheme(), postParcelUri.getScheme()); } finally { parcel.recycle(); } } public void testToSafeString() { public void testToSafeString() { checkToSafeString("tel:xxxxxx", "tel:Google"); checkToSafeString("tel:xxxxxx", "tel:Google"); checkToSafeString("tel:xxxxxxxxxx", "tel:1234567890"); checkToSafeString("tel:xxxxxxxxxx", "tel:1234567890"); Loading Loading
core/java/android/net/Uri.java +17 −19 Original line number Original line Diff line number Diff line Loading @@ -874,10 +874,11 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { } } static Uri readFrom(Parcel parcel) { static Uri readFrom(Parcel parcel) { final StringUri stringUri = new StringUri(parcel.readString8()); return new OpaqueUri( return new OpaqueUri( parcel.readString8(), stringUri.parseScheme(), Part.readFrom(parcel), stringUri.getSsp(), Part.readFrom(parcel) stringUri.getFragmentPart() ); ); } } Loading @@ -887,9 +888,7 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { public void writeToParcel(Parcel parcel, int flags) { public void writeToParcel(Parcel parcel, int flags) { parcel.writeInt(TYPE_ID); parcel.writeInt(TYPE_ID); parcel.writeString8(scheme); parcel.writeString8(toString()); ssp.writeTo(parcel); fragment.writeTo(parcel); } } public boolean isHierarchical() { public boolean isHierarchical() { Loading Loading @@ -1188,22 +1187,25 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { Part query, Part fragment) { Part query, Part fragment) { this.scheme = scheme; this.scheme = scheme; this.authority = Part.nonNull(authority); this.authority = Part.nonNull(authority); this.path = path == null ? PathPart.NULL : path; this.path = generatePath(path); this.query = Part.nonNull(query); this.query = Part.nonNull(query); this.fragment = Part.nonNull(fragment); this.fragment = Part.nonNull(fragment); } } static Uri readFrom(Parcel parcel) { private PathPart generatePath(PathPart originalPath) { final String scheme = parcel.readString8(); final Part authority = Part.readFrom(parcel); // In RFC3986 the path should be determined based on whether there is a scheme or // In RFC3986 the path should be determined based on whether there is a scheme or // authority present (https://www.rfc-editor.org/rfc/rfc3986.html#section-3.3). // authority present (https://www.rfc-editor.org/rfc/rfc3986.html#section-3.3). final boolean hasSchemeOrAuthority = final boolean hasSchemeOrAuthority = (scheme != null && scheme.length() > 0) || !authority.isEmpty(); (scheme != null && scheme.length() > 0) || !authority.isEmpty(); final PathPart path = PathPart.readFrom(hasSchemeOrAuthority, parcel); final PathPart newPath = hasSchemeOrAuthority ? PathPart.makeAbsolute(originalPath) final Part query = Part.readFrom(parcel); : originalPath; final Part fragment = Part.readFrom(parcel); return newPath == null ? PathPart.NULL : newPath; return new HierarchicalUri(scheme, authority, path, query, fragment); } static Uri readFrom(Parcel parcel) { final StringUri stringUri = new StringUri(parcel.readString8()); return new HierarchicalUri(stringUri.getScheme(), stringUri.getAuthorityPart(), stringUri.getPathPart(), stringUri.getQueryPart(), stringUri.getFragmentPart()); } } public int describeContents() { public int describeContents() { Loading @@ -1212,11 +1214,7 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { public void writeToParcel(Parcel parcel, int flags) { public void writeToParcel(Parcel parcel, int flags) { parcel.writeInt(TYPE_ID); parcel.writeInt(TYPE_ID); parcel.writeString8(scheme); parcel.writeString8(toString()); authority.writeTo(parcel); path.writeTo(parcel); query.writeTo(parcel); fragment.writeTo(parcel); } } public boolean isHierarchical() { public boolean isHierarchical() { Loading
core/tests/coretests/src/android/net/UriTest.java +60 −56 Original line number Original line Diff line number Diff line Loading @@ -25,8 +25,6 @@ import junit.framework.TestCase; import java.io.File; import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Arrays; import java.util.Iterator; import java.util.Iterator; import java.util.List; import java.util.List; Loading Loading @@ -852,84 +850,90 @@ public class UriTest extends TestCase { return (Uri) hierarchicalUriConstructor.newInstance("https", authority, path, null, null); return (Uri) hierarchicalUriConstructor.newInstance("https", authority, path, null, null); } } /** Attempting to unparcel a legacy parcel format of Uri.{,Path}Part should fail. */ private Uri buildUriFromParts(boolean argumentsEncoded, public void testUnparcelLegacyPart_fails() throws Exception { assertUnparcelLegacyPart_fails(Class.forName("android.net.Uri$Part")); assertUnparcelLegacyPart_fails(Class.forName("android.net.Uri$PathPart")); } private static void assertUnparcelLegacyPart_fails(Class partClass) throws Exception { Parcel parcel = Parcel.obtain(); parcel.writeInt(0 /* BOTH */); parcel.writeString("encoded"); parcel.writeString("decoded"); parcel.setDataPosition(0); Method readFromMethod = partClass.getDeclaredMethod("readFrom", Parcel.class); readFromMethod.setAccessible(true); try { readFromMethod.invoke(null, parcel); fail(); } catch (InvocationTargetException expected) { Throwable targetException = expected.getTargetException(); // Check that the exception was thrown for the correct reason. assertEquals("Unknown representation: 0", targetException.getMessage()); } finally { parcel.recycle(); } } private Uri buildUriFromRawParcel(boolean argumentsEncoded, String scheme, String scheme, String authority, String authority, String path, String path, String query, String query, String fragment) { String fragment) { // Representation value (from AbstractPart.REPRESENTATION_{ENCODED,DECODED}). final Uri.Builder builder = new Uri.Builder(); final int representation = argumentsEncoded ? 1 : 2; builder.scheme(scheme); Parcel parcel = Parcel.obtain(); if (argumentsEncoded) { try { builder.encodedAuthority(authority); parcel.writeInt(3); // hierarchical builder.encodedPath(path); parcel.writeString8(scheme); builder.encodedQuery(query); parcel.writeInt(representation); builder.encodedFragment(fragment); parcel.writeString8(authority); } else { parcel.writeInt(representation); builder.authority(authority); parcel.writeString8(path); builder.path(path); parcel.writeInt(representation); builder.query(query); parcel.writeString8(query); builder.fragment(fragment); parcel.writeInt(representation); parcel.writeString8(fragment); parcel.setDataPosition(0); return Uri.CREATOR.createFromParcel(parcel); } finally { parcel.recycle(); } } return builder.build(); } } public void testUnparcelMalformedPath() { public void testUnparcelMalformedPath() { // Regression tests for b/171966843. // Regression tests for b/171966843. // Test cases with arguments encoded (covering testing `scheme` * `authority` options). // Test cases with arguments encoded (covering testing `scheme` * `authority` options). Uri uri0 = buildUriFromRawParcel(true, "https", "google.com", "@evil.com", null, null); Uri uri0 = buildUriFromParts(true, "https", "google.com", "@evil.com", null, null); assertEquals("https://google.com/@evil.com", uri0.toString()); assertEquals("https://google.com/@evil.com", uri0.toString()); Uri uri1 = buildUriFromRawParcel(true, null, "google.com", "@evil.com", "name=spark", "x"); Uri uri1 = buildUriFromParts(true, null, "google.com", "@evil.com", "name=spark", "x"); assertEquals("//google.com/@evil.com?name=spark#x", uri1.toString()); assertEquals("//google.com/@evil.com?name=spark#x", uri1.toString()); Uri uri2 = buildUriFromRawParcel(true, "http:", null, "@evil.com", null, null); Uri uri2 = buildUriFromParts(true, "http:", null, "@evil.com", null, null); assertEquals("http::/@evil.com", uri2.toString()); assertEquals("http::/@evil.com", uri2.toString()); Uri uri3 = buildUriFromRawParcel(true, null, null, "@evil.com", null, null); Uri uri3 = buildUriFromParts(true, null, null, "@evil.com", null, null); assertEquals("@evil.com", uri3.toString()); assertEquals("@evil.com", uri3.toString()); // Test cases with arguments not encoded (covering testing `scheme` * `authority` options). // Test cases with arguments not encoded (covering testing `scheme` * `authority` options). Uri uriA = buildUriFromRawParcel(false, "https", "google.com", "@evil.com", null, null); Uri uriA = buildUriFromParts(false, "https", "google.com", "@evil.com", null, null); assertEquals("https://google.com/%40evil.com", uriA.toString()); assertEquals("https://google.com/%40evil.com", uriA.toString()); Uri uriB = buildUriFromRawParcel(false, null, "google.com", "@evil.com", null, null); Uri uriB = buildUriFromParts(false, null, "google.com", "@evil.com", null, null); assertEquals("//google.com/%40evil.com", uriB.toString()); assertEquals("//google.com/%40evil.com", uriB.toString()); Uri uriC = buildUriFromRawParcel(false, "http:", null, "@evil.com", null, null); Uri uriC = buildUriFromParts(false, "http:", null, "@evil.com", null, null); assertEquals("http::/%40evil.com", uriC.toString()); assertEquals("http::/%40evil.com", uriC.toString()); Uri uriD = buildUriFromRawParcel(false, null, null, "@evil.com", "name=spark", "y"); Uri uriD = buildUriFromParts(false, null, null, "@evil.com", "name=spark", "y"); assertEquals("%40evil.com?name%3Dspark#y", uriD.toString()); assertEquals("%40evil.com?name%3Dspark#y", uriD.toString()); } } public void testParsedUriFromStringEquality() { Uri uri = buildUriFromParts( true, "https", "google.com", "@evil.com", null, null); assertEquals(uri, Uri.parse(uri.toString())); Uri uri2 = buildUriFromParts( true, "content://evil.authority?foo=", "safe.authority", "@evil.com", null, null); assertEquals(uri2, Uri.parse(uri2.toString())); Uri uri3 = buildUriFromParts( false, "content://evil.authority?foo=", "safe.authority", "@evil.com", null, null); assertEquals(uri3, Uri.parse(uri3.toString())); } public void testParceledUrisAreEqual() { Uri opaqueUri = Uri.fromParts("fake://uri#", "ssp", "fragment"); Parcel parcel = Parcel.obtain(); try { opaqueUri.writeToParcel(parcel, 0); parcel.setDataPosition(0); Uri postParcelUri = Uri.CREATOR.createFromParcel(parcel); Uri parsedUri = Uri.parse(postParcelUri.toString()); assertEquals(parsedUri.getScheme(), postParcelUri.getScheme()); } finally { parcel.recycle(); } Uri hierarchicalUri = new Uri.Builder().scheme("fake://uri#").authority("auth").build(); parcel = Parcel.obtain(); try { hierarchicalUri.writeToParcel(parcel, 0); parcel.setDataPosition(0); Uri postParcelUri = Uri.CREATOR.createFromParcel(parcel); Uri parsedUri = Uri.parse(postParcelUri.toString()); assertEquals(parsedUri.getScheme(), postParcelUri.getScheme()); } finally { parcel.recycle(); } } public void testToSafeString() { public void testToSafeString() { checkToSafeString("tel:xxxxxx", "tel:Google"); checkToSafeString("tel:xxxxxx", "tel:Google"); checkToSafeString("tel:xxxxxxxxxx", "tel:1234567890"); checkToSafeString("tel:xxxxxxxxxx", "tel:1234567890"); Loading