Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Filter allowed CustomTabs browsers #353

Merged
merged 9 commits into from
Sep 25, 2020
Prev Previous commit
Next Next commit
add tests for the BrowserPicker class
  • Loading branch information
lbalmaceda committed Sep 23, 2020
commit 2070eb9fe9b9ab0954a45145e175190c0b8190c8
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,16 @@ String getBestBrowserPackage(@NonNull PackageManager pm) {
}
}

//If the browser packages were filtered, use the allowed packages list as preference.
//If the browser packages were filtered, use the allowed packages list as order preference.
//A user-selected default browser will always be picked up first.
List<String> preferenceList = isFilterEnabled ? allowedPackages : CHROME_BROWSERS;
List<String> preferenceList = allowedPackages;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the order of preference is dictated by either the "allowed packages" in the case that the developer has provided those, or the default browser + chrome browsers, in the case of the legacy scenario

if (!isFilterEnabled) {
preferenceList = new ArrayList<>();
if (defaultBrowser != null) {
preferenceList.add(defaultBrowser);
}
preferenceList.addAll(CHROME_BROWSERS);
}

//If the list was filtered, the customTabsBrowsers and regularBrowsers Lists will contain only allowed packages.
final String customTabBrowser = getFirstMatch(customTabsBrowsers, preferenceList, defaultBrowser);
Expand Down
201 changes: 194 additions & 7 deletions auth0/src/test/java/com/auth0/android/provider/BrowserPickerTest.java
Original file line number Diff line number Diff line change
@@ -1,38 +1,225 @@
package com.auth0.android.provider;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.test.espresso.intent.matcher.IntentMatchers;

import org.hamcrest.MatcherAssert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import static org.robolectric.Robolectric.setupActivity;

@RunWith(RobolectricTestRunner.class)
@Config(sdk = 18)
public class BrowserPickerTest {
private static final String CHROME_STABLE = "com.android.chrome";
private static final String CHROME_SYSTEM = "com.google.android.apps.chrome";
private static final String CHROME_BETA = "com.android.chrome.beta";
private static final String CHROME_DEV = "com.android.chrome.dev";
private static final String CUSTOM_BROWSER_1 = "com.browser.customtabs1";
private static final String CUSTOM_BROWSER_2 = "com.browser.customtabs2";
private static final List<String> ALL_BROWSERS = Arrays.asList(
CHROME_BETA, CHROME_SYSTEM,
CHROME_STABLE, CHROME_DEV,
CUSTOM_BROWSER_1, CUSTOM_BROWSER_2);

private Activity activity;
private BrowserPicker allBrowserPicker;
private BrowserPicker filteredBrowserPicker;
private static final List<String> PACKAGES_TO_FILTER_FROM = Arrays.asList(CUSTOM_BROWSER_1, CUSTOM_BROWSER_2, CHROME_DEV);

@Before
public void setUp() {
activity = spy(setupActivity(Activity.class));
allBrowserPicker = BrowserPicker.newBuilder().build();
filteredBrowserPicker = BrowserPicker.newBuilder().withAllowedPackages(PACKAGES_TO_FILTER_FROM).build();
}

// ********************************************************************************
// ** Regular non-filtered picker: Asserts we don't change the previous behavior **
// ********************************************************************************
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tests for maintaining legacy behavior below


@Test
public void shouldReturnNullBrowserIfNoBrowserAvailable() {
setupBrowserContext(activity, Collections.<String>emptyList(), null, null);
String bestPackage = allBrowserPicker.getBestBrowserPackage(activity.getPackageManager());
MatcherAssert.assertThat(bestPackage, is(nullValue()));
}

@Test
public void shouldPreferDefaultBrowserIfIsCustomTabsCapable() {
setupBrowserContext(activity, ALL_BROWSERS, Arrays.asList(CUSTOM_BROWSER_1, CUSTOM_BROWSER_2), CUSTOM_BROWSER_1);
String bestPackage = allBrowserPicker.getBestBrowserPackage(activity.getPackageManager());
MatcherAssert.assertThat(bestPackage, is(CUSTOM_BROWSER_1));
}

@Test
public void shouldPreferFirstCustomTabsCapableBrowserOverNotCustomTabsCapableDefault() {
setupBrowserContext(activity, ALL_BROWSERS, Arrays.asList(CUSTOM_BROWSER_1, CUSTOM_BROWSER_2), CHROME_DEV);
String bestPackage = allBrowserPicker.getBestBrowserPackage(activity.getPackageManager());
MatcherAssert.assertThat(bestPackage, is(CUSTOM_BROWSER_1));
}

@Test
public void shouldPreferDefaultBrowserIfNoneIsCustomTabsCapable() {
setupBrowserContext(activity, ALL_BROWSERS, null, CHROME_DEV);
String bestPackage = allBrowserPicker.getBestBrowserPackage(activity.getPackageManager());
MatcherAssert.assertThat(bestPackage, is(CHROME_DEV));
}

@Test
public void shouldPreferChromeBrowsersIfDefaultBrowserIsNotSet() {
List<String> currentBrowsers = Arrays.asList(CHROME_BETA, CHROME_SYSTEM, CHROME_STABLE, CHROME_DEV, CUSTOM_BROWSER_1, CUSTOM_BROWSER_2);
setupBrowserContext(activity, currentBrowsers, null, null);
String bestPackage = allBrowserPicker.getBestBrowserPackage(activity.getPackageManager());
MatcherAssert.assertThat(bestPackage, is(CHROME_STABLE));

currentBrowsers = Arrays.asList(CHROME_BETA, CHROME_SYSTEM, CHROME_DEV, CUSTOM_BROWSER_1, CUSTOM_BROWSER_2);
setupBrowserContext(activity, currentBrowsers, null, null);
bestPackage = allBrowserPicker.getBestBrowserPackage(activity.getPackageManager());
MatcherAssert.assertThat(bestPackage, is(CHROME_SYSTEM));

currentBrowsers = Arrays.asList(CHROME_BETA, CHROME_DEV, CUSTOM_BROWSER_1, CUSTOM_BROWSER_2);
setupBrowserContext(activity, currentBrowsers, null, null);
bestPackage = allBrowserPicker.getBestBrowserPackage(activity.getPackageManager());
MatcherAssert.assertThat(bestPackage, is(CHROME_BETA));

currentBrowsers = Arrays.asList(CHROME_DEV, CUSTOM_BROWSER_1, CUSTOM_BROWSER_2);
setupBrowserContext(activity, currentBrowsers, null, null);
bestPackage = allBrowserPicker.getBestBrowserPackage(activity.getPackageManager());
MatcherAssert.assertThat(bestPackage, is(CHROME_DEV));

currentBrowsers = Arrays.asList(CUSTOM_BROWSER_1, CUSTOM_BROWSER_2);
setupBrowserContext(activity, currentBrowsers, null, null);
bestPackage = allBrowserPicker.getBestBrowserPackage(activity.getPackageManager());
MatcherAssert.assertThat(bestPackage, is(currentBrowsers.get(0)));

currentBrowsers = Collections.singletonList(CUSTOM_BROWSER_1);
setupBrowserContext(activity, currentBrowsers, null, null);
bestPackage = allBrowserPicker.getBestBrowserPackage(activity.getPackageManager());
MatcherAssert.assertThat(bestPackage, is(currentBrowsers.get(0)));
}

@Test
public void shouldMaintainLegacyBehavior() {
List<String> currentBrowsers = Arrays.asList(CHROME_BETA, CHROME_SYSTEM, CHROME_STABLE, CHROME_DEV, CUSTOM_BROWSER_1, CUSTOM_BROWSER_2);
List<String> currentCompatibleBrowsers = Arrays.asList(CHROME_BETA, CHROME_SYSTEM, CHROME_STABLE, CHROME_DEV, CUSTOM_BROWSER_1);
setupBrowserContext(activity, currentBrowsers, currentCompatibleBrowsers, CUSTOM_BROWSER_2);
String bestPackage = allBrowserPicker.getBestBrowserPackage(activity.getPackageManager());
MatcherAssert.assertThat(bestPackage, is(CHROME_STABLE));

currentBrowsers = Arrays.asList(CHROME_BETA, CHROME_SYSTEM, CHROME_DEV, CUSTOM_BROWSER_1, CUSTOM_BROWSER_2);
currentCompatibleBrowsers = Arrays.asList(CHROME_BETA, CHROME_SYSTEM, CHROME_DEV, CUSTOM_BROWSER_1);
setupBrowserContext(activity, currentBrowsers, currentCompatibleBrowsers, CUSTOM_BROWSER_2);
bestPackage = allBrowserPicker.getBestBrowserPackage(activity.getPackageManager());
MatcherAssert.assertThat(bestPackage, is(CHROME_SYSTEM));

currentBrowsers = Arrays.asList(CHROME_BETA, CHROME_DEV, CUSTOM_BROWSER_1, CUSTOM_BROWSER_2);
currentCompatibleBrowsers = Arrays.asList(CHROME_BETA, CHROME_DEV, CUSTOM_BROWSER_1);
setupBrowserContext(activity, currentBrowsers, currentCompatibleBrowsers, CUSTOM_BROWSER_2);
bestPackage = allBrowserPicker.getBestBrowserPackage(activity.getPackageManager());
MatcherAssert.assertThat(bestPackage, is(CHROME_BETA));

currentBrowsers = Arrays.asList(CHROME_DEV, CUSTOM_BROWSER_1, CUSTOM_BROWSER_2);
currentCompatibleBrowsers = Arrays.asList(CHROME_DEV, CUSTOM_BROWSER_1);
setupBrowserContext(activity, currentBrowsers, currentCompatibleBrowsers, CUSTOM_BROWSER_2);
bestPackage = allBrowserPicker.getBestBrowserPackage(activity.getPackageManager());
MatcherAssert.assertThat(bestPackage, is(CHROME_DEV));

currentBrowsers = Arrays.asList(CUSTOM_BROWSER_1, CUSTOM_BROWSER_2);
currentCompatibleBrowsers = Arrays.asList(CUSTOM_BROWSER_1);
setupBrowserContext(activity, currentBrowsers, currentCompatibleBrowsers, CUSTOM_BROWSER_2);
bestPackage = allBrowserPicker.getBestBrowserPackage(activity.getPackageManager());
MatcherAssert.assertThat(bestPackage, is(currentCompatibleBrowsers.get(0)));

currentBrowsers = Collections.singletonList(CUSTOM_BROWSER_1);
currentCompatibleBrowsers = Arrays.asList();
setupBrowserContext(activity, currentBrowsers, currentCompatibleBrowsers, CUSTOM_BROWSER_2);
bestPackage = allBrowserPicker.getBestBrowserPackage(activity.getPackageManager());
MatcherAssert.assertThat(bestPackage, is(CUSTOM_BROWSER_1));
}

// ********************************************************************************
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tests for the introduced changes (allowed list filtering) below

// ** Filtered picker: Filters by allowed packages and their order of preference **
// ** Filtered browser packages: CUSTOM_BROWSER_1, CUSTOM_BROWSER_2, and CHROME_DEV
// ********************************************************************************

@Test
public void whenFilteringShouldPreferFirstCustomTabsCapableBrowserOverNotCustomTabsCapableDefault() {
setupBrowserContext(activity, ALL_BROWSERS, Arrays.asList(CUSTOM_BROWSER_1, CUSTOM_BROWSER_2), CHROME_DEV);
String bestPackage = filteredBrowserPicker.getBestBrowserPackage(activity.getPackageManager());
MatcherAssert.assertThat(bestPackage, is(CUSTOM_BROWSER_1));
}

@Test
public void whenFilteringShouldPreferDefaultBrowserIfIsCustomTabsCapable() {
setupBrowserContext(activity, ALL_BROWSERS, Arrays.asList(CUSTOM_BROWSER_1, CUSTOM_BROWSER_2), CUSTOM_BROWSER_1);
String bestPackage = filteredBrowserPicker.getBestBrowserPackage(activity.getPackageManager());
MatcherAssert.assertThat(bestPackage, is(CUSTOM_BROWSER_1));
}

@Test
public void whenFilteringShouldNeverPickRestrictedBrowsers() {
List<String> currentBrowsers = Arrays.asList(CHROME_BETA, CHROME_SYSTEM, CHROME_STABLE, CHROME_DEV, CUSTOM_BROWSER_1, CUSTOM_BROWSER_2);
setupBrowserContext(activity, currentBrowsers, Collections.singletonList(CHROME_STABLE), CHROME_STABLE);
String bestPackage = filteredBrowserPicker.getBestBrowserPackage(activity.getPackageManager());
MatcherAssert.assertThat(bestPackage, is(PACKAGES_TO_FILTER_FROM.get(0)));

currentBrowsers = Arrays.asList(CHROME_BETA, CUSTOM_BROWSER_2);
setupBrowserContext(activity, currentBrowsers, Collections.singletonList(CHROME_STABLE), CHROME_STABLE);
bestPackage = filteredBrowserPicker.getBestBrowserPackage(activity.getPackageManager());
MatcherAssert.assertThat(bestPackage, is(CUSTOM_BROWSER_2));

currentBrowsers = Arrays.asList(CHROME_BETA, CUSTOM_BROWSER_2, CUSTOM_BROWSER_1);
setupBrowserContext(activity, currentBrowsers, Collections.singletonList(CUSTOM_BROWSER_1), CUSTOM_BROWSER_1);
bestPackage = filteredBrowserPicker.getBestBrowserPackage(activity.getPackageManager());
MatcherAssert.assertThat(bestPackage, is(CUSTOM_BROWSER_1));
}


static void setupBrowserContext(@NonNull Context context, @NonNull String[] customTabEnabledPackages, @Nullable String defaultBrowserPackage) {
/**
* Sets up a given context for using browsers with Custom Tabs.
* Optionally, supports specifying which of those browsers is set as default by the user.
*/
static void setupBrowserContext(@NonNull Context context, @NonNull List<String> browserPackages, @Nullable List<String> customTabPackages, @Nullable String defaultBrowserPackage) {
PackageManager pm = mock(PackageManager.class);
when(context.getPackageManager()).thenReturn(pm);
ResolveInfo defaultPackage = resolveInfoForPackageName(defaultBrowserPackage);
when(pm.resolveActivity(any(Intent.class), anyInt())).thenReturn(defaultPackage);

List<ResolveInfo> customTabsCapable = new ArrayList<>();
for (String customTabEnabledPackage : customTabEnabledPackages) {
ResolveInfo info = resolveInfoForPackageName(customTabEnabledPackage);
when(pm.resolveService(any(Intent.class), eq(0))).thenReturn(info);
customTabsCapable.add(info);
List<ResolveInfo> allBrowsers = new ArrayList<>();
for (String browser : browserPackages) {
ResolveInfo info = resolveInfoForPackageName(browser);
if (customTabPackages != null && customTabPackages.contains(browser)) {
when(pm.resolveService(Matchers.argThat(IntentMatchers.hasPackage(browser)), eq(0))).thenReturn(info);
}
allBrowsers.add(info);
}
when(pm.queryIntentActivities(any(Intent.class), eq(0))).thenReturn(customTabsCapable);
when(pm.queryIntentActivities(any(Intent.class), eq(0))).thenReturn(allBrowsers);
}

private static ResolveInfo resolveInfoForPackageName(@Nullable String packageName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Color;
import android.net.Uri;
import android.support.customtabs.CustomTabsCallback;
Expand All @@ -30,7 +27,6 @@
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;

import java.util.ArrayList;
import java.util.List;

import static android.support.test.espresso.intent.matcher.IntentMatchers.hasFlag;
Expand Down Expand Up @@ -239,92 +235,4 @@ private void connectBoundService() throws Exception {
verify(customTabsClient).newSession(Matchers.<CustomTabsCallback>eq(null));
verify(customTabsClient).warmup(eq(0L));
}

// @Test
// public void shouldChooseNullBrowserIfNoBrowserAvailable() {
// ctOptions
// String bestPackage = CustomTabsController.getBestSupportedBrowserPackage(context, null);
// MatcherAssert.assertThat(bestPackage, is(nullValue()));
// }
//
// @Test
// public void shouldChooseDefaultBrowserIfIsCustomTabsCapable() {
// preparePackageManagerForCustomTabs(DEFAULT_BROWSER_PACKAGE, DEFAULT_BROWSER_PACKAGE);
// String bestPackage = CustomTabsController.getBestSupportedBrowserPackage(context, null);
// MatcherAssert.assertThat(bestPackage, is(DEFAULT_BROWSER_PACKAGE));
// }
//
// @Test
// public void shouldReturnNullIfNoBrowserIsCustomTabsCapable() {
// preparePackageManagerForCustomTabs(DEFAULT_BROWSER_PACKAGE);
// String bestPackage = CustomTabsController.getBestSupportedBrowserPackage(context, null);
// MatcherAssert.assertThat(bestPackage, is(nullValue()));
// }
//
// @Test
// public void shouldChooseChromeStableOverOtherCustomTabsCapableBrowsers() {
// preparePackageManagerForCustomTabs(DEFAULT_BROWSER_PACKAGE, CHROME_STABLE_PACKAGE, CHROME_SYSTEM_PACKAGE, CHROME_BETA_PACKAGE, CHROME_DEV_PACKAGE, CUSTOM_TABS_BROWSER_1, CUSTOM_TABS_BROWSER_2);
// String bestPackage = CustomTabsController.getBestSupportedBrowserPackage(context, null);
// MatcherAssert.assertThat(bestPackage, is(CHROME_STABLE_PACKAGE));
// }
//
// @Test
// public void shouldChooseChromeSystemOverOtherCustomTabsCapableBrowsers() {
// preparePackageManagerForCustomTabs(DEFAULT_BROWSER_PACKAGE, CHROME_SYSTEM_PACKAGE, CHROME_BETA_PACKAGE, CHROME_DEV_PACKAGE, CUSTOM_TABS_BROWSER_1, CUSTOM_TABS_BROWSER_2);
// String bestPackage = CustomTabsController.getBestSupportedBrowserPackage(context, null);
// MatcherAssert.assertThat(bestPackage, is(CHROME_SYSTEM_PACKAGE));
// }
//
// @Test
// public void shouldChooseChromeBetaOverOtherCustomTabsCapableBrowsers() {
// preparePackageManagerForCustomTabs(DEFAULT_BROWSER_PACKAGE, CHROME_BETA_PACKAGE, CHROME_DEV_PACKAGE, CUSTOM_TABS_BROWSER_1, CUSTOM_TABS_BROWSER_2);
// String bestPackage = CustomTabsController.getBestSupportedBrowserPackage(context, null);
// MatcherAssert.assertThat(bestPackage, is(CHROME_BETA_PACKAGE));
// }
//
// @Test
// public void shouldChooseChromeDevOverOtherCustomTabsCapableBrowsers() {
// preparePackageManagerForCustomTabs(DEFAULT_BROWSER_PACKAGE, CHROME_DEV_PACKAGE, CUSTOM_TABS_BROWSER_1, CUSTOM_TABS_BROWSER_2);
// String bestPackage = CustomTabsController.getBestSupportedBrowserPackage(context, null);
// MatcherAssert.assertThat(bestPackage, is(CHROME_DEV_PACKAGE));
// }
//
// @Test
// public void shouldChooseCustomTabsCapableBrowserIfAvailable() {
// preparePackageManagerForCustomTabs(DEFAULT_BROWSER_PACKAGE, CUSTOM_TABS_BROWSER_1, CUSTOM_TABS_BROWSER_2);
// String bestPackage = CustomTabsController.getBestSupportedBrowserPackage(context, null);
// MatcherAssert.assertThat(bestPackage, is(CUSTOM_TABS_BROWSER_1));
// }
// private static final String CHROME_STABLE_PACKAGE = "com.android.chrome";
// private static final String CHROME_SYSTEM_PACKAGE = "com.google.android.apps.chrome";
// private static final String CHROME_BETA_PACKAGE = "com.android.chrome.beta";
// private static final String CHROME_DEV_PACKAGE = "com.android.chrome.dev";
// private static final String CUSTOM_TABS_BROWSER_1 = "com.browser.customtabs1";
// private static final String CUSTOM_TABS_BROWSER_2 = "com.browser.customtabs2";

@SuppressWarnings("WrongConstant")
private void preparePackageManagerForCustomTabs(String defaultBrowserPackage, String... customTabEnabledPackages) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved to BrowserPicker

PackageManager pm = mock(PackageManager.class);
when(context.getPackageManager()).thenReturn(pm);
ResolveInfo defaultPackage = resolveInfoForPackageName(defaultBrowserPackage);
when(pm.resolveActivity(any(Intent.class), anyInt())).thenReturn(defaultPackage);

List<ResolveInfo> customTabsCapable = new ArrayList<>();
for (String customTabEnabledPackage : customTabEnabledPackages) {
ResolveInfo info = resolveInfoForPackageName(customTabEnabledPackage);
when(pm.resolveService(any(Intent.class), eq(0))).thenReturn(info);
customTabsCapable.add(info);
}
when(pm.queryIntentActivities(any(Intent.class), eq(0))).thenReturn(customTabsCapable);
}

private ResolveInfo resolveInfoForPackageName(String packageName) {
if (packageName == null) {
return null;
}
ResolveInfo resInfo = mock(ResolveInfo.class);
resInfo.activityInfo = new ActivityInfo();
resInfo.activityInfo.packageName = packageName;
return resInfo;
}
}
Loading