Chromium Code Reviews| 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 a9b5424f22948798560bdbc803c658000c769658..e0343a584396c792021658b8112f28937905b87d 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,22 +5,43 @@ |
| 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.net.Uri; |
| +import android.os.AsyncTask; |
| import android.os.Bundle; |
| +import android.text.TextUtils; |
| import org.chromium.webapk.lib.common.WebApkMetaDataKeys; |
| +import java.util.ArrayList; |
| +import java.util.Arrays; |
| +import java.util.List; |
| + |
| /** |
| * Contains utility methods for interacting with WebAPKs. |
| */ |
| public class WebApkUtils { |
| + private static final String SHARED_PREF = "metadata"; |
| + private static final String SHARED_PREF_RUNTIME_HOST = "runtime_host"; |
| + private static final String CHROME_STABLE_PACKAGE = "com.android.chrome"; |
| + private static final String CHROME_BETA_PACKAGE = "com.chrome.beta"; |
| + private static final String CHROME_DEV_PACKAGE = "com.chrome.dev"; |
| + private static final String CHROME_CANARY_PACKAGE = "com.chrome.canary"; |
|
pkotwicz
2017/05/09 21:38:28
Personally, I would inline the package names in |s
Yaron
2017/05/10 17:47:57
+1
Xi Han
2017/05/10 18:27:25
Done.
|
| - /** |
| - * Caches the value read from Application Metadata which specifies the host browser's package |
| - * name. |
| - */ |
| + // The package names of different versions of Chromes that support WebAPKs. |
| + private static final List<String> sBrowsersSupportingWwebApk; |
|
pkotwicz
2017/05/09 21:38:27
Nit: sBrowsersSupportingWwebApk -> sBrowsersSuppor
Xi Han
2017/05/10 18:27:25
Done.
|
| + |
| + static { |
| + sBrowsersSupportingWwebApk = new ArrayList<String>(Arrays.asList(CHROME_STABLE_PACKAGE, |
| + CHROME_BETA_PACKAGE, CHROME_DEV_PACKAGE, CHROME_CANARY_PACKAGE)); |
| + } |
| + |
| + /** Caches the package name of the host browser. */ |
| private static String sHostPackage; |
| /** |
| @@ -45,19 +66,51 @@ public class WebApkUtils { |
| * @param context A context. |
| * @return The package name. Returns null on an error. |
| */ |
| - public static String getHostBrowserPackageName(Context context) { |
| + public static String getHostBrowserPackageName(final Context context) { |
| if (sHostPackage != null) return sHostPackage; |
| + |
| String hostPackage = null; |
| - try { |
| - ApplicationInfo ai = context.getPackageManager().getApplicationInfo( |
| - context.getPackageName(), PackageManager.GET_META_DATA); |
| - Bundle bundle = ai.metaData; |
| - hostPackage = bundle.getString(WebApkMetaDataKeys.RUNTIME_HOST); |
| - } catch (NameNotFoundException e) { |
| - e.printStackTrace(); |
| + // Gets the package name of the host browser if it is specified in AndroidManifest.xml. |
| + String hostBrowserFromManifest = getHostBrowserFromAndroidManifest(context); |
| + |
| + // Gets all installed browsers that support WebAPKs. |
| + List<String> packagesSupportingWebApks = |
| + getInstalledBrowsersSupportingWebApks(context.getPackageManager()); |
| + |
| + if (packagesSupportingWebApks.isEmpty()) { |
| + hostPackage = null; |
|
Yaron
2017/05/10 17:47:57
hostPackage is already null and just a local varia
Xi Han
2017/05/10 18:27:25
Acknowledged.
|
| + } else if (!TextUtils.isEmpty(hostBrowserFromManifest) |
| + && packagesSupportingWebApks.contains(hostBrowserFromManifest)) { |
| + hostPackage = hostBrowserFromManifest; |
| + } else { |
| + // Gets the package name of the host browser if it is stored in the SharedPreference. |
| + String cachedHostBrowser = getHostBrowserFromSharedPreference(context); |
| + if (!TextUtils.isEmpty(cachedHostBrowser) |
| + && packagesSupportingWebApks.contains(cachedHostBrowser)) { |
| + hostPackage = cachedHostBrowser; |
| + } else { |
| + // Gets the package name of the default browser on the Android device. |
| + // TODO(hanxi): adds a new dialog to ask users to select a host browser when the |
| + // default browser doesn't support WebAPKs. |
| + String defaultBrowser = getDefaultBrowserPackageName(context.getPackageManager()); |
| + if (!TextUtils.isEmpty(defaultBrowser) |
| + && packagesSupportingWebApks.contains(defaultBrowser)) { |
| + hostPackage = defaultBrowser; |
|
pkotwicz
2017/05/09 21:38:27
Can you change lines 99-107 into iterating over a
Xi Han
2017/05/10 18:27:25
Good idea, thanks!
|
| + } else if (packagesSupportingWebApks.contains(CHROME_STABLE_PACKAGE)) { |
| + hostPackage = CHROME_STABLE_PACKAGE; |
| + } else if (packagesSupportingWebApks.contains(CHROME_BETA_PACKAGE)) { |
| + hostPackage = CHROME_BETA_PACKAGE; |
| + } else if (packagesSupportingWebApks.contains(CHROME_DEV_PACKAGE)) { |
| + hostPackage = CHROME_DEV_PACKAGE; |
| + } else if (packagesSupportingWebApks.contains(CHROME_CANARY_PACKAGE)) { |
| + hostPackage = CHROME_CANARY_PACKAGE; |
| + } |
| + } |
| } |
| + |
| // Set {@link sHostPackage} to a non-null value so that the value is computed only once. |
| sHostPackage = hostPackage != null ? hostPackage : ""; |
| + writeHostBrowserToSharedPref(context, sHostPackage); |
| return sHostPackage; |
| } |
| @@ -81,4 +134,71 @@ public class WebApkUtils { |
| } |
| return -1; |
| } |
| + |
| + /** Returns the package name of the host browser cached in the SharedPreferences. */ |
| + private static String getHostBrowserFromSharedPreference(Context context) { |
| + SharedPreferences sharedPref = |
| + context.getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE); |
| + return sharedPref.getString(SHARED_PREF_RUNTIME_HOST, null); |
| + } |
| + |
| + /** |
| + * Returns all of the installed browsers that supports WebAPKs. |
| + * TODO(hanxi): Investigate the best way to know which browser supports WebAPKs. |
| + */ |
| + private static List<String> getInstalledBrowsersSupportingWebApks( |
| + PackageManager packageManager) { |
|
pkotwicz
2017/05/09 21:38:27
I don't know what to think about this function.
I
Xi Han
2017/05/10 18:27:25
How about changing the variable |packagesSupportin
|
| + Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://")); |
| + List<ResolveInfo> resolvedActivityList = packageManager.queryIntentActivities( |
| + browserIntent, PackageManager.MATCH_DEFAULT_ONLY); |
| + |
| + List<String> packagesSupportingWebApks = new ArrayList<>(); |
| + for (ResolveInfo info : resolvedActivityList) { |
| + if (sBrowsersSupportingWwebApk.contains(info.activityInfo.packageName)) { |
| + packagesSupportingWebApks.add(info.activityInfo.packageName); |
| + } |
| + } |
| + return packagesSupportingWebApks; |
| + } |
| + |
| + /** Returns the package name of the "runtime host" in the AndroidManifest.xml. */ |
| + private static String getHostBrowserFromAndroidManifest(Context context) { |
|
pkotwicz
2017/05/09 21:38:28
Should this function take a PackageManager as an a
Xi Han
2017/05/10 18:27:25
Done.
|
| + try { |
| + ApplicationInfo ai = context.getPackageManager().getApplicationInfo( |
| + context.getPackageName(), PackageManager.GET_META_DATA); |
| + Bundle bundle = ai.metaData; |
| + return bundle.getString(WebApkMetaDataKeys.RUNTIME_HOST); |
| + } catch (NameNotFoundException e) { |
| + e.printStackTrace(); |
|
pkotwicz
2017/05/09 21:38:27
We probably remove e.printStackTrace() (I know tha
Xi Han
2017/05/10 18:27:25
Done.
|
| + return null; |
| + } |
| + } |
| + |
| + /** 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 SharedPreferences. */ |
| + private static void writeHostBrowserToSharedPref( |
| + final Context context, final String hostPackage) { |
| + if (TextUtils.isEmpty(hostPackage)) return; |
| + |
| + new AsyncTask<String, Void, Void>() { |
| + @Override |
| + protected Void doInBackground(String... params) { |
| + SharedPreferences sharedPref = |
| + context.getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE); |
| + SharedPreferences.Editor editor = sharedPref.edit(); |
| + editor.putString(SHARED_PREF_RUNTIME_HOST, params[0]); |
| + editor.apply(); |
| + return null; |
| + } |
| + }.execute(hostPackage); |
|
pkotwicz
2017/05/09 21:38:27
Is it worth to save to SharedPreferences in an Asy
Yaron
2017/05/10 17:47:57
Ya, it's not necessary for apply
Xi Han
2017/05/10 18:27:25
Ok, removed.
|
| + } |
| } |