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

Side by Side Diff: chrome/android/webapk/libs/client/src/org/chromium/webapk/lib/client/WebApkValidator.java

Issue 2707993003: [Android]: Hide add-to-homescreen app menu item when WebAPK is installed (Closed)
Patch Set: Add new state for 'Add to Homescreen' Menu item Created 3 years, 9 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 unified diff | Download patch
OLDNEW
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.lib.client; 5 package org.chromium.webapk.lib.client;
6 6
7 import static org.chromium.webapk.lib.common.WebApkConstants.WEBAPK_PACKAGE_PREF IX; 7 import static org.chromium.webapk.lib.common.WebApkConstants.WEBAPK_PACKAGE_PREF IX;
8 8
9 import android.content.Context; 9 import android.content.Context;
10 import android.content.Intent; 10 import android.content.Intent;
11 import android.content.pm.PackageInfo; 11 import android.content.pm.PackageInfo;
12 import android.content.pm.PackageManager; 12 import android.content.pm.PackageManager;
13 import android.content.pm.PackageManager.NameNotFoundException; 13 import android.content.pm.PackageManager.NameNotFoundException;
14 import android.content.pm.ResolveInfo; 14 import android.content.pm.ResolveInfo;
15 import android.content.pm.Signature; 15 import android.content.pm.Signature;
16 import android.util.Log; 16 import android.util.Log;
17 17
18 import java.util.Arrays; 18 import java.util.Arrays;
19 import java.util.LinkedList;
19 import java.util.List; 20 import java.util.List;
20 21
21 /** 22 /**
22 * Checks whether a URL belongs to a WebAPK, and whether a WebAPK is signed by t he WebAPK Minting 23 * Checks whether a URL belongs to a WebAPK, and whether a WebAPK is signed by t he WebAPK Minting
23 * Server. 24 * Server.
24 */ 25 */
25 public class WebApkValidator { 26 public class WebApkValidator {
26 27
27 private static final String TAG = "WebApkValidator"; 28 private static final String TAG = "WebApkValidator";
28 private static byte[] sExpectedSignature; 29 private static byte[] sExpectedSignature;
29 30
30 /** 31 /**
31 * Queries the PackageManager to determine whether a WebAPK can handle the U RL. Ignores 32 * Queries the PackageManager to determine whether a WebAPK can handle the U RL. Ignores
32 * whether the user has selected a default handler for the URL and whether t he default 33 * whether the user has selected a default handler for the URL and whether t he default
33 * handler is the WebAPK. 34 * handler is the WebAPK.
34 * 35 *
35 * NOTE(yfriedman): This can fail if multiple WebAPKs can match the supplied url. 36 * NOTE(yfriedman): This can fail if multiple WebAPKs can match the supplied url.
36 * 37 *
37 * @param context The application context. 38 * @param context The application context.
38 * @param url The url to check. 39 * @param url The url to check.
39 * @return Package name of WebAPK which can handle the URL. Null if the url should not be 40 * @return Package name of WebAPK which can handle the URL. Null if the url should not be
40 * handled by a WebAPK. 41 * handled by a WebAPK.
41 */ 42 */
42 public static String queryWebApkPackage(Context context, String url) { 43 public static String queryWebApkPackage(Context context, String url) {
44 return findWebApkPackage(context, resolveInfosForUrl(context, url));
45 }
46
47 /**
48 * Queries the PackageManager to determine whether a WebAPK can handle the U RL. Ignores
49 * whether the user has selected a default handler for the URL and whether t he default
50 * handler is the WebAPK.
51 *
52 * NOTE: This can fail if multiple WebAPKs can match the supplied url.
nyquist 2017/02/28 07:04:19 What does fail mean in this scenario? From the cod
gonzalon 2017/02/28 16:12:24 Yes, I added a clarification on the comment about
53 *
54 * @param context The application context.
55 * @param url The url to check.
nyquist 2017/02/28 07:04:19 Nit: Comments are written in normal English, so UR
gonzalon 2017/02/28 16:12:24 Done.
56 * @return Resolve Info of a WebAPK which can handle the URL. Null if the ur l should not be
57 * handled by a WebAPK.
58 */
59 public static ResolveInfo queryResolveInfo(Context context, String url) {
60 return findResolveInfo(context, resolveInfosForUrl(context, url));
61 }
62
63 /**
64 * Fetches the list of resolve infos from the PackageManager that can handle the URL.
nyquist 2017/02/28 07:04:19 {@link ResolveInfo}s
gonzalon 2017/02/28 16:12:24 Done.
65 *
66 * @param context The application context.
67 * @param url The url to check.
68 * @return The list of resolve infos found that can handle the URL.
69 */
70 private static List<ResolveInfo> resolveInfosForUrl(Context context, String url) {
nyquist 2017/02/28 07:04:19 Would you want to annotate this with @Nonnull and/
gonzalon 2017/02/28 16:12:23 Done.
43 Intent intent; 71 Intent intent;
44 try { 72 try {
45 intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME); 73 intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
46 } catch (Exception e) { 74 } catch (Exception e) {
47 return null; 75 return new LinkedList<>();
48 } 76 }
49 77
50 intent.addCategory(Intent.CATEGORY_BROWSABLE); 78 intent.addCategory(Intent.CATEGORY_BROWSABLE);
51 intent.setComponent(null); 79 intent.setComponent(null);
52 Intent selector = intent.getSelector(); 80 Intent selector = intent.getSelector();
53 if (selector != null) { 81 if (selector != null) {
54 selector.addCategory(Intent.CATEGORY_BROWSABLE); 82 selector.addCategory(Intent.CATEGORY_BROWSABLE);
55 selector.setComponent(null); 83 selector.setComponent(null);
56 } 84 }
57 85 return context.getPackageManager().queryIntentActivities(
58 List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntent Activities(
59 intent, PackageManager.GET_RESOLVED_FILTER); 86 intent, PackageManager.GET_RESOLVED_FILTER);
60 return findWebApkPackage(context, resolveInfos);
61 } 87 }
62 88
63 /** 89 /**
64 * @param context The context to use to check whether WebAPK is valid. 90 * @param context The context to use to check whether WebAPK is valid.
65 * @param infos The ResolveInfos to search. 91 * @param infos The ResolveInfos to search.
66 * @return Package name of the ResolveInfo which corresponds to a WebAPK. Nu ll if none of the 92 * @return Package name of the ResolveInfo which corresponds to a WebAPK. Nu ll if none of the
67 * ResolveInfos corresponds to a WebAPK. 93 * ResolveInfos corresponds to a WebAPK.
68 */ 94 */
69 public static String findWebApkPackage(Context context, List<ResolveInfo> in fos) { 95 public static String findWebApkPackage(Context context, List<ResolveInfo> in fos) {
96 ResolveInfo resolveInfo = findResolveInfo(context, infos);
97 if (resolveInfo != null) {
98 return resolveInfo.activityInfo.packageName;
99 }
100 return null;
101 }
102
103 /**
104 * @param context The context to use to check whether WebAPK is valid.
105 * @param infos The ResolveInfos to search.
106 * @return ResolveInfo which corresponds to a WebAPK. Null if none of the Re solveInfos
107 * corresponds to a WebAPK.
108 */
109 private static ResolveInfo findResolveInfo(Context context, List<ResolveInfo > infos) {
70 for (ResolveInfo info : infos) { 110 for (ResolveInfo info : infos) {
71 if (info.activityInfo != null 111 if (info.activityInfo != null
72 && isValidWebApk(context, info.activityInfo.packageName)) { 112 && isValidWebApk(context, info.activityInfo.packageName)) {
73 return info.activityInfo.packageName; 113 return info;
74 } 114 }
75 } 115 }
76 return null; 116 return null;
77 } 117 }
78 118
79 /** 119 /**
80 * Returns whether the provided WebAPK is installed and passes signature che cks. 120 * Returns whether the provided WebAPK is installed and passes signature che cks.
81 * @param context A context 121 * @param context A context
82 * @param webappPackageName The package name to check 122 * @param webappPackageName The package name to check
83 * @return true iff the WebAPK is installed and passes security checks 123 * @return true iff the WebAPK is installed and passes security checks
84 */ 124 */
85 public static boolean isValidWebApk(Context context, String webappPackageNam e) { 125 public static boolean isValidWebApk(Context context, String webappPackageNam e) {
86 if (sExpectedSignature == null) { 126 if (sExpectedSignature == null) {
87 Log.wtf(TAG, "WebApk validation failure - expected signature not set ." 127 Log.wtf(TAG, "WebApk validation failure - expected signature not set ."
88 + "missing call to WebApkValidator.initWithBrowserHostSignat ure"); 128 + "missing call to WebApkValidator.initWithBrowserHostSignat ure");
89 } 129 }
90 if (!webappPackageName.startsWith(WEBAPK_PACKAGE_PREFIX)) { 130 if (!webappPackageName.startsWith(WEBAPK_PACKAGE_PREFIX)) {
91 return false; 131 return false;
92 } 132 }
93 // check signature 133 // check signature
94 PackageInfo packageInfo = null; 134 PackageInfo packageInfo = null;
95 try { 135 try {
96 packageInfo = context.getPackageManager().getPackageInfo(webappPacka geName, 136 packageInfo = context.getPackageManager().getPackageInfo(webappPacka geName,
97 PackageManager.GET_SIGNATURES); 137 PackageManager.GET_SIGNATURES);
98 } catch (NameNotFoundException e) { 138 } catch (NameNotFoundException e) {
99 e.printStackTrace(); 139 e.printStackTrace();
nyquist 2017/02/28 07:04:19 While you're at it, could you pleas remove this li
gonzalon 2017/02/28 16:12:23 Done.
100 Log.d(TAG, "WebApk not found"); 140 Log.d(TAG, "WebApk not found");
101 return false; 141 return false;
102 } 142 }
103 143
104 final Signature[] arrSignatures = packageInfo.signatures; 144 final Signature[] arrSignatures = packageInfo.signatures;
105 if (arrSignatures != null && arrSignatures.length == 2) { 145 if (arrSignatures != null && arrSignatures.length == 2) {
106 for (Signature signature : arrSignatures) { 146 for (Signature signature : arrSignatures) {
107 if (Arrays.equals(sExpectedSignature, signature.toByteArray())) { 147 if (Arrays.equals(sExpectedSignature, signature.toByteArray())) {
108 Log.d(TAG, "WebApk valid - signature match!"); 148 Log.d(TAG, "WebApk valid - signature match!");
109 return true; 149 return true;
110 } 150 }
111 } 151 }
112 } 152 }
113 Log.d(TAG, "WebApk invalid"); 153 Log.d(TAG, "WebApk invalid");
114 return false; 154 return false;
115 } 155 }
116 156
117 /** 157 /**
118 * Initializes the WebApkValidator with the expected signature that WebAPKs must be signed 158 * Initializes the WebApkValidator with the expected signature that WebAPKs must be signed
119 * with for the current host. 159 * with for the current host.
120 * @param expectedSignature 160 * @param expectedSignature
121 */ 161 */
122 public static void initWithBrowserHostSignature(byte[] expectedSignature) { 162 public static void initWithBrowserHostSignature(byte[] expectedSignature) {
123 if (sExpectedSignature != null) { 163 if (sExpectedSignature != null) {
124 return; 164 return;
125 } 165 }
126 sExpectedSignature = Arrays.copyOf(expectedSignature, expectedSignature. length); 166 sExpectedSignature = Arrays.copyOf(expectedSignature, expectedSignature. length);
127 } 167 }
128 } 168 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698