OLD | NEW |
| (Empty) |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 package org.chromium.content.browser.installedapp; | |
6 | |
7 import android.content.pm.ApplicationInfo; | |
8 import android.content.pm.PackageManager; | |
9 import android.content.pm.PackageManager.NameNotFoundException; | |
10 import android.content.res.AssetManager; | |
11 import android.content.res.Resources; | |
12 import android.os.Bundle; | |
13 | |
14 import org.junit.Assert; | |
15 import org.junit.Before; | |
16 import org.junit.Test; | |
17 import org.junit.runner.RunWith; | |
18 | |
19 import org.robolectric.RuntimeEnvironment; | |
20 import org.robolectric.annotation.Config; | |
21 import org.robolectric.res.builder.DefaultPackageManager; | |
22 | |
23 import org.chromium.base.test.util.Feature; | |
24 import org.chromium.installedapp.mojom.InstalledAppProvider; | |
25 import org.chromium.installedapp.mojom.RelatedApplication; | |
26 import org.chromium.testing.local.LocalRobolectricTestRunner; | |
27 | |
28 import java.net.URI; | |
29 import java.net.URISyntaxException; | |
30 import java.util.HashMap; | |
31 | |
32 /** | |
33 * Ensure that the InstalledAppProvider returns the correct apps. | |
34 */ | |
35 @RunWith(LocalRobolectricTestRunner.class) | |
36 @Config(manifest = Config.NONE) | |
37 public class InstalledAppProviderTest { | |
38 private static final String ASSET_STATEMENTS_KEY = | |
39 InstalledAppProviderImpl.ASSET_STATEMENTS_KEY; | |
40 private static final String RELATION_HANDLE_ALL_URLS = | |
41 "delegate_permission/common.handle_all_urls"; | |
42 private static final String NAMESPACE_WEB = | |
43 InstalledAppProviderImpl.ASSET_STATEMENT_NAMESPACE_WEB; | |
44 private static final String PLATFORM_ANDROID = | |
45 InstalledAppProviderImpl.RELATED_APP_PLATFORM_ANDROID; | |
46 private static final String PLATFORM_OTHER = "itunes"; | |
47 // Note: Android package name and origin deliberately unrelated (there is no
requirement that | |
48 // they be the same). | |
49 private static final String PACKAGE_NAME_1 = "com.app1.package"; | |
50 private static final String PACKAGE_NAME_2 = "com.app2.package"; | |
51 private static final String PACKAGE_NAME_3 = "com.app3.package"; | |
52 private static final String URL_UNRELATED = "https://appstore.example.com/ap
p1"; | |
53 private static final String ORIGIN = "https://example.com:8000"; | |
54 private static final String URL_ON_ORIGIN = | |
55 "https://example.com:8000/path/to/page.html?key=value#fragment"; | |
56 private static final String ORIGIN_SYNTAX_ERROR = "https:{"; | |
57 private static final String ORIGIN_MISSING_SCHEME = "path/only"; | |
58 private static final String ORIGIN_MISSING_HOST = "file:///path/piece"; | |
59 private static final String ORIGIN_MISSING_PORT = "http://example.com"; | |
60 private static final String ORIGIN_DIFFERENT_SCHEME = "http://example.com:80
00"; | |
61 private static final String ORIGIN_DIFFERENT_HOST = "https://example.org:800
0"; | |
62 private static final String ORIGIN_DIFFERENT_PORT = "https://example.com:800
1"; | |
63 | |
64 private FakePackageManager mPackageManager; | |
65 private FakeFrameUrlDelegate mFrameUrlDelegate; | |
66 private InstalledAppProviderImpl mInstalledAppProvider; | |
67 | |
68 /** | |
69 * FakePackageManager allows for the "installation" of Android package names
and setting up | |
70 * Resources for installed packages. | |
71 */ | |
72 private static class FakePackageManager extends DefaultPackageManager { | |
73 private final HashMap<String, Bundle> mMetaDataMap; | |
74 private final HashMap<String, Resources> mResourceMap; | |
75 | |
76 public FakePackageManager() { | |
77 super(); | |
78 mMetaDataMap = new HashMap<String, Bundle>(); | |
79 mResourceMap = new HashMap<String, Resources>(); | |
80 } | |
81 | |
82 @Override | |
83 public ApplicationInfo getApplicationInfo(String packageName, int flags) | |
84 throws NameNotFoundException { | |
85 if (packageName == null) throw new NullPointerException(); | |
86 | |
87 Bundle metaData = mMetaDataMap.get(packageName); | |
88 if (metaData == null) throw new NameNotFoundException(packageName); | |
89 | |
90 // Create an application with this metadata (but only if |flags| all
ows). Doing it this | |
91 // way (rather than simply storing the ApplicationInfo in a map) ens
ures that the | |
92 // |flags| is set correctly. | |
93 ApplicationInfo appInfo = new ApplicationInfo(); | |
94 appInfo.packageName = packageName; | |
95 if ((flags & PackageManager.GET_META_DATA) != 0) { | |
96 appInfo.metaData = metaData; | |
97 } | |
98 return appInfo; | |
99 } | |
100 | |
101 @Override | |
102 public Resources getResourcesForApplication(ApplicationInfo app) | |
103 throws NameNotFoundException { | |
104 if (app == null) throw new NullPointerException(); | |
105 | |
106 Resources result = mResourceMap.get(app.packageName); | |
107 if (result == null) throw new NameNotFoundException(app.packageName)
; | |
108 | |
109 return result; | |
110 } | |
111 | |
112 public void setMetaDataAndResourcesForTest( | |
113 String packageName, Bundle metaData, Resources resources) { | |
114 mMetaDataMap.put(packageName, metaData); | |
115 mResourceMap.put(packageName, resources); | |
116 } | |
117 } | |
118 | |
119 /** | |
120 * Fakes the Resources object, allowing lookup of a single String value. | |
121 * | |
122 * Note: The real Resources object defines a mapping to many values. This fa
ke object only | |
123 * allows a single value in the mapping, and it must be a String (which is a
ll that is required | |
124 * for these tests). | |
125 */ | |
126 private static class FakeResources extends Resources { | |
127 private final int mId; | |
128 private final String mValue; | |
129 | |
130 // Do not warn about deprecated call to Resources(); the documentation s
ays code is not | |
131 // supposed to create its own Resources object, but we are using it to f
ake out the | |
132 // Resources, and there is no other way to do that. | |
133 @SuppressWarnings("deprecation") | |
134 public FakeResources(int identifier, String value) { | |
135 super(new AssetManager(), null, null); | |
136 mId = identifier; | |
137 mValue = value; | |
138 } | |
139 | |
140 @Override | |
141 public int getIdentifier(String name, String defType, String defPackage)
{ | |
142 if (name == null) throw new NullPointerException(); | |
143 | |
144 // There is *no guarantee* (in the Digital Asset Links spec) about w
hat the string | |
145 // resource should be called ("asset_statements" is just an example)
. Therefore, | |
146 // getIdentifier cannot be used to get the asset statements string.
Always fail the | |
147 // lookup here, to ensure the implementation isn't relying on any pa
rticular hard-coded | |
148 // string. | |
149 return 0; | |
150 } | |
151 | |
152 @Override | |
153 public String getString(int id) { | |
154 if (id != mId) { | |
155 throw new Resources.NotFoundException("id 0x" + Integer.toHexStr
ing(id)); | |
156 } | |
157 | |
158 return mValue; | |
159 } | |
160 } | |
161 | |
162 private static final class FakeFrameUrlDelegate | |
163 implements InstalledAppProviderImpl.FrameUrlDelegate { | |
164 private URI mFrameUrl; | |
165 | |
166 public FakeFrameUrlDelegate(String frameUrl) { | |
167 setFrameUrl(frameUrl); | |
168 } | |
169 | |
170 public void setFrameUrl(String frameUrl) { | |
171 if (frameUrl == null) { | |
172 mFrameUrl = null; | |
173 return; | |
174 } | |
175 | |
176 try { | |
177 mFrameUrl = new URI(frameUrl); | |
178 } catch (URISyntaxException e) { | |
179 throw new AssertionError(e); | |
180 } | |
181 } | |
182 | |
183 @Override | |
184 public URI getUrl() { | |
185 return mFrameUrl; | |
186 } | |
187 } | |
188 | |
189 /** | |
190 * Creates a metaData bundle with a single resource-id key. | |
191 */ | |
192 private static Bundle createMetaData(String metaDataName, int metaDataResour
ceId) { | |
193 Bundle metaData = new Bundle(); | |
194 metaData.putInt(metaDataName, metaDataResourceId); | |
195 return metaData; | |
196 } | |
197 | |
198 /** | |
199 * Sets a resource with a single key-value pair in an Android package's mani
fest. | |
200 * | |
201 * The value is always a string. | |
202 */ | |
203 private void setStringResource(String packageName, String key, String value)
{ | |
204 int identifier = 0x1234; | |
205 Bundle metaData = createMetaData(key, identifier); | |
206 FakeResources resources = new FakeResources(identifier, value); | |
207 mPackageManager.setMetaDataAndResourcesForTest(packageName, metaData, re
sources); | |
208 } | |
209 | |
210 /** | |
211 * Creates a valid Android asset statement string. | |
212 */ | |
213 private String createAssetStatement(String platform, String relation, String
url) { | |
214 return String.format( | |
215 "{\"relation\": [\"%s\"], \"target\": {\"namespace\": \"%s\", \"
site\": \"%s\"}}", | |
216 relation, platform, url); | |
217 } | |
218 | |
219 /** | |
220 * Sets an asset statement to an Android package's manifest (in the fake pac
kage manager). | |
221 * | |
222 * Only one asset statement can be set for a given package (if this is calle
d twice on the same | |
223 * package, overwrites the previous asset statement). | |
224 * | |
225 * This corresponds to a Statement List in the Digital Asset Links spec v1. | |
226 */ | |
227 private void setAssetStatement( | |
228 String packageName, String platform, String relation, String url) { | |
229 String statements = "[" + createAssetStatement(platform, relation, url)
+ "]"; | |
230 setStringResource(packageName, ASSET_STATEMENTS_KEY, statements); | |
231 } | |
232 | |
233 /** | |
234 * Creates a RelatedApplication to put in the web app manifest. | |
235 */ | |
236 private RelatedApplication createRelatedApplication(String platform, String
id, String url) { | |
237 RelatedApplication application = new RelatedApplication(); | |
238 application.platform = platform; | |
239 application.id = id; | |
240 application.url = url; | |
241 return application; | |
242 } | |
243 | |
244 /** | |
245 * Calls filterInstalledApps with the given inputs, and tests that the expec
ted result is | |
246 * returned. | |
247 */ | |
248 private void verifyInstalledApps(RelatedApplication[] manifestRelatedApps, | |
249 RelatedApplication[] expectedInstalledRelatedApps) { | |
250 mInstalledAppProvider.filterInstalledApps( | |
251 manifestRelatedApps, new InstalledAppProvider.FilterInstalledApp
sResponse() { | |
252 @Override | |
253 public void call(RelatedApplication[] installedRelatedApps)
{ | |
254 Assert.assertEquals( | |
255 expectedInstalledRelatedApps.length, installedRe
latedApps.length); | |
256 | |
257 for (int i = 0; i < installedRelatedApps.length; i++) { | |
258 Assert.assertEquals( | |
259 expectedInstalledRelatedApps[i], installedRe
latedApps[i]); | |
260 } | |
261 } | |
262 }); | |
263 } | |
264 | |
265 @Before | |
266 public void setUp() { | |
267 mPackageManager = new FakePackageManager(); | |
268 RuntimeEnvironment.setRobolectricPackageManager(mPackageManager); | |
269 mFrameUrlDelegate = new FakeFrameUrlDelegate(URL_ON_ORIGIN); | |
270 mInstalledAppProvider = | |
271 new InstalledAppProviderImpl(mFrameUrlDelegate, RuntimeEnvironme
nt.application); | |
272 } | |
273 | |
274 /** | |
275 * Origin of the page using the API is missing certain parts of the URI. | |
276 */ | |
277 @Test | |
278 @Feature({"InstalledApp"}) | |
279 public void testOriginMissingParts() { | |
280 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
281 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
}; | |
282 setAssetStatement(PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URL
S, ORIGIN); | |
283 RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplicati
on[] {}; | |
284 | |
285 mFrameUrlDelegate.setFrameUrl(ORIGIN_MISSING_SCHEME); | |
286 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
287 | |
288 mFrameUrlDelegate.setFrameUrl(ORIGIN_MISSING_HOST); | |
289 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
290 } | |
291 | |
292 /** | |
293 * No related Android apps. | |
294 * | |
295 * An Android app relates to the web app, but not mutual. | |
296 */ | |
297 @Test | |
298 @Feature({"InstalledApp"}) | |
299 public void testNoRelatedApps() { | |
300 // The web manifest has no related apps. | |
301 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {}; | |
302 | |
303 // One Android app is installed named |PACKAGE_NAME_1|. It has a related
web app with origin | |
304 // |ORIGIN|. | |
305 setAssetStatement(PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URL
S, ORIGIN); | |
306 | |
307 RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplicati
on[] {}; | |
308 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
309 } | |
310 | |
311 /** | |
312 * One related Android app with no id (package name). | |
313 * | |
314 * An Android app relates to the web app, but not mutual. | |
315 */ | |
316 @Test | |
317 @Feature({"InstalledApp"}) | |
318 public void testOneRelatedAppNoId() { | |
319 RelatedApplication manifestRelatedApps[] = | |
320 new RelatedApplication[] {createRelatedApplication(PLATFORM_ANDR
OID, null, null)}; | |
321 | |
322 setAssetStatement(PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URL
S, ORIGIN); | |
323 | |
324 RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplicati
on[] {}; | |
325 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
326 } | |
327 | |
328 /** | |
329 * One related app (from a non-Android platform). | |
330 * | |
331 * An Android app with the same id relates to the web app. This should be ig
nored since the | |
332 * manifest doesn't mention the Android app. | |
333 */ | |
334 @Test | |
335 @Feature({"InstalledApp"}) | |
336 public void testOneRelatedNonAndroidApp() { | |
337 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
338 createRelatedApplication(PLATFORM_OTHER, PACKAGE_NAME_1, null)}; | |
339 | |
340 setAssetStatement(PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URL
S, ORIGIN); | |
341 | |
342 RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplicati
on[] {}; | |
343 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
344 } | |
345 | |
346 /** | |
347 * One related Android app; Android app is not installed. | |
348 * | |
349 * Another Android app relates to the web app, but not mutual. | |
350 */ | |
351 @Test | |
352 @Feature({"InstalledApp"}) | |
353 public void testOneRelatedAppNotInstalled() { | |
354 // The web manifest has a related Android app named |PACKAGE_NAME_1|. | |
355 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
356 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
}; | |
357 | |
358 // One Android app is installed named |PACKAGE_NAME_2|. It has a related
web app with origin | |
359 // |ORIGIN|. | |
360 setAssetStatement(PACKAGE_NAME_2, NAMESPACE_WEB, RELATION_HANDLE_ALL_URL
S, ORIGIN); | |
361 | |
362 RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplicati
on[] {}; | |
363 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
364 } | |
365 | |
366 /** | |
367 * Android app manifest has an asset_statements key, but the resource it lin
ks to is missing. | |
368 */ | |
369 @Test | |
370 @Feature({"InstalledApp"}) | |
371 public void testOneRelatedAppBrokenAssetStatementsResource() { | |
372 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
373 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
}; | |
374 | |
375 Bundle metaData = createMetaData(ASSET_STATEMENTS_KEY, 0x1234); | |
376 String statements = | |
377 "[" + createAssetStatement(NAMESPACE_WEB, RELATION_HANDLE_ALL_UR
LS, ORIGIN) + "]"; | |
378 FakeResources resources = new FakeResources(0x4321, statements); | |
379 mPackageManager.setMetaDataAndResourcesForTest(PACKAGE_NAME_1, metaData,
resources); | |
380 RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplicati
on[] {}; | |
381 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
382 } | |
383 | |
384 /** | |
385 * One related Android app; Android app is not mutually related (has no asse
t_statements). | |
386 */ | |
387 @Test | |
388 @Feature({"InstalledApp"}) | |
389 public void testOneRelatedAppNoAssetStatements() { | |
390 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
391 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
}; | |
392 | |
393 setStringResource(PACKAGE_NAME_1, null, null); | |
394 RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplicati
on[] {}; | |
395 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
396 } | |
397 | |
398 /** | |
399 * One related Android app; Android app is related to other origins. | |
400 * | |
401 * Tests three cases: | |
402 * - The Android app is related to a web app with a different scheme. | |
403 * - The Android app is related to a web app with a different host. | |
404 * - The Android app is related to a web app with a different port. | |
405 */ | |
406 @Test | |
407 @Feature({"InstalledApp"}) | |
408 public void testOneRelatedAppRelatedToDifferentOrigins() { | |
409 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
410 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
}; | |
411 | |
412 setAssetStatement( | |
413 PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN_
DIFFERENT_SCHEME); | |
414 RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplicati
on[] {}; | |
415 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
416 | |
417 setAssetStatement( | |
418 PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN_
DIFFERENT_HOST); | |
419 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
420 | |
421 setAssetStatement( | |
422 PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN_
DIFFERENT_PORT); | |
423 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
424 } | |
425 | |
426 /** | |
427 * One related Android app; Android app is installed and mutually related. | |
428 */ | |
429 @Test | |
430 @Feature({"InstalledApp"}) | |
431 public void testOneInstalledRelatedApp() { | |
432 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
433 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
}; | |
434 | |
435 setAssetStatement(PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URL
S, ORIGIN); | |
436 | |
437 RelatedApplication[] expectedInstalledRelatedApps = manifestRelatedApps; | |
438 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
439 } | |
440 | |
441 /** | |
442 * Change the frame URL and ensure the app relates to the new URL, not the o
ld one. | |
443 * | |
444 * This simulates navigating the frame while keeping the same Mojo service o
pen. | |
445 */ | |
446 @Test | |
447 @Feature({"InstalledApp"}) | |
448 public void testDynamicallyChangingUrl() { | |
449 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
450 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
}; | |
451 | |
452 setAssetStatement( | |
453 PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN_
DIFFERENT_SCHEME); | |
454 | |
455 // Should be empty, since Android app does not relate to this frame's or
igin. | |
456 RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplicati
on[] {}; | |
457 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
458 | |
459 // Simulate a navigation to a different origin. | |
460 mFrameUrlDelegate.setFrameUrl(ORIGIN_DIFFERENT_SCHEME); | |
461 | |
462 // Now the result should include the Android app that relates to the new
origin. | |
463 expectedInstalledRelatedApps = manifestRelatedApps; | |
464 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
465 | |
466 // Simulate the native RenderFrameHost disappearing. | |
467 mFrameUrlDelegate.setFrameUrl(null); | |
468 | |
469 expectedInstalledRelatedApps = new RelatedApplication[] {}; | |
470 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
471 } | |
472 | |
473 /** | |
474 * One related Android app (installed and mutually related), with a non-null
URL field. | |
475 */ | |
476 @Test | |
477 @Feature({"InstalledApp"}) | |
478 public void testInstalledRelatedAppWithUrl() { | |
479 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
480 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, URL_U
NRELATED)}; | |
481 | |
482 setAssetStatement(PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URL
S, ORIGIN); | |
483 | |
484 RelatedApplication[] expectedInstalledRelatedApps = manifestRelatedApps; | |
485 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
486 } | |
487 | |
488 /** | |
489 * One related Android app; Android app is related to multiple origins. | |
490 */ | |
491 @Test | |
492 @Feature({"InstalledApp"}) | |
493 public void testMultipleAssetStatements() { | |
494 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
495 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
}; | |
496 | |
497 // Create an asset_statements field with multiple statements. The second
one matches the web | |
498 // app. | |
499 String statements = "[" | |
500 + createAssetStatement( | |
501 NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN_DIFFER
ENT_HOST) | |
502 + ", " + createAssetStatement(NAMESPACE_WEB, RELATION_HANDLE_ALL
_URLS, ORIGIN) | |
503 + "]"; | |
504 setStringResource(PACKAGE_NAME_1, ASSET_STATEMENTS_KEY, statements); | |
505 | |
506 RelatedApplication[] expectedInstalledRelatedApps = manifestRelatedApps; | |
507 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
508 } | |
509 | |
510 /** | |
511 * A JSON syntax error in the Android app's asset statement. | |
512 */ | |
513 @Test | |
514 @Feature({"InstalledApp"}) | |
515 public void testAssetStatementSyntaxError() { | |
516 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
517 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
}; | |
518 | |
519 String statements = "[{\"target\" {}}]"; | |
520 setStringResource(PACKAGE_NAME_1, ASSET_STATEMENTS_KEY, statements); | |
521 | |
522 RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplicati
on[] {}; | |
523 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
524 } | |
525 | |
526 /** | |
527 * The Android app's asset statement is not an array. | |
528 */ | |
529 @Test | |
530 @Feature({"InstalledApp"}) | |
531 public void testAssetStatementNotArray() { | |
532 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
533 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
}; | |
534 | |
535 String statement = createAssetStatement(NAMESPACE_WEB, RELATION_HANDLE_A
LL_URLS, ORIGIN); | |
536 setStringResource(PACKAGE_NAME_1, ASSET_STATEMENTS_KEY, statement); | |
537 | |
538 RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplicati
on[] {}; | |
539 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
540 } | |
541 | |
542 /** | |
543 * The Android app's asset statement array contains non-objects. | |
544 */ | |
545 @Test | |
546 @Feature({"InstalledApp"}) | |
547 public void testAssetStatementArrayNoObjects() { | |
548 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
549 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
}; | |
550 | |
551 String statements = "[" | |
552 + createAssetStatement(NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS,
ORIGIN) + ", 4]"; | |
553 setStringResource(PACKAGE_NAME_1, ASSET_STATEMENTS_KEY, statements); | |
554 | |
555 // Expect it to ignore the integer and successfully parse the valid obje
ct. | |
556 RelatedApplication[] expectedInstalledRelatedApps = manifestRelatedApps; | |
557 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
558 } | |
559 | |
560 /** | |
561 * Android app has no "relation" in the asset statement. | |
562 * | |
563 * Currently, the relation string (in the Android package's asset statement)
is ignored, so the | |
564 * app is still returned as "installed". | |
565 */ | |
566 @Test | |
567 @Feature({"InstalledApp"}) | |
568 public void testAssetStatementNoRelation() { | |
569 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
570 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
}; | |
571 | |
572 String statements = String.format( | |
573 "[{\"target\": {\"namespace\": \"%s\", \"site\": \"%s\"}}]", NAM
ESPACE_WEB, ORIGIN); | |
574 setStringResource(PACKAGE_NAME_1, ASSET_STATEMENTS_KEY, statements); | |
575 | |
576 // TODO(mgiuca): [Spec issue] Should we require a specific relation stri
ng, rather than any | |
577 // or no relation? | |
578 RelatedApplication[] expectedInstalledRelatedApps = manifestRelatedApps; | |
579 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
580 } | |
581 | |
582 /** | |
583 * Android app is related with a non-standard relation. | |
584 * | |
585 * Currently, the relation string (in the Android package's asset statement)
is ignored, so any | |
586 * will do. Is this desirable, or do we want to require a specific relation
string? | |
587 */ | |
588 @Test | |
589 @Feature({"InstalledApp"}) | |
590 public void testAssetStatementNonStandardRelation() { | |
591 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
592 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
}; | |
593 | |
594 setAssetStatement(PACKAGE_NAME_1, NAMESPACE_WEB, "nonstandard/relation",
ORIGIN); | |
595 | |
596 // TODO(mgiuca): [Spec issue] Should we require a specific relation stri
ng, rather than any | |
597 // or no relation? | |
598 RelatedApplication[] expectedInstalledRelatedApps = manifestRelatedApps; | |
599 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
600 } | |
601 | |
602 /** | |
603 * Android app has no "target" in the asset statement. | |
604 */ | |
605 @Test | |
606 @Feature({"InstalledApp"}) | |
607 public void testAssetStatementNoTarget() { | |
608 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
609 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
}; | |
610 | |
611 String statements = String.format("[{\"relation\": [\"%s\"]}]", RELATION
_HANDLE_ALL_URLS); | |
612 setStringResource(PACKAGE_NAME_1, ASSET_STATEMENTS_KEY, statements); | |
613 | |
614 RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplicati
on[] {}; | |
615 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
616 } | |
617 | |
618 /** | |
619 * Android app has no "namespace" in the asset statement. | |
620 */ | |
621 @Test | |
622 @Feature({"InstalledApp"}) | |
623 public void testAssetStatementNoNamespace() { | |
624 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
625 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
}; | |
626 | |
627 String statements = | |
628 String.format("[{\"relation\": [\"%s\"], \"target\": {\"site\":
\"%s\"}}]", | |
629 RELATION_HANDLE_ALL_URLS, ORIGIN); | |
630 setStringResource(PACKAGE_NAME_1, ASSET_STATEMENTS_KEY, statements); | |
631 | |
632 RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplicati
on[] {}; | |
633 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
634 } | |
635 | |
636 /** | |
637 * Android app is related, but not to the web namespace. | |
638 */ | |
639 @Test | |
640 @Feature({"InstalledApp"}) | |
641 public void testNonWebAssetStatement() { | |
642 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
643 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
}; | |
644 | |
645 setAssetStatement(PACKAGE_NAME_1, "play", RELATION_HANDLE_ALL_URLS, ORIG
IN); | |
646 | |
647 RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplicati
on[] {}; | |
648 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
649 } | |
650 | |
651 /** | |
652 * Android app has no "site" in the asset statement. | |
653 */ | |
654 @Test | |
655 @Feature({"InstalledApp"}) | |
656 public void testAssetStatementNoSite() { | |
657 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
658 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
}; | |
659 | |
660 String statements = | |
661 String.format("[{\"relation\": [\"%s\"], \"target\": {\"namespac
e\": \"%s\"}}]", | |
662 RELATION_HANDLE_ALL_URLS, NAMESPACE_WEB); | |
663 setStringResource(PACKAGE_NAME_1, ASSET_STATEMENTS_KEY, statements); | |
664 | |
665 RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplicati
on[] {}; | |
666 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
667 } | |
668 | |
669 /** | |
670 * Android app has a syntax error in the "site" field of the asset statement
. | |
671 */ | |
672 @Test | |
673 @Feature({"InstalledApp"}) | |
674 public void testAssetStatementSiteSyntaxError() { | |
675 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
676 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
}; | |
677 | |
678 setAssetStatement( | |
679 PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN_
SYNTAX_ERROR); | |
680 | |
681 RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplicati
on[] {}; | |
682 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
683 } | |
684 | |
685 /** | |
686 * Android app has a "site" field missing certain parts of the URI (scheme,
host, port). | |
687 */ | |
688 @Test | |
689 @Feature({"InstalledApp"}) | |
690 public void testAssetStatementSiteMissingParts() { | |
691 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
692 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
}; | |
693 | |
694 setAssetStatement( | |
695 PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN_
MISSING_SCHEME); | |
696 RelatedApplication[] expectedInstalledRelatedApps = new RelatedApplicati
on[] {}; | |
697 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
698 | |
699 setAssetStatement( | |
700 PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN_
MISSING_HOST); | |
701 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
702 | |
703 setAssetStatement( | |
704 PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URLS, ORIGIN_
MISSING_PORT); | |
705 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
706 } | |
707 | |
708 /** | |
709 * One related Android app; Android app is related with a path part in the "
site" field. | |
710 * | |
711 * The path part shouldn't really be there (according to the Digital Asset L
inks spec), but if | |
712 * it is, we are lenient and just ignore it (matching only the origin). | |
713 */ | |
714 @Test | |
715 @Feature({"InstalledApp"}) | |
716 public void testAssetStatementSiteHasPath() { | |
717 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
718 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
}; | |
719 | |
720 String site = ORIGIN + "/path"; | |
721 setAssetStatement(PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URL
S, site); | |
722 | |
723 RelatedApplication[] expectedInstalledRelatedApps = manifestRelatedApps; | |
724 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
725 } | |
726 | |
727 /** | |
728 * One related Android app; Android app is installed and mutually related. | |
729 * | |
730 * Another Android app relates to the web app, but not mutual. | |
731 */ | |
732 @Test | |
733 @Feature({"InstalledApp"}) | |
734 public void testExtraInstalledApp() { | |
735 RelatedApplication manifestRelatedApps[] = new RelatedApplication[] { | |
736 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
}; | |
737 | |
738 setAssetStatement(PACKAGE_NAME_1, NAMESPACE_WEB, RELATION_HANDLE_ALL_URL
S, ORIGIN); | |
739 setAssetStatement(PACKAGE_NAME_2, NAMESPACE_WEB, RELATION_HANDLE_ALL_URL
S, ORIGIN); | |
740 | |
741 RelatedApplication[] expectedInstalledRelatedApps = manifestRelatedApps; | |
742 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
743 } | |
744 | |
745 /** | |
746 * Two related Android apps; Android apps both installed and mutually relate
d. | |
747 * | |
748 * Web app also related to an app with the same name on another platform, an
d another Android | |
749 * app which is not installed. | |
750 */ | |
751 @Test | |
752 @Feature({"InstalledApp"}) | |
753 public void testMultipleInstalledRelatedApps() { | |
754 RelatedApplication[] manifestRelatedApps = new RelatedApplication[] { | |
755 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_1, null)
, | |
756 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_2, null)
, | |
757 createRelatedApplication(PLATFORM_OTHER, PACKAGE_NAME_2, null), | |
758 createRelatedApplication(PLATFORM_ANDROID, PACKAGE_NAME_3, null)
}; | |
759 | |
760 setAssetStatement(PACKAGE_NAME_2, NAMESPACE_WEB, RELATION_HANDLE_ALL_URL
S, ORIGIN); | |
761 setAssetStatement(PACKAGE_NAME_3, NAMESPACE_WEB, RELATION_HANDLE_ALL_URL
S, ORIGIN); | |
762 | |
763 RelatedApplication[] expectedInstalledRelatedApps = | |
764 new RelatedApplication[] {manifestRelatedApps[1], manifestRelate
dApps[3]}; | |
765 verifyInstalledApps(manifestRelatedApps, expectedInstalledRelatedApps); | |
766 } | |
767 } | |
OLD | NEW |