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; | |
| 11 import android.os.Bundle; | 15 import android.os.Bundle; |
| 16 import android.text.TextUtils; | |
| 12 | 17 |
| 18 import org.chromium.webapk.lib.common.WebApkConstants; | |
| 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 public static final String SHARED_PREF_RUNTIME_HOST = "runtime_host"; | |
| 30 | |
| 31 // The package names of the channels of Chrome that support WebAPKs. The mos t preferred one | |
| 32 // comes first. | |
| 33 private static List<String> sBrowsersSupportingWebApk = new ArrayList<String >( | |
| 34 Arrays.asList("com.google.android.apps.chrome", "com.android.chrome" , "com.chrome.beta", | |
| 35 "com.chrome.dev", "com.chrome.canary")); | |
| 19 | 36 |
| 20 /** | 37 /** |
| 21 * Caches the value read from Application Metadata which specifies the host browser's package | 38 * Caches the package name of the host browser. {@link sHostPackage} might r efer to a browser |
| 22 * name. | 39 * which has been uninstalled. A notification can keep the WebAPK process al ive after the host |
| 40 * browser has been uninstalled. | |
| 23 */ | 41 */ |
| 24 private static String sHostPackage; | 42 private static String sHostPackage; |
| 25 | 43 |
| 44 public static void resetCachedHostPackageForTesting() { | |
|
Yaron
2017/05/15 18:41:37
Can you confirm whether these are removed for rele
Xi Han
2017/05/16 13:50:39
I have confirmed that these functions aren't in th
| |
| 45 sHostPackage = null; | |
| 46 } | |
| 47 | |
| 48 public static void setBrowsersSupportingWebApkForTesting(List<String> browse rs) { | |
| 49 sBrowsersSupportingWebApk = browsers; | |
| 50 } | |
| 51 | |
| 26 /** | 52 /** |
| 27 * Returns a Context for the host browser that was specified when building t he WebAPK. | 53 * Returns a Context for the host browser that was specified when building t he WebAPK. |
| 28 * @param context A context. | 54 * @param context A context. |
| 29 * @return The remote context. Returns null on an error. | 55 * @return The remote context. Returns null on an error. |
| 30 */ | 56 */ |
| 31 public static Context getHostBrowserContext(Context context) { | 57 public static Context getHostBrowserContext(Context context) { |
| 32 try { | 58 try { |
| 33 String hostPackage = getHostBrowserPackageName(context); | 59 String hostPackage = getHostBrowserPackageName(context); |
| 34 return context.getApplicationContext().createPackageContext( | 60 return context.getApplicationContext().createPackageContext( |
| 35 hostPackage, | 61 hostPackage, |
| 36 Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_IN CLUDE_CODE); | 62 Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_IN CLUDE_CODE); |
| 37 } catch (NameNotFoundException e) { | 63 } catch (NameNotFoundException e) { |
| 38 e.printStackTrace(); | 64 e.printStackTrace(); |
| 39 } | 65 } |
| 40 return null; | 66 return null; |
| 41 } | 67 } |
| 42 | 68 |
| 43 /** | 69 /** |
| 44 * Returns the package name for the host browser that was specified when bui lding the WebAPK. | 70 * Returns the package name of the host browser to launch the WebAPK. Also c aches the package |
| 71 * name in the SharedPreference if it is not null. | |
| 45 * @param context A context. | 72 * @param context A context. |
| 46 * @return The package name. Returns null on an error. | 73 * @return The package name. Returns null on an error. |
| 47 */ | 74 */ |
| 48 public static String getHostBrowserPackageName(Context context) { | 75 public static String getHostBrowserPackageName(Context context) { |
| 49 if (sHostPackage != null) return sHostPackage; | 76 if (sHostPackage == null) { |
| 50 String hostPackage = null; | 77 sHostPackage = getHostBrowserPackageNameInternal(context); |
| 51 try { | 78 if (sHostPackage != null) { |
| 52 ApplicationInfo ai = context.getPackageManager().getApplicationInfo( | 79 writeHostBrowserToSharedPref(context, sHostPackage); |
| 53 context.getPackageName(), PackageManager.GET_META_DATA); | 80 } |
| 54 Bundle bundle = ai.metaData; | |
| 55 hostPackage = bundle.getString(WebApkMetaDataKeys.RUNTIME_HOST); | |
| 56 } catch (NameNotFoundException e) { | |
| 57 e.printStackTrace(); | |
| 58 } | 81 } |
| 59 // Set {@link sHostPackage} to a non-null value so that the value is com puted only once. | 82 |
| 60 sHostPackage = hostPackage != null ? hostPackage : ""; | |
| 61 return sHostPackage; | 83 return sHostPackage; |
| 62 } | 84 } |
| 63 | 85 |
| 64 /** | 86 /** |
| 87 * Returns the package name of the host browser to launch the WebAPK, or nul l if not find one. | |
| 88 */ | |
| 89 private static String getHostBrowserPackageNameInternal(Context context) { | |
| 90 // Gets all installed browsers that support WebAPKs. | |
| 91 List<String> installedBrowsers = getInstalledBrowsers(context.getPackage Manager()); | |
| 92 if (installedBrowsers.isEmpty()) { | |
| 93 return null; | |
| 94 } | |
| 95 | |
| 96 // Gets the package name of the host browser if it is specified in Andro idManifest.xml. | |
| 97 String hostBrowserFromManifest = getHostBrowserFromAndroidManifest( | |
| 98 context.getPackageManager(), context.getPackageName()); | |
| 99 if (!TextUtils.isEmpty(hostBrowserFromManifest) | |
| 100 && installedBrowsers.contains(hostBrowserFromManifest)) { | |
| 101 return hostBrowserFromManifest; | |
| 102 } | |
| 103 | |
| 104 // Gets the package name of the host browser if it is stored in the Shar edPreference. | |
| 105 String cachedHostBrowser = getHostBrowserFromSharedPreference(context); | |
| 106 if (!TextUtils.isEmpty(cachedHostBrowser) | |
| 107 && installedBrowsers.contains(cachedHostBrowser)) { | |
| 108 return cachedHostBrowser; | |
| 109 } | |
| 110 | |
| 111 // Gets the package name of the default browser on the Android device. | |
| 112 // TODO(hanxi): Investigate the best way to know which browser supports WebAPKs. | |
| 113 String defaultBrowser = getDefaultBrowserPackageName(context.getPackageM anager()); | |
| 114 if (!TextUtils.isEmpty(defaultBrowser) && installedBrowsers.contains(def aultBrowser) | |
| 115 && sBrowsersSupportingWebApk.contains(defaultBrowser)) { | |
| 116 return defaultBrowser; | |
| 117 } | |
| 118 | |
| 119 // TODO(hanxi): adds a new dialog to ask users to select a host browser when the default | |
| 120 // browser doesn't support WebAPKs. | |
| 121 for (String name : sBrowsersSupportingWebApk) { | |
| 122 if (installedBrowsers.contains(name)) { | |
| 123 return name; | |
| 124 } | |
| 125 } | |
| 126 | |
| 127 return null; | |
| 128 } | |
| 129 | |
| 130 /** | |
| 65 * Returns the uid for the host browser that was specified when building the WebAPK. | 131 * Returns the uid for the host browser that was specified when building the WebAPK. |
| 66 * @param context A context. | 132 * @param context A context. |
| 67 * @return The application uid. Returns -1 on an error. | 133 * @return The application uid. Returns -1 on an error. |
| 68 */ | 134 */ |
| 69 public static int getHostBrowserUid(Context context) { | 135 public static int getHostBrowserUid(Context context) { |
| 70 String hostPackageName = getHostBrowserPackageName(context); | 136 String hostPackageName = getHostBrowserPackageName(context); |
| 71 if (hostPackageName == null) { | 137 if (hostPackageName == null) { |
| 72 return -1; | 138 return -1; |
| 73 } | 139 } |
| 74 try { | 140 try { |
| 75 PackageManager packageManager = context.getPackageManager(); | 141 PackageManager packageManager = context.getPackageManager(); |
| 76 ApplicationInfo appInfo = packageManager.getApplicationInfo( | 142 ApplicationInfo appInfo = packageManager.getApplicationInfo( |
| 77 hostPackageName, PackageManager.GET_META_DATA); | 143 hostPackageName, PackageManager.GET_META_DATA); |
| 78 return appInfo.uid; | 144 return appInfo.uid; |
| 79 } catch (NameNotFoundException e) { | 145 } catch (NameNotFoundException e) { |
| 80 e.printStackTrace(); | 146 e.printStackTrace(); |
| 81 } | 147 } |
| 82 return -1; | 148 return -1; |
| 83 } | 149 } |
| 150 | |
| 151 /** Returns the package name of the host browser cached in the SharedPrefere nces. */ | |
| 152 private static String getHostBrowserFromSharedPreference(Context context) { | |
| 153 SharedPreferences sharedPref = | |
| 154 context.getSharedPreferences(WebApkConstants.PREF_PACKAGE, Conte xt.MODE_PRIVATE); | |
| 155 return sharedPref.getString(SHARED_PREF_RUNTIME_HOST, null); | |
| 156 } | |
| 157 | |
| 158 /** Returns a list of package names of all the installed browsers on the dev ice. */ | |
| 159 private static List<String> getInstalledBrowsers(PackageManager packageManag er) { | |
|
Yaron
2017/05/15 18:41:38
Ok, so Peter was right that ordering matters for t
Xi Han
2017/05/16 13:50:39
You are right, updated to set.
| |
| 160 Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http:// ")); | |
| 161 List<ResolveInfo> resolvedActivityList = packageManager.queryIntentActiv ities( | |
| 162 browserIntent, PackageManager.MATCH_DEFAULT_ONLY); | |
| 163 | |
| 164 List<String> packagesSupportingWebApks = new ArrayList<>(); | |
| 165 for (ResolveInfo info : resolvedActivityList) { | |
| 166 packagesSupportingWebApks.add(info.activityInfo.packageName); | |
| 167 } | |
| 168 return packagesSupportingWebApks; | |
| 169 } | |
| 170 | |
| 171 /** Returns the package name of the "runtime host" in the AndroidManifest.xm l. */ | |
| 172 private static String getHostBrowserFromAndroidManifest( | |
| 173 PackageManager packageManager, String webApkPackageName) { | |
| 174 try { | |
| 175 ApplicationInfo ai = packageManager.getApplicationInfo( | |
| 176 webApkPackageName, PackageManager.GET_META_DATA); | |
| 177 Bundle bundle = ai.metaData; | |
| 178 return bundle.getString(WebApkMetaDataKeys.RUNTIME_HOST); | |
| 179 } catch (NameNotFoundException e) { | |
| 180 return null; | |
| 181 } | |
| 182 } | |
| 183 | |
| 184 /** Returns the package name of the default browser on the Android device. * / | |
| 185 private static String getDefaultBrowserPackageName(PackageManager packageMan ager) { | |
| 186 Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http:// ")); | |
| 187 ResolveInfo resolveInfo = | |
| 188 packageManager.resolveActivity(browserIntent, PackageManager.MAT CH_DEFAULT_ONLY); | |
| 189 if (resolveInfo == null || resolveInfo.activityInfo == null) return null ; | |
| 190 | |
| 191 return resolveInfo.activityInfo.packageName; | |
| 192 } | |
| 193 | |
| 194 /** Writes the package name of the host browser to the SharedPreferences. */ | |
| 195 private static void writeHostBrowserToSharedPref( | |
| 196 final Context context, final String hostPackage) { | |
| 197 if (TextUtils.isEmpty(hostPackage)) return; | |
| 198 | |
| 199 SharedPreferences sharedPref = | |
| 200 context.getSharedPreferences(WebApkConstants.PREF_PACKAGE, Conte xt.MODE_PRIVATE); | |
| 201 SharedPreferences.Editor editor = sharedPref.edit(); | |
| 202 editor.putString(SHARED_PREF_RUNTIME_HOST, hostPackage); | |
| 203 editor.apply(); | |
| 204 } | |
| 84 } | 205 } |
| OLD | NEW |