blob: b7370331ad0eff847851ef77f7f59fee4a711d14 [file] [log] [blame]
Gustav Sennton53b78242016-04-07 15:56:10 +01001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.webkit;
18
19import android.content.Context;
20import android.content.pm.ApplicationInfo;
21import android.content.pm.PackageInfo;
22import android.content.pm.Signature;
23import android.os.Bundle;
24import android.util.Base64;
25import android.test.AndroidTestCase;
26
27import android.webkit.WebViewFactory;
28import android.webkit.WebViewProviderInfo;
29import android.webkit.WebViewProviderResponse;
30
31import java.util.concurrent.CountDownLatch;
32
33import org.hamcrest.Description;
34
35import org.mockito.Mockito;
36import org.mockito.Matchers;
37import org.mockito.ArgumentMatcher;
38
39
40/**
41 * Tests for WebViewUpdateService
42 */
43public class WebViewUpdateServiceTest extends AndroidTestCase {
44 private final static String TAG = WebViewUpdateServiceTest.class.getSimpleName();
45
46 private WebViewUpdateServiceImpl mWebViewUpdateServiceImpl;
47 private TestSystemImpl mTestSystemImpl;
48
49 private static final String WEBVIEW_LIBRARY_FLAG = "com.android.webview.WebViewLibrary";
50
51 @Override
52 protected void setUp() throws Exception {
53 super.setUp();
54 }
55
56 /**
57 * Creates a new instance.
58 */
59 public WebViewUpdateServiceTest() {
60 }
61
62 private void setupWithPackages(WebViewProviderInfo[] packages) {
63 setupWithPackages(packages, true);
64 }
65
66 private void setupWithPackages(WebViewProviderInfo[] packages,
67 boolean fallbackLogicEnabled) {
68 setupWithPackages(packages, fallbackLogicEnabled, 1);
69 }
70
71 private void setupWithPackages(WebViewProviderInfo[] packages,
72 boolean fallbackLogicEnabled, int numRelros) {
73 setupWithPackages(packages, fallbackLogicEnabled, numRelros,
74 true /* isDebuggable == true -> don't check package signatures */);
75 }
76
77 private void setupWithPackages(WebViewProviderInfo[] packages,
78 boolean fallbackLogicEnabled, int numRelros, boolean isDebuggable) {
79 TestSystemImpl testing = new TestSystemImpl(packages, fallbackLogicEnabled, numRelros,
80 isDebuggable);
81 mTestSystemImpl = Mockito.spy(testing);
82 mWebViewUpdateServiceImpl =
83 new WebViewUpdateServiceImpl(null /*Context*/, mTestSystemImpl);
84 }
85
86 private void setEnabledAndValidPackageInfos(WebViewProviderInfo[] providers) {
87 for(WebViewProviderInfo wpi : providers) {
88 mTestSystemImpl.setPackageInfo(createPackageInfo(wpi.packageName, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +010089 true /* valid */, true /* installed */));
Gustav Sennton53b78242016-04-07 15:56:10 +010090 }
91 }
92
Gustav Senntona9159042016-04-11 16:32:52 +010093 private void checkCertainPackageUsedAfterWebViewBootPreparation(String expectedProviderName,
Gustav Sennton53b78242016-04-07 15:56:10 +010094 WebViewProviderInfo[] webviewPackages) {
Gustav Senntona9159042016-04-11 16:32:52 +010095 checkCertainPackageUsedAfterWebViewBootPreparation(
96 expectedProviderName, webviewPackages, 1);
Gustav Sennton53b78242016-04-07 15:56:10 +010097 }
98
Gustav Senntona9159042016-04-11 16:32:52 +010099 private void checkCertainPackageUsedAfterWebViewBootPreparation(String expectedProviderName,
Gustav Sennton53b78242016-04-07 15:56:10 +0100100 WebViewProviderInfo[] webviewPackages, int numRelros) {
101 setupWithPackages(webviewPackages, true, numRelros);
102 // Add (enabled and valid) package infos for each provider
103 setEnabledAndValidPackageInfos(webviewPackages);
104
105 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
106
107 Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
108 Mockito.argThat(new IsPackageInfoWithName(expectedProviderName)));
109
110 for (int n = 0; n < numRelros; n++) {
111 mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
112 }
113
114 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
115 assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status);
116 assertEquals(expectedProviderName, response.packageInfo.packageName);
117 }
118
119 // For matching the package name of a PackageInfo
120 private class IsPackageInfoWithName extends ArgumentMatcher<PackageInfo> {
121 private final String mPackageName;
122
123 IsPackageInfoWithName(String name) {
124 mPackageName = name;
125 }
126
127 @Override
128 public boolean matches(Object p) {
129 return ((PackageInfo) p).packageName.equals(mPackageName);
130 }
131
132 // Provide a more useful description in case of mismatch
133 @Override
134 public void describeTo (Description description) {
135 description.appendText(String.format("PackageInfo with name '%s'", mPackageName));
136 }
137 }
138
139 private static PackageInfo createPackageInfo(
Gustav Sennton0df2c552016-06-14 15:32:19 +0100140 String packageName, boolean enabled, boolean valid, boolean installed) {
Gustav Sennton53b78242016-04-07 15:56:10 +0100141 PackageInfo p = new PackageInfo();
142 p.packageName = packageName;
143 p.applicationInfo = new ApplicationInfo();
144 p.applicationInfo.enabled = enabled;
145 p.applicationInfo.metaData = new Bundle();
Gustav Sennton0df2c552016-06-14 15:32:19 +0100146 if (installed) {
147 p.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED;
148 } else {
149 p.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED;
150 }
Gustav Sennton53b78242016-04-07 15:56:10 +0100151 if (valid) {
152 // no flag means invalid
153 p.applicationInfo.metaData.putString(WEBVIEW_LIBRARY_FLAG, "blah");
154 }
155 return p;
156 }
157
Gustav Sennton0df2c552016-06-14 15:32:19 +0100158 private static PackageInfo createPackageInfo(String packageName, boolean enabled, boolean valid,
159 boolean installed, Signature[] signatures, long updateTime) {
160 PackageInfo p = createPackageInfo(packageName, enabled, valid, installed);
Gustav Sennton53b78242016-04-07 15:56:10 +0100161 p.signatures = signatures;
Gustav Sennton0df2c552016-06-14 15:32:19 +0100162 p.lastUpdateTime = updateTime;
163 return p;
164 }
165
166 private static PackageInfo createPackageInfo(String packageName, boolean enabled, boolean valid,
167 boolean installed, Signature[] signatures, long updateTime, boolean hidden) {
168 PackageInfo p =
169 createPackageInfo(packageName, enabled, valid, installed, signatures, updateTime);
170 if (hidden) {
171 p.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
172 } else {
173 p.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
174 }
Gustav Sennton53b78242016-04-07 15:56:10 +0100175 return p;
176 }
177
Gustav Senntona9159042016-04-11 16:32:52 +0100178 private void checkPreparationPhasesForPackage(String expectedPackage, int numPreparation) {
179 // Verify that onWebViewProviderChanged was called for the numPreparation'th time for the
180 // expected package
181 Mockito.verify(mTestSystemImpl, Mockito.times(numPreparation)).onWebViewProviderChanged(
182 Mockito.argThat(new IsPackageInfoWithName(expectedPackage)));
183
184 mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
185
186 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
187 assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status);
188 assertEquals(expectedPackage, response.packageInfo.packageName);
189 }
190
Gustav Sennton53b78242016-04-07 15:56:10 +0100191
192 // ****************
193 // Tests
194 // ****************
195
196
197 public void testWithSinglePackage() {
198 String testPackageName = "test.package.name";
Gustav Senntona9159042016-04-11 16:32:52 +0100199 checkCertainPackageUsedAfterWebViewBootPreparation(testPackageName,
Gustav Sennton53b78242016-04-07 15:56:10 +0100200 new WebViewProviderInfo[] {
201 new WebViewProviderInfo(testPackageName, "",
202 true /*default available*/, false /* fallback */, null)});
203 }
204
205 public void testDefaultPackageUsedOverNonDefault() {
206 String defaultPackage = "defaultPackage";
207 String nonDefaultPackage = "nonDefaultPackage";
208 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
209 new WebViewProviderInfo(nonDefaultPackage, "", false, false, null),
210 new WebViewProviderInfo(defaultPackage, "", true, false, null)};
Gustav Senntona9159042016-04-11 16:32:52 +0100211 checkCertainPackageUsedAfterWebViewBootPreparation(defaultPackage, packages);
Gustav Sennton53b78242016-04-07 15:56:10 +0100212 }
213
214 public void testSeveralRelros() {
215 String singlePackage = "singlePackage";
Gustav Senntona9159042016-04-11 16:32:52 +0100216 checkCertainPackageUsedAfterWebViewBootPreparation(
Gustav Sennton53b78242016-04-07 15:56:10 +0100217 singlePackage,
218 new WebViewProviderInfo[] {
219 new WebViewProviderInfo(singlePackage, "", true /*def av*/, false, null)},
220 2);
221 }
222
223 // Ensure that package with valid signatures is chosen rather than package with invalid
224 // signatures.
225 public void testWithSignatures() {
226 String validPackage = "valid package";
227 String invalidPackage = "invalid package";
228
229 Signature validSignature = new Signature("11");
230 Signature invalidExpectedSignature = new Signature("22");
231 Signature invalidPackageSignature = new Signature("33");
232
233 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
234 new WebViewProviderInfo(invalidPackage, "", true, false, new String[]{
235 Base64.encodeToString(
236 invalidExpectedSignature.toByteArray(), Base64.DEFAULT)}),
237 new WebViewProviderInfo(validPackage, "", true, false, new String[]{
238 Base64.encodeToString(
239 validSignature.toByteArray(), Base64.DEFAULT)})
240 };
241 setupWithPackages(packages, true /* fallback logic enabled */, 1 /* numRelros */,
242 false /* isDebuggable */);
243 mTestSystemImpl.setPackageInfo(createPackageInfo(invalidPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100244 true /* valid */, true /* installed */, new Signature[]{invalidPackageSignature}
245 , 0 /* updateTime */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100246 mTestSystemImpl.setPackageInfo(createPackageInfo(validPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100247 true /* valid */, true /* installed */, new Signature[]{validSignature}
248 , 0 /* updateTime */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100249
250 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
251
Gustav Sennton53b78242016-04-07 15:56:10 +0100252
Gustav Senntona9159042016-04-11 16:32:52 +0100253 checkPreparationPhasesForPackage(validPackage, 1 /* first preparation for this package */);
Gustav Sennton53b78242016-04-07 15:56:10 +0100254
255 WebViewProviderInfo[] validPackages = mWebViewUpdateServiceImpl.getValidWebViewPackages();
256 assertEquals(1, validPackages.length);
257 assertEquals(validPackage, validPackages[0].packageName);
258 }
259
260 public void testFailWaitingForRelro() {
261 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
262 new WebViewProviderInfo("packagename", "", true, true, null)};
263 setupWithPackages(packages);
264 setEnabledAndValidPackageInfos(packages);
265
266 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
267
268 Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
269 Mockito.argThat(new IsPackageInfoWithName(packages[0].packageName)));
270
271 // Never call notifyRelroCreation()
272
273 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
274 assertEquals(WebViewFactory.LIBLOAD_FAILED_WAITING_FOR_RELRO, response.status);
275 }
276
277 public void testFailListingEmptyWebviewPackages() {
278 WebViewProviderInfo[] packages = new WebViewProviderInfo[0];
279 setupWithPackages(packages);
280 setEnabledAndValidPackageInfos(packages);
281
282 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
283
284 Mockito.verify(mTestSystemImpl, Mockito.never()).onWebViewProviderChanged(
285 Matchers.anyObject());
286
287 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
288 assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status);
289 }
290
291 public void testFailListingInvalidWebviewPackage() {
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100292 WebViewProviderInfo wpi = new WebViewProviderInfo("package", "", true, true, null);
Gustav Sennton53b78242016-04-07 15:56:10 +0100293 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {wpi};
294 setupWithPackages(packages);
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100295 mTestSystemImpl.setPackageInfo(
Gustav Sennton0df2c552016-06-14 15:32:19 +0100296 createPackageInfo(wpi.packageName, true /* enabled */, false /* valid */,
297 true /* installed */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100298
299 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100300
301 Mockito.verify(mTestSystemImpl, Mockito.never()).onWebViewProviderChanged(
302 Matchers.anyObject());
303
Gustav Sennton53b78242016-04-07 15:56:10 +0100304 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
305 assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status);
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100306
307 // Verify that we can recover from failing to list webview packages.
308 mTestSystemImpl.setPackageInfo(
Gustav Sennton0df2c552016-06-14 15:32:19 +0100309 createPackageInfo(wpi.packageName, true /* enabled */, true /* valid */,
310 true /* installed */));
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100311 mWebViewUpdateServiceImpl.packageStateChanged(wpi.packageName,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100312 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0);
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100313
314 checkPreparationPhasesForPackage(wpi.packageName, 1);
Gustav Sennton53b78242016-04-07 15:56:10 +0100315 }
316
317 // Test that switching provider using changeProviderAndSetting works.
318 public void testSwitchingProvider() {
319 String firstPackage = "first";
320 String secondPackage = "second";
321 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
322 new WebViewProviderInfo(firstPackage, "", true, false, null),
323 new WebViewProviderInfo(secondPackage, "", true, false, null)};
324 checkSwitchingProvider(packages, firstPackage, secondPackage);
325 }
326
327 public void testSwitchingProviderToNonDefault() {
328 String defaultPackage = "defaultPackage";
329 String nonDefaultPackage = "nonDefaultPackage";
330 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
331 new WebViewProviderInfo(defaultPackage, "", true, false, null),
332 new WebViewProviderInfo(nonDefaultPackage, "", false, false, null)};
333 checkSwitchingProvider(packages, defaultPackage, nonDefaultPackage);
334 }
335
336 private void checkSwitchingProvider(WebViewProviderInfo[] packages, String initialPackage,
337 String finalPackage) {
Gustav Senntona9159042016-04-11 16:32:52 +0100338 checkCertainPackageUsedAfterWebViewBootPreparation(initialPackage, packages);
Gustav Sennton53b78242016-04-07 15:56:10 +0100339
340 mWebViewUpdateServiceImpl.changeProviderAndSetting(finalPackage);
Gustav Senntona9159042016-04-11 16:32:52 +0100341 checkPreparationPhasesForPackage(finalPackage, 1 /* first preparation for this package */);
Gustav Sennton53b78242016-04-07 15:56:10 +0100342
343 Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(initialPackage));
344 }
345
346 // Change provider during relro creation by using changeProviderAndSetting
347 public void testSwitchingProviderDuringRelroCreation() {
348 checkChangingProviderDuringRelroCreation(true);
349 }
350
351 // Change provider during relro creation by enabling a provider
352 public void testChangingProviderThroughEnablingDuringRelroCreation() {
353 checkChangingProviderDuringRelroCreation(false);
354 }
355
356 private void checkChangingProviderDuringRelroCreation(boolean settingsChange) {
357 String firstPackage = "first";
358 String secondPackage = "second";
359 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
360 new WebViewProviderInfo(firstPackage, "", true, false, null),
361 new WebViewProviderInfo(secondPackage, "", true, false, null)};
362 setupWithPackages(packages);
363 if (settingsChange) {
364 // Have all packages be enabled, so that we can change provider however we want to
365 setEnabledAndValidPackageInfos(packages);
366 } else {
367 // Have all packages be disabled so that we can change one to enabled later
368 for(WebViewProviderInfo wpi : packages) {
369 mTestSystemImpl.setPackageInfo(createPackageInfo(wpi.packageName,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100370 false /* enabled */, true /* valid */, true /* installed */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100371 }
372 }
373
374 CountDownLatch countdown = new CountDownLatch(1);
375
376 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
377
378 Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
379 Mockito.argThat(new IsPackageInfoWithName(firstPackage)));
380
381 assertEquals(firstPackage, mWebViewUpdateServiceImpl.getCurrentWebViewPackageName());
382
383 new Thread(new Runnable() {
384 @Override
385 public void run() {
386 WebViewProviderResponse threadResponse =
387 mWebViewUpdateServiceImpl.waitForAndGetProvider();
388 assertEquals(WebViewFactory.LIBLOAD_SUCCESS, threadResponse.status);
389 assertEquals(secondPackage, threadResponse.packageInfo.packageName);
390 // Verify that we killed the first package
391 Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(firstPackage));
392 countdown.countDown();
393 }
394 }).start();
395 try {
Gustav Sennton0df2c552016-06-14 15:32:19 +0100396 Thread.sleep(500); // Let the new thread run / be blocked
Gustav Sennton53b78242016-04-07 15:56:10 +0100397 } catch (InterruptedException e) {
398 }
399
400 if (settingsChange) {
401 mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage);
402 } else {
403 // Switch provider by enabling the second one
404 mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100405 true /* valid */, true /* installed */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100406 mWebViewUpdateServiceImpl.packageStateChanged(
Gustav Sennton0df2c552016-06-14 15:32:19 +0100407 secondPackage, WebViewUpdateService.PACKAGE_CHANGED, 0);
Gustav Sennton53b78242016-04-07 15:56:10 +0100408 }
409 mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
410 // first package done, should start on second
411
412 Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
413 Mockito.argThat(new IsPackageInfoWithName(secondPackage)));
414
415 mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
416 // second package done, the other thread should now be unblocked
417 try {
418 countdown.await();
419 } catch (InterruptedException e) {
420 }
421 }
422
423 public void testRunFallbackLogicIfEnabled() {
424 checkFallbackLogicBeingRun(true);
425 }
426
427 public void testDontRunFallbackLogicIfDisabled() {
428 checkFallbackLogicBeingRun(false);
429 }
430
431 private void checkFallbackLogicBeingRun(boolean fallbackLogicEnabled) {
432 String primaryPackage = "primary";
433 String fallbackPackage = "fallback";
434 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
435 new WebViewProviderInfo(
436 primaryPackage, "", true /* default available */, false /* fallback */, null),
437 new WebViewProviderInfo(
438 fallbackPackage, "", true /* default available */, true /* fallback */, null)};
439 setupWithPackages(packages, fallbackLogicEnabled);
440 setEnabledAndValidPackageInfos(packages);
441
442 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
443 // Verify that we disable the fallback package if fallback logic enabled, and don't disable
444 // the fallback package if that logic is disabled
445 if (fallbackLogicEnabled) {
446 Mockito.verify(mTestSystemImpl).uninstallAndDisablePackageForAllUsers(
447 Matchers.anyObject(), Mockito.eq(fallbackPackage));
448 } else {
449 Mockito.verify(mTestSystemImpl, Mockito.never()).uninstallAndDisablePackageForAllUsers(
450 Matchers.anyObject(), Matchers.anyObject());
451 }
452 Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
453 Mockito.argThat(new IsPackageInfoWithName(primaryPackage)));
454
455 // Enable fallback package
456 mTestSystemImpl.setPackageInfo(createPackageInfo(fallbackPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100457 true /* valid */, true /* installed */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100458 mWebViewUpdateServiceImpl.packageStateChanged(
Gustav Sennton0df2c552016-06-14 15:32:19 +0100459 fallbackPackage, WebViewUpdateService.PACKAGE_CHANGED, 0);
Gustav Sennton53b78242016-04-07 15:56:10 +0100460
461 if (fallbackLogicEnabled) {
462 // Check that we have now disabled the fallback package twice
463 Mockito.verify(mTestSystemImpl, Mockito.times(2)).uninstallAndDisablePackageForAllUsers(
464 Matchers.anyObject(), Mockito.eq(fallbackPackage));
465 } else {
466 // Check that we still haven't disabled any package
467 Mockito.verify(mTestSystemImpl, Mockito.never()).uninstallAndDisablePackageForAllUsers(
468 Matchers.anyObject(), Matchers.anyObject());
469 }
470 }
471
472 /**
473 * Scenario for installing primary package when fallback enabled.
474 * 1. Start with only fallback installed
475 * 2. Install non-fallback
476 * 3. Fallback should be disabled
477 */
478 public void testInstallingNonFallbackPackage() {
479 String primaryPackage = "primary";
480 String fallbackPackage = "fallback";
481 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
482 new WebViewProviderInfo(
483 primaryPackage, "", true /* default available */, false /* fallback */, null),
484 new WebViewProviderInfo(
485 fallbackPackage, "", true /* default available */, true /* fallback */, null)};
486 setupWithPackages(packages, true /* isFallbackLogicEnabled */);
487 mTestSystemImpl.setPackageInfo(
Gustav Sennton0df2c552016-06-14 15:32:19 +0100488 createPackageInfo(fallbackPackage, true /* enabled */ , true /* valid */,
489 true /* installed */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100490
491 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
492 Mockito.verify(mTestSystemImpl, Mockito.never()).uninstallAndDisablePackageForAllUsers(
493 Matchers.anyObject(), Matchers.anyObject());
Gustav Sennton53b78242016-04-07 15:56:10 +0100494
Gustav Senntona9159042016-04-11 16:32:52 +0100495 checkPreparationPhasesForPackage(fallbackPackage,
496 1 /* first preparation for this package*/);
Gustav Sennton53b78242016-04-07 15:56:10 +0100497
498 // Install primary package
499 mTestSystemImpl.setPackageInfo(
Gustav Sennton0df2c552016-06-14 15:32:19 +0100500 createPackageInfo(primaryPackage, true /* enabled */ , true /* valid */,
501 true /* installed */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100502 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100503 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0);
Gustav Sennton53b78242016-04-07 15:56:10 +0100504
Gustav Senntona9159042016-04-11 16:32:52 +0100505 // Verify fallback disabled, primary package used as provider, and fallback package killed
Gustav Sennton53b78242016-04-07 15:56:10 +0100506 Mockito.verify(mTestSystemImpl).uninstallAndDisablePackageForAllUsers(
507 Matchers.anyObject(), Mockito.eq(fallbackPackage));
Gustav Senntona9159042016-04-11 16:32:52 +0100508 checkPreparationPhasesForPackage(primaryPackage, 1 /* first preparation for this package*/);
Gustav Sennton53b78242016-04-07 15:56:10 +0100509 Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(fallbackPackage));
510 }
511
512 public void testFallbackChangesEnabledState() {
513 String primaryPackage = "primary";
514 String fallbackPackage = "fallback";
515 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
516 new WebViewProviderInfo(
517 primaryPackage, "", true /* default available */, false /* fallback */, null),
518 new WebViewProviderInfo(
519 fallbackPackage, "", true /* default available */, true /* fallback */, null)};
520 setupWithPackages(packages, true /* fallbackLogicEnabled */);
521 setEnabledAndValidPackageInfos(packages);
522
523 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
524
525 // Verify fallback disabled at boot when primary package enabled
526 Mockito.verify(mTestSystemImpl).enablePackageForUser(
527 Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */,
528 Matchers.anyInt());
529
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100530 checkPreparationPhasesForPackage(primaryPackage, 1);
531
532 // Disable primary package and ensure fallback becomes enabled and used
Gustav Sennton53b78242016-04-07 15:56:10 +0100533 mTestSystemImpl.setPackageInfo(
Gustav Sennton0df2c552016-06-14 15:32:19 +0100534 createPackageInfo(primaryPackage, false /* enabled */, true /* valid */,
535 true /* installed */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100536 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100537 WebViewUpdateService.PACKAGE_CHANGED, 0);
Gustav Sennton53b78242016-04-07 15:56:10 +0100538
Gustav Sennton53b78242016-04-07 15:56:10 +0100539 Mockito.verify(mTestSystemImpl).enablePackageForUser(
540 Mockito.eq(fallbackPackage), Mockito.eq(true) /* enable */,
541 Matchers.anyInt());
542
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100543 checkPreparationPhasesForPackage(fallbackPackage, 1);
544
545
546 // Again enable primary package and verify primary is used and fallback becomes disabled
Gustav Sennton53b78242016-04-07 15:56:10 +0100547 mTestSystemImpl.setPackageInfo(
Gustav Sennton0df2c552016-06-14 15:32:19 +0100548 createPackageInfo(primaryPackage, true /* enabled */, true /* valid */,
549 true /* installed */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100550 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100551 WebViewUpdateService.PACKAGE_CHANGED, 0);
Gustav Sennton53b78242016-04-07 15:56:10 +0100552
553 // Verify fallback is disabled a second time when primary package becomes enabled
554 Mockito.verify(mTestSystemImpl, Mockito.times(2)).enablePackageForUser(
555 Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */,
556 Matchers.anyInt());
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100557
558 checkPreparationPhasesForPackage(primaryPackage, 2);
Gustav Sennton53b78242016-04-07 15:56:10 +0100559 }
560
561 public void testAddUserWhenFallbackLogicEnabled() {
562 checkAddingNewUser(true);
563 }
564
565 public void testAddUserWhenFallbackLogicDisabled() {
566 checkAddingNewUser(false);
567 }
568
569 public void checkAddingNewUser(boolean fallbackLogicEnabled) {
570 String primaryPackage = "primary";
571 String fallbackPackage = "fallback";
572 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
573 new WebViewProviderInfo(
574 primaryPackage, "", true /* default available */, false /* fallback */, null),
575 new WebViewProviderInfo(
576 fallbackPackage, "", true /* default available */, true /* fallback */, null)};
577 setupWithPackages(packages, fallbackLogicEnabled);
578 setEnabledAndValidPackageInfos(packages);
579 int newUser = 100;
580 mWebViewUpdateServiceImpl.handleNewUser(newUser);
581 if (fallbackLogicEnabled) {
582 // Verify fallback package becomes disabled for new user
583 Mockito.verify(mTestSystemImpl).enablePackageForUser(
584 Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */,
585 Mockito.eq(newUser));
586 } else {
587 // Verify that we don't disable fallback for new user
588 Mockito.verify(mTestSystemImpl, Mockito.never()).enablePackageForUser(
589 Mockito.anyObject(), Matchers.anyBoolean() /* enable */,
590 Matchers.anyInt() /* user */);
591 }
592 }
593
594 /**
595 * Timing dependent test where we verify that the list of valid webview packages becoming empty
596 * at a certain point doesn't crash us or break our state.
597 */
598 public void testNotifyRelroDoesntCrashIfNoPackages() {
599 String firstPackage = "first";
600 String secondPackage = "second";
601 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
602 new WebViewProviderInfo(firstPackage, "", true /* default available */,
603 false /* fallback */, null),
604 new WebViewProviderInfo(secondPackage, "", true /* default available */,
605 false /* fallback */, null)};
606 setupWithPackages(packages);
607 // Add (enabled and valid) package infos for each provider
608 setEnabledAndValidPackageInfos(packages);
609
610 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
611
612 Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
613 Mockito.argThat(new IsPackageInfoWithName(firstPackage)));
614
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100615 // Change provider during relro creation to enter a state where we are
616 // waiting for relro creation to complete just to re-run relro creation.
617 // (so that in next notifyRelroCreationCompleted() call we have to list webview packages)
Gustav Sennton53b78242016-04-07 15:56:10 +0100618 mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage);
619
620 // Make packages invalid to cause exception to be thrown
621 mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100622 false /* valid */, true /* installed */, null /* signatures */,
623 0 /* updateTime */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100624 mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100625 false /* valid */, true /* installed */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100626
627 // This shouldn't throw an exception!
628 mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
629
630 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
631 assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status);
632
633 // Now make a package valid again and verify that we can switch back to that
634 mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100635 true /* valid */, true /* installed */, null /* signatures */,
636 1 /* updateTime */ ));
Gustav Sennton53b78242016-04-07 15:56:10 +0100637
638 mWebViewUpdateServiceImpl.packageStateChanged(firstPackage,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100639 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0);
Gustav Sennton53b78242016-04-07 15:56:10 +0100640
Gustav Senntona9159042016-04-11 16:32:52 +0100641 // Ensure we use firstPackage
642 checkPreparationPhasesForPackage(firstPackage, 2 /* second preparation for this package */);
643 }
Gustav Sennton53b78242016-04-07 15:56:10 +0100644
Gustav Senntona9159042016-04-11 16:32:52 +0100645 /**
646 * Verify that even if a user-chosen package is removed temporarily we start using it again when
647 * it is added back.
648 */
649 public void testTempRemovePackageDoesntSwitchProviderPermanently() {
650 String firstPackage = "first";
651 String secondPackage = "second";
652 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
653 new WebViewProviderInfo(firstPackage, "", true /* default available */,
654 false /* fallback */, null),
655 new WebViewProviderInfo(secondPackage, "", true /* default available */,
656 false /* fallback */, null)};
657 checkCertainPackageUsedAfterWebViewBootPreparation(firstPackage, packages);
Gustav Sennton53b78242016-04-07 15:56:10 +0100658
Gustav Senntona9159042016-04-11 16:32:52 +0100659 // Explicitly use the second package
660 mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage);
661 checkPreparationPhasesForPackage(secondPackage, 1 /* first time for this package */);
662
663 // Remove second package (invalidate it) and verify that first package is used
664 mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100665 false /* valid */, true /* installed */));
Gustav Senntona9159042016-04-11 16:32:52 +0100666 mWebViewUpdateServiceImpl.packageStateChanged(secondPackage,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100667 WebViewUpdateService.PACKAGE_ADDED, 0);
Gustav Senntona9159042016-04-11 16:32:52 +0100668 checkPreparationPhasesForPackage(firstPackage, 2 /* second time for this package */);
669
670 // Now make the second package valid again and verify that it is used again
671 mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100672 true /* valid */, true /* installed */));
Gustav Senntona9159042016-04-11 16:32:52 +0100673 mWebViewUpdateServiceImpl.packageStateChanged(secondPackage,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100674 WebViewUpdateService.PACKAGE_ADDED, 0);
Gustav Senntona9159042016-04-11 16:32:52 +0100675 checkPreparationPhasesForPackage(secondPackage, 2 /* second time for this package */);
676 }
677
678 /**
679 * Ensure that we update the user-chosen setting across boots if the chosen package is no
680 * longer installed and valid.
681 */
682 public void testProviderSettingChangedDuringBootIfProviderNotAvailable() {
683 String chosenPackage = "chosenPackage";
684 String nonChosenPackage = "non-chosenPackage";
685 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
686 new WebViewProviderInfo(chosenPackage, "", true /* default available */,
687 false /* fallback */, null),
688 new WebViewProviderInfo(nonChosenPackage, "", true /* default available */,
689 false /* fallback */, null)};
690
691 setupWithPackages(packages);
692 // Only 'install' nonChosenPackage
693 mTestSystemImpl.setPackageInfo(
Gustav Sennton0df2c552016-06-14 15:32:19 +0100694 createPackageInfo(nonChosenPackage, true /* enabled */, true /* valid */, true /* installed */));
Gustav Senntona9159042016-04-11 16:32:52 +0100695
696 // Set user-chosen package
697 mTestSystemImpl.updateUserSetting(null, chosenPackage);
698
699 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
700
701 // Verify that we switch the setting to point to the current package
702 Mockito.verify(mTestSystemImpl).updateUserSetting(
703 Mockito.anyObject(), Mockito.eq(nonChosenPackage));
704 assertEquals(nonChosenPackage, mTestSystemImpl.getUserChosenWebViewProvider(null));
705
706 checkPreparationPhasesForPackage(nonChosenPackage, 1);
Gustav Sennton53b78242016-04-07 15:56:10 +0100707 }
708
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100709 public void testRecoverFailedListingWebViewPackagesSettingsChange() {
710 checkRecoverAfterFailListingWebviewPackages(true);
711 }
712
713 public void testRecoverFailedListingWebViewPackagesAddedPackage() {
714 checkRecoverAfterFailListingWebviewPackages(false);
715 }
716
717 /**
718 * Test that we can recover correctly from failing to list WebView packages.
719 * settingsChange: whether to fail during changeProviderAndSetting or packageStateChanged
720 */
721 public void checkRecoverAfterFailListingWebviewPackages(boolean settingsChange) {
722 String firstPackage = "first";
723 String secondPackage = "second";
724 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
725 new WebViewProviderInfo(firstPackage, "", true /* default available */,
726 false /* fallback */, null),
727 new WebViewProviderInfo(secondPackage, "", true /* default available */,
728 false /* fallback */, null)};
729 checkCertainPackageUsedAfterWebViewBootPreparation(firstPackage, packages);
730
731 // Make both packages invalid so that we fail listing WebView packages
732 mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100733 false /* valid */, true /* installed */));
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100734 mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100735 false /* valid */, true /* installed */));
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100736
737 // Change package to hit the webview packages listing problem.
738 if (settingsChange) {
739 mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage);
740 } else {
741 mWebViewUpdateServiceImpl.packageStateChanged(secondPackage,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100742 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0);
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100743 }
744
745 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
746 assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status);
747
748 // Make second package valid and verify that we can load it again
749 mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100750 true /* valid */, true /* installed */));
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100751
752 mWebViewUpdateServiceImpl.packageStateChanged(secondPackage,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100753 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0);
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100754
755
756 checkPreparationPhasesForPackage(secondPackage, 1);
757 }
758
759 public void testDontKillIfPackageReplaced() {
760 checkDontKillIfPackageRemoved(true);
761 }
762
763 public void testDontKillIfPackageRemoved() {
764 checkDontKillIfPackageRemoved(false);
765 }
766
767 public void checkDontKillIfPackageRemoved(boolean replaced) {
768 String firstPackage = "first";
769 String secondPackage = "second";
770 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
771 new WebViewProviderInfo(firstPackage, "", true /* default available */,
772 false /* fallback */, null),
773 new WebViewProviderInfo(secondPackage, "", true /* default available */,
774 false /* fallback */, null)};
775 checkCertainPackageUsedAfterWebViewBootPreparation(firstPackage, packages);
776
777 // Replace or remove the current webview package
778 if (replaced) {
779 mTestSystemImpl.setPackageInfo(
Gustav Sennton0df2c552016-06-14 15:32:19 +0100780 createPackageInfo(firstPackage, true /* enabled */, false /* valid */,
781 true /* installed */));
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100782 mWebViewUpdateServiceImpl.packageStateChanged(firstPackage,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100783 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0);
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100784 } else {
785 mTestSystemImpl.removePackageInfo(firstPackage);
786 mWebViewUpdateServiceImpl.packageStateChanged(firstPackage,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100787 WebViewUpdateService.PACKAGE_REMOVED, 0);
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100788 }
789
790 checkPreparationPhasesForPackage(secondPackage, 1);
791
792 Mockito.verify(mTestSystemImpl, Mockito.never()).killPackageDependents(
793 Mockito.anyObject());
794 }
795
796 public void testKillIfSettingChanged() {
797 String firstPackage = "first";
798 String secondPackage = "second";
799 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
800 new WebViewProviderInfo(firstPackage, "", true /* default available */,
801 false /* fallback */, null),
802 new WebViewProviderInfo(secondPackage, "", true /* default available */,
803 false /* fallback */, null)};
804 checkCertainPackageUsedAfterWebViewBootPreparation(firstPackage, packages);
805
806 mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage);
807
808 checkPreparationPhasesForPackage(secondPackage, 1);
809
810 Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(firstPackage));
811 }
812
813 /**
814 * Test that we kill apps using an old provider when we change the provider setting, even if the
815 * new provider is not the one we intended to change to.
816 */
817 public void testKillIfChangeProviderIncorrectly() {
818 String firstPackage = "first";
819 String secondPackage = "second";
820 String thirdPackage = "third";
821 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
822 new WebViewProviderInfo(firstPackage, "", true /* default available */,
823 false /* fallback */, null),
824 new WebViewProviderInfo(secondPackage, "", true /* default available */,
825 false /* fallback */, null),
826 new WebViewProviderInfo(thirdPackage, "", true /* default available */,
827 false /* fallback */, null)};
828 setupWithPackages(packages);
829 setEnabledAndValidPackageInfos(packages);
830
831 // Start with the setting pointing to the third package
832 mTestSystemImpl.updateUserSetting(null, thirdPackage);
833
834 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
835 checkPreparationPhasesForPackage(thirdPackage, 1);
836
837 mTestSystemImpl.setPackageInfo(
Gustav Sennton0df2c552016-06-14 15:32:19 +0100838 createPackageInfo(secondPackage, true /* enabled */, false /* valid */, true /* installed */));
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100839
840 // Try to switch to the invalid second package, this should result in switching to the first
841 // package, since that is more preferred than the third one.
842 assertEquals(firstPackage,
843 mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage));
844
845 checkPreparationPhasesForPackage(firstPackage, 1);
846
847 Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(thirdPackage));
848 }
Gustav Sennton0df2c552016-06-14 15:32:19 +0100849
850 // Ensure that the update service uses an uninstalled package if that is the only package
851 // available.
852 public void testWithSingleUninstalledPackage() {
853 String testPackageName = "test.package.name";
854 WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] {
855 new WebViewProviderInfo(testPackageName, "",
856 true /*default available*/, false /* fallback */, null)};
857 setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */);
858 mTestSystemImpl.setPackageInfo(createPackageInfo(testPackageName, true /* enabled */,
859 true /* valid */, false /* installed */));
860
861 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
862
863 checkPreparationPhasesForPackage(testPackageName, 1 /* first preparation phase */);
864 }
865
866 public void testNonhiddenPackageUserOverHidden() {
867 checkVisiblePackageUserOverNonVisible(false /* true == uninstalled, false == hidden */);
868 }
869
870 public void testInstalledPackageUsedOverUninstalled() {
871 checkVisiblePackageUserOverNonVisible(true /* true == uninstalled, false == hidden */);
872 }
873
874 private void checkVisiblePackageUserOverNonVisible(boolean uninstalledNotHidden) {
875 boolean testUninstalled = uninstalledNotHidden;
876 boolean testHidden = !uninstalledNotHidden;
877 String installedPackage = "installedPackage";
878 String uninstalledPackage = "uninstalledPackage";
879 WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] {
880 new WebViewProviderInfo(uninstalledPackage, "", true /* available by default */,
881 false /* fallback */, null),
882 new WebViewProviderInfo(installedPackage, "", true /* available by default */,
883 false /* fallback */, null)};
884
885 setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */);
886 mTestSystemImpl.setPackageInfo(createPackageInfo(installedPackage, true /* enabled */,
887 true /* valid */, true /* installed */));
888 mTestSystemImpl.setPackageInfo(createPackageInfo(uninstalledPackage, true /* enabled */,
889 true /* valid */, (testUninstalled ? false : true) /* installed */,
890 null /* signatures */, 0 /* updateTime */, (testHidden ? true : false)));
891
892 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
893
894 checkPreparationPhasesForPackage(installedPackage, 1 /* first preparation phase */);
895 }
896
897 public void testCantSwitchToHiddenPackage () {
898 checkCantSwitchToNonVisiblePackage(false /* true == uninstalled, false == hidden */);
899 }
900
901
902 public void testCantSwitchToUninstalledPackage () {
903 checkCantSwitchToNonVisiblePackage(true /* true == uninstalled, false == hidden */);
904 }
905
906 /**
907 * Ensure that we won't prioritize an uninstalled (or hidden) package even if it is user-chosen,
908 * and that an uninstalled (or hidden) package is not considered valid (in the
909 * getValidWebViewPackages() API).
910 */
911 private void checkCantSwitchToNonVisiblePackage(boolean uninstalledNotHidden) {
912 boolean testUninstalled = uninstalledNotHidden;
913 boolean testHidden = !uninstalledNotHidden;
914 String installedPackage = "installedPackage";
915 String uninstalledPackage = "uninstalledPackage";
916 WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] {
917 new WebViewProviderInfo(uninstalledPackage, "", true /* available by default */,
918 false /* fallback */, null),
919 new WebViewProviderInfo(installedPackage, "", true /* available by default */,
920 false /* fallback */, null)};
921
922 setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */);
923 mTestSystemImpl.setPackageInfo(createPackageInfo(installedPackage, true /* enabled */,
924 true /* valid */, true /* installed */));
925 mTestSystemImpl.setPackageInfo(createPackageInfo(uninstalledPackage, true /* enabled */,
926 true /* valid */, (testUninstalled ? false : true) /* installed */,
927 null /* signatures */, 0 /* updateTime */,
928 (testHidden ? true : false) /* hidden */));
929
930 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
931
932 checkPreparationPhasesForPackage(installedPackage, 1 /* first preparation phase */);
933
934 // Ensure that only the installed package is considered valid
935 WebViewProviderInfo[] validPackages = mWebViewUpdateServiceImpl.getValidWebViewPackages();
936 assertEquals(1, validPackages.length);
937 assertEquals(installedPackage, validPackages[0].packageName);
938
939 // ensure that we don't switch to the uninstalled package (it will be used if it becomes
940 // installed later)
941 assertEquals(installedPackage,
942 mWebViewUpdateServiceImpl.changeProviderAndSetting(uninstalledPackage));
943
944 // We should only have called onWebViewProviderChanged once (before calling
945 // changeProviderAndSetting
946 Mockito.verify(mTestSystemImpl, Mockito.times(1)).onWebViewProviderChanged(
947 Mockito.argThat(new IsPackageInfoWithName(installedPackage)));
948 }
949
950 public void testHiddenPackageNotPrioritizedEvenIfChosen() {
951 checkNonvisiblePackageNotPrioritizedEvenIfChosen(
952 false /* true == uninstalled, false == hidden */);
953 }
954
955 public void testUninstalledPackageNotPrioritizedEvenIfChosen() {
956 checkNonvisiblePackageNotPrioritizedEvenIfChosen(
957 true /* true == uninstalled, false == hidden */);
958 }
959
960 public void checkNonvisiblePackageNotPrioritizedEvenIfChosen(boolean uninstalledNotHidden) {
961 boolean testUninstalled = uninstalledNotHidden;
962 boolean testHidden = !uninstalledNotHidden;
963 String installedPackage = "installedPackage";
964 String uninstalledPackage = "uninstalledPackage";
965 WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] {
966 new WebViewProviderInfo(uninstalledPackage, "", true /* available by default */,
967 false /* fallback */, null),
968 new WebViewProviderInfo(installedPackage, "", true /* available by default */,
969 false /* fallback */, null)};
970
971 setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */);
972 mTestSystemImpl.setPackageInfo(createPackageInfo(installedPackage, true /* enabled */,
973 true /* valid */, true /* installed */));
974 mTestSystemImpl.setPackageInfo(createPackageInfo(uninstalledPackage, true /* enabled */,
975 true /* valid */, (testUninstalled ? false : true) /* installed */,
976 null /* signatures */, 0 /* updateTime */,
977 (testHidden ? true : false) /* hidden */));
978
979 // Start with the setting pointing to the uninstalled package
980 mTestSystemImpl.updateUserSetting(null, uninstalledPackage);
981
982 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
983
984 checkPreparationPhasesForPackage(installedPackage, 1 /* first preparation phase */);
985 }
986
987 /**
988 * Ensures that fallback becomes enabled if the primary package is uninstalled for the current
989 * user.
990 */
991 public void testFallbackEnabledIfPrimaryUninstalled() {
992 String primaryPackage = "primary";
993 String fallbackPackage = "fallback";
994 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
995 new WebViewProviderInfo(
996 primaryPackage, "", true /* default available */, false /* fallback */, null),
997 new WebViewProviderInfo(
998 fallbackPackage, "", true /* default available */, true /* fallback */, null)};
999 setupWithPackages(packages, true /* fallback logic enabled */);
1000 mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */,
1001 true /* valid */, false /* installed */));
1002 mTestSystemImpl.setPackageInfo(createPackageInfo(fallbackPackage, true /* enabled */,
1003 true /* valid */, true /* installed */));
1004
1005 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
1006 // Verify that we enable the fallback package
1007 Mockito.verify(mTestSystemImpl).enablePackageForAllUsers(
1008 Mockito.anyObject(), Mockito.eq(fallbackPackage), Mockito.eq(true) /* enable */);
1009
1010 checkPreparationPhasesForPackage(fallbackPackage, 1 /* first preparation phase */);
1011 }
1012
1013 public void testPreparationRunsIffNewPackage() {
1014 String primaryPackage = "primary";
1015 String fallbackPackage = "fallback";
1016 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
1017 new WebViewProviderInfo(
1018 primaryPackage, "", true /* default available */, false /* fallback */, null),
1019 new WebViewProviderInfo(
1020 fallbackPackage, "", true /* default available */, true /* fallback */, null)};
1021 setupWithPackages(packages, true /* fallback logic enabled */);
1022 mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */,
1023 true /* valid */, true /* installed */, null /* signatures */,
1024 10 /* lastUpdateTime*/ ));
1025 mTestSystemImpl.setPackageInfo(createPackageInfo(fallbackPackage, true /* enabled */,
1026 true /* valid */, true /* installed */));
1027
1028 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
1029
1030 checkPreparationPhasesForPackage(primaryPackage, 1 /* first preparation phase */);
1031 Mockito.verify(mTestSystemImpl, Mockito.times(1)).enablePackageForUser(
1032 Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */,
1033 Matchers.anyInt() /* user */);
1034
1035
1036 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
1037 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0 /* userId */);
1038 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
1039 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 1 /* userId */);
1040 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
1041 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 2 /* userId */);
1042 // package still has the same update-time so we shouldn't run preparation here
1043 Mockito.verify(mTestSystemImpl, Mockito.times(1)).onWebViewProviderChanged(
1044 Mockito.argThat(new IsPackageInfoWithName(primaryPackage)));
1045 Mockito.verify(mTestSystemImpl, Mockito.times(1)).enablePackageForUser(
1046 Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */,
1047 Matchers.anyInt() /* user */);
1048
1049 // Ensure we can still load the package
1050 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
1051 assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status);
1052 assertEquals(primaryPackage, response.packageInfo.packageName);
1053
1054
1055 mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */,
1056 true /* valid */, true /* installed */, null /* signatures */,
1057 20 /* lastUpdateTime*/ ));
1058 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
1059 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0);
1060 // The package has now changed - ensure that we have run the preparation phase a second time
1061 checkPreparationPhasesForPackage(primaryPackage, 2 /* second preparation phase */);
1062
1063
1064 mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */,
1065 true /* valid */, true /* installed */, null /* signatures */,
1066 50 /* lastUpdateTime*/ ));
1067 // Receive intent for different user
1068 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
1069 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 2);
1070
1071 checkPreparationPhasesForPackage(primaryPackage, 3 /* third preparation phase */);
1072 }
1073
Gustav Sennton53b78242016-04-07 15:56:10 +01001074}