1/* 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 */, 89 true /* valid */, true /* installed */)); 90 } 91 } 92 93 private void checkCertainPackageUsedAfterWebViewBootPreparation(String expectedProviderName, 94 WebViewProviderInfo[] webviewPackages) { 95 checkCertainPackageUsedAfterWebViewBootPreparation( 96 expectedProviderName, webviewPackages, 1); 97 } 98 99 private void checkCertainPackageUsedAfterWebViewBootPreparation(String expectedProviderName, 100 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( 140 String packageName, boolean enabled, boolean valid, boolean installed) { 141 PackageInfo p = new PackageInfo(); 142 p.packageName = packageName; 143 p.applicationInfo = new ApplicationInfo(); 144 p.applicationInfo.enabled = enabled; 145 p.applicationInfo.metaData = new Bundle(); 146 if (installed) { 147 p.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED; 148 } else { 149 p.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED; 150 } 151 if (valid) { 152 // no flag means invalid 153 p.applicationInfo.metaData.putString(WEBVIEW_LIBRARY_FLAG, "blah"); 154 } 155 return p; 156 } 157 158 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); 161 p.signatures = signatures; 162 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 } 175 return p; 176 } 177 178 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 191 192 // **************** 193 // Tests 194 // **************** 195 196 197 public void testWithSinglePackage() { 198 String testPackageName = "test.package.name"; 199 checkCertainPackageUsedAfterWebViewBootPreparation(testPackageName, 200 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)}; 211 checkCertainPackageUsedAfterWebViewBootPreparation(defaultPackage, packages); 212 } 213 214 public void testSeveralRelros() { 215 String singlePackage = "singlePackage"; 216 checkCertainPackageUsedAfterWebViewBootPreparation( 217 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 */, 244 true /* valid */, true /* installed */, new Signature[]{invalidPackageSignature} 245 , 0 /* updateTime */)); 246 mTestSystemImpl.setPackageInfo(createPackageInfo(validPackage, true /* enabled */, 247 true /* valid */, true /* installed */, new Signature[]{validSignature} 248 , 0 /* updateTime */)); 249 250 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer(); 251 252 253 checkPreparationPhasesForPackage(validPackage, 1 /* first preparation for this package */); 254 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() { 292 WebViewProviderInfo wpi = new WebViewProviderInfo("package", "", true, true, null); 293 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {wpi}; 294 setupWithPackages(packages); 295 mTestSystemImpl.setPackageInfo( 296 createPackageInfo(wpi.packageName, true /* enabled */, false /* valid */, 297 true /* installed */)); 298 299 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer(); 300 301 Mockito.verify(mTestSystemImpl, Mockito.never()).onWebViewProviderChanged( 302 Matchers.anyObject()); 303 304 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); 305 assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status); 306 307 // Verify that we can recover from failing to list webview packages. 308 mTestSystemImpl.setPackageInfo( 309 createPackageInfo(wpi.packageName, true /* enabled */, true /* valid */, 310 true /* installed */)); 311 mWebViewUpdateServiceImpl.packageStateChanged(wpi.packageName, 312 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0); 313 314 checkPreparationPhasesForPackage(wpi.packageName, 1); 315 } 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) { 338 checkCertainPackageUsedAfterWebViewBootPreparation(initialPackage, packages); 339 340 mWebViewUpdateServiceImpl.changeProviderAndSetting(finalPackage); 341 checkPreparationPhasesForPackage(finalPackage, 1 /* first preparation for this package */); 342 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, 370 false /* enabled */, true /* valid */, true /* installed */)); 371 } 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 { 396 Thread.sleep(500); // Let the new thread run / be blocked 397 } 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 */, 405 true /* valid */, true /* installed */)); 406 mWebViewUpdateServiceImpl.packageStateChanged( 407 secondPackage, WebViewUpdateService.PACKAGE_CHANGED, 0); 408 } 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 */, 457 true /* valid */, true /* installed */)); 458 mWebViewUpdateServiceImpl.packageStateChanged( 459 fallbackPackage, WebViewUpdateService.PACKAGE_CHANGED, 0); 460 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( 488 createPackageInfo(fallbackPackage, true /* enabled */ , true /* valid */, 489 true /* installed */)); 490 491 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer(); 492 Mockito.verify(mTestSystemImpl, Mockito.never()).uninstallAndDisablePackageForAllUsers( 493 Matchers.anyObject(), Matchers.anyObject()); 494 495 checkPreparationPhasesForPackage(fallbackPackage, 496 1 /* first preparation for this package*/); 497 498 // Install primary package 499 mTestSystemImpl.setPackageInfo( 500 createPackageInfo(primaryPackage, true /* enabled */ , true /* valid */, 501 true /* installed */)); 502 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, 503 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0); 504 505 // Verify fallback disabled, primary package used as provider, and fallback package killed 506 Mockito.verify(mTestSystemImpl).uninstallAndDisablePackageForAllUsers( 507 Matchers.anyObject(), Mockito.eq(fallbackPackage)); 508 checkPreparationPhasesForPackage(primaryPackage, 1 /* first preparation for this package*/); 509 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 530 checkPreparationPhasesForPackage(primaryPackage, 1); 531 532 // Disable primary package and ensure fallback becomes enabled and used 533 mTestSystemImpl.setPackageInfo( 534 createPackageInfo(primaryPackage, false /* enabled */, true /* valid */, 535 true /* installed */)); 536 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, 537 WebViewUpdateService.PACKAGE_CHANGED, 0); 538 539 Mockito.verify(mTestSystemImpl).enablePackageForUser( 540 Mockito.eq(fallbackPackage), Mockito.eq(true) /* enable */, 541 Matchers.anyInt()); 542 543 checkPreparationPhasesForPackage(fallbackPackage, 1); 544 545 546 // Again enable primary package and verify primary is used and fallback becomes disabled 547 mTestSystemImpl.setPackageInfo( 548 createPackageInfo(primaryPackage, true /* enabled */, true /* valid */, 549 true /* installed */)); 550 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, 551 WebViewUpdateService.PACKAGE_CHANGED, 0); 552 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()); 557 558 checkPreparationPhasesForPackage(primaryPackage, 2); 559 } 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 615 // 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) 618 mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage); 619 620 // Make packages invalid to cause exception to be thrown 621 mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, true /* enabled */, 622 false /* valid */, true /* installed */, null /* signatures */, 623 0 /* updateTime */)); 624 mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */, 625 false /* valid */, true /* installed */)); 626 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 */, 635 true /* valid */, true /* installed */, null /* signatures */, 636 1 /* updateTime */ )); 637 638 mWebViewUpdateServiceImpl.packageStateChanged(firstPackage, 639 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0); 640 641 // Ensure we use firstPackage 642 checkPreparationPhasesForPackage(firstPackage, 2 /* second preparation for this package */); 643 } 644 645 /** 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); 658 659 // 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 */, 665 false /* valid */, true /* installed */)); 666 mWebViewUpdateServiceImpl.packageStateChanged(secondPackage, 667 WebViewUpdateService.PACKAGE_ADDED, 0); 668 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 */, 672 true /* valid */, true /* installed */)); 673 mWebViewUpdateServiceImpl.packageStateChanged(secondPackage, 674 WebViewUpdateService.PACKAGE_ADDED, 0); 675 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( 694 createPackageInfo(nonChosenPackage, true /* enabled */, true /* valid */, true /* installed */)); 695 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); 707 } 708 709 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 */, 733 false /* valid */, true /* installed */)); 734 mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */, 735 false /* valid */, true /* installed */)); 736 737 // Change package to hit the webview packages listing problem. 738 if (settingsChange) { 739 mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage); 740 } else { 741 mWebViewUpdateServiceImpl.packageStateChanged(secondPackage, 742 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0); 743 } 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 */, 750 true /* valid */, true /* installed */)); 751 752 mWebViewUpdateServiceImpl.packageStateChanged(secondPackage, 753 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0); 754 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( 780 createPackageInfo(firstPackage, true /* enabled */, false /* valid */, 781 true /* installed */)); 782 mWebViewUpdateServiceImpl.packageStateChanged(firstPackage, 783 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0); 784 } else { 785 mTestSystemImpl.removePackageInfo(firstPackage); 786 mWebViewUpdateServiceImpl.packageStateChanged(firstPackage, 787 WebViewUpdateService.PACKAGE_REMOVED, 0); 788 } 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( 838 createPackageInfo(secondPackage, true /* enabled */, false /* valid */, true /* installed */)); 839 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 } 849 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 1074} 1075