Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2977)

Unified Diff: chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java

Issue 2858563004: Add support for webapk without runtimeHost (Closed)
Patch Set: Nits. Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java
index 4096cdc427006ea2b62cd292d7c1146df61c3a87..bc8c754d6fd63be19c5028d606cc9fb6465fd055 100644
--- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java
+++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java
@@ -5,23 +5,89 @@
package org.chromium.webapk.shell_apk;
import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.text.TextUtils;
+import org.chromium.webapk.lib.common.WebApkConstants;
import org.chromium.webapk.lib.common.WebApkMetaDataKeys;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
/**
* Contains utility methods for interacting with WebAPKs.
*/
public class WebApkUtils {
+ public static final String SHARED_PREF_RUNTIME_HOST = "runtime_host";
+
+ /**
+ * The package names of the channels of Chrome that support WebAPKs. The most preferred one
+ * comes first.
+ */
+ private static List<String> sBrowsersSupportingWebApk = new ArrayList<String>(
+ Arrays.asList("com.google.android.apps.chrome", "com.android.chrome", "com.chrome.beta",
+ "com.chrome.dev", "com.chrome.canary"));
+
+ /** Stores information about a potential host browser for the WebAPK. */
+ public static class BrowserItem {
+ private String mPackageName;
+ private CharSequence mApplicationLabel;
+ private Drawable mIcon;
+ private boolean mSupportsWebApks;
+
+ public BrowserItem(String packageName, CharSequence applicationLabel, Drawable icon,
+ boolean supportsWebApks) {
+ mPackageName = packageName;
+ mApplicationLabel = applicationLabel;
+ mIcon = icon;
+ mSupportsWebApks = supportsWebApks;
+ }
+
+ /** Returns the package name of a browser. */
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ /** Returns the application name of a browser. */
+ public CharSequence getApplicationName() {
+ return mApplicationLabel;
+ }
+
+ /** Returns a drawable of the browser icon. */
+ public Drawable getApplicationIcon() {
+ return mIcon;
+ }
+
+ /** Returns whether the browser supports WebAPKs. */
+ public boolean supportsWebApks() {
+ return mSupportsWebApks;
+ }
+ }
/**
- * Caches the value read from Application Metadata which specifies the host browser's package
- * name.
+ * Caches the package name of the host browser. {@link sHostPackage} might refer to a browser
+ * which has been uninstalled. A notification can keep the WebAPK process alive after the host
+ * browser has been uninstalled.
*/
private static String sHostPackage;
+ /** For testing only. */
+ public static void resetCachedHostPackageForTesting() {
+ sHostPackage = null;
+ }
+
/**
* Returns a Context for the host browser that was specified when building the WebAPK.
* @param context A context.
@@ -31,8 +97,7 @@ public class WebApkUtils {
try {
String hostPackage = getHostBrowserPackageName(context);
return context.getApplicationContext().createPackageContext(
- hostPackage,
- Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE);
+ hostPackage, Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
@@ -40,15 +105,19 @@ public class WebApkUtils {
}
/**
- * Returns the package name for the host browser that was specified when building the WebAPK.
+ * Returns the package name of the host browser to launch the WebAPK. Also caches the package
+ * name in the SharedPreference if it is not null.
* @param context A context.
* @return The package name. Returns null on an error.
*/
public static String getHostBrowserPackageName(Context context) {
- if (sHostPackage != null) return sHostPackage;
- String hostPackage = readMetaDataFromManifest(context, WebApkMetaDataKeys.RUNTIME_HOST);
- // Set {@link sHostPackage} to a non-null value so that the value is computed only once.
- sHostPackage = hostPackage != null ? hostPackage : "";
+ if (sHostPackage == null) {
+ sHostPackage = getHostBrowserPackageNameInternal(context);
+ if (sHostPackage != null) {
+ writeHostBrowserToSharedPref(context, sHostPackage);
+ }
+ }
+
return sHostPackage;
}
@@ -64,6 +133,84 @@ public class WebApkUtils {
return ai.metaData.getString(key);
}
+ /**
+ * Returns the package name of the host browser to launch the WebAPK, or null if we did not find
+ * one.
+ */
+ private static String getHostBrowserPackageNameInternal(Context context) {
+ Set<String> installedBrowsers = getInstalledBrowsers(context.getPackageManager());
+ if (installedBrowsers.isEmpty()) {
+ return null;
+ }
+
+ // Gets the package name of the host browser if it is stored in the SharedPreference.
+ String cachedHostBrowser = getHostBrowserFromSharedPreference(context);
+ if (!TextUtils.isEmpty(cachedHostBrowser)
+ && installedBrowsers.contains(cachedHostBrowser)) {
+ return cachedHostBrowser;
+ }
+
+ // Gets the package name of the host browser if it is specified in AndroidManifest.xml.
+ String hostBrowserFromManifest =
+ readMetaDataFromManifest(context, WebApkMetaDataKeys.RUNTIME_HOST);
+ if (!TextUtils.isEmpty(hostBrowserFromManifest)) {
+ if (installedBrowsers.contains(hostBrowserFromManifest)) {
+ return hostBrowserFromManifest;
+ }
+ return null;
+ }
+
+ // Gets the package name of the default browser on the Android device.
+ // TODO(hanxi): Investigate the best way to know which browser supports WebAPKs.
+ String defaultBrowser = getDefaultBrowserPackageName(context.getPackageManager());
+ if (!TextUtils.isEmpty(defaultBrowser) && installedBrowsers.contains(defaultBrowser)
+ && sBrowsersSupportingWebApk.contains(defaultBrowser)) {
+ return defaultBrowser;
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns a list of browsers to choose host browser from. The list includes all the installed
+ * browsers, and if none of the installed browser supports WebAPKs, Chrome will be added to the
+ * list as well.
+ */
+ public static List<BrowserItem> getBrowserInfosForHostBrowserSelection(
+ PackageManager packageManager) {
+ Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://"));
+ List<ResolveInfo> resolvedActivityList = packageManager.queryIntentActivities(
+ browserIntent, PackageManager.MATCH_DEFAULT_ONLY);
+
+ boolean hasBrowserSupportingWebApks = false;
+ List<BrowserItem> browsers = new ArrayList<>();
+ for (ResolveInfo info : resolvedActivityList) {
+ boolean supportsWebApk = false;
+ if (sBrowsersSupportingWebApk.contains(info.activityInfo.packageName)) {
+ supportsWebApk = true;
+ hasBrowserSupportingWebApks = true;
+ }
+ browsers.add(new BrowserItem(info.activityInfo.packageName,
+ info.loadLabel(packageManager), info.loadIcon(packageManager), supportsWebApk));
+ }
+
+ Collections.sort(browsers, new Comparator<BrowserItem>() {
+ @Override
+ public int compare(BrowserItem a, BrowserItem b) {
+ if (a.mSupportsWebApks == b.mSupportsWebApks) {
+ return a.getPackageName().compareTo(b.getPackageName());
+ }
+ return a.mSupportsWebApks ? -1 : 1;
+ }
+ });
+
+ if (hasBrowserSupportingWebApks) return browsers;
+
+ // TODO(hanxi): add Chrome's icon to WebAPKs.
+ browsers.add(new BrowserItem("com.android.chrome", "Chrome", null, true));
+ return browsers;
+ }
+
/**
* Returns the uid for the host browser that was specified when building the WebAPK.
* @param context A context.
@@ -84,4 +231,58 @@ public class WebApkUtils {
}
return -1;
}
+
+ /** Returns the package name of the host browser cached in the SharedPreferences. */
+ public static String getHostBrowserFromSharedPreference(Context context) {
+ SharedPreferences sharedPref =
+ context.getSharedPreferences(WebApkConstants.PREF_PACKAGE, Context.MODE_PRIVATE);
+ return sharedPref.getString(SHARED_PREF_RUNTIME_HOST, null);
+ }
+
+ /** Returns a set of package names of all the installed browsers on the device. */
+ public static Set<String> getInstalledBrowsers(PackageManager packageManager) {
+ Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://"));
+ List<ResolveInfo> resolvedActivityList = packageManager.queryIntentActivities(
+ browserIntent, PackageManager.MATCH_DEFAULT_ONLY);
+
+ Set<String> packagesSupportingWebApks = new HashSet<String>();
+ for (ResolveInfo info : resolvedActivityList) {
+ packagesSupportingWebApks.add(info.activityInfo.packageName);
+ }
+ return packagesSupportingWebApks;
+ }
+
+ /** Returns the package name of the default browser on the Android device. */
+ private static String getDefaultBrowserPackageName(PackageManager packageManager) {
+ Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://"));
+ ResolveInfo resolveInfo =
+ packageManager.resolveActivity(browserIntent, PackageManager.MATCH_DEFAULT_ONLY);
+ if (resolveInfo == null || resolveInfo.activityInfo == null) return null;
+
+ return resolveInfo.activityInfo.packageName;
+ }
+
+ /**
+ * Writes the package name of the host browser to the SharedPreferences. If the host browser is
+ * different than the previous one stored, delete the SharedPreference before storing the new
+ * host browser.
+ */
+ public static void writeHostBrowserToSharedPref(Context context, String hostPackage) {
+ if (TextUtils.isEmpty(hostPackage)) return;
+
+ SharedPreferences sharedPref =
+ context.getSharedPreferences(WebApkConstants.PREF_PACKAGE, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = sharedPref.edit();
+ editor.putString(SHARED_PREF_RUNTIME_HOST, hostPackage);
+ editor.apply();
+ }
+
+ /** Deletes the SharedPreferences. */
+ public static void deleteSharedPref(Context context) {
+ SharedPreferences sharedPref =
+ context.getSharedPreferences(WebApkConstants.PREF_PACKAGE, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = sharedPref.edit();
+ editor.clear();
+ editor.apply();
+ }
}

Powered by Google App Engine
This is Rietveld 408576698