Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.webapk.shell_apk; | 5 package org.chromium.webapk.shell_apk; |
| 6 | 6 |
| 7 import android.content.Context; | 7 import android.content.Context; |
| 8 import android.content.Intent; | |
| 9 import android.content.SharedPreferences; | |
| 8 import android.content.pm.ApplicationInfo; | 10 import android.content.pm.ApplicationInfo; |
| 9 import android.content.pm.PackageManager; | 11 import android.content.pm.PackageManager; |
| 10 import android.content.pm.PackageManager.NameNotFoundException; | 12 import android.content.pm.PackageManager.NameNotFoundException; |
| 13 import android.content.pm.ResolveInfo; | |
| 14 import android.net.Uri; | |
| 15 import android.os.AsyncTask; | |
| 11 import android.os.Bundle; | 16 import android.os.Bundle; |
| 17 import android.text.TextUtils; | |
| 12 | 18 |
| 13 import org.chromium.webapk.lib.common.WebApkMetaDataKeys; | 19 import org.chromium.webapk.lib.common.WebApkMetaDataKeys; |
| 14 | 20 |
| 21 import java.util.ArrayList; | |
| 22 import java.util.Arrays; | |
| 23 import java.util.List; | |
| 24 | |
| 15 /** | 25 /** |
| 16 * Contains utility methods for interacting with WebAPKs. | 26 * Contains utility methods for interacting with WebAPKs. |
| 17 */ | 27 */ |
| 18 public class WebApkUtils { | 28 public class WebApkUtils { |
| 29 private static final String SHARED_PREF = "metadata"; | |
| 30 private static final String SHARED_PREF_RUNTIME_HOST = "runtime_host"; | |
| 31 private static final String CHROME_STABLE_PACKAGE = "com.android.chrome"; | |
| 32 private static final String CHROME_BETA_PACKAGE = "com.chrome.beta"; | |
| 33 private static final String CHROME_DEV_PACKAGE = "com.chrome.dev"; | |
| 34 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.
| |
| 19 | 35 |
| 20 /** | 36 // The package names of different versions of Chromes that support WebAPKs. |
| 21 * Caches the value read from Application Metadata which specifies the host browser's package | 37 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.
| |
| 22 * name. | 38 |
| 23 */ | 39 static { |
| 40 sBrowsersSupportingWwebApk = new ArrayList<String>(Arrays.asList(CHROME_ STABLE_PACKAGE, | |
| 41 CHROME_BETA_PACKAGE, CHROME_DEV_PACKAGE, CHROME_CANARY_PACKAGE)) ; | |
| 42 } | |
| 43 | |
| 44 /** Caches the package name of the host browser. */ | |
| 24 private static String sHostPackage; | 45 private static String sHostPackage; |
| 25 | 46 |
| 26 /** | 47 /** |
| 27 * Returns a Context for the host browser that was specified when building t he WebAPK. | 48 * Returns a Context for the host browser that was specified when building t he WebAPK. |
| 28 * @param context A context. | 49 * @param context A context. |
| 29 * @return The remote context. Returns null on an error. | 50 * @return The remote context. Returns null on an error. |
| 30 */ | 51 */ |
| 31 public static Context getHostBrowserContext(Context context) { | 52 public static Context getHostBrowserContext(Context context) { |
| 32 try { | 53 try { |
| 33 String hostPackage = getHostBrowserPackageName(context); | 54 String hostPackage = getHostBrowserPackageName(context); |
| 34 return context.getApplicationContext().createPackageContext( | 55 return context.getApplicationContext().createPackageContext( |
| 35 hostPackage, | 56 hostPackage, |
| 36 Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_IN CLUDE_CODE); | 57 Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_IN CLUDE_CODE); |
| 37 } catch (NameNotFoundException e) { | 58 } catch (NameNotFoundException e) { |
| 38 e.printStackTrace(); | 59 e.printStackTrace(); |
| 39 } | 60 } |
| 40 return null; | 61 return null; |
| 41 } | 62 } |
| 42 | 63 |
| 43 /** | 64 /** |
| 44 * Returns the package name for the host browser that was specified when bui lding the WebAPK. | 65 * Returns the package name for the host browser that was specified when bui lding the WebAPK. |
| 45 * @param context A context. | 66 * @param context A context. |
| 46 * @return The package name. Returns null on an error. | 67 * @return The package name. Returns null on an error. |
| 47 */ | 68 */ |
| 48 public static String getHostBrowserPackageName(Context context) { | 69 public static String getHostBrowserPackageName(final Context context) { |
| 49 if (sHostPackage != null) return sHostPackage; | 70 if (sHostPackage != null) return sHostPackage; |
| 71 | |
| 50 String hostPackage = null; | 72 String hostPackage = null; |
| 51 try { | 73 // Gets the package name of the host browser if it is specified in Andro idManifest.xml. |
| 52 ApplicationInfo ai = context.getPackageManager().getApplicationInfo( | 74 String hostBrowserFromManifest = getHostBrowserFromAndroidManifest(conte xt); |
| 53 context.getPackageName(), PackageManager.GET_META_DATA); | 75 |
| 54 Bundle bundle = ai.metaData; | 76 // Gets all installed browsers that support WebAPKs. |
| 55 hostPackage = bundle.getString(WebApkMetaDataKeys.RUNTIME_HOST); | 77 List<String> packagesSupportingWebApks = |
| 56 } catch (NameNotFoundException e) { | 78 getInstalledBrowsersSupportingWebApks(context.getPackageManager( )); |
| 57 e.printStackTrace(); | 79 |
| 80 if (packagesSupportingWebApks.isEmpty()) { | |
| 81 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.
| |
| 82 } else if (!TextUtils.isEmpty(hostBrowserFromManifest) | |
| 83 && packagesSupportingWebApks.contains(hostBrowserFromManifest)) { | |
| 84 hostPackage = hostBrowserFromManifest; | |
| 85 } else { | |
| 86 // Gets the package name of the host browser if it is stored in the SharedPreference. | |
| 87 String cachedHostBrowser = getHostBrowserFromSharedPreference(contex t); | |
| 88 if (!TextUtils.isEmpty(cachedHostBrowser) | |
| 89 && packagesSupportingWebApks.contains(cachedHostBrowser)) { | |
| 90 hostPackage = cachedHostBrowser; | |
| 91 } else { | |
| 92 // Gets the package name of the default browser on the Android d evice. | |
| 93 // TODO(hanxi): adds a new dialog to ask users to select a host browser when the | |
| 94 // default browser doesn't support WebAPKs. | |
| 95 String defaultBrowser = getDefaultBrowserPackageName(context.get PackageManager()); | |
| 96 if (!TextUtils.isEmpty(defaultBrowser) | |
| 97 && packagesSupportingWebApks.contains(defaultBrowser)) { | |
| 98 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!
| |
| 99 } else if (packagesSupportingWebApks.contains(CHROME_STABLE_PACK AGE)) { | |
| 100 hostPackage = CHROME_STABLE_PACKAGE; | |
| 101 } else if (packagesSupportingWebApks.contains(CHROME_BETA_PACKAG E)) { | |
| 102 hostPackage = CHROME_BETA_PACKAGE; | |
| 103 } else if (packagesSupportingWebApks.contains(CHROME_DEV_PACKAGE )) { | |
| 104 hostPackage = CHROME_DEV_PACKAGE; | |
| 105 } else if (packagesSupportingWebApks.contains(CHROME_CANARY_PACK AGE)) { | |
| 106 hostPackage = CHROME_CANARY_PACKAGE; | |
| 107 } | |
| 108 } | |
| 58 } | 109 } |
| 110 | |
| 59 // Set {@link sHostPackage} to a non-null value so that the value is com puted only once. | 111 // Set {@link sHostPackage} to a non-null value so that the value is com puted only once. |
| 60 sHostPackage = hostPackage != null ? hostPackage : ""; | 112 sHostPackage = hostPackage != null ? hostPackage : ""; |
| 113 writeHostBrowserToSharedPref(context, sHostPackage); | |
| 61 return sHostPackage; | 114 return sHostPackage; |
| 62 } | 115 } |
| 63 | 116 |
| 64 /** | 117 /** |
| 65 * Returns the uid for the host browser that was specified when building the WebAPK. | 118 * Returns the uid for the host browser that was specified when building the WebAPK. |
| 66 * @param context A context. | 119 * @param context A context. |
| 67 * @return The application uid. Returns -1 on an error. | 120 * @return The application uid. Returns -1 on an error. |
| 68 */ | 121 */ |
| 69 public static int getHostBrowserUid(Context context) { | 122 public static int getHostBrowserUid(Context context) { |
| 70 String hostPackageName = getHostBrowserPackageName(context); | 123 String hostPackageName = getHostBrowserPackageName(context); |
| 71 if (hostPackageName == null) { | 124 if (hostPackageName == null) { |
| 72 return -1; | 125 return -1; |
| 73 } | 126 } |
| 74 try { | 127 try { |
| 75 PackageManager packageManager = context.getPackageManager(); | 128 PackageManager packageManager = context.getPackageManager(); |
| 76 ApplicationInfo appInfo = packageManager.getApplicationInfo( | 129 ApplicationInfo appInfo = packageManager.getApplicationInfo( |
| 77 hostPackageName, PackageManager.GET_META_DATA); | 130 hostPackageName, PackageManager.GET_META_DATA); |
| 78 return appInfo.uid; | 131 return appInfo.uid; |
| 79 } catch (NameNotFoundException e) { | 132 } catch (NameNotFoundException e) { |
| 80 e.printStackTrace(); | 133 e.printStackTrace(); |
| 81 } | 134 } |
| 82 return -1; | 135 return -1; |
| 83 } | 136 } |
| 137 | |
| 138 /** Returns the package name of the host browser cached in the SharedPrefere nces. */ | |
| 139 private static String getHostBrowserFromSharedPreference(Context context) { | |
| 140 SharedPreferences sharedPref = | |
| 141 context.getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE); | |
| 142 return sharedPref.getString(SHARED_PREF_RUNTIME_HOST, null); | |
| 143 } | |
| 144 | |
| 145 /** | |
| 146 * Returns all of the installed browsers that supports WebAPKs. | |
| 147 * TODO(hanxi): Investigate the best way to know which browser supports WebA PKs. | |
| 148 */ | |
| 149 private static List<String> getInstalledBrowsersSupportingWebApks( | |
| 150 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
| |
| 151 Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http:// ")); | |
| 152 List<ResolveInfo> resolvedActivityList = packageManager.queryIntentActiv ities( | |
| 153 browserIntent, PackageManager.MATCH_DEFAULT_ONLY); | |
| 154 | |
| 155 List<String> packagesSupportingWebApks = new ArrayList<>(); | |
| 156 for (ResolveInfo info : resolvedActivityList) { | |
| 157 if (sBrowsersSupportingWwebApk.contains(info.activityInfo.packageNam e)) { | |
| 158 packagesSupportingWebApks.add(info.activityInfo.packageName); | |
| 159 } | |
| 160 } | |
| 161 return packagesSupportingWebApks; | |
| 162 } | |
| 163 | |
| 164 /** Returns the package name of the "runtime host" in the AndroidManifest.xm l. */ | |
| 165 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.
| |
| 166 try { | |
| 167 ApplicationInfo ai = context.getPackageManager().getApplicationInfo( | |
| 168 context.getPackageName(), PackageManager.GET_META_DATA); | |
| 169 Bundle bundle = ai.metaData; | |
| 170 return bundle.getString(WebApkMetaDataKeys.RUNTIME_HOST); | |
| 171 } catch (NameNotFoundException e) { | |
| 172 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.
| |
| 173 return null; | |
| 174 } | |
| 175 } | |
| 176 | |
| 177 /** Returns the package name of the default browser on the Android device. * / | |
| 178 private static String getDefaultBrowserPackageName(PackageManager packageMan ager) { | |
| 179 Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http:// ")); | |
| 180 ResolveInfo resolveInfo = | |
| 181 packageManager.resolveActivity(browserIntent, PackageManager.MAT CH_DEFAULT_ONLY); | |
| 182 if (resolveInfo == null || resolveInfo.activityInfo == null) return null ; | |
| 183 | |
| 184 return resolveInfo.activityInfo.packageName; | |
| 185 } | |
| 186 | |
| 187 /** Writes the package name of the host browser to SharedPreferences. */ | |
| 188 private static void writeHostBrowserToSharedPref( | |
| 189 final Context context, final String hostPackage) { | |
| 190 if (TextUtils.isEmpty(hostPackage)) return; | |
| 191 | |
| 192 new AsyncTask<String, Void, Void>() { | |
| 193 @Override | |
| 194 protected Void doInBackground(String... params) { | |
| 195 SharedPreferences sharedPref = | |
| 196 context.getSharedPreferences(SHARED_PREF, Context.MODE_P RIVATE); | |
| 197 SharedPreferences.Editor editor = sharedPref.edit(); | |
| 198 editor.putString(SHARED_PREF_RUNTIME_HOST, params[0]); | |
| 199 editor.apply(); | |
| 200 return null; | |
| 201 } | |
| 202 }.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.
| |
| 203 } | |
| 84 } | 204 } |
| OLD | NEW |