Commit 6e196c29 authored by Peter Kotwicz's avatar Peter Kotwicz Committed by Commit Bot

[Android WebAPK] Enable launching non-Chrome browser from WebAPK

This CL changes the WebAPK host browser selection logic to launch a
non-Chrome browser if:
  - there is no installed Chrome browser
  AND
  - the non-Chrome browser is the default browser

BUG=1008716

Change-Id: Id14860628d6d170c0aee2e843ca719c1e94652d4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1828351
Commit-Queue: Peter Kotwicz <pkotwicz@chromium.org>
Reviewed-by: default avatarYaron Friedman <yfriedman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#701416}
parent 11e2fb46
...@@ -12,4 +12,4 @@ ...@@ -12,4 +12,4 @@
# //chrome/android/webapk/shell_apk:webapk is changed. This includes # //chrome/android/webapk/shell_apk:webapk is changed. This includes
# Java files, Android resource files and AndroidManifest.xml. Does not affect # Java files, Android resource files and AndroidManifest.xml. Does not affect
# Chrome.apk # Chrome.apk
current_shell_apk_version = 108 current_shell_apk_version = 109
...@@ -193,6 +193,16 @@ public class HostBrowserUtilsTest { ...@@ -193,6 +193,16 @@ public class HostBrowserUtilsTest {
setHostBrowserInSharedPreferences(null); setHostBrowserInSharedPreferences(null);
Assert.assertEquals(BROWSERS_SUPPORTING_WEBAPKS[0], Assert.assertEquals(BROWSERS_SUPPORTING_WEBAPKS[0],
HostBrowserUtils.computeHostBrowserPackageClearCachedDataOnChange(mContext)); HostBrowserUtils.computeHostBrowserPackageClearCachedDataOnChange(mContext));
// Shared pref browser: Null
// Default browser: Does not support WebAPKs
// > 1 installed browsers
setInstalledBrowsersAndClearedCachedData(DefaultBrowserWebApkSupport.NO,
new String[] {
BROWSERS_NOT_SUPPORTING_WEBAPKS[0], BROWSERS_NOT_SUPPORTING_WEBAPKS[1]});
setHostBrowserInSharedPreferences(null);
Assert.assertEquals(DEFAULT_BROWSER_NOT_SUPPORTING_WEBAPKS,
HostBrowserUtils.computeHostBrowserPackageClearCachedDataOnChange(mContext));
} }
/** /**
......
...@@ -32,13 +32,15 @@ import org.chromium.webapk.test.WebApkTestHelper; ...@@ -32,13 +32,15 @@ import org.chromium.webapk.test.WebApkTestHelper;
@RunWith(LocalRobolectricTestRunner.class) @RunWith(LocalRobolectricTestRunner.class)
@Config(manifest = Config.NONE) @Config(manifest = Config.NONE)
public final class MainActivityTest { public final class MainActivityTest {
private PackageManager mPackageManager;
private static final String BROWSER_PACKAGE_NAME = "com.android.chrome"; private static final String BROWSER_PACKAGE_NAME = "com.android.chrome";
private PackageManager mPackageManager;
private TestBrowserInstaller mBrowserInstaller = new TestBrowserInstaller();
@Before @Before
public void setUp() { public void setUp() {
mPackageManager = RuntimeEnvironment.application.getPackageManager(); mPackageManager = RuntimeEnvironment.application.getPackageManager();
new TestBrowserInstaller().installModernBrowser(BROWSER_PACKAGE_NAME); mBrowserInstaller.installModernBrowser(BROWSER_PACKAGE_NAME);
} }
/** /**
...@@ -177,14 +179,41 @@ public final class MainActivityTest { ...@@ -177,14 +179,41 @@ public final class MainActivityTest {
assertWebApkLaunched(startedActivityIntent, expectedStartUrl); assertWebApkLaunched(startedActivityIntent, expectedStartUrl);
} }
/**
* Tests that if the only installed browser does not support WebAPKs that the browser is
* launched in tabbed mode.
*/
@Test
public void testShouldLaunchInTabNonChromeBrowser() throws Exception {
final String nonChromeBrowserPackageName = "com.crazy.browser";
mBrowserInstaller.setInstalledBrowserWithVersion(
nonChromeBrowserPackageName, "10000.0.000.0");
final String startUrl = "https://www.google.com/";
Bundle bundle = new Bundle();
bundle.putString(WebApkMetaDataKeys.START_URL, startUrl);
bundle.putString(WebApkMetaDataKeys.SCOPE, startUrl);
// Unbound WebAPK, no runtime host.
WebApkTestHelper.registerWebApkWithMetaData(
WebApkUtilsTest.WEBAPK_PACKAGE_NAME, bundle, null /* shareTargetMetaData */);
Intent launchIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(startUrl));
Robolectric.buildActivity(MainActivity.class, launchIntent).create();
Intent startedActivityIntent = ShadowApplication.getInstance().getNextStartedActivity();
assertTabbedBrowserLaunched(startedActivityIntent, nonChromeBrowserPackageName, startUrl);
}
/** /**
* Tests that a WebAPK should be launched as a tab if Chrome's version number is lower than * Tests that a WebAPK should be launched as a tab if Chrome's version number is lower than
* {@link HostBrowserUtils#MINIMUM_REQUIRED_CHROME_VERSION}. * {@link HostBrowserUtils#MINIMUM_REQUIRED_CHROME_VERSION}.
*/ */
@Test @Test
public void testShouldLaunchInTabWhenChromeVersionIsTooLow() throws Exception { public void testShouldLaunchInTabWhenChromeVersionIsTooLow() throws Exception {
mBrowserInstaller.setInstalledBrowserWithVersion(BROWSER_PACKAGE_NAME, "56.0.000.0");
final String startUrl = "https://www.google.com/"; final String startUrl = "https://www.google.com/";
final String oldVersionName = "56.0.000.0";
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putString(WebApkMetaDataKeys.START_URL, startUrl); bundle.putString(WebApkMetaDataKeys.START_URL, startUrl);
...@@ -193,15 +222,11 @@ public final class MainActivityTest { ...@@ -193,15 +222,11 @@ public final class MainActivityTest {
WebApkTestHelper.registerWebApkWithMetaData( WebApkTestHelper.registerWebApkWithMetaData(
WebApkUtilsTest.WEBAPK_PACKAGE_NAME, bundle, null /* shareTargetMetaData */); WebApkUtilsTest.WEBAPK_PACKAGE_NAME, bundle, null /* shareTargetMetaData */);
mPackageManager.getPackageInfo(BROWSER_PACKAGE_NAME, 0).versionName = oldVersionName;
Intent launchIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(startUrl)); Intent launchIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(startUrl));
Robolectric.buildActivity(MainActivity.class, launchIntent).create(); Robolectric.buildActivity(MainActivity.class, launchIntent).create();
Intent startedActivityIntent = ShadowApplication.getInstance().getNextStartedActivity(); Intent startedActivityIntent = ShadowApplication.getInstance().getNextStartedActivity();
Assert.assertEquals(BROWSER_PACKAGE_NAME, startedActivityIntent.getPackage()); assertTabbedBrowserLaunched(startedActivityIntent, BROWSER_PACKAGE_NAME, startUrl);
Assert.assertEquals(Intent.ACTION_VIEW, startedActivityIntent.getAction());
Assert.assertEquals(startUrl, startedActivityIntent.getDataString());
} }
/** /**
...@@ -210,8 +235,9 @@ public final class MainActivityTest { ...@@ -210,8 +235,9 @@ public final class MainActivityTest {
*/ */
@Test @Test
public void testShouldNotLaunchInTabWithNewVersionOfChrome() throws Exception { public void testShouldNotLaunchInTabWithNewVersionOfChrome() throws Exception {
mBrowserInstaller.setInstalledBrowserWithVersion(BROWSER_PACKAGE_NAME, "57.0.000.0");
final String startUrl = "https://www.google.com/"; final String startUrl = "https://www.google.com/";
final String newVersionName = "57.0.000.0";
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putString(WebApkMetaDataKeys.START_URL, startUrl); bundle.putString(WebApkMetaDataKeys.START_URL, startUrl);
...@@ -220,8 +246,6 @@ public final class MainActivityTest { ...@@ -220,8 +246,6 @@ public final class MainActivityTest {
WebApkTestHelper.registerWebApkWithMetaData( WebApkTestHelper.registerWebApkWithMetaData(
WebApkUtilsTest.WEBAPK_PACKAGE_NAME, bundle, null /* shareTargetMetaData */); WebApkUtilsTest.WEBAPK_PACKAGE_NAME, bundle, null /* shareTargetMetaData */);
mPackageManager.getPackageInfo(BROWSER_PACKAGE_NAME, 0).versionName = newVersionName;
Intent launchIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(startUrl)); Intent launchIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(startUrl));
Robolectric.buildActivity(MainActivity.class, launchIntent).create(); Robolectric.buildActivity(MainActivity.class, launchIntent).create();
...@@ -266,6 +290,17 @@ public final class MainActivityTest { ...@@ -266,6 +290,17 @@ public final class MainActivityTest {
} }
} }
/**
* Asserts that the passed-in intent is an intent to launch the passed-in browser package in
* tabbed mode.
*/
private void assertTabbedBrowserLaunched(
Intent intent, String browserPackageName, String expectedStartUrl) {
Assert.assertEquals(browserPackageName, intent.getPackage());
Assert.assertEquals(Intent.ACTION_VIEW, intent.getAction());
Assert.assertEquals(expectedStartUrl, intent.getDataString());
}
/** /**
* Asserts that the passed in intent is an intent to launch {@link BROWSER_PACKAGE_NAME} in * Asserts that the passed in intent is an intent to launch {@link BROWSER_PACKAGE_NAME} in
* WebAPK mode. * WebAPK mode.
......
...@@ -28,9 +28,7 @@ public class TestBrowserInstaller { ...@@ -28,9 +28,7 @@ public class TestBrowserInstaller {
* Changes the installed browsers to the passed-in list. * Changes the installed browsers to the passed-in list.
*/ */
public void setInstalledModernBrowsers(String defaultBrowserPackage, String[] newPackages) { public void setInstalledModernBrowsers(String defaultBrowserPackage, String[] newPackages) {
while (!mInstalledBrowsers.isEmpty()) { uninstallAllBrowsers();
uninstallBrowser(mInstalledBrowsers.iterator().next());
}
installModernBrowser(defaultBrowserPackage); installModernBrowser(defaultBrowserPackage);
if (newPackages != null) { if (newPackages != null) {
...@@ -40,6 +38,14 @@ public class TestBrowserInstaller { ...@@ -40,6 +38,14 @@ public class TestBrowserInstaller {
} }
} }
/**
* Changes the installed browser to a browser with the passed-in package and version name.
*/
public void setInstalledBrowserWithVersion(String browser, String versionName) {
uninstallAllBrowsers();
installBrowserWithVersion(browser, versionName);
}
/** /**
* Installs browser with the passed-in package name and large version name. * Installs browser with the passed-in package name and large version name.
*/ */
...@@ -48,7 +54,7 @@ public class TestBrowserInstaller { ...@@ -48,7 +54,7 @@ public class TestBrowserInstaller {
} }
/** /**
* Installs browser with the passed-in package name and version code. * Installs browser with the passed-in package name and version name.
*/ */
public void installBrowserWithVersion(String packageName, String versionName) { public void installBrowserWithVersion(String packageName, String versionName) {
if (mInstalledBrowsers.contains(packageName)) return; if (mInstalledBrowsers.contains(packageName)) return;
...@@ -61,6 +67,15 @@ public class TestBrowserInstaller { ...@@ -61,6 +67,15 @@ public class TestBrowserInstaller {
mInstalledBrowsers.add(packageName); mInstalledBrowsers.add(packageName);
} }
/**
* Uninstalls all browsers.
*/
public void uninstallAllBrowsers() {
while (!mInstalledBrowsers.isEmpty()) {
uninstallBrowser(mInstalledBrowsers.iterator().next());
}
}
/** /**
* Uninstalls browser with the given package name. * Uninstalls browser with the given package name.
*/ */
......
...@@ -26,9 +26,8 @@ import android.widget.TextView; ...@@ -26,9 +26,8 @@ import android.widget.TextView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Map;
/** /**
* Shows the dialog to choose a host browser to launch WebAPK. Calls the listener callback when the * Shows the dialog to choose a host browser to launch WebAPK. Calls the listener callback when the
...@@ -52,14 +51,14 @@ public class ChooseHostBrowserDialog { ...@@ -52,14 +51,14 @@ public class ChooseHostBrowserDialog {
private String mPackageName; private String mPackageName;
private CharSequence mApplicationLabel; private CharSequence mApplicationLabel;
private Drawable mIcon; private Drawable mIcon;
private boolean mSupportsWebApks; private boolean mEnable;
public BrowserItem(String packageName, CharSequence applicationLabel, Drawable icon, public BrowserItem(
boolean supportsWebApks) { String packageName, CharSequence applicationLabel, Drawable icon, boolean enable) {
mPackageName = packageName; mPackageName = packageName;
mApplicationLabel = applicationLabel; mApplicationLabel = applicationLabel;
mIcon = icon; mIcon = icon;
mSupportsWebApks = supportsWebApks; mEnable = enable;
} }
/** Returns the package name of a browser. */ /** Returns the package name of a browser. */
...@@ -77,9 +76,9 @@ public class ChooseHostBrowserDialog { ...@@ -77,9 +76,9 @@ public class ChooseHostBrowserDialog {
return mIcon; return mIcon;
} }
/** Returns whether the browser supports WebAPKs. */ /** Returns whether to enable the browser list entry. */
public boolean supportsWebApks() { public boolean enable() {
return mSupportsWebApks; return mEnable;
} }
} }
...@@ -87,11 +86,11 @@ public class ChooseHostBrowserDialog { ...@@ -87,11 +86,11 @@ public class ChooseHostBrowserDialog {
* Shows the dialog for choosing a host browser. * Shows the dialog for choosing a host browser.
* @param context The current Context. * @param context The current Context.
* @param listener The listener for the dialog. * @param listener The listener for the dialog.
* @param infos The set of ResolvedInfos of the browsers that are shown on the dialog. * @param infos Browser-package-name->ResolveInfo mapping for all of the installed browsers.
* @param appName The name of the WebAPK for which the dialog is shown. * @param appName The name of the WebAPK for which the dialog is shown.
*/ */
public static void show(Context context, final DialogListener listener, Set<ResolveInfo> infos, public static void show(Context context, final DialogListener listener,
String appName) { Map<String, ResolveInfo> infos, String appName) {
final List<BrowserItem> browserItems = final List<BrowserItem> browserItems =
getBrowserInfosForHostBrowserSelection(context.getPackageManager(), infos); getBrowserInfosForHostBrowserSelection(context.getPackageManager(), infos);
...@@ -128,7 +127,7 @@ public class ChooseHostBrowserDialog { ...@@ -128,7 +127,7 @@ public class ChooseHostBrowserDialog {
@Override @Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
BrowserItem browserItem = browserItems.get(position); BrowserItem browserItem = browserItems.get(position);
if (browserItem.supportsWebApks()) { if (browserItem.enable()) {
onDismissCanceler.canceled = true; onDismissCanceler.canceled = true;
listener.onHostBrowserSelected(browserItem.getPackageName()); listener.onHostBrowserSelected(browserItem.getPackageName());
dialog.cancel(); dialog.cancel();
...@@ -149,18 +148,23 @@ public class ChooseHostBrowserDialog { ...@@ -149,18 +148,23 @@ public class ChooseHostBrowserDialog {
/** Returns a list of BrowserItem for all of the installed browsers. */ /** Returns a list of BrowserItem for all of the installed browsers. */
private static List<BrowserItem> getBrowserInfosForHostBrowserSelection( private static List<BrowserItem> getBrowserInfosForHostBrowserSelection(
PackageManager packageManager, Set<ResolveInfo> resolveInfos) { PackageManager packageManager, Map<String, ResolveInfo> resolveInfos) {
List<BrowserItem> browsers = new ArrayList<>(); boolean hasBrowserSupportingWebApk = false;
List<String> browsersSupportingWebApk = HostBrowserUtils.getBrowsersSupportingWebApk(); for (String installedBrowserPackage : resolveInfos.keySet()) {
Set<String> packages = new HashSet<>(); if (HostBrowserUtils.doesBrowserSupportWebApks(installedBrowserPackage)) {
hasBrowserSupportingWebApk = true;
for (ResolveInfo info : resolveInfos) { break;
if (packages.contains(info.activityInfo.packageName)) continue; }
packages.add(info.activityInfo.packageName); }
browsers.add(new BrowserItem(info.activityInfo.packageName, List<BrowserItem> browsers = new ArrayList<>();
info.loadLabel(packageManager), info.loadIcon(packageManager), for (Map.Entry<String, ResolveInfo> entry : resolveInfos.entrySet()) {
browsersSupportingWebApk.contains(info.activityInfo.packageName))); String browserPackage = entry.getKey();
ResolveInfo info = entry.getValue();
boolean enable = !hasBrowserSupportingWebApk
|| HostBrowserUtils.doesBrowserSupportWebApks(browserPackage);
browsers.add(new BrowserItem(browserPackage, info.loadLabel(packageManager),
info.loadIcon(packageManager), enable));
} }
if (browsers.size() <= 1) return browsers; if (browsers.size() <= 1) return browsers;
...@@ -168,10 +172,10 @@ public class ChooseHostBrowserDialog { ...@@ -168,10 +172,10 @@ public class ChooseHostBrowserDialog {
Collections.sort(browsers, new Comparator<BrowserItem>() { Collections.sort(browsers, new Comparator<BrowserItem>() {
@Override @Override
public int compare(BrowserItem a, BrowserItem b) { public int compare(BrowserItem a, BrowserItem b) {
if (a.mSupportsWebApks == b.mSupportsWebApks) { if (a.mEnable == b.mEnable) {
return a.getPackageName().compareTo(b.getPackageName()); return a.getPackageName().compareTo(b.getPackageName());
} }
return a.mSupportsWebApks ? -1 : 1; return a.mEnable ? -1 : 1;
} }
}); });
...@@ -205,8 +209,8 @@ public class ChooseHostBrowserDialog { ...@@ -205,8 +209,8 @@ public class ChooseHostBrowserDialog {
res.getDimensionPixelSize(R.dimen.list_column_padding), 0, 0, 0); res.getDimensionPixelSize(R.dimen.list_column_padding), 0, 0, 0);
BrowserItem item = mBrowsers.get(position); BrowserItem item = mBrowsers.get(position);
name.setEnabled(item.supportsWebApks()); name.setEnabled(item.enable());
if (item.supportsWebApks()) { if (item.enable()) {
name.setText(item.getApplicationName()); name.setText(item.getApplicationName());
name.setTextColor(WebApkUtils.getColor(res, R.color.black_alpha_87)); name.setTextColor(WebApkUtils.getColor(res, R.color.black_alpha_87));
icon.setAlpha(SUPPORTED_ICON_OPACITY); icon.setAlpha(SUPPORTED_ICON_OPACITY);
...@@ -224,13 +228,13 @@ public class ChooseHostBrowserDialog { ...@@ -224,13 +228,13 @@ public class ChooseHostBrowserDialog {
icon.setAlpha(UNSUPPORTED_ICON_OPACITY); icon.setAlpha(UNSUPPORTED_ICON_OPACITY);
} }
icon.setImageDrawable(item.getApplicationIcon()); icon.setImageDrawable(item.getApplicationIcon());
icon.setEnabled(item.supportsWebApks()); icon.setEnabled(item.enable());
return convertView; return convertView;
} }
@Override @Override
public boolean isEnabled(int position) { public boolean isEnabled(int position) {
return mBrowsers.get(position).supportsWebApks(); return mBrowsers.get(position).enable();
} }
} }
} }
...@@ -15,9 +15,10 @@ import android.text.TextUtils; ...@@ -15,9 +15,10 @@ import android.text.TextUtils;
import org.chromium.webapk.lib.common.WebApkMetaDataKeys; import org.chromium.webapk.lib.common.WebApkMetaDataKeys;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/** /**
* Contains methods for getting information about host browser. * Contains methods for getting information about host browser.
...@@ -39,8 +40,8 @@ public class HostBrowserUtils { ...@@ -39,8 +40,8 @@ public class HostBrowserUtils {
/** /**
* The package names of the browsers that support WebAPKs. The most preferred one comes first. * The package names of the browsers that support WebAPKs. The most preferred one comes first.
*/ */
private static List<String> sBrowsersSupportingWebApk = private static Set<String> sBrowsersSupportingWebApk =
new ArrayList<String>(Arrays.asList("com.google.android.apps.chrome", new HashSet<String>(Arrays.asList("com.google.android.apps.chrome",
"com.android.chrome", "com.chrome.beta", "com.chrome.dev", "com.chrome.canary", "com.android.chrome", "com.chrome.beta", "com.chrome.dev", "com.chrome.canary",
"org.chromium.chrome", "org.chromium.chrome.tests", ARC_INTENT_HELPER_BROWSER)); "org.chromium.chrome", "org.chromium.chrome.tests", ARC_INTENT_HELPER_BROWSER));
...@@ -52,12 +53,9 @@ public class HostBrowserUtils { ...@@ -52,12 +53,9 @@ public class HostBrowserUtils {
sHostPackage = null; sHostPackage = null;
} }
/** /** Returns whether the passed-in browser package name supports WebAPKs. */
* Returns a list of browsers that support WebAPKs. TODO(hanxi): Replace this function once we public static boolean doesBrowserSupportWebApks(String browserPackageName) {
* figure out a better way to know which browser supports WebAPKs. return sBrowsersSupportingWebApk.contains(browserPackageName);
*/
public static List<String> getBrowsersSupportingWebApk() {
return sBrowsersSupportingWebApk;
} }
/** /**
...@@ -118,6 +116,10 @@ public class HostBrowserUtils { ...@@ -118,6 +116,10 @@ public class HostBrowserUtils {
/** Queries the given host browser's major version. */ /** Queries the given host browser's major version. */
public static int queryHostBrowserMajorChromiumVersion( public static int queryHostBrowserMajorChromiumVersion(
Context context, String hostBrowserPackageName) { Context context, String hostBrowserPackageName) {
if (!doesBrowserSupportWebApks(hostBrowserPackageName)) {
return -1;
}
PackageInfo info; PackageInfo info;
try { try {
info = context.getPackageManager().getPackageInfo(hostBrowserPackageName, 0); info = context.getPackageManager().getPackageInfo(hostBrowserPackageName, 0);
...@@ -145,7 +147,7 @@ public class HostBrowserUtils { ...@@ -145,7 +147,7 @@ public class HostBrowserUtils {
public static boolean shouldLaunchInTab(HostBrowserLauncherParams params) { public static boolean shouldLaunchInTab(HostBrowserLauncherParams params) {
String hostBrowserPackageName = params.getHostBrowserPackageName(); String hostBrowserPackageName = params.getHostBrowserPackageName();
int hostBrowserMajorChromiumVersion = params.getHostBrowserMajorChromiumVersion(); int hostBrowserMajorChromiumVersion = params.getHostBrowserMajorChromiumVersion();
if (!sBrowsersSupportingWebApk.contains(hostBrowserPackageName)) { if (!doesBrowserSupportWebApks(hostBrowserPackageName)) {
return true; return true;
} }
...@@ -193,26 +195,36 @@ public class HostBrowserUtils { ...@@ -193,26 +195,36 @@ public class HostBrowserUtils {
// Gets the package name of the default browser on the Android device. // Gets the package name of the default browser on the Android device.
// TODO(hanxi): Investigate the best way to know which browser supports WebAPKs. // TODO(hanxi): Investigate the best way to know which browser supports WebAPKs.
String defaultBrowser = getDefaultBrowserPackageName(context.getPackageManager()); String defaultBrowser = getDefaultBrowserPackageName(packageManager);
if (!TextUtils.isEmpty(defaultBrowser) && sBrowsersSupportingWebApk.contains(defaultBrowser) if (!TextUtils.isEmpty(defaultBrowser) && doesBrowserSupportWebApks(defaultBrowser)
&& WebApkUtils.isInstalled(packageManager, defaultBrowser)) { && WebApkUtils.isInstalled(packageManager, defaultBrowser)) {
return defaultBrowser; return defaultBrowser;
} }
Map<String, ResolveInfo> installedBrowsers =
WebApkUtils.getInstalledBrowserResolveInfos(packageManager);
if (installedBrowsers.size() == 1) {
return installedBrowsers.keySet().iterator().next();
}
// If there is only one browser supporting WebAPK, and we can't decide which browser to use // If there is only one browser supporting WebAPK, and we can't decide which browser to use
// by looking up cache, metadata and default browser, open with that browser. // by looking up cache, metadata and default browser, open with that browser.
int availableBrowserCounter = 0; int numSupportedBrowsersInstalled = 0;
String lastSupportedBrowser = null; String lastSupportedBrowser = null;
for (String packageName : sBrowsersSupportingWebApk) { for (String browserPackageName : installedBrowsers.keySet()) {
if (availableBrowserCounter > 1) break; if (numSupportedBrowsersInstalled > 1) break;
if (WebApkUtils.isInstalled(packageManager, packageName)) { if (doesBrowserSupportWebApks(browserPackageName)) {
availableBrowserCounter++; numSupportedBrowsersInstalled++;
lastSupportedBrowser = packageName; lastSupportedBrowser = browserPackageName;
} }
} }
if (availableBrowserCounter == 1) { if (numSupportedBrowsersInstalled == 1) {
return lastSupportedBrowser; return lastSupportedBrowser;
} }
if (numSupportedBrowsersInstalled == 0 && installedBrowsers.containsKey(defaultBrowser)) {
return defaultBrowser;
}
return null; return null;
} }
...@@ -227,9 +239,7 @@ public class HostBrowserUtils { ...@@ -227,9 +239,7 @@ public class HostBrowserUtils {
Intent browserIntent = WebApkUtils.getQueryInstalledBrowsersIntent(); Intent browserIntent = WebApkUtils.getQueryInstalledBrowsersIntent();
ResolveInfo resolveInfo = ResolveInfo resolveInfo =
packageManager.resolveActivity(browserIntent, PackageManager.MATCH_DEFAULT_ONLY); packageManager.resolveActivity(browserIntent, PackageManager.MATCH_DEFAULT_ONLY);
if (resolveInfo == null || resolveInfo.activityInfo == null) return null; return WebApkUtils.getPackageNameFromResolveInfo(resolveInfo);
return resolveInfo.activityInfo.packageName;
} }
/** Deletes the internal storage for the given context. */ /** Deletes the internal storage for the given context. */
......
...@@ -16,8 +16,7 @@ import android.util.Log; ...@@ -16,8 +16,7 @@ import android.util.Log;
import org.chromium.webapk.lib.common.WebApkMetaDataKeys; import org.chromium.webapk.lib.common.WebApkMetaDataKeys;
import java.util.List; import java.util.Map;
import java.util.Set;
/** Selects host browser to launch, showing a dialog to select browser if necessary. */ /** Selects host browser to launch, showing a dialog to select browser if necessary. */
public class LaunchHostBrowserSelector { public class LaunchHostBrowserSelector {
...@@ -77,9 +76,9 @@ public class LaunchHostBrowserSelector { ...@@ -77,9 +76,9 @@ public class LaunchHostBrowserSelector {
return; return;
} }
Set<ResolveInfo> infos = Map<String, ResolveInfo> infos =
WebApkUtils.getInstalledBrowserResolveInfos(mContext.getPackageManager()); WebApkUtils.getInstalledBrowserResolveInfos(mContext.getPackageManager());
if (hasBrowserSupportingWebApks(infos)) { if (!infos.isEmpty()) {
showChooseHostBrowserDialog(infos, selectCallback); showChooseHostBrowserDialog(infos, selectCallback);
} else { } else {
showInstallHostBrowserDialog(metadata, selectCallback); showInstallHostBrowserDialog(metadata, selectCallback);
...@@ -96,19 +95,9 @@ public class LaunchHostBrowserSelector { ...@@ -96,19 +95,9 @@ public class LaunchHostBrowserSelector {
} }
} }
/** Returns whether there is any installed browser supporting WebAPKs. */
private static boolean hasBrowserSupportingWebApks(Set<ResolveInfo> resolveInfos) {
List<String> browsersSupportingWebApk = HostBrowserUtils.getBrowsersSupportingWebApk();
for (ResolveInfo info : resolveInfos) {
if (browsersSupportingWebApk.contains(info.activityInfo.packageName)) {
return true;
}
}
return false;
}
/** Shows a dialog to choose the host browser. */ /** Shows a dialog to choose the host browser. */
private void showChooseHostBrowserDialog(Set<ResolveInfo> infos, Callback selectCallback) { private void showChooseHostBrowserDialog(
Map<String, ResolveInfo> infos, Callback selectCallback) {
ChooseHostBrowserDialog.DialogListener listener = ChooseHostBrowserDialog.DialogListener listener =
new ChooseHostBrowserDialog.DialogListener() { new ChooseHostBrowserDialog.DialogListener() {
@Override @Override
......
...@@ -39,6 +39,10 @@ public class WebApkServiceFactory extends Service { ...@@ -39,6 +39,10 @@ public class WebApkServiceFactory extends Service {
@Override @Override
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
final String hostBrowserPackage = HostBrowserUtils.getCachedHostBrowserPackage(this); final String hostBrowserPackage = HostBrowserUtils.getCachedHostBrowserPackage(this);
if (!HostBrowserUtils.doesBrowserSupportWebApks(hostBrowserPackage)) {
Log.w(TAG, "Host browser does not support WebAPKs.");
return null;
}
ClassLoader webApkClassLoader = HostBrowserClassLoader.getClassLoaderInstance( ClassLoader webApkClassLoader = HostBrowserClassLoader.getClassLoaderInstance(
this, hostBrowserPackage, WEBAPK_SERVICE_IMPL_CLASS_NAME); this, hostBrowserPackage, WEBAPK_SERVICE_IMPL_CLASS_NAME);
if (webApkClassLoader == null) { if (webApkClassLoader == null) {
......
...@@ -34,9 +34,9 @@ import android.widget.TextView; ...@@ -34,9 +34,9 @@ import android.widget.TextView;
import org.chromium.webapk.lib.common.WebApkMetaDataKeys; import org.chromium.webapk.lib.common.WebApkMetaDataKeys;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Map;
/** /**
* Contains utility methods for interacting with WebAPKs. * Contains utility methods for interacting with WebAPKs.
...@@ -105,22 +105,31 @@ public class WebApkUtils { ...@@ -105,22 +105,31 @@ public class WebApkUtils {
return returnUrlBuilder.toString(); return returnUrlBuilder.toString();
} }
/** Returns a set of ResolveInfo for all of the installed browsers. */ /** Returns a browser-package-name->ResolveInfo mapping for all of the installed browsers. */
public static Set<ResolveInfo> getInstalledBrowserResolveInfos(PackageManager packageManager) { public static Map<String, ResolveInfo> getInstalledBrowserResolveInfos(
PackageManager packageManager) {
Intent browserIntent = getQueryInstalledBrowsersIntent(); Intent browserIntent = getQueryInstalledBrowsersIntent();
// Note: {@link PackageManager#queryIntentActivities()} does not return ResolveInfos for // Note: {@link PackageManager#queryIntentActivities()} does not return ResolveInfos for
// disabled browsers. // disabled browsers.
Set<ResolveInfo> result = new HashSet<>(); List<ResolveInfo> resolveInfos =
List<ResolveInfo> resolveInfosAll =
packageManager.queryIntentActivities(browserIntent, PackageManager.MATCH_ALL); packageManager.queryIntentActivities(browserIntent, PackageManager.MATCH_ALL);
List<ResolveInfo> resolveInfosDefaultOnly = packageManager.queryIntentActivities( resolveInfos.addAll(packageManager.queryIntentActivities(
browserIntent, PackageManager.MATCH_DEFAULT_ONLY); browserIntent, PackageManager.MATCH_DEFAULT_ONLY));
result.addAll(resolveInfosAll); Map<String, ResolveInfo> result = new HashMap<>();
result.addAll(resolveInfosDefaultOnly); for (ResolveInfo resolveInfo : resolveInfos) {
result.put(getPackageNameFromResolveInfo(resolveInfo), resolveInfo);
}
return result; return result;
} }
/** Returns the package name for the passed-in ResolveInfo. */
public static String getPackageNameFromResolveInfo(ResolveInfo resolveInfo) {
return (resolveInfo != null && resolveInfo.activityInfo != null)
? resolveInfo.activityInfo.packageName
: null;
}
/** Builds a context for the passed in remote package name. */ /** Builds a context for the passed in remote package name. */
public static Context fetchRemoteContext(Context context, String remotePackageName) { public static Context fetchRemoteContext(Context context, String remotePackageName) {
try { try {
......
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