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 |