| Index: content/public/android/junit/src/org/chromium/content/browser/installedapp/InstalledAppProviderTest.java
|
| diff --git a/content/public/android/junit/src/org/chromium/content/browser/installedapp/InstalledAppProviderTest.java b/content/public/android/junit/src/org/chromium/content/browser/installedapp/InstalledAppProviderTest.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..163e8c54c81d0a734e83c89d0ce62696cd263898
|
| --- /dev/null
|
| +++ b/content/public/android/junit/src/org/chromium/content/browser/installedapp/InstalledAppProviderTest.java
|
| @@ -0,0 +1,756 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package org.chromium.content.browser.installedapp;
|
| +
|
| +import android.content.pm.ApplicationInfo;
|
| +import android.content.pm.PackageManager;
|
| +import android.content.pm.PackageManager.NameNotFoundException;
|
| +import android.content.res.AssetManager;
|
| +import android.content.res.Resources;
|
| +import android.os.Bundle;
|
| +
|
| +import org.junit.Assert;
|
| +import org.junit.Before;
|
| +import org.junit.Test;
|
| +import org.junit.runner.RunWith;
|
| +
|
| +import org.robolectric.RuntimeEnvironment;
|
| +import org.robolectric.annotation.Config;
|
| +import org.robolectric.res.builder.DefaultPackageManager;
|
| +
|
| +import org.chromium.base.test.util.Feature;
|
| +import org.chromium.installedapp.mojom.InstalledAppProvider;
|
| +import org.chromium.installedapp.mojom.RelatedApplication;
|
| +import org.chromium.testing.local.LocalRobolectricTestRunner;
|
| +
|
| +import java.net.URI;
|
| +import java.net.URISyntaxException;
|
| +import java.util.HashMap;
|
| +
|
| +/**
|
| + * Ensure that the InstalledAppProvider returns the correct apps.
|
| + */
|
| +@RunWith(LocalRobolectricTestRunner.class)
|
| +@Config(manifest = Config.NONE)
|
| +public class InstalledAppProviderTest {
|
| + private static final String ASSET_STATEMENTS_KEY =
|
| + InstalledAppProviderImpl.ASSET_STATEMENTS_KEY;
|
| + private static final String RELATION_HANDLE_ALL_URLS =
|
| + "delegate_permission/common.handle_all_urls";
|
| + private static final String NAMESPACE_WEB =
|
| + InstalledAppProviderImpl.ASSET_STATEMENT_NAMESPACE_WEB;
|
| + private static final String PLATFORM_ANDROID =
|
| + InstalledAppProviderImpl.RELATED_APP_PLATFORM_ANDROID;
|
| + private static final String PLATFORM_OTHER = "itunes";
|
| + // Note: Android package name and origin deliberately unrelated (there is no requirement that
|
| + // they be the same).
|
| + private static final String PACKAGE_NAME_1 = "com.app1.package";
|
| + private static final String PACKAGE_NAME_2 = "com.app2.package";
|
| + private static final String PACKAGE_NAME_3 = "com.app3.package";
|
| + private static final String URL_UNRELATED = "https://appstore.example.com/app1";
|
| + private static final String ORIGIN = "https://example.com:8000";
|
| + private static final String URL_ON_ORIGIN =
|
| + "https://example.com:8000/path/to/page.html?key=value#fragment";
|
| + private static final String ORIGIN_SYNTAX_ERROR = "https:{";
|
| + private static final String ORIGIN_MISSING_SCHEME = "path/only";
|
| + private static final String ORIGIN_MISSING_HOST = "file:///path/piece";
|
| + private static final String ORIGIN_MISSING_PORT = "http://example.com";
|
| + private static final String ORIGIN_DIFFERENT_SCHEME = "http://example.com:8000";
|
| + private static final String ORIGIN_DIFFERENT_HOST = "https://example.org:8000";
|
| + private static final String ORIGIN_DIFFERENT_PORT = "https://example.com:8001";
|
| +
|
| + private FakePackageManager mPackageManager;
|
| + private FakePageUrlDelegate mPageUrlDelegate;
|
| + private InstalledAppProviderImpl mInstalledAppProvider;
|
| +
|
| + /**
|
| + * FakePackageManager allows for the "installation" of Android package names and setting up
|
| + * Resources for installed packages.
|
| + */
|
| + private static class FakePackageManager extends DefaultPackageManager {
|
| + private final HashMap<String, Bundle> mMetaDataMap;
|
| + private final HashMap<String, Resources> mResourceMap;
|
| +
|
| + public FakePackageManager() {
|
| + super();
|
| + mMetaDataMap = new HashMap<String, Bundle>();
|
| + mResourceMap = new HashMap<String, Resources>();
|
| + }
|
| +
|
| + @Override
|
| + public ApplicationInfo getApplicationInfo(String packageName, int flags)
|
| + throws NameNotFoundException {
|
| + if (packageName == null) throw new NullPointerException();
|
| +
|
| + Bundle metaData = mMetaDataMap.get(packageName);
|
| + if (metaData == null) throw new NameNotFoundException(packageName);
|
| +
|
| + // Create an application with this metadata (but only if |flags| allows). Doing it this
|
| + // way (rather than simply storing the ApplicationInfo in a map) ensures that the
|
| + // |flags| is set correctly.
|
| + ApplicationInfo appInfo = new ApplicationInfo();
|
| + appInfo.packageName = packageName;
|
| + if ((flags & PackageManager.GET_META_DATA) != 0) {
|
| + appInfo.metaData = metaData;
|
| + }
|
| + return appInfo;
|
| + }
|
| +
|
| + @Override
|
| + public Resources getResourcesForApplication(ApplicationInfo app)
|
| + throws NameNotFoundException {
|
| + if (app == null) throw new NullPointerException();
|
| +
|
| + Resources result = mResourceMap.get(app.packageName);
|
| + if (result == null) throw new NameNotFoundException(app.packageName);
|
| +
|
| + return result;
|
| + }
|
| +
|
| + public void setMetaDataAndResourcesForTest(
|
| + String packageName, Bundle metaData, Resources resources) {
|
| + mMetaDataMap.put(packageName, metaData);
|
| + mResourceMap.put(packageName, resources);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Fakes the Resources object, allowing lookup of a single String value.
|
| + *
|
| + * Note: The real Resources object defines a mapping to many values. This fake object only
|
| + * allows a single value in the mapping, and it must be a String (which is all that is required
|
| + * for these tests).
|
| + */
|
| + private static class FakeResources extends Resources {
|
| + private final int mId;
|
| + private final String mValue;
|
| +
|
| + // Do not warn about deprecated call to Resources(); the documentation says code is not
|
| + // supposed to create its own Resources object, but we are using it to fake out the
|
| + // Resources, and there is no other way to do that.
|
| + @SuppressWarnings("deprecation")
|
| + public FakeResources(int identifier, String value) {
|
| + super(new AssetManager(), null, null);
|
| + mId = identifier;
|
| + mValue = value;
|
| + }
|
| +
|
| + @Override
|
| + public int getIdentifier(String name, String defType, String defPackage) {
|
| + if (name == null) throw new NullPointerException();
|
| +
|
| + // There is *no guarantee* (in the Digital Asset Links spec) about what the string
|
| + // resource should be called ("asset_statements" is just an example). Therefore,
|
| + // getIdentifier cannot be used to get the asset statements string. Always fail the
|
| + // lookup here, to ensure the implementation isn't relying on any particular hard-coded
|
| + // string.
|
| + return 0;
|
| + }
|
| +
|
| + @Override
|
| + public String getString(int id) {
|
| + if (id != mId) {
|
| + throw new Resources.NotFoundException("id 0x" + Integer.toHexString(id));
|
| + }
|
| +
|
| + return mValue;
|
| + }
|
| + }
|
| +
|
| + private static final class FakePageUrlDelegate
|
| + implements InstalledAppProviderImpl.PageUrlDelegate {
|
| + private URI mPageUrl;
|
| +
|
| + public FakePageUrlDelegate(String pageUrl) {
|
| + setPageUrl(pageUrl);
|
| + }
|
| +
|
| + public void setPageUrl(String pageUrl) {
|
| + try {
|
| + mPageUrl = new URI(pageUrl);
|
| + } catch (URISyntaxException e) {
|
| + throw new AssertionError(e);
|
| + }
|
| + }
|
| +
|
| + @Override
|
| + public URI getUrl() {
|
| + return mPageUrl;
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Creates a metaData bundle with a single resource-id key.
|
| + */
|
| + private static Bundle createMetaData(String metaDataName, int metaDataResourceId) {
|
| + Bundle metaData = new Bundle();
|
| + metaData.putInt(metaDataName, metaDataResourceId);
|
| + return metaData;
|
| + }
|
| +
|
| + /**
|
| + * Sets a resource with a single key-value pair in an Android package's manifest.
|
| + *
|
| + * The value is always a string.
|
| + */
|
| + private void setStringResource(String packageName, String key, String value) {
|
| + int identifier = 0x1234;
|
| + Bundle metaData = createMetaData(key, identifier);
|
| + FakeResources resources = new FakeResources(identifier, value);
|
| + mPackageManager.setMetaDataAndResourcesForTest(packageName, metaData, resources);
|
| + }
|
| +
|
| + /**
|
| + * Creates a valid Android asset statement string.
|
| + */
|
| + private String createAssetStatement(String platform, String relation, String url) {
|
| + return String.format(
|
| + "{\"relation\": [\"%s\"], \"target\": {\"namespace\": \"%s\", \"site\": \"%s\"}}",
|
| + relation, platform, url);
|
| + }
|
| +
|
| + /**
|
| + * Sets an asset statement to an Android package's manifest (in the fake package manager).
|
| + *
|
| + * Only one asset statement can be set for a given package (if this is called twice on the same
|
| + * package, overwrites the previous asset statement).
|
| + *
|
| + * This corresponds to a Statement List in the Digital Asset Links spec v1.
|
| + */
|
| + private void setAssetStatement(
|
| + String packageName, String platform, String relation, String url) {
|
| + String statements = "[" + createAssetStatement(platform, relation, url) + "]";
|
| + setStringResource(packageName, ASSET_STATEMENTS_KEY, statements);
|
| + }
|
| +
|
| + /**
|
| + * Creates a RelatedApplication to put in the web app manifest.
|
| + */
|
| + private RelatedApplication createRelatedApplication(String platform, String id, String url) {
|
| + RelatedApplication application = new RelatedApplication();
|
| + application.platform = platform;
|
| + application.id = id;
|
| + application.url = url;
|
| + return application;
|
| + }
|
| +
|
| + /**
|
| + * Calls filterInstalledApps with the given inputs, and tests that the expected result is
|
| + * returned.
|
| + */
|
| + private void verifyInstalledApps(RelatedApplication[] manifestRelatedApps,
|
| + RelatedApplication[] expectedInstalledRelatedApps) {
|
| + mInstalledAppProvider.filterInstalledApps(
|
| + manifestRelatedApps, new InstalledAppProvider.FilterInstalledAppsResponse() {
|
| + @Override
|
| + public void call(RelatedApplication[] installedRelatedApps) {
|
| + Assert.assertEquals(
|
| + expectedInstalledRelatedApps.length, installedRelatedApps.length);
|
| +
|
| + for (int i = 0; i < installedRelatedApps.length; i++) {
|
| + Assert.assertEquals(
|
| + expectedInstalledRelatedApps[i], installedRelatedApps[i]);
|
| + }
|
| + }
|
| + });
|
| + }
|
| +
|
| + @Before
|
| + public void setUp() {
|
| + mPackageManager = new FakePackageManager();
|
| + RuntimeEnvironment.setRobolectricPackageManager(mPackageManager);
|
| + mPageUrlDelegate = new FakePageUrlDelegate(URL_ON_ORIGIN);
|
| + mInstalledAppProvider =
|
| + new InstalledAppProviderImpl(mPageUrlDelegate, RuntimeEnvironment.application);
|
| + }
|
| +
|
| + /**
|
| + * Origin of the page using the API is missing certain parts of the URI.
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testOriginMissingParts() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)};
|
| + setAssetStatement(PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN);
|
| + RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplication[] {};
|
| +
|
| + mPageUrlDelegate.setPageUrl(ORIGIN_MISSING_SCHEME);
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| +
|
| + mPageUrlDelegate.setPageUrl(ORIGIN_MISSING_HOST);
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * No related Android apps.
|
| + *
|
| + * An Android app relates to the web app, but not mutual.
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testNoRelatedApps() {
|
| + // The web manifest has no related apps.
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {};
|
| +
|
| + // One Android app is installed named |PACKAGE_NAME_1|. It has a related web app with origin
|
| + // |ORIGIN|.
|
| + setAssetStatement(PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN);
|
| +
|
| + RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplication[] {};
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * One related Android app with no id (package name).
|
| + *
|
| + * An Android app relates to the web app, but not mutual.
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testOneRelatedAppNoId() {
|
| + RelatedApplication manifestRelatedApps[] =
|
| + new RelatedApplication[] {createRelatedApplication(PLATFORM_ANDROID, null, null)};
|
| +
|
| + setAssetStatement(PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN);
|
| +
|
| + RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplication[] {};
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * One related app (from a non-Android platform).
|
| + *
|
| + * An Android app with the same id relates to the web app. This should be ignored since the
|
| + * manifest doesn't mention the Android app.
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testOneRelatedNonAndroidApp() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_OTHER, PACKAGE_NAME_1, null)};
|
| +
|
| + setAssetStatement(PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN);
|
| +
|
| + RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplication[] {};
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * One related Android app; Android app is not installed.
|
| + *
|
| + * Another Android app relates to the web app, but not mutual.
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testOneRelatedAppNotInstalled() {
|
| + // The web manifest has a related Android app named |PACKAGE_NAME_1|.
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)};
|
| +
|
| + // One Android app is installed named |PACKAGE_NAME_2|. It has a related web app with origin
|
| + // |ORIGIN|.
|
| + setAssetStatement(PACKAGE_NAME_2, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN);
|
| +
|
| + RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplication[] {};
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * Android app manifest has an asset_statements key, but the resource it links to is missing.
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testOneRelatedAppBrokenAssetStatementsResource() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)};
|
| +
|
| + Bundle metaData = createMetaData(ASSET_STATEMENTS_KEY, 0x1234);
|
| + String statements =
|
| + "[" + createAssetStatement(NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN) + "]";
|
| + FakeResources resources = new FakeResources(0x4321, statements);
|
| + mPackageManager.setMetaDataAndResourcesForTest(PACKAGE_NAME_1, metaData, resources);
|
| + RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplication[] {};
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * One related Android app; Android app is not mutually related (has no asset_statements).
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testOneRelatedAppNoAssetStatements() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)};
|
| +
|
| + setStringResource(PACKAGE_NAME_1, null, null);
|
| + RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplication[] {};
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * One related Android app; Android app is related to other origins.
|
| + *
|
| + * Tests three cases:
|
| + * - The Android app is related to a web app with a different scheme.
|
| + * - The Android app is related to a web app with a different host.
|
| + * - The Android app is related to a web app with a different port.
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testOneRelatedAppRelatedToDifferentOrigins() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)};
|
| +
|
| + setAssetStatement(
|
| + PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN_DIFFERENT_SCHEME);
|
| + RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplication[] {};
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| +
|
| + setAssetStatement(
|
| + PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN_DIFFERENT_HOST);
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| +
|
| + setAssetStatement(
|
| + PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN_DIFFERENT_PORT);
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * One related Android app; Android app is installed and mutually related.
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testOneInstalledRelatedApp() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)};
|
| +
|
| + setAssetStatement(PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN);
|
| +
|
| + RelatedApplication[] expectedInstalledRelatedApps = manifestRelatedApps;
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * Change the page URL and ensure the app relates to the new URL, not the old one.
|
| + *
|
| + * This simulates navigating the page while keeping the same Mojo service open.
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testDynamicallyChangingUrl() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)};
|
| +
|
| + setAssetStatement(
|
| + PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN_DIFFERENT_SCHEME);
|
| +
|
| + // Should be empty, since Android app does not relate to this page's origin.
|
| + RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplication[] {};
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| +
|
| + // Simulate a navigation to a different origin.
|
| + mPageUrlDelegate.setPageUrl(ORIGIN_DIFFERENT_SCHEME);
|
| +
|
| + // Now the result should include the Android app that relates to the new origin.
|
| + expectedInstalledRelatedApps = manifestRelatedApps;
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * One related Android app (installed and mutually related), with a non-null URL field.
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testInstalledRelatedAppWithUrl() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, URL_UNRELATED)};
|
| +
|
| + setAssetStatement(PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN);
|
| +
|
| + RelatedApplication[] expectedInstalledRelatedApps = manifestRelatedApps;
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * One related Android app; Android app is related to multiple origins.
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testMultipleAssetStatements() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)};
|
| +
|
| + // Create an asset_statements field with multiple statements. The second one matches the web
|
| + // app.
|
| + String statements = "["
|
| + + createAssetStatement(
|
| + NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN_DIFFERENT_HOST)
|
| + + ", " + createAssetStatement(NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN)
|
| + + "]";
|
| + setStringResource(PACKAGE_NAME_1, ASSET_STATEMENTS_KEY, statements);
|
| +
|
| + RelatedApplication[] expectedInstalledRelatedApps = manifestRelatedApps;
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * A JSON syntax error in the Android app's asset statement.
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testAssetStatementSyntaxError() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)};
|
| +
|
| + String statements = "[{\"target\" {}}]";
|
| + setStringResource(PACKAGE_NAME_1, ASSET_STATEMENTS_KEY, statements);
|
| +
|
| + RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplication[] {};
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * The Android app's asset statement is not an array.
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testAssetStatementNotArray() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)};
|
| +
|
| + String statement = createAssetStatement(NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN);
|
| + setStringResource(PACKAGE_NAME_1, ASSET_STATEMENTS_KEY, statement);
|
| +
|
| + RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplication[] {};
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * The Android app's asset statement array contains non-objects.
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testAssetStatementArrayNoObjects() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)};
|
| +
|
| + String statements = "["
|
| + + createAssetStatement(NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN) + ", 4]";
|
| + setStringResource(PACKAGE_NAME_1, ASSET_STATEMENTS_KEY, statements);
|
| +
|
| + // Expect it to ignore the integer and successfully parse the valid object.
|
| + RelatedApplication[] expectedInstalledRelatedApps = manifestRelatedApps;
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * Android app has no "relation" in the asset statement.
|
| + *
|
| + * Currently, the relation string (in the Android package's asset statement) is ignored, so the
|
| + * app is still returned as "installed".
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testAssetStatementNoRelation() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)};
|
| +
|
| + String statements = String.format(
|
| + "[{\"target\": {\"namespace\": \"%s\", \"site\": \"%s\"}}]", NAMESPACE_WEB, ORIGIN);
|
| + setStringResource(PACKAGE_NAME_1, ASSET_STATEMENTS_KEY, statements);
|
| +
|
| + // TODO(mgiuca): [Spec issue] Should we require a specific relation string, rather than any
|
| + // or no relation?
|
| + RelatedApplication[] expectedInstalledRelatedApps = manifestRelatedApps;
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * Android app is related with a non-standard relation.
|
| + *
|
| + * Currently, the relation string (in the Android package's asset statement) is ignored, so any
|
| + * will do. Is this desirable, or do we want to require a specific relation string?
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testAssetStatementNonStandardRelation() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)};
|
| +
|
| + setAssetStatement(PACKAGE_NAME_1, NAMESPACE_WEB, "nonstandard/relation", ORIGIN);
|
| +
|
| + // TODO(mgiuca): [Spec issue] Should we require a specific relation string, rather than any
|
| + // or no relation?
|
| + RelatedApplication[] expectedInstalledRelatedApps = manifestRelatedApps;
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * Android app has no "target" in the asset statement.
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testAssetStatementNoTarget() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)};
|
| +
|
| + String statements = String.format("[{\"relation\": [\"%s\"]}]", RELATION_HANDLE_ALL_URLS);
|
| + setStringResource(PACKAGE_NAME_1, ASSET_STATEMENTS_KEY, statements);
|
| +
|
| + RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplication[] {};
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * Android app has no "namespace" in the asset statement.
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testAssetStatementNoNamespace() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)};
|
| +
|
| + String statements =
|
| + String.format("[{\"relation\": [\"%s\"], \"target\": {\"site\": \"%s\"}}]",
|
| + RELATION_HANDLE_ALL_URLS, ORIGIN);
|
| + setStringResource(PACKAGE_NAME_1, ASSET_STATEMENTS_KEY, statements);
|
| +
|
| + RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplication[] {};
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * Android app is related, but not to the web namespace.
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testNonWebAssetStatement() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)};
|
| +
|
| + setAssetStatement(PACKAGE_NAME_1, "play", RELATION_HANDLE_ALL_URLS, ORIGIN);
|
| +
|
| + RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplication[] {};
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * Android app has no "site" in the asset statement.
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testAssetStatementNoSite() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)};
|
| +
|
| + String statements =
|
| + String.format("[{\"relation\": [\"%s\"], \"target\": {\"namespace\": \"%s\"}}]",
|
| + RELATION_HANDLE_ALL_URLS, NAMESPACE_WEB);
|
| + setStringResource(PACKAGE_NAME_1, ASSET_STATEMENTS_KEY, statements);
|
| +
|
| + RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplication[] {};
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * Android app has a syntax error in the "site" field of the asset statement.
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testAssetStatementSiteSyntaxError() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)};
|
| +
|
| + setAssetStatement(
|
| + PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN_SYNTAX_ERROR);
|
| +
|
| + RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplication[] {};
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * Android app has a "site" field missing certain parts of the URI (scheme, host, port).
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testAssetStatementSiteMissingParts() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)};
|
| +
|
| + setAssetStatement(
|
| + PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN_MISSING_SCHEME);
|
| + RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplication[] {};
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| +
|
| + setAssetStatement(
|
| + PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN_MISSING_HOST);
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| +
|
| + setAssetStatement(
|
| + PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN_MISSING_PORT);
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * One related Android app; Android app is related with a path part in the "site" field.
|
| + *
|
| + * The path part shouldn't really be there (according to the Digital Asset Links spec), but if
|
| + * it is, we are lenient and just ignore it (matching only the origin).
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testAssetStatementSiteHasPath() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)};
|
| +
|
| + String site = ORIGIN + "/path";
|
| + setAssetStatement(PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, site);
|
| +
|
| + RelatedApplication[] expectedInstalledRelatedApps = manifestRelatedApps;
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * One related Android app; Android app is installed and mutually related.
|
| + *
|
| + * Another Android app relates to the web app, but not mutual.
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testExtraInstalledApp() {
|
| + RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)};
|
| +
|
| + setAssetStatement(PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN);
|
| + setAssetStatement(PACKAGE_NAME_2, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN);
|
| +
|
| + RelatedApplication[] expectedInstalledRelatedApps = manifestRelatedApps;
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +
|
| + /**
|
| + * Two related Android apps; Android apps both installed and mutually related.
|
| + *
|
| + * Web app also related to an app with the same name on another platform, and another Android
|
| + * app which is not installed.
|
| + */
|
| + @Test
|
| + @Feature({"InstalledApp"})
|
| + public void testMultipleInstalledRelatedApps() {
|
| + RelatedApplication[] manifestRelatedApps = new RelatedApplication[] {
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null),
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_2, null),
|
| + createRelatedApplication(PLATFORM_OTHER, PACKAGE_NAME_2, null),
|
| + createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_3, null)};
|
| +
|
| + setAssetStatement(PACKAGE_NAME_2, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN);
|
| + setAssetStatement(PACKAGE_NAME_3, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN);
|
| +
|
| + RelatedApplication[] expectedInstalledRelatedApps =
|
| + new RelatedApplication[] {manifestRelatedApps[1], manifestRelatedApps[3]};
|
| + verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps);
|
| + }
|
| +}
|
|
|