Commit a2f69efc authored by Rayan Kanso's avatar Rayan Kanso Committed by Commit Bot

[gIRA] Add the ability to find WebAPKs by manifestURLs.

This is limited to bound WebAPKs. This is the first step to make WebAPKs
discoverable via getInstalledRelatedApps.

Bug: 1043970
Change-Id: I1cbb86159d15554c129894b6c405c1efefa42587
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2012287
Commit-Queue: Rayan Kanso <rayankans@chromium.org>
Reviewed-by: default avatarPeter Kotwicz <pkotwicz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#734214}
parent e76d2356
......@@ -11,6 +11,7 @@ import static org.junit.Assert.assertTrue;
import static org.chromium.webapk.lib.common.WebApkMetaDataKeys.SCOPE;
import static org.chromium.webapk.lib.common.WebApkMetaDataKeys.START_URL;
import static org.chromium.webapk.lib.common.WebApkMetaDataKeys.WEB_MANIFEST_URL;
import android.content.Intent;
import android.content.pm.ActivityInfo;
......@@ -46,6 +47,7 @@ public class WebApkValidatorTest {
private static final String TEST_STARTURL = "https://non-empty.com/starturl";
private static final String MAPSLITE_PACKAGE_NAME = "com.google.android.apps.mapslite";
private static final String MAPSLITE_EXAMPLE_STARTURL = "https://www.google.com/maps";
private static final String MANIFEST_URL = "https://www.foo.com/manifest.json";
private static final byte[] EXPECTED_SIGNATURE = new byte[] {48, -126, 3, -121, 48, -126, 2,
111, -96, 3, 2, 1, 2, 2, 4, 20, -104, -66, -126, 48, 13, 6, 9, 42, -122, 72, -122, -9,
......@@ -90,7 +92,7 @@ public class WebApkValidatorTest {
mPackageManager.addResolveInfoForIntent(intent, newResolveInfo(WEBAPK_PACKAGE_NAME));
mPackageManager.addPackage(newPackageInfoWithBrowserSignature(
WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE), TEST_STARTURL));
WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE), TEST_STARTURL, null));
assertEquals(WEBAPK_PACKAGE_NAME,
WebApkValidator.queryFirstWebApkPackage(
......@@ -111,7 +113,7 @@ public class WebApkValidatorTest {
mPackageManager.addResolveInfoForIntent(intent, newResolveInfo(WEBAPK_PACKAGE_NAME));
mPackageManager.addPackage(newPackageInfoWithBrowserSignature(
WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE), TEST_STARTURL));
WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE), TEST_STARTURL, null));
assertNull(WebApkValidator.queryFirstWebApkPackage(
RuntimeEnvironment.application, URL_OF_WEBAPK));
......@@ -132,7 +134,7 @@ public class WebApkValidatorTest {
mPackageManager.addResolveInfoForIntent(intent, newResolveInfo(WEBAPK_PACKAGE_NAME));
mPackageManager.addPackage(newPackageInfoWithBrowserSignature(
WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE), TEST_STARTURL));
WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE), TEST_STARTURL, null));
assertNull(WebApkValidator.queryFirstWebApkPackage(
RuntimeEnvironment.application, URL_WITHOUT_WEBAPK));
......@@ -154,7 +156,7 @@ public class WebApkValidatorTest {
mPackageManager.addResolveInfoForIntent(intent, newResolveInfo(WEBAPK_PACKAGE_NAME));
mPackageManager.addPackage(newPackageInfoWithBrowserSignature(
WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE), TEST_STARTURL));
WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE), TEST_STARTURL, null));
assertTrue(WebApkValidator.canWebApkHandleUrl(
RuntimeEnvironment.application, WEBAPK_PACKAGE_NAME, URL_OF_WEBAPK));
......@@ -176,7 +178,7 @@ public class WebApkValidatorTest {
mPackageManager.addResolveInfoForIntent(intent, newResolveInfo(WEBAPK_PACKAGE_NAME));
mPackageManager.addPackage(newPackageInfoWithBrowserSignature(
WEBAPK_PACKAGE_NAME, new Signature(SIGNATURE_1), TEST_STARTURL));
WEBAPK_PACKAGE_NAME, new Signature(SIGNATURE_1), TEST_STARTURL, null));
assertFalse(WebApkValidator.canWebApkHandleUrl(
RuntimeEnvironment.application, WEBAPK_PACKAGE_NAME, URL_OF_WEBAPK));
......@@ -196,7 +198,7 @@ public class WebApkValidatorTest {
mPackageManager.addResolveInfoForIntent(intent, newResolveInfo(WEBAPK_PACKAGE_NAME));
mPackageManager.addPackage(newPackageInfoWithBrowserSignature(
WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE), TEST_STARTURL));
WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE), TEST_STARTURL, null));
assertFalse(WebApkValidator.canWebApkHandleUrl(
RuntimeEnvironment.application, WEBAPK_PACKAGE_NAME, URL_OF_WEBAPK));
......@@ -218,7 +220,7 @@ public class WebApkValidatorTest {
mPackageManager.addResolveInfoForIntent(intent, newResolveInfo(WEBAPK_PACKAGE_NAME));
mPackageManager.addPackage(newPackageInfoWithBrowserSignature(
WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE), TEST_STARTURL));
WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE), TEST_STARTURL, null));
assertFalse(WebApkValidator.canWebApkHandleUrl(
RuntimeEnvironment.application, WEBAPK_PACKAGE_NAME, URL_WITHOUT_WEBAPK));
......@@ -234,7 +236,7 @@ public class WebApkValidatorTest {
@Test
public void testIsValidWebApkReturnsTrueForValidWebApk() {
mPackageManager.addPackage(newPackageInfoWithBrowserSignature(
WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE), TEST_STARTURL));
WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE), TEST_STARTURL, null));
assertTrue(
WebApkValidator.isValidWebApk(RuntimeEnvironment.application, WEBAPK_PACKAGE_NAME));
......@@ -246,8 +248,8 @@ public class WebApkValidatorTest {
*/
@Test
public void testIsValidWebApkFalseForInvalidPackageName() {
mPackageManager.addPackage(newPackageInfoWithBrowserSignature(
INVALID_WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE), TEST_STARTURL));
mPackageManager.addPackage(newPackageInfoWithBrowserSignature(INVALID_WEBAPK_PACKAGE_NAME,
new Signature(EXPECTED_SIGNATURE), TEST_STARTURL, null));
assertFalse(WebApkValidator.isValidWebApk(
RuntimeEnvironment.application, INVALID_WEBAPK_PACKAGE_NAME));
......@@ -259,11 +261,11 @@ public class WebApkValidatorTest {
*/
@Test
public void testIsValidWebApkForMapsLite() {
mPackageManager.addPackage(newPackageInfoWithBrowserSignature(
MAPSLITE_PACKAGE_NAME, new Signature(SIGNATURE_1), MAPSLITE_EXAMPLE_STARTURL));
mPackageManager.addPackage(newPackageInfoWithBrowserSignature(MAPSLITE_PACKAGE_NAME,
new Signature(SIGNATURE_1), MAPSLITE_EXAMPLE_STARTURL, null));
mPackageManager.addPackage(
newPackageInfoWithBrowserSignature(MAPSLITE_PACKAGE_NAME + ".other",
new Signature(SIGNATURE_1), MAPSLITE_EXAMPLE_STARTURL));
new Signature(SIGNATURE_1), MAPSLITE_EXAMPLE_STARTURL, null));
assertTrue(WebApkValidator.isValidWebApk(
RuntimeEnvironment.application, MAPSLITE_PACKAGE_NAME));
......@@ -280,7 +282,7 @@ public class WebApkValidatorTest {
@Test
public void testIsNotValidWebApkForMapsLiteBadStartUrl() {
mPackageManager.addPackage(newPackageInfoWithBrowserSignature(
MAPSLITE_PACKAGE_NAME, new Signature(SIGNATURE_1), TEST_STARTURL));
MAPSLITE_PACKAGE_NAME, new Signature(SIGNATURE_1), TEST_STARTURL, null));
assertFalse(WebApkValidator.isValidWebApk(
RuntimeEnvironment.application, MAPSLITE_PACKAGE_NAME));
}
......@@ -294,7 +296,7 @@ public class WebApkValidatorTest {
Signature[] signatures = new Signature[] {new Signature(SIGNATURE_1),
new Signature(EXPECTED_SIGNATURE), new Signature(SIGNATURE_2)};
mPackageManager.addPackage(
newPackageInfo(WEBAPK_PACKAGE_NAME, signatures, null, TEST_STARTURL));
newPackageInfo(WEBAPK_PACKAGE_NAME, signatures, null, TEST_STARTURL, null));
assertFalse(
WebApkValidator.isValidWebApk(RuntimeEnvironment.application, WEBAPK_PACKAGE_NAME));
......@@ -309,7 +311,7 @@ public class WebApkValidatorTest {
Signature signatures[] =
new Signature[] {new Signature(SIGNATURE_1), new Signature(SIGNATURE_2)};
mPackageManager.addPackage(
newPackageInfo(WEBAPK_PACKAGE_NAME, signatures, null, TEST_STARTURL));
newPackageInfo(WEBAPK_PACKAGE_NAME, signatures, null, TEST_STARTURL, null));
assertFalse(
WebApkValidator.isValidWebApk(RuntimeEnvironment.application, WEBAPK_PACKAGE_NAME));
......@@ -326,8 +328,8 @@ public class WebApkValidatorTest {
for (String filename : filenames) {
mPackageManager.removePackage(packageName);
mPackageManager.addPackage(
newPackageInfo(packageName, signature, testFilePath(filename), TEST_STARTURL));
mPackageManager.addPackage(newPackageInfo(
packageName, signature, testFilePath(filename), TEST_STARTURL, null));
assertTrue(filename + " did not verify",
WebApkValidator.isValidWebApk(RuntimeEnvironment.application, packageName));
}
......@@ -352,13 +354,62 @@ public class WebApkValidatorTest {
for (String filename : filenames) {
mPackageManager.removePackage(packageName);
mPackageManager.addPackage(
newPackageInfo(packageName, signature, testFilePath(filename), TEST_STARTURL));
mPackageManager.addPackage(newPackageInfo(
packageName, signature, testFilePath(filename), TEST_STARTURL, null));
assertFalse(filename,
WebApkValidator.isValidWebApk(RuntimeEnvironment.application, packageName));
}
}
/**
* Tests {@link WebApkValidator#queryBoundWebApkForManifestUrl()} for a valid installed entry.
*/
@Test
public void testQueryBoundWebApkForManifestUrl() {
mPackageManager.addPackage(newPackageInfoWithBrowserSignature(
WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE), null, MANIFEST_URL));
assertEquals(WEBAPK_PACKAGE_NAME,
WebApkValidator.queryBoundWebApkForManifestUrl(
RuntimeEnvironment.application, MANIFEST_URL));
}
/**
* Tests {@link WebApkValidator#queryBoundWebApkForManifestUrl()} with an invalid package name.
*/
@Test
public void testQueryBoundWebApkForManifestUrlWithInvalidPackageName() {
mPackageManager.addPackage(newPackageInfoWithBrowserSignature(INVALID_WEBAPK_PACKAGE_NAME,
new Signature(EXPECTED_SIGNATURE), null, MANIFEST_URL));
assertNull(WebApkValidator.queryBoundWebApkForManifestUrl(
RuntimeEnvironment.application, MANIFEST_URL));
}
/**
* Tests {@link WebApkValidator#queryBoundWebApkForManifestUrl()} with an invalid signature.
*/
@Test
public void testQueryBoundWebApkForManifestUrlWithInvalidSignature() {
mPackageManager.addPackage(newPackageInfoWithBrowserSignature(
WEBAPK_PACKAGE_NAME, new Signature(SIGNATURE_1), null, MANIFEST_URL));
assertNull(WebApkValidator.queryBoundWebApkForManifestUrl(
RuntimeEnvironment.application, MANIFEST_URL));
}
/**
* Tests {@link WebApkValidator#queryBoundWebApkForManifestUrl()} with an invalid manifest URL.
*/
@Test
public void testQueryBoundWebApkForManifestUrlWithInvalidManifestUrl() {
mPackageManager.addPackage(newPackageInfoWithBrowserSignature(
WEBAPK_PACKAGE_NAME, new Signature(SIGNATURE_1), null, MANIFEST_URL));
assertNull(WebApkValidator.queryBoundWebApkForManifestUrl(
RuntimeEnvironment.application, "https://evil.com/manifest.json"));
}
// Get the full test file path.
private static String testFilePath(String fileName) {
return TestDir.getTestFilePath(TEST_DATA_DIR + fileName);
......@@ -372,8 +423,8 @@ public class WebApkValidatorTest {
return resolveInfo;
}
private static PackageInfo newPackageInfo(
String packageName, Signature[] signatures, String sourceDir, String startUrl) {
private static PackageInfo newPackageInfo(String packageName, Signature[] signatures,
String sourceDir, String startUrl, String manifestUrl) {
PackageInfo packageInfo = new PackageInfo();
packageInfo.packageName = packageName;
packageInfo.signatures = signatures;
......@@ -381,6 +432,7 @@ public class WebApkValidatorTest {
packageInfo.applicationInfo.metaData = new Bundle();
packageInfo.applicationInfo.metaData.putString(START_URL, startUrl + "?morestuff");
packageInfo.applicationInfo.metaData.putString(SCOPE, startUrl);
packageInfo.applicationInfo.metaData.putString(WEB_MANIFEST_URL, manifestUrl);
packageInfo.applicationInfo.sourceDir = sourceDir;
return packageInfo;
}
......@@ -388,8 +440,8 @@ public class WebApkValidatorTest {
// The browser signature is expected to always be the second signature - the first (and any
// additional ones after the second) are ignored.
private static PackageInfo newPackageInfoWithBrowserSignature(
String packageName, Signature signature, String startUrl) {
return newPackageInfo(
packageName, new Signature[] {new Signature(""), signature}, null, startUrl);
String packageName, Signature signature, String startUrl, String manifestUrl) {
return newPackageInfo(packageName, new Signature[] {new Signature(""), signature}, null,
startUrl, manifestUrl);
}
}
......@@ -7,6 +7,7 @@ package org.chromium.webapk.lib.client;
import static org.chromium.webapk.lib.common.WebApkConstants.WEBAPK_PACKAGE_PREFIX;
import static org.chromium.webapk.lib.common.WebApkMetaDataKeys.SCOPE;
import static org.chromium.webapk.lib.common.WebApkMetaDataKeys.START_URL;
import static org.chromium.webapk.lib.common.WebApkMetaDataKeys.WEB_MANIFEST_URL;
import android.content.Context;
import android.content.Intent;
......@@ -356,6 +357,40 @@ public class WebApkValidator {
}
}
/**
* Determines if a bound WebAPK generated from |manifestUrl| is installed on the device.
* @param context The context to use to check whether WebAPK is valid.
* @param manifestUrl The URL of the manifest that was used to generate the WebAPK.
* @return The WebAPK's package name if installed, or null otherwise.
*/
public static @Nullable String queryBoundWebApkForManifestUrl(
Context context, String manifestUrl) {
assert manifestUrl != null;
List<PackageInfo> packages = context.getPackageManager().getInstalledPackages(
PackageManager.GET_SIGNATURES | PackageManager.GET_META_DATA);
// Filter out unbound & invalid WebAPKs.
for (int i = 0; i < packages.size(); i++) {
PackageInfo info = packages.get(i);
if (!verifyV1WebApk(info, info.packageName)) {
continue;
}
// |info| belongs to a valid, bound, WebAPK. Check that the metadata contains
// |manifestUrl|.
String packageManifestUrl = info.applicationInfo.metaData.getString(WEB_MANIFEST_URL);
if (!TextUtils.equals(packageManifestUrl, manifestUrl)) {
continue;
}
return info.packageName;
}
return null;
}
/**
* Initializes the WebApkValidator.
* @param expectedSignature V1 WebAPK RSA signature.
......
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