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

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

Issue 2772483002: Commment signed webapks working and verified. (Closed)
Patch Set: Resond to Peter's comments. Created 3 years, 8 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.junit.Assert.assertEquals; 7 import static org.junit.Assert.assertEquals;
8 import static org.junit.Assert.assertFalse;
8 import static org.junit.Assert.assertNull; 9 import static org.junit.Assert.assertNull;
10 import static org.junit.Assert.assertTrue;
11
12 import static org.chromium.webapk.lib.common.WebApkMetaDataKeys.START_URL;
9 13
10 import android.content.Intent; 14 import android.content.Intent;
11 import android.content.pm.ActivityInfo; 15 import android.content.pm.ActivityInfo;
16 import android.content.pm.ApplicationInfo;
12 import android.content.pm.PackageInfo; 17 import android.content.pm.PackageInfo;
13 import android.content.pm.PackageManager.NameNotFoundException; 18 import android.content.pm.PackageManager.NameNotFoundException;
14 import android.content.pm.ResolveInfo; 19 import android.content.pm.ResolveInfo;
15 import android.content.pm.Signature; 20 import android.content.pm.Signature;
21 import android.os.Bundle;
16 22
17 import org.chromium.testing.local.LocalRobolectricTestRunner;
18 import org.junit.Assert; 23 import org.junit.Assert;
19 import org.junit.Before; 24 import org.junit.Before;
20 import org.junit.Test; 25 import org.junit.Test;
21 import org.junit.runner.RunWith; 26 import org.junit.runner.RunWith;
22 import org.robolectric.RuntimeEnvironment; 27 import org.robolectric.RuntimeEnvironment;
23 import org.robolectric.annotation.Config; 28 import org.robolectric.annotation.Config;
24 import org.robolectric.res.builder.RobolectricPackageManager; 29 import org.robolectric.res.builder.RobolectricPackageManager;
25 30
31 import org.chromium.testing.local.LocalRobolectricTestRunner;
32 import org.chromium.testing.local.TestDir;
33
26 import java.net.URISyntaxException; 34 import java.net.URISyntaxException;
27 import java.util.ArrayList; 35 import java.util.ArrayList;
28 import java.util.List; 36 import java.util.List;
29 37
30 /** 38 /** Unit tests for {@link org.chromium.webapk.lib.client.WebApkValidator}. */
31 * Unit tests for {@link org.chromium.webapk.lib.client.WebApkValidator}.
32 */
33 @RunWith(LocalRobolectricTestRunner.class) 39 @RunWith(LocalRobolectricTestRunner.class)
34 @Config(manifest = Config.NONE) 40 @Config(manifest = Config.NONE)
35 public class WebApkValidatorTest { 41 public class WebApkValidatorTest {
36 private static final String WEBAPK_PACKAGE_NAME = "org.chromium.webapk.foo"; 42 private static final String WEBAPK_PACKAGE_NAME = "org.chromium.webapk.foo";
37 private static final String INVALID_WEBAPK_PACKAGE_NAME = "invalid.org.chrom ium.webapk.foo"; 43 private static final String INVALID_WEBAPK_PACKAGE_NAME = "invalid.org.chrom ium.webapk.foo";
38 private static final String URL_OF_WEBAPK = "https://www.foo.com"; 44 private static final String URL_OF_WEBAPK = "https://www.foo.com";
39 private static final String URL_WITHOUT_WEBAPK = "https://www.other.com"; 45 private static final String URL_WITHOUT_WEBAPK = "https://www.other.com";
46 private static final String TEST_DATA_DIR = "webapks/";
40 47
41 private static final byte[] EXPECTED_SIGNATURE = new byte[] { 48 private static final byte[] EXPECTED_SIGNATURE = new byte[] {48, -126, 3, -1 21, 48, -126, 2,
42 48, -126, 3, -121, 48, -126, 2, 111, -96, 3, 2, 1, 2, 2, 4, 20, -104, -6 6, -126, 48, 13, 49 111, -96, 3, 2, 1, 2, 2, 4, 20, -104, -66, -126, 48, 13, 6, 9, 42, - 122, 72, -122, -9,
43 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 11, 5, 0, 48, 116, 49, 11, 48, 9 , 6, 3, 85, 4, 50 13, 1, 1, 11, 5, 0, 48, 116, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 6 7, 65, 49, 16, 48,
44 6, 19, 2, 67, 65, 49, 16, 48, 14, 6, 3, 85, 4, 8, 19, 7, 79, 110, 116, 9 7, 114, 105, 51 14, 6, 3, 85, 4, 8, 19, 7, 79, 110, 116, 97, 114, 105, 111, 49, 17, 48, 15, 6, 3, 85, 4,
45 111, 49, 17, 48, 15, 6, 3, 85, 4, 7, 19, 8, 87, 97, 116, 101, 114, 108, 111, 111, 49, 52 7, 19, 8, 87, 97, 116, 101, 114, 108, 111, 111, 49, 17, 48, 15, 6, 3 , 85, 4, 10, 19, 8,
46 17, 48, 15, 6, 3, 85, 4, 10, 19, 8, 67, 104, 114, 111, 109, 105, 117, 10 9, 49, 17, 48}; 53 67, 104, 114, 111, 109, 105, 117, 109, 49, 17, 48};
47 54
48 private static final byte[] SIGNATURE_1 = new byte[] { 55 private static final byte[] SIGNATURE_1 = new byte[] {13, 52, 51, 48, 51, 48 , 51, 49, 53, 49,
49 13, 52, 51, 48, 51, 48, 51, 49, 53, 49, 54, 52, 52, 90, 48, 116, 49, 11, 48, 9, 6, 3, 56 54, 52, 52, 90, 48, 116, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 67, 6 5, 49, 16, 48, 14,
50 85, 4, 6, 19, 2, 67, 65, 49, 16, 48, 14, 6, 3, 85, 4, 8, 19, 7, 79, 110, 116, 97, 114}; 57 6, 3, 85, 4, 8, 19, 7, 79, 110, 116, 97, 114};
51 58
52 private static final byte[] SIGNATURE_2 = new byte[] { 59 private static final byte[] SIGNATURE_2 = new byte[] {49, 17, 48, 15, 6, 3, 85, 4, 10, 19, 8,
53 49, 17, 48, 15, 6, 3, 85, 4, 10, 19, 8, 67, 104, 114, 111, 109, 105, 117 , 109, 49, 17, 60 67, 104, 114, 111, 109, 105, 117, 109, 49, 17, 48, 15, 6, 3, 85, 4, 11, 19, 8, 67, 104,
54 48, 15, 6, 3, 85, 4, 11, 19, 8, 67, 104, 114, 111, 109, 105, 117, 109, 4 9, 26, 48, 24}; 61 114, 111, 109, 105, 117, 109, 49, 26, 48, 24};
62
63 // This is the public key used for the test files (chrome/test/data/webapks/ public.der)
64 private static final byte[] PUBLIC_KEY = new byte[] {48, 89, 48, 19, 6, 7, 4 2, -122, 72, -50,
65 61, 2, 1, 6, 8, 42, -122, 72, -50, 61, 3, 1, 7, 3, 66, 0, 4, 126, 12 6, 112, -21, 2, 44,
66 118, -29, 29, 86, -65, 118, -107, -82, 20, 118, 53, -103, 73, -58, - 17, 24, 95, -11, 28,
67 60, -31, -7, -19, -125, -92, 120, -5, -128, 19, 19, -127, 13, -44, 2 5, 28, -14, 32, 55,
68 12, 68, -17, -43, 29, -125, 95, -121, 11, 81, -128, 25, 7, -87, -106 , -119, -126, -42,
69 102, -84};
55 70
56 private RobolectricPackageManager mPackageManager; 71 private RobolectricPackageManager mPackageManager;
57 72
58 @Before 73 @Before
59 public void setUp() { 74 public void setUp() {
60 mPackageManager = (RobolectricPackageManager) RuntimeEnvironment 75 mPackageManager =
61 .application.getPackageManager(); 76 (RobolectricPackageManager) RuntimeEnvironment.application.getPa ckageManager();
62 WebApkValidator.initWithBrowserHostSignature(EXPECTED_SIGNATURE); 77 WebApkValidator.initWithBrowserHostSignature(EXPECTED_SIGNATURE, PUBLIC_ KEY);
63 } 78 }
64 79
65 /** 80 /**
66 * Tests {@link WebApkValidator.queryWebApkPackage()} returns a WebAPK's pac kage name if the 81 * Tests {@link WebApkValidator.queryWebApkPackage()} returns a WebAPK's pac kage name if the
67 * WebAPK can handle the given URL and the WebAPK is valid. 82 * WebAPK can handle the given URL and the WebAPK is valid.
68 */ 83 */
69 @Test 84 @Test
70 public void testQueryWebApkPackageReturnsPackageIfTheURLCanBeHandled() { 85 public void testQueryWebApkPackageReturnsPackageIfTheURLCanBeHandled() {
71 try { 86 try {
72 Intent intent = Intent.parseUri(URL_OF_WEBAPK, Intent.URI_INTENT_SCH EME); 87 Intent intent = Intent.parseUri(URL_OF_WEBAPK, Intent.URI_INTENT_SCH EME);
73 intent.addCategory(Intent.CATEGORY_BROWSABLE); 88 intent.addCategory(Intent.CATEGORY_BROWSABLE);
74 89
75 mPackageManager.addResolveInfoForIntent(intent, newResolveInfo(WEBAP K_PACKAGE_NAME)); 90 mPackageManager.addResolveInfoForIntent(intent, newResolveInfo(WEBAP K_PACKAGE_NAME));
76 mPackageManager.addPackage(newPackageInfoWithBrowserSignature( 91 mPackageManager.addPackage(newPackageInfoWithBrowserSignature(
77 WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE))); 92 WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE)));
78 93
79 assertEquals(WEBAPK_PACKAGE_NAME, WebApkValidator.queryWebApkPackage ( 94 assertEquals(WEBAPK_PACKAGE_NAME,
80 RuntimeEnvironment.application, URL_OF_WEBAPK)); 95 WebApkValidator.queryWebApkPackage(
96 RuntimeEnvironment.application, URL_OF_WEBAPK));
81 } catch (URISyntaxException e) { 97 } catch (URISyntaxException e) {
82 Assert.fail("URI is invalid."); 98 Assert.fail("URI is invalid.");
83 } 99 }
84 } 100 }
85 101
86 /** 102 /** Tests {@link WebApkValidator.queryWebApkPackage()} returns null for a no n-browsable Intent.
pkotwicz 2017/03/31 03:59:24 Why this change?
ScottK 2017/04/03 17:44:17 Google's vim auto formatter, apparently - reverted
87 * Tests {@link WebApkValidator.queryWebApkPackage()} returns null for a non -browsable Intent.
88 */ 103 */
89 @Test 104 @Test
90 public void testQueryWebApkPackageReturnsNullForNonBrowsableIntent() { 105 public void testQueryWebApkPackageReturnsNullForNonBrowsableIntent() {
91 try { 106 try {
92 Intent intent = Intent.parseUri(URL_OF_WEBAPK, Intent.URI_INTENT_SCH EME); 107 Intent intent = Intent.parseUri(URL_OF_WEBAPK, Intent.URI_INTENT_SCH EME);
93 108
94 mPackageManager.addResolveInfoForIntent(intent, newResolveInfo(WEBAP K_PACKAGE_NAME)); 109 mPackageManager.addResolveInfoForIntent(intent, newResolveInfo(WEBAP K_PACKAGE_NAME));
95 mPackageManager.addPackage(newPackageInfoWithBrowserSignature( 110 mPackageManager.addPackage(newPackageInfoWithBrowserSignature(
96 WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE))); 111 WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE)));
97 112
98 assertNull(WebApkValidator.queryWebApkPackage( 113 assertNull(WebApkValidator.queryWebApkPackage(
99 RuntimeEnvironment.application, URL_OF_WEBAPK)); 114 RuntimeEnvironment.application, URL_OF_WEBAPK));
100 } catch (URISyntaxException e) { 115 } catch (URISyntaxException e) {
101 Assert.fail("URI is invalid."); 116 Assert.fail("URI is invalid.");
102 } 117 }
103 } 118 }
104 119
105 /** 120 /**
106 * Tests {@link WebApkValidator.queryWebApkPackage()} returns null if no Web APK handles 121 * Tests {@link WebApkValidator.queryWebApkPackage()} returns null if no Web APK handles the
107 * the given URL. 122 * given URL.
108 */ 123 */
109 @Test 124 @Test
110 public void testQueryWebApkPackageReturnsNullWhenNoWebApkHandlesTheURL() { 125 public void testQueryWebApkPackageReturnsNullWhenNoWebApkHandlesTheURL() {
111 try { 126 try {
112 Intent intent = Intent.parseUri(URL_OF_WEBAPK, Intent.URI_INTENT_SCH EME); 127 Intent intent = Intent.parseUri(URL_OF_WEBAPK, Intent.URI_INTENT_SCH EME);
113 intent.addCategory(Intent.CATEGORY_BROWSABLE); 128 intent.addCategory(Intent.CATEGORY_BROWSABLE);
114 129
115 mPackageManager.addResolveInfoForIntent(intent, newResolveInfo(WEBAP K_PACKAGE_NAME)); 130 mPackageManager.addResolveInfoForIntent(intent, newResolveInfo(WEBAP K_PACKAGE_NAME));
116 mPackageManager.addPackage(newPackageInfoWithBrowserSignature( 131 mPackageManager.addPackage(newPackageInfoWithBrowserSignature(
117 WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE))); 132 WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE)));
(...skipping 15 matching lines...) Expand all
133 infos.add(newResolveInfo(WEBAPK_PACKAGE_NAME)); 148 infos.add(newResolveInfo(WEBAPK_PACKAGE_NAME));
134 mPackageManager.addPackage(newPackageInfoWithBrowserSignature( 149 mPackageManager.addPackage(newPackageInfoWithBrowserSignature(
135 WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE))); 150 WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE)));
136 151
137 assertEquals(WEBAPK_PACKAGE_NAME, 152 assertEquals(WEBAPK_PACKAGE_NAME,
138 WebApkValidator.findWebApkPackage(RuntimeEnvironment.application , infos)); 153 WebApkValidator.findWebApkPackage(RuntimeEnvironment.application , infos));
139 } 154 }
140 155
141 /** 156 /**
142 * Tests {@link WebApkValidator.findWebApkPackage} returns null if none of t he packages for the 157 * Tests {@link WebApkValidator.findWebApkPackage} returns null if none of t he packages for the
143 * ResolveInfos start with {@link WebApkConstants.WEBAPK_PACKAGE_PREFIX}. 158 * ResolveInfos start with {@link WebApkConstants.WEBAPK_PACKAGE_PREFIX}.
pkotwicz 2017/03/31 03:59:24 You probably need to update this comment
ScottK 2017/04/03 17:44:18 Done.
144 */ 159 */
145 @Test 160 @Test
146 public void testFindWebApkPackageReturnsNullForInvalidPackageName() { 161 public void testFindWebApkPackageReturnsNullForInvalidPackageName() {
147 List<ResolveInfo> infos = new ArrayList<ResolveInfo>(); 162 List<ResolveInfo> infos = new ArrayList<ResolveInfo>();
148 infos.add(newResolveInfo(INVALID_WEBAPK_PACKAGE_NAME)); 163 infos.add(newResolveInfo(INVALID_WEBAPK_PACKAGE_NAME));
149 mPackageManager.addPackage(newPackageInfoWithBrowserSignature( 164 mPackageManager.addPackage(newPackageInfoWithBrowserSignature(
150 INVALID_WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE))) ; 165 INVALID_WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE))) ;
151 166
152 assertNull(WebApkValidator.findWebApkPackage(RuntimeEnvironment.applicat ion, infos)); 167 assertNull(WebApkValidator.findWebApkPackage(RuntimeEnvironment.applicat ion, infos));
153 } 168 }
(...skipping 23 matching lines...) Expand all
177 throws NameNotFoundException { 192 throws NameNotFoundException {
178 List<ResolveInfo> infos = new ArrayList<ResolveInfo>(); 193 List<ResolveInfo> infos = new ArrayList<ResolveInfo>();
179 infos.add(newResolveInfo(WEBAPK_PACKAGE_NAME)); 194 infos.add(newResolveInfo(WEBAPK_PACKAGE_NAME));
180 Signature signatures[] = 195 Signature signatures[] =
181 new Signature[] {new Signature(SIGNATURE_1), new Signature(SIGNA TURE_2)}; 196 new Signature[] {new Signature(SIGNATURE_1), new Signature(SIGNA TURE_2)};
182 mPackageManager.addPackage(newPackageInfo(WEBAPK_PACKAGE_NAME, signature s)); 197 mPackageManager.addPackage(newPackageInfo(WEBAPK_PACKAGE_NAME, signature s));
183 198
184 assertNull(WebApkValidator.findWebApkPackage(RuntimeEnvironment.applicat ion, infos)); 199 assertNull(WebApkValidator.findWebApkPackage(RuntimeEnvironment.applicat ion, infos));
185 } 200 }
186 201
202 /** Tests {@link WebApkValidator.isValidWebApk} for comment signed webapks. */
pkotwicz 2017/03/31 03:59:24 Can you make the comment more descriptive. The com
ScottK 2017/04/03 17:44:17 Done.
203 @Test
204 public void testIsValidWebApkCommentSigned() {
205 String[] filenames = {"example.apk", "java-example.apk"};
206 String packageName = "com.webapk.a9c419502bb98fcb7";
207 Signature[] signature = new Signature[] {new Signature(SIGNATURE_1)};
208
209 for (String filename : filenames) {
pkotwicz 2017/03/31 03:59:24 Maybe you should call mPackageManager.removePackag
ScottK 2017/04/03 17:44:17 Done.
210 mPackageManager.addPackage(
211 newPackageInfo(packageName, signature, testFilename(filename )));
212 assertTrue(filename + " did not verify",
213 WebApkValidator.isValidWebApk(RuntimeEnvironment.application , packageName));
214 }
215 }
216
217 /** Tests {@link WebApkValidator.isValidWebApk} for comment signed webapks. */
218 @Test
219 public void testIsValidWebApkCommentSignedFailures() {
220 String[] filenames = {
221 "bad-sig.apk", "bad-utf8-fname.apk", "empty.apk", "extra-len-too -large.apk",
222 "fcomment-too-large.apk", "no-cd.apk", "no-comment.apk", "no-eoc d.apk",
223 "no-lfh.apk", "not-an.apk", "too-many-metainf.apk", "truncated.a pk", "zeros.apk",
224 "zeros-at-end.apk",
225 };
226 String packageName = "com.webapk.a9c419502bb98fcb7";
227 Signature[] signature = new Signature[] {new Signature(SIGNATURE_1)};
228
229 for (String filename : filenames) {
230 mPackageManager.addPackage(
231 newPackageInfo(packageName, signature, testFilename(filename )));
232 assertFalse(filename,
233 WebApkValidator.isValidWebApk(RuntimeEnvironment.application , packageName));
234 }
235 }
236
237 // Get the full test filename.
238 private static String testFilename(String fname) {
pkotwicz 2017/03/31 03:59:24 Nit: testFilename() -> testFilePath()
ScottK 2017/04/03 17:44:17 Done.
239 return TestDir.getTestFilePath(TEST_DATA_DIR + fname);
240 }
241
187 private static ResolveInfo newResolveInfo(String packageName) { 242 private static ResolveInfo newResolveInfo(String packageName) {
188 ActivityInfo activityInfo = new ActivityInfo(); 243 ActivityInfo activityInfo = new ActivityInfo();
189 activityInfo.packageName = packageName; 244 activityInfo.packageName = packageName;
190 ResolveInfo resolveInfo = new ResolveInfo(); 245 ResolveInfo resolveInfo = new ResolveInfo();
191 resolveInfo.activityInfo = activityInfo; 246 resolveInfo.activityInfo = activityInfo;
192 return resolveInfo; 247 return resolveInfo;
193 } 248 }
194 249
195 private static PackageInfo newPackageInfo(String packageName, Signature[] si gnatures) { 250 private static PackageInfo newPackageInfo(String packageName, Signature[] si gnatures) {
pkotwicz 2017/03/31 03:59:24 Nit: I would pass the sourceDir to this function (
ScottK 2017/04/03 17:44:17 Done.
196 PackageInfo packageInfo = new PackageInfo(); 251 PackageInfo packageInfo = new PackageInfo();
197 packageInfo.packageName = packageName; 252 packageInfo.packageName = packageName;
198 packageInfo.signatures = signatures; 253 packageInfo.signatures = signatures;
254 packageInfo.applicationInfo = new ApplicationInfo();
255 packageInfo.applicationInfo.metaData = new Bundle();
256 packageInfo.applicationInfo.metaData.putString(START_URL, "https://non-e mpty.com/starturl");
199 return packageInfo; 257 return packageInfo;
200 } 258 }
201 259
260 private static PackageInfo newPackageInfo(
261 String packageName, Signature[] signatures, String sourceDir) {
262 PackageInfo packageInfo = newPackageInfo(packageName, signatures);
263 packageInfo.applicationInfo.sourceDir = sourceDir;
264 return packageInfo;
265 }
266
202 // The browser signature is expected to always be the second signature - the first (and any 267 // The browser signature is expected to always be the second signature - the first (and any
203 // additional ones after the second) are ignored. 268 // additional ones after the second) are ignored.
204 private static PackageInfo newPackageInfoWithBrowserSignature( 269 private static PackageInfo newPackageInfoWithBrowserSignature(
205 String packageName, Signature signature) { 270 String packageName, Signature signature) {
206 return newPackageInfo(packageName, new Signature[] {new Signature(""), s ignature}); 271 return newPackageInfo(packageName, new Signature[] {new Signature(""), s ignature});
207 } 272 }
208 } 273 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698