WebViewUpdateServiceTest.java revision 963dbbbdb616646240dde9a4b2b7b7592ddfefaa
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 static org.junit.Assert.assertArrayEquals; 20import static org.junit.Assert.assertEquals; 21import static org.junit.Assert.assertFalse; 22import static org.junit.Assert.assertTrue; 23 24import android.content.Context; 25import android.content.pm.ApplicationInfo; 26import android.content.pm.PackageInfo; 27import android.content.pm.Signature; 28import android.os.Build; 29import android.os.Bundle; 30import android.support.test.InstrumentationRegistry; 31import android.support.test.runner.AndroidJUnit4; 32import android.test.suitebuilder.annotation.MediumTest; 33import android.util.Base64; 34import android.webkit.WebViewFactory; 35import android.webkit.WebViewProviderInfo; 36import android.webkit.WebViewProviderResponse; 37 38import org.junit.Test; 39import org.junit.runner.RunWith; 40 41import org.mockito.Mockito; 42import org.mockito.Matchers; 43import org.mockito.compat.ArgumentMatcher; 44 45import java.util.concurrent.CountDownLatch; 46 47 48/** 49 * Tests for WebViewUpdateService 50 runtest --path frameworks/base/services/tests/servicestests/ \ 51 -c com.android.server.webkit.WebViewUpdateServiceTest 52 */ 53// Use MediumTest instead of SmallTest as the implementation of WebViewUpdateService 54// is intended to work on several threads and uses at least one sleep/wait-statement. 55@RunWith(AndroidJUnit4.class) 56@MediumTest 57public class WebViewUpdateServiceTest { 58 private final static String TAG = WebViewUpdateServiceTest.class.getSimpleName(); 59 60 private WebViewUpdateServiceImpl mWebViewUpdateServiceImpl; 61 private TestSystemImpl mTestSystemImpl; 62 63 private static final String WEBVIEW_LIBRARY_FLAG = "com.android.webview.WebViewLibrary"; 64 65 /** 66 * Creates a new instance. 67 */ 68 public WebViewUpdateServiceTest() { 69 } 70 71 private void setupWithPackages(WebViewProviderInfo[] packages) { 72 setupWithPackages(packages, true); 73 } 74 75 private void setupWithPackages(WebViewProviderInfo[] packages, 76 boolean fallbackLogicEnabled) { 77 setupWithPackages(packages, fallbackLogicEnabled, 1); 78 } 79 80 private void setupWithPackages(WebViewProviderInfo[] packages, 81 boolean fallbackLogicEnabled, int numRelros) { 82 setupWithPackages(packages, fallbackLogicEnabled, numRelros, 83 true /* isDebuggable == true -> don't check package signatures */); 84 } 85 86 private void setupWithPackages(WebViewProviderInfo[] packages, 87 boolean fallbackLogicEnabled, int numRelros, boolean isDebuggable) { 88 setupWithPackages(packages, fallbackLogicEnabled, numRelros, isDebuggable, 89 false /* multiProcessDefault */); 90 } 91 92 private void setupWithPackages(WebViewProviderInfo[] packages, 93 boolean fallbackLogicEnabled, int numRelros, boolean isDebuggable, 94 boolean multiProcessDefault) { 95 TestSystemImpl testing = new TestSystemImpl(packages, fallbackLogicEnabled, numRelros, 96 isDebuggable, multiProcessDefault); 97 mTestSystemImpl = Mockito.spy(testing); 98 mWebViewUpdateServiceImpl = 99 new WebViewUpdateServiceImpl(null /*Context*/, mTestSystemImpl); 100 } 101 102 private void setEnabledAndValidPackageInfos(WebViewProviderInfo[] providers) { 103 // Set package infos for the primary user (user 0). 104 setEnabledAndValidPackageInfosForUser(TestSystemImpl.PRIMARY_USER_ID, providers); 105 } 106 107 private void setEnabledAndValidPackageInfosForUser(int userId, 108 WebViewProviderInfo[] providers) { 109 for(WebViewProviderInfo wpi : providers) { 110 mTestSystemImpl.setPackageInfoForUser(userId, createPackageInfo(wpi.packageName, 111 true /* enabled */, true /* valid */, true /* installed */)); 112 } 113 } 114 115 private void checkCertainPackageUsedAfterWebViewBootPreparation(String expectedProviderName, 116 WebViewProviderInfo[] webviewPackages) { 117 checkCertainPackageUsedAfterWebViewBootPreparation( 118 expectedProviderName, webviewPackages, 1); 119 } 120 121 private void checkCertainPackageUsedAfterWebViewBootPreparation(String expectedProviderName, 122 WebViewProviderInfo[] webviewPackages, int numRelros) { 123 setupWithPackages(webviewPackages, true, numRelros); 124 // Add (enabled and valid) package infos for each provider 125 setEnabledAndValidPackageInfos(webviewPackages); 126 127 runWebViewBootPreparationOnMainSync(); 128 129 Mockito.verify(mTestSystemImpl).onWebViewProviderChanged( 130 Mockito.argThat(new IsPackageInfoWithName(expectedProviderName))); 131 132 for (int n = 0; n < numRelros; n++) { 133 mWebViewUpdateServiceImpl.notifyRelroCreationCompleted(); 134 } 135 136 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); 137 assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status); 138 assertEquals(expectedProviderName, response.packageInfo.packageName); 139 } 140 141 // For matching the package name of a PackageInfo 142 private class IsPackageInfoWithName extends ArgumentMatcher<PackageInfo> { 143 private final String mPackageName; 144 145 IsPackageInfoWithName(String name) { 146 mPackageName = name; 147 } 148 149 @Override 150 public boolean matchesObject(Object p) { 151 return ((PackageInfo) p).packageName.equals(mPackageName); 152 } 153 154 @Override 155 public String toString() { 156 return String.format("PackageInfo with name '%s'", mPackageName); 157 } 158 } 159 160 private static PackageInfo createPackageInfo( 161 String packageName, boolean enabled, boolean valid, boolean installed) { 162 PackageInfo p = new PackageInfo(); 163 p.packageName = packageName; 164 p.applicationInfo = new ApplicationInfo(); 165 p.applicationInfo.enabled = enabled; 166 p.applicationInfo.metaData = new Bundle(); 167 if (installed) { 168 p.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED; 169 } else { 170 p.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED; 171 } 172 if (valid) { 173 // no flag means invalid 174 p.applicationInfo.metaData.putString(WEBVIEW_LIBRARY_FLAG, "blah"); 175 } 176 // Default to this package being valid in terms of targetSdkVersion. 177 p.applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT; 178 return p; 179 } 180 181 private static PackageInfo createPackageInfo(String packageName, boolean enabled, boolean valid, 182 boolean installed, Signature[] signatures, long updateTime) { 183 PackageInfo p = createPackageInfo(packageName, enabled, valid, installed); 184 p.signatures = signatures; 185 p.lastUpdateTime = updateTime; 186 return p; 187 } 188 189 private static PackageInfo createPackageInfo(String packageName, boolean enabled, boolean valid, 190 boolean installed, Signature[] signatures, long updateTime, boolean hidden) { 191 PackageInfo p = 192 createPackageInfo(packageName, enabled, valid, installed, signatures, updateTime); 193 if (hidden) { 194 p.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN; 195 } else { 196 p.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN; 197 } 198 return p; 199 } 200 201 private static PackageInfo createPackageInfo(String packageName, boolean enabled, boolean valid, 202 boolean installed, Signature[] signatures, long updateTime, boolean hidden, 203 int versionCode, boolean isSystemApp) { 204 PackageInfo p = createPackageInfo(packageName, enabled, valid, installed, signatures, 205 updateTime, hidden); 206 p.versionCode = versionCode; 207 p.applicationInfo.versionCode = versionCode; 208 if (isSystemApp) p.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; 209 return p; 210 } 211 212 private void checkPreparationPhasesForPackage(String expectedPackage, int numPreparation) { 213 // Verify that onWebViewProviderChanged was called for the numPreparation'th time for the 214 // expected package 215 Mockito.verify(mTestSystemImpl, Mockito.times(numPreparation)).onWebViewProviderChanged( 216 Mockito.argThat(new IsPackageInfoWithName(expectedPackage))); 217 218 mWebViewUpdateServiceImpl.notifyRelroCreationCompleted(); 219 220 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); 221 assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status); 222 assertEquals(expectedPackage, response.packageInfo.packageName); 223 } 224 225 /** 226 * The WebView preparation boot phase is run on the main thread (especially on a thread with a 227 * looper) so to avoid bugs where our tests fail because a looper hasn't been attached to the 228 * thread running prepareWebViewInSystemServer we run it on the main thread. 229 */ 230 private void runWebViewBootPreparationOnMainSync() { 231 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { 232 @Override 233 public void run() { 234 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer(); 235 } 236 }); 237 } 238 239 240 // **************** 241 // Tests 242 // **************** 243 244 245 @Test 246 public void testWithSinglePackage() { 247 String testPackageName = "test.package.name"; 248 checkCertainPackageUsedAfterWebViewBootPreparation(testPackageName, 249 new WebViewProviderInfo[] { 250 new WebViewProviderInfo(testPackageName, "", 251 true /*default available*/, false /* fallback */, null)}); 252 } 253 254 @Test 255 public void testDefaultPackageUsedOverNonDefault() { 256 String defaultPackage = "defaultPackage"; 257 String nonDefaultPackage = "nonDefaultPackage"; 258 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 259 new WebViewProviderInfo(nonDefaultPackage, "", false, false, null), 260 new WebViewProviderInfo(defaultPackage, "", true, false, null)}; 261 checkCertainPackageUsedAfterWebViewBootPreparation(defaultPackage, packages); 262 } 263 264 @Test 265 public void testSeveralRelros() { 266 String singlePackage = "singlePackage"; 267 checkCertainPackageUsedAfterWebViewBootPreparation( 268 singlePackage, 269 new WebViewProviderInfo[] { 270 new WebViewProviderInfo(singlePackage, "", true /*def av*/, false, null)}, 271 2); 272 } 273 274 // Ensure that package with valid signatures is chosen rather than package with invalid 275 // signatures. 276 @Test 277 public void testWithSignatures() { 278 String validPackage = "valid package"; 279 String invalidPackage = "invalid package"; 280 281 Signature validSignature = new Signature("11"); 282 Signature invalidExpectedSignature = new Signature("22"); 283 Signature invalidPackageSignature = new Signature("33"); 284 285 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 286 new WebViewProviderInfo(invalidPackage, "", true, false, new String[]{ 287 Base64.encodeToString( 288 invalidExpectedSignature.toByteArray(), Base64.DEFAULT)}), 289 new WebViewProviderInfo(validPackage, "", true, false, new String[]{ 290 Base64.encodeToString( 291 validSignature.toByteArray(), Base64.DEFAULT)}) 292 }; 293 setupWithPackages(packages, true /* fallback logic enabled */, 1 /* numRelros */, 294 false /* isDebuggable */); 295 mTestSystemImpl.setPackageInfo(createPackageInfo(invalidPackage, true /* enabled */, 296 true /* valid */, true /* installed */, new Signature[]{invalidPackageSignature} 297 , 0 /* updateTime */)); 298 mTestSystemImpl.setPackageInfo(createPackageInfo(validPackage, true /* enabled */, 299 true /* valid */, true /* installed */, new Signature[]{validSignature} 300 , 0 /* updateTime */)); 301 302 runWebViewBootPreparationOnMainSync(); 303 304 305 checkPreparationPhasesForPackage(validPackage, 1 /* first preparation for this package */); 306 307 WebViewProviderInfo[] validPackages = mWebViewUpdateServiceImpl.getValidWebViewPackages(); 308 assertEquals(1, validPackages.length); 309 assertEquals(validPackage, validPackages[0].packageName); 310 } 311 312 @Test 313 public void testFailWaitingForRelro() { 314 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 315 new WebViewProviderInfo("packagename", "", true, true, null)}; 316 setupWithPackages(packages); 317 setEnabledAndValidPackageInfos(packages); 318 319 runWebViewBootPreparationOnMainSync(); 320 321 Mockito.verify(mTestSystemImpl).onWebViewProviderChanged( 322 Mockito.argThat(new IsPackageInfoWithName(packages[0].packageName))); 323 324 // Never call notifyRelroCreation() 325 326 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); 327 assertEquals(WebViewFactory.LIBLOAD_FAILED_WAITING_FOR_RELRO, response.status); 328 } 329 330 @Test 331 public void testFailListingEmptyWebviewPackages() { 332 WebViewProviderInfo[] packages = new WebViewProviderInfo[0]; 333 setupWithPackages(packages); 334 setEnabledAndValidPackageInfos(packages); 335 336 runWebViewBootPreparationOnMainSync(); 337 338 Mockito.verify(mTestSystemImpl, Mockito.never()).onWebViewProviderChanged( 339 Matchers.anyObject()); 340 341 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); 342 assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status); 343 assertEquals(null, mWebViewUpdateServiceImpl.getCurrentWebViewPackage()); 344 345 // Now install a package 346 String singlePackage = "singlePackage"; 347 packages = new WebViewProviderInfo[]{ 348 new WebViewProviderInfo(singlePackage, "", true, false, null)}; 349 setupWithPackages(packages); 350 setEnabledAndValidPackageInfos(packages); 351 352 mWebViewUpdateServiceImpl.packageStateChanged(singlePackage, 353 WebViewUpdateService.PACKAGE_ADDED, TestSystemImpl.PRIMARY_USER_ID); 354 355 checkPreparationPhasesForPackage(singlePackage, 1 /* number of finished preparations */); 356 assertEquals(singlePackage, 357 mWebViewUpdateServiceImpl.getCurrentWebViewPackage().packageName); 358 359 // Remove the package again 360 mTestSystemImpl.removePackageInfo(singlePackage); 361 mWebViewUpdateServiceImpl.packageStateChanged(singlePackage, 362 WebViewUpdateService.PACKAGE_ADDED, TestSystemImpl.PRIMARY_USER_ID); 363 364 // Package removed - ensure our interface states that there is no package 365 response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); 366 assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status); 367 assertEquals(null, mWebViewUpdateServiceImpl.getCurrentWebViewPackage()); 368 } 369 370 @Test 371 public void testFailListingInvalidWebviewPackage() { 372 WebViewProviderInfo wpi = new WebViewProviderInfo("package", "", true, true, null); 373 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {wpi}; 374 setupWithPackages(packages); 375 mTestSystemImpl.setPackageInfo( 376 createPackageInfo(wpi.packageName, true /* enabled */, false /* valid */, 377 true /* installed */)); 378 379 runWebViewBootPreparationOnMainSync(); 380 381 Mockito.verify(mTestSystemImpl, Mockito.never()).onWebViewProviderChanged( 382 Matchers.anyObject()); 383 384 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); 385 assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status); 386 387 // Verify that we can recover from failing to list webview packages. 388 mTestSystemImpl.setPackageInfo( 389 createPackageInfo(wpi.packageName, true /* enabled */, true /* valid */, 390 true /* installed */)); 391 mWebViewUpdateServiceImpl.packageStateChanged(wpi.packageName, 392 WebViewUpdateService.PACKAGE_ADDED_REPLACED, TestSystemImpl.PRIMARY_USER_ID); 393 394 checkPreparationPhasesForPackage(wpi.packageName, 1); 395 } 396 397 // Test that switching provider using changeProviderAndSetting works. 398 @Test 399 public void testSwitchingProvider() { 400 String firstPackage = "first"; 401 String secondPackage = "second"; 402 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 403 new WebViewProviderInfo(firstPackage, "", true, false, null), 404 new WebViewProviderInfo(secondPackage, "", true, false, null)}; 405 checkSwitchingProvider(packages, firstPackage, secondPackage); 406 } 407 408 @Test 409 public void testSwitchingProviderToNonDefault() { 410 String defaultPackage = "defaultPackage"; 411 String nonDefaultPackage = "nonDefaultPackage"; 412 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 413 new WebViewProviderInfo(defaultPackage, "", true, false, null), 414 new WebViewProviderInfo(nonDefaultPackage, "", false, false, null)}; 415 checkSwitchingProvider(packages, defaultPackage, nonDefaultPackage); 416 } 417 418 private void checkSwitchingProvider(WebViewProviderInfo[] packages, String initialPackage, 419 String finalPackage) { 420 checkCertainPackageUsedAfterWebViewBootPreparation(initialPackage, packages); 421 422 mWebViewUpdateServiceImpl.changeProviderAndSetting(finalPackage); 423 checkPreparationPhasesForPackage(finalPackage, 1 /* first preparation for this package */); 424 425 Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(initialPackage)); 426 } 427 428 // Change provider during relro creation by using changeProviderAndSetting 429 @Test 430 public void testSwitchingProviderDuringRelroCreation() { 431 checkChangingProviderDuringRelroCreation(true); 432 } 433 434 // Change provider during relro creation by enabling a provider 435 @Test 436 public void testChangingProviderThroughEnablingDuringRelroCreation() { 437 checkChangingProviderDuringRelroCreation(false); 438 } 439 440 private void checkChangingProviderDuringRelroCreation(boolean settingsChange) { 441 String firstPackage = "first"; 442 String secondPackage = "second"; 443 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 444 new WebViewProviderInfo(firstPackage, "", true, false, null), 445 new WebViewProviderInfo(secondPackage, "", true, false, null)}; 446 setupWithPackages(packages); 447 // Have all packages be enabled, so that we can change provider however we want to 448 setEnabledAndValidPackageInfos(packages); 449 450 CountDownLatch countdown = new CountDownLatch(1); 451 452 runWebViewBootPreparationOnMainSync(); 453 454 Mockito.verify(mTestSystemImpl).onWebViewProviderChanged( 455 Mockito.argThat(new IsPackageInfoWithName(firstPackage))); 456 457 assertEquals(firstPackage, 458 mWebViewUpdateServiceImpl.getCurrentWebViewPackage().packageName); 459 460 new Thread(new Runnable() { 461 @Override 462 public void run() { 463 WebViewProviderResponse threadResponse = 464 mWebViewUpdateServiceImpl.waitForAndGetProvider(); 465 assertEquals(WebViewFactory.LIBLOAD_SUCCESS, threadResponse.status); 466 assertEquals(secondPackage, threadResponse.packageInfo.packageName); 467 // Verify that we killed the first package if we performed a settings change - 468 // otherwise we had to disable the first package, in which case its dependents 469 // should have been killed by the framework. 470 if (settingsChange) { 471 Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(firstPackage)); 472 } 473 countdown.countDown(); 474 } 475 }).start(); 476 try { 477 Thread.sleep(500); // Let the new thread run / be blocked 478 } catch (InterruptedException e) { 479 } 480 481 if (settingsChange) { 482 mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage); 483 } else { 484 // Enable the second provider 485 mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */, 486 true /* valid */, true /* installed */)); 487 mWebViewUpdateServiceImpl.packageStateChanged( 488 secondPackage, WebViewUpdateService.PACKAGE_CHANGED, TestSystemImpl.PRIMARY_USER_ID); 489 490 // Ensure we haven't changed package yet. 491 assertEquals(firstPackage, 492 mWebViewUpdateServiceImpl.getCurrentWebViewPackage().packageName); 493 494 // Switch provider by disabling the first one 495 mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, false /* enabled */, 496 true /* valid */, true /* installed */)); 497 mWebViewUpdateServiceImpl.packageStateChanged( 498 firstPackage, WebViewUpdateService.PACKAGE_CHANGED, TestSystemImpl.PRIMARY_USER_ID); 499 } 500 mWebViewUpdateServiceImpl.notifyRelroCreationCompleted(); 501 // first package done, should start on second 502 503 Mockito.verify(mTestSystemImpl).onWebViewProviderChanged( 504 Mockito.argThat(new IsPackageInfoWithName(secondPackage))); 505 506 mWebViewUpdateServiceImpl.notifyRelroCreationCompleted(); 507 // second package done, the other thread should now be unblocked 508 try { 509 countdown.await(); 510 } catch (InterruptedException e) { 511 } 512 } 513 514 @Test 515 public void testRunFallbackLogicIfEnabled() { 516 checkFallbackLogicBeingRun(true); 517 } 518 519 @Test 520 public void testDontRunFallbackLogicIfDisabled() { 521 checkFallbackLogicBeingRun(false); 522 } 523 524 private void checkFallbackLogicBeingRun(boolean fallbackLogicEnabled) { 525 String primaryPackage = "primary"; 526 String fallbackPackage = "fallback"; 527 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 528 new WebViewProviderInfo( 529 primaryPackage, "", true /* default available */, false /* fallback */, null), 530 new WebViewProviderInfo( 531 fallbackPackage, "", true /* default available */, true /* fallback */, null)}; 532 setupWithPackages(packages, fallbackLogicEnabled); 533 setEnabledAndValidPackageInfos(packages); 534 535 runWebViewBootPreparationOnMainSync(); 536 // Verify that we disable the fallback package if fallback logic enabled, and don't disable 537 // the fallback package if that logic is disabled 538 if (fallbackLogicEnabled) { 539 Mockito.verify(mTestSystemImpl).uninstallAndDisablePackageForAllUsers( 540 Matchers.anyObject(), Mockito.eq(fallbackPackage)); 541 } else { 542 Mockito.verify(mTestSystemImpl, Mockito.never()).uninstallAndDisablePackageForAllUsers( 543 Matchers.anyObject(), Matchers.anyObject()); 544 } 545 Mockito.verify(mTestSystemImpl).onWebViewProviderChanged( 546 Mockito.argThat(new IsPackageInfoWithName(primaryPackage))); 547 548 // Enable fallback package 549 mTestSystemImpl.setPackageInfo(createPackageInfo(fallbackPackage, true /* enabled */, 550 true /* valid */, true /* installed */)); 551 mWebViewUpdateServiceImpl.packageStateChanged( 552 fallbackPackage, WebViewUpdateService.PACKAGE_CHANGED, TestSystemImpl.PRIMARY_USER_ID); 553 554 if (fallbackLogicEnabled) { 555 // Check that we have now disabled the fallback package twice 556 Mockito.verify(mTestSystemImpl, Mockito.times(2)).uninstallAndDisablePackageForAllUsers( 557 Matchers.anyObject(), Mockito.eq(fallbackPackage)); 558 } else { 559 // Check that we still haven't disabled any package 560 Mockito.verify(mTestSystemImpl, Mockito.never()).uninstallAndDisablePackageForAllUsers( 561 Matchers.anyObject(), Matchers.anyObject()); 562 } 563 } 564 565 /** 566 * Scenario for installing primary package when fallback enabled. 567 * 1. Start with only fallback installed 568 * 2. Install non-fallback 569 * 3. Fallback should be disabled 570 */ 571 @Test 572 public void testInstallingNonFallbackPackage() { 573 String primaryPackage = "primary"; 574 String fallbackPackage = "fallback"; 575 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 576 new WebViewProviderInfo( 577 primaryPackage, "", true /* default available */, false /* fallback */, null), 578 new WebViewProviderInfo( 579 fallbackPackage, "", true /* default available */, true /* fallback */, null)}; 580 setupWithPackages(packages, true /* isFallbackLogicEnabled */); 581 mTestSystemImpl.setPackageInfo( 582 createPackageInfo(fallbackPackage, true /* enabled */ , true /* valid */, 583 true /* installed */)); 584 585 runWebViewBootPreparationOnMainSync(); 586 Mockito.verify(mTestSystemImpl, Mockito.never()).uninstallAndDisablePackageForAllUsers( 587 Matchers.anyObject(), Matchers.anyObject()); 588 589 checkPreparationPhasesForPackage(fallbackPackage, 590 1 /* first preparation for this package*/); 591 592 // Install primary package 593 mTestSystemImpl.setPackageInfo( 594 createPackageInfo(primaryPackage, true /* enabled */ , true /* valid */, 595 true /* installed */)); 596 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, 597 WebViewUpdateService.PACKAGE_ADDED_REPLACED, TestSystemImpl.PRIMARY_USER_ID); 598 599 // Verify fallback disabled, primary package used as provider, and fallback package killed 600 Mockito.verify(mTestSystemImpl).uninstallAndDisablePackageForAllUsers( 601 Matchers.anyObject(), Mockito.eq(fallbackPackage)); 602 checkPreparationPhasesForPackage(primaryPackage, 1 /* first preparation for this package*/); 603 Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(fallbackPackage)); 604 } 605 606 @Test 607 public void testFallbackChangesEnabledStateSingleUser() { 608 for (PackageRemovalType removalType : REMOVAL_TYPES) { 609 checkFallbackChangesEnabledState(false /* multiUser */, removalType); 610 } 611 } 612 613 @Test 614 public void testFallbackChangesEnabledStateMultiUser() { 615 for (PackageRemovalType removalType : REMOVAL_TYPES) { 616 checkFallbackChangesEnabledState(true /* multiUser */, removalType); 617 } 618 } 619 620 /** 621 * Represents how to remove a package during a tests (disabling it / uninstalling it / hiding 622 * it). 623 */ 624 private enum PackageRemovalType { 625 UNINSTALL, DISABLE, HIDE 626 } 627 628 private PackageRemovalType[] REMOVAL_TYPES = PackageRemovalType.class.getEnumConstants(); 629 630 public void checkFallbackChangesEnabledState(boolean multiUser, 631 PackageRemovalType removalType) { 632 String primaryPackage = "primary"; 633 String fallbackPackage = "fallback"; 634 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 635 new WebViewProviderInfo( 636 primaryPackage, "", true /* default available */, false /* fallback */, null), 637 new WebViewProviderInfo( 638 fallbackPackage, "", true /* default available */, true /* fallback */, null)}; 639 setupWithPackages(packages, true /* fallbackLogicEnabled */); 640 int secondaryUserId = 10; 641 int userIdToChangePackageFor = multiUser ? secondaryUserId : TestSystemImpl.PRIMARY_USER_ID; 642 if (multiUser) { 643 mTestSystemImpl.addUser(secondaryUserId); 644 setEnabledAndValidPackageInfosForUser(secondaryUserId, packages); 645 } 646 setEnabledAndValidPackageInfosForUser(TestSystemImpl.PRIMARY_USER_ID, packages); 647 648 runWebViewBootPreparationOnMainSync(); 649 650 // Verify fallback disabled at boot when primary package enabled 651 checkEnablePackageForUserCalled(fallbackPackage, false, multiUser 652 ? new int[] {TestSystemImpl.PRIMARY_USER_ID, secondaryUserId} 653 : new int[] {TestSystemImpl.PRIMARY_USER_ID}, 1 /* numUsages */); 654 655 checkPreparationPhasesForPackage(primaryPackage, 1); 656 657 boolean enabled = !(removalType == PackageRemovalType.DISABLE); 658 boolean installed = !(removalType == PackageRemovalType.UNINSTALL); 659 boolean hidden = (removalType == PackageRemovalType.HIDE); 660 // Disable primary package and ensure fallback becomes enabled and used 661 mTestSystemImpl.setPackageInfoForUser(userIdToChangePackageFor, 662 createPackageInfo(primaryPackage, enabled /* enabled */, true /* valid */, 663 installed /* installed */, null /* signature */, 0 /* updateTime */, 664 hidden /* hidden */)); 665 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, 666 removalType == PackageRemovalType.DISABLE 667 ? WebViewUpdateService.PACKAGE_CHANGED : WebViewUpdateService.PACKAGE_REMOVED, 668 userIdToChangePackageFor); // USER ID 669 670 checkEnablePackageForUserCalled(fallbackPackage, true, multiUser 671 ? new int[] {TestSystemImpl.PRIMARY_USER_ID, secondaryUserId} 672 : new int[] {TestSystemImpl.PRIMARY_USER_ID}, 1 /* numUsages */); 673 674 checkPreparationPhasesForPackage(fallbackPackage, 1); 675 676 677 // Again enable primary package and verify primary is used and fallback becomes disabled 678 mTestSystemImpl.setPackageInfoForUser(userIdToChangePackageFor, 679 createPackageInfo(primaryPackage, true /* enabled */, true /* valid */, 680 true /* installed */)); 681 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, 682 removalType == PackageRemovalType.DISABLE 683 ? WebViewUpdateService.PACKAGE_CHANGED : WebViewUpdateService.PACKAGE_ADDED, 684 userIdToChangePackageFor); 685 686 // Verify fallback is disabled a second time when primary package becomes enabled 687 checkEnablePackageForUserCalled(fallbackPackage, false, multiUser 688 ? new int[] {TestSystemImpl.PRIMARY_USER_ID, secondaryUserId} 689 : new int[] {TestSystemImpl.PRIMARY_USER_ID}, 2 /* numUsages */); 690 691 checkPreparationPhasesForPackage(primaryPackage, 2); 692 } 693 694 private void checkEnablePackageForUserCalled(String packageName, boolean expectEnabled, 695 int[] userIds, int numUsages) { 696 for (int userId : userIds) { 697 Mockito.verify(mTestSystemImpl, Mockito.times(numUsages)).enablePackageForUser( 698 Mockito.eq(packageName), Mockito.eq(expectEnabled), Mockito.eq(userId)); 699 } 700 } 701 702 @Test 703 public void testAddUserWhenFallbackLogicEnabled() { 704 checkAddingNewUser(true); 705 } 706 707 @Test 708 public void testAddUserWhenFallbackLogicDisabled() { 709 checkAddingNewUser(false); 710 } 711 712 public void checkAddingNewUser(boolean fallbackLogicEnabled) { 713 String primaryPackage = "primary"; 714 String fallbackPackage = "fallback"; 715 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 716 new WebViewProviderInfo( 717 primaryPackage, "", true /* default available */, false /* fallback */, null), 718 new WebViewProviderInfo( 719 fallbackPackage, "", true /* default available */, true /* fallback */, null)}; 720 setupWithPackages(packages, fallbackLogicEnabled); 721 setEnabledAndValidPackageInfosForUser(TestSystemImpl.PRIMARY_USER_ID, packages); 722 int newUser = 100; 723 mTestSystemImpl.addUser(newUser); 724 setEnabledAndValidPackageInfosForUser(newUser, packages); 725 mWebViewUpdateServiceImpl.handleNewUser(newUser); 726 if (fallbackLogicEnabled) { 727 // Verify fallback package becomes disabled for new user 728 Mockito.verify(mTestSystemImpl).enablePackageForUser( 729 Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */, 730 Mockito.eq(newUser)); 731 } else { 732 // Verify that we don't disable fallback for new user 733 Mockito.verify(mTestSystemImpl, Mockito.never()).enablePackageForUser( 734 Mockito.anyObject(), Matchers.anyBoolean() /* enable */, 735 Matchers.anyInt() /* user */); 736 } 737 } 738 739 /** 740 * Ensures that adding a new user for which the current WebView package is uninstalled causes a 741 * change of WebView provider. 742 */ 743 @Test 744 public void testAddingNewUserWithUninstalledPackage() { 745 String primaryPackage = "primary"; 746 String fallbackPackage = "fallback"; 747 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 748 new WebViewProviderInfo( 749 primaryPackage, "", true /* default available */, false /* fallback */, null), 750 new WebViewProviderInfo( 751 fallbackPackage, "", true /* default available */, true /* fallback */, null)}; 752 setupWithPackages(packages, true /* fallbackLogicEnabled */); 753 setEnabledAndValidPackageInfosForUser(TestSystemImpl.PRIMARY_USER_ID, packages); 754 int newUser = 100; 755 mTestSystemImpl.addUser(newUser); 756 // Let the primary package be uninstalled for the new user 757 mTestSystemImpl.setPackageInfoForUser(newUser, 758 createPackageInfo(primaryPackage, true /* enabled */, true /* valid */, 759 false /* installed */)); 760 mTestSystemImpl.setPackageInfoForUser(newUser, 761 createPackageInfo(fallbackPackage, false /* enabled */, true /* valid */, 762 true /* installed */)); 763 mWebViewUpdateServiceImpl.handleNewUser(newUser); 764 // Verify fallback package doesn't become disabled for the primary user. 765 Mockito.verify(mTestSystemImpl, Mockito.never()).enablePackageForUser( 766 Mockito.anyObject(), Mockito.eq(false) /* enable */, 767 Mockito.eq(TestSystemImpl.PRIMARY_USER_ID) /* user */); 768 // Verify that we enable the fallback package for the secondary user. 769 Mockito.verify(mTestSystemImpl, Mockito.times(1)).enablePackageForUser( 770 Mockito.eq(fallbackPackage), Mockito.eq(true) /* enable */, 771 Mockito.eq(newUser) /* user */); 772 checkPreparationPhasesForPackage(fallbackPackage, 1 /* numRelros */); 773 } 774 775 /** 776 * Timing dependent test where we verify that the list of valid webview packages becoming empty 777 * at a certain point doesn't crash us or break our state. 778 */ 779 @Test 780 public void testNotifyRelroDoesntCrashIfNoPackages() { 781 String firstPackage = "first"; 782 String secondPackage = "second"; 783 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 784 new WebViewProviderInfo(firstPackage, "", true /* default available */, 785 false /* fallback */, null), 786 new WebViewProviderInfo(secondPackage, "", true /* default available */, 787 false /* fallback */, null)}; 788 setupWithPackages(packages); 789 // Add (enabled and valid) package infos for each provider 790 setEnabledAndValidPackageInfos(packages); 791 792 runWebViewBootPreparationOnMainSync(); 793 794 Mockito.verify(mTestSystemImpl).onWebViewProviderChanged( 795 Mockito.argThat(new IsPackageInfoWithName(firstPackage))); 796 797 // Change provider during relro creation to enter a state where we are 798 // waiting for relro creation to complete just to re-run relro creation. 799 // (so that in next notifyRelroCreationCompleted() call we have to list webview packages) 800 mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage); 801 802 // Make packages invalid to cause exception to be thrown 803 mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, true /* enabled */, 804 false /* valid */, true /* installed */, null /* signatures */, 805 0 /* updateTime */)); 806 mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */, 807 false /* valid */, true /* installed */)); 808 809 // This shouldn't throw an exception! 810 mWebViewUpdateServiceImpl.notifyRelroCreationCompleted(); 811 812 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); 813 assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status); 814 815 // Now make a package valid again and verify that we can switch back to that 816 mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, true /* enabled */, 817 true /* valid */, true /* installed */, null /* signatures */, 818 1 /* updateTime */ )); 819 820 mWebViewUpdateServiceImpl.packageStateChanged(firstPackage, 821 WebViewUpdateService.PACKAGE_ADDED_REPLACED, TestSystemImpl.PRIMARY_USER_ID); 822 823 // Ensure we use firstPackage 824 checkPreparationPhasesForPackage(firstPackage, 2 /* second preparation for this package */); 825 } 826 827 /** 828 * Verify that even if a user-chosen package is removed temporarily we start using it again when 829 * it is added back. 830 */ 831 @Test 832 public void testTempRemovePackageDoesntSwitchProviderPermanently() { 833 String firstPackage = "first"; 834 String secondPackage = "second"; 835 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 836 new WebViewProviderInfo(firstPackage, "", true /* default available */, 837 false /* fallback */, null), 838 new WebViewProviderInfo(secondPackage, "", true /* default available */, 839 false /* fallback */, null)}; 840 checkCertainPackageUsedAfterWebViewBootPreparation(firstPackage, packages); 841 842 // Explicitly use the second package 843 mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage); 844 checkPreparationPhasesForPackage(secondPackage, 1 /* first time for this package */); 845 846 // Remove second package (invalidate it) and verify that first package is used 847 mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */, 848 false /* valid */, true /* installed */)); 849 mWebViewUpdateServiceImpl.packageStateChanged(secondPackage, 850 WebViewUpdateService.PACKAGE_ADDED, TestSystemImpl.PRIMARY_USER_ID); 851 checkPreparationPhasesForPackage(firstPackage, 2 /* second time for this package */); 852 853 // Now make the second package valid again and verify that it is used again 854 mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */, 855 true /* valid */, true /* installed */)); 856 mWebViewUpdateServiceImpl.packageStateChanged(secondPackage, 857 WebViewUpdateService.PACKAGE_ADDED, TestSystemImpl.PRIMARY_USER_ID); 858 checkPreparationPhasesForPackage(secondPackage, 2 /* second time for this package */); 859 } 860 861 /** 862 * Ensure that we update the user-chosen setting across boots if the chosen package is no 863 * longer installed and valid. 864 */ 865 @Test 866 public void testProviderSettingChangedDuringBootIfProviderNotAvailable() { 867 String chosenPackage = "chosenPackage"; 868 String nonChosenPackage = "non-chosenPackage"; 869 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 870 new WebViewProviderInfo(chosenPackage, "", true /* default available */, 871 false /* fallback */, null), 872 new WebViewProviderInfo(nonChosenPackage, "", true /* default available */, 873 false /* fallback */, null)}; 874 875 setupWithPackages(packages); 876 // Only 'install' nonChosenPackage 877 mTestSystemImpl.setPackageInfo( 878 createPackageInfo(nonChosenPackage, true /* enabled */, true /* valid */, true /* installed */)); 879 880 // Set user-chosen package 881 mTestSystemImpl.updateUserSetting(null, chosenPackage); 882 883 runWebViewBootPreparationOnMainSync(); 884 885 // Verify that we switch the setting to point to the current package 886 Mockito.verify(mTestSystemImpl).updateUserSetting( 887 Mockito.anyObject(), Mockito.eq(nonChosenPackage)); 888 assertEquals(nonChosenPackage, mTestSystemImpl.getUserChosenWebViewProvider(null)); 889 890 checkPreparationPhasesForPackage(nonChosenPackage, 1); 891 } 892 893 @Test 894 public void testRecoverFailedListingWebViewPackagesSettingsChange() { 895 checkRecoverAfterFailListingWebviewPackages(true); 896 } 897 898 @Test 899 public void testRecoverFailedListingWebViewPackagesAddedPackage() { 900 checkRecoverAfterFailListingWebviewPackages(false); 901 } 902 903 /** 904 * Test that we can recover correctly from failing to list WebView packages. 905 * settingsChange: whether to fail during changeProviderAndSetting or packageStateChanged 906 */ 907 public void checkRecoverAfterFailListingWebviewPackages(boolean settingsChange) { 908 String firstPackage = "first"; 909 String secondPackage = "second"; 910 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 911 new WebViewProviderInfo(firstPackage, "", true /* default available */, 912 false /* fallback */, null), 913 new WebViewProviderInfo(secondPackage, "", true /* default available */, 914 false /* fallback */, null)}; 915 checkCertainPackageUsedAfterWebViewBootPreparation(firstPackage, packages); 916 917 // Make both packages invalid so that we fail listing WebView packages 918 mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, true /* enabled */, 919 false /* valid */, true /* installed */)); 920 mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */, 921 false /* valid */, true /* installed */)); 922 923 // Change package to hit the webview packages listing problem. 924 if (settingsChange) { 925 mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage); 926 } else { 927 mWebViewUpdateServiceImpl.packageStateChanged(secondPackage, 928 WebViewUpdateService.PACKAGE_ADDED_REPLACED, TestSystemImpl.PRIMARY_USER_ID); 929 } 930 931 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); 932 assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status); 933 934 // Make second package valid and verify that we can load it again 935 mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */, 936 true /* valid */, true /* installed */)); 937 938 mWebViewUpdateServiceImpl.packageStateChanged(secondPackage, 939 WebViewUpdateService.PACKAGE_ADDED_REPLACED, TestSystemImpl.PRIMARY_USER_ID); 940 941 942 checkPreparationPhasesForPackage(secondPackage, 1); 943 } 944 945 @Test 946 public void testDontKillIfPackageReplaced() { 947 checkDontKillIfPackageRemoved(true); 948 } 949 950 @Test 951 public void testDontKillIfPackageRemoved() { 952 checkDontKillIfPackageRemoved(false); 953 } 954 955 public void checkDontKillIfPackageRemoved(boolean replaced) { 956 String firstPackage = "first"; 957 String secondPackage = "second"; 958 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 959 new WebViewProviderInfo(firstPackage, "", true /* default available */, 960 false /* fallback */, null), 961 new WebViewProviderInfo(secondPackage, "", true /* default available */, 962 false /* fallback */, null)}; 963 checkCertainPackageUsedAfterWebViewBootPreparation(firstPackage, packages); 964 965 // Replace or remove the current webview package 966 if (replaced) { 967 mTestSystemImpl.setPackageInfo( 968 createPackageInfo(firstPackage, true /* enabled */, false /* valid */, 969 true /* installed */)); 970 mWebViewUpdateServiceImpl.packageStateChanged(firstPackage, 971 WebViewUpdateService.PACKAGE_ADDED_REPLACED, TestSystemImpl.PRIMARY_USER_ID); 972 } else { 973 mTestSystemImpl.removePackageInfo(firstPackage); 974 mWebViewUpdateServiceImpl.packageStateChanged(firstPackage, 975 WebViewUpdateService.PACKAGE_REMOVED, TestSystemImpl.PRIMARY_USER_ID); 976 } 977 978 checkPreparationPhasesForPackage(secondPackage, 1); 979 980 Mockito.verify(mTestSystemImpl, Mockito.never()).killPackageDependents( 981 Mockito.anyObject()); 982 } 983 984 @Test 985 public void testKillIfSettingChanged() { 986 String firstPackage = "first"; 987 String secondPackage = "second"; 988 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 989 new WebViewProviderInfo(firstPackage, "", true /* default available */, 990 false /* fallback */, null), 991 new WebViewProviderInfo(secondPackage, "", true /* default available */, 992 false /* fallback */, null)}; 993 checkCertainPackageUsedAfterWebViewBootPreparation(firstPackage, packages); 994 995 mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage); 996 997 checkPreparationPhasesForPackage(secondPackage, 1); 998 999 Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(firstPackage)); 1000 } 1001 1002 /** 1003 * Test that we kill apps using an old provider when we change the provider setting, even if the 1004 * new provider is not the one we intended to change to. 1005 */ 1006 @Test 1007 public void testKillIfChangeProviderIncorrectly() { 1008 String firstPackage = "first"; 1009 String secondPackage = "second"; 1010 String thirdPackage = "third"; 1011 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 1012 new WebViewProviderInfo(firstPackage, "", true /* default available */, 1013 false /* fallback */, null), 1014 new WebViewProviderInfo(secondPackage, "", true /* default available */, 1015 false /* fallback */, null), 1016 new WebViewProviderInfo(thirdPackage, "", true /* default available */, 1017 false /* fallback */, null)}; 1018 setupWithPackages(packages); 1019 setEnabledAndValidPackageInfos(packages); 1020 1021 // Start with the setting pointing to the third package 1022 mTestSystemImpl.updateUserSetting(null, thirdPackage); 1023 1024 runWebViewBootPreparationOnMainSync(); 1025 checkPreparationPhasesForPackage(thirdPackage, 1); 1026 1027 mTestSystemImpl.setPackageInfo( 1028 createPackageInfo(secondPackage, true /* enabled */, false /* valid */, true /* installed */)); 1029 1030 // Try to switch to the invalid second package, this should result in switching to the first 1031 // package, since that is more preferred than the third one. 1032 assertEquals(firstPackage, 1033 mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage)); 1034 1035 checkPreparationPhasesForPackage(firstPackage, 1); 1036 1037 Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(thirdPackage)); 1038 } 1039 1040 @Test 1041 public void testLowerPackageVersionNotValid() { 1042 checkPackageVersions(new int[]{200000} /* system version */, 100000/* candidate version */, 1043 false /* expected validity */); 1044 } 1045 1046 @Test 1047 public void testEqualPackageVersionValid() { 1048 checkPackageVersions(new int[]{100000} /* system version */, 100000 /* candidate version */, 1049 true /* expected validity */); 1050 } 1051 1052 @Test 1053 public void testGreaterPackageVersionValid() { 1054 checkPackageVersions(new int[]{100000} /* system versions */, 200000 /* candidate version */, 1055 true /* expected validity */); 1056 } 1057 1058 @Test 1059 public void testLastFiveDigitsIgnored() { 1060 checkPackageVersions(new int[]{654321} /* system version */, 612345 /* candidate version */, 1061 true /* expected validity */); 1062 } 1063 1064 @Test 1065 public void testMinimumSystemVersionUsedTwoDefaultsCandidateValid() { 1066 checkPackageVersions(new int[]{300000, 100000} /* system versions */, 1067 200000 /* candidate version */, true /* expected validity */); 1068 } 1069 1070 @Test 1071 public void testMinimumSystemVersionUsedTwoDefaultsCandidateInvalid() { 1072 checkPackageVersions(new int[]{300000, 200000} /* system versions */, 1073 100000 /* candidate version */, false /* expected validity */); 1074 } 1075 1076 @Test 1077 public void testMinimumSystemVersionUsedSeveralDefaultsCandidateValid() { 1078 checkPackageVersions(new int[]{100000, 200000, 300000, 400000, 500000} /* system versions */, 1079 100000 /* candidate version */, true /* expected validity */); 1080 } 1081 1082 @Test 1083 public void testMinimumSystemVersionUsedSeveralDefaultsCandidateInvalid() { 1084 checkPackageVersions(new int[]{200000, 300000, 400000, 500000, 600000} /* system versions */, 1085 100000 /* candidate version */, false /* expected validity */); 1086 } 1087 1088 @Test 1089 public void testMinimumSystemVersionUsedFallbackIgnored() { 1090 checkPackageVersions(new int[]{300000, 400000, 500000, 600000, 700000} /* system versions */, 1091 200000 /* candidate version */, false /* expected validity */, true /* add fallback */, 1092 100000 /* fallback version */, false /* expected validity of fallback */); 1093 } 1094 1095 @Test 1096 public void testFallbackValid() { 1097 checkPackageVersions(new int[]{300000, 400000, 500000, 600000, 700000} /* system versions */, 1098 200000/* candidate version */, false /* expected validity */, true /* add fallback */, 1099 300000 /* fallback version */, true /* expected validity of fallback */); 1100 } 1101 1102 private void checkPackageVersions(int[] systemVersions, int candidateVersion, 1103 boolean candidateShouldBeValid) { 1104 checkPackageVersions(systemVersions, candidateVersion, candidateShouldBeValid, 1105 false, 0, false); 1106 } 1107 1108 /** 1109 * Utility method for checking that package version restriction works as it should. 1110 * I.e. that a package with lower version than the system-default is not valid and that a 1111 * package with greater than or equal version code is considered valid. 1112 */ 1113 private void checkPackageVersions(int[] systemVersions, int candidateVersion, 1114 boolean candidateShouldBeValid, boolean addFallback, int fallbackVersion, 1115 boolean fallbackShouldBeValid) { 1116 int numSystemPackages = systemVersions.length; 1117 int numFallbackPackages = (addFallback ? 1 : 0); 1118 int numPackages = systemVersions.length + 1 + numFallbackPackages; 1119 String candidatePackage = "candidatePackage"; 1120 String systemPackage = "systemPackage"; 1121 String fallbackPackage = "fallbackPackage"; 1122 1123 // Each package needs a valid signature since we set isDebuggable to false 1124 Signature signature = new Signature("11"); 1125 String encodedSignatureString = 1126 Base64.encodeToString(signature.toByteArray(), Base64.DEFAULT); 1127 1128 // Set up config 1129 // 1. candidatePackage 1130 // 2-N. default available non-fallback packages 1131 // N+1. default available fallback package 1132 WebViewProviderInfo[] packages = new WebViewProviderInfo[numPackages]; 1133 packages[0] = new WebViewProviderInfo(candidatePackage, "", 1134 false /* available by default */, false /* fallback */, 1135 new String[]{encodedSignatureString}); 1136 for(int n = 1; n < numSystemPackages + 1; n++) { 1137 packages[n] = new WebViewProviderInfo(systemPackage + n, "", 1138 true /* available by default */, false /* fallback */, 1139 new String[]{encodedSignatureString}); 1140 } 1141 if (addFallback) { 1142 packages[packages.length-1] = new WebViewProviderInfo(fallbackPackage, "", 1143 true /* available by default */, true /* fallback */, 1144 new String[]{encodedSignatureString}); 1145 } 1146 1147 setupWithPackages(packages, true /* fallback logic enabled */, 1 /* numRelros */, 1148 false /* isDebuggable */); 1149 1150 // Set package infos 1151 mTestSystemImpl.setPackageInfo( 1152 createPackageInfo(candidatePackage, true /* enabled */, true /* valid */, 1153 true /* installed */, new Signature[]{signature}, 0 /* updateTime */, 1154 false /* hidden */, candidateVersion, false /* isSystemApp */)); 1155 for(int n = 1; n < numSystemPackages + 1; n++) { 1156 mTestSystemImpl.setPackageInfo( 1157 createPackageInfo(systemPackage + n, true /* enabled */, true /* valid */, 1158 true /* installed */, new Signature[]{signature}, 0 /* updateTime */, 1159 false /* hidden */, systemVersions[n-1], true /* isSystemApp */)); 1160 } 1161 if (addFallback) { 1162 mTestSystemImpl.setPackageInfo( 1163 createPackageInfo(fallbackPackage, true /* enabled */, true /* valid */, 1164 true /* installed */, new Signature[]{signature}, 0 /* updateTime */, 1165 false /* hidden */, fallbackVersion, true /* isSystemApp */)); 1166 } 1167 1168 WebViewProviderInfo[] validPackages = mWebViewUpdateServiceImpl.getValidWebViewPackages(); 1169 int expectedNumValidPackages = numSystemPackages; 1170 if (candidateShouldBeValid) { 1171 expectedNumValidPackages++; 1172 } else { 1173 // Ensure the candidate package is not one of the valid packages 1174 for(int n = 0; n < validPackages.length; n++) { 1175 assertFalse(candidatePackage.equals(validPackages[n].packageName)); 1176 } 1177 } 1178 1179 if (fallbackShouldBeValid) { 1180 expectedNumValidPackages += numFallbackPackages; 1181 } else { 1182 // Ensure the fallback package is not one of the valid packages 1183 for(int n = 0; n < validPackages.length; n++) { 1184 assertFalse(fallbackPackage.equals(validPackages[n].packageName)); 1185 } 1186 } 1187 1188 assertEquals(expectedNumValidPackages, validPackages.length); 1189 1190 runWebViewBootPreparationOnMainSync(); 1191 1192 // The non-system package is not available by default so it shouldn't be used here 1193 checkPreparationPhasesForPackage(systemPackage + "1", 1); 1194 1195 // Try explicitly switching to the candidate package 1196 String packageChange = mWebViewUpdateServiceImpl.changeProviderAndSetting(candidatePackage); 1197 if (candidateShouldBeValid) { 1198 assertEquals(candidatePackage, packageChange); 1199 checkPreparationPhasesForPackage(candidatePackage, 1); 1200 } else { 1201 assertEquals(systemPackage + "1", packageChange); 1202 // We didn't change package so the webview preparation won't run here 1203 } 1204 } 1205 1206 /** 1207 * Ensure that the update service does use an uninstalled package when that is the only 1208 * package available. 1209 */ 1210 @Test 1211 public void testWithSingleUninstalledPackage() { 1212 String testPackageName = "test.package.name"; 1213 WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] { 1214 new WebViewProviderInfo(testPackageName, "", 1215 true /*default available*/, false /* fallback */, null)}; 1216 setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */); 1217 mTestSystemImpl.setPackageInfo(createPackageInfo(testPackageName, true /* enabled */, 1218 true /* valid */, false /* installed */)); 1219 1220 runWebViewBootPreparationOnMainSync(); 1221 1222 Mockito.verify(mTestSystemImpl, Mockito.never()).onWebViewProviderChanged( 1223 Matchers.anyObject()); 1224 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); 1225 assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status); 1226 assertEquals(null, mWebViewUpdateServiceImpl.getCurrentWebViewPackage()); 1227 } 1228 1229 @Test 1230 public void testNonhiddenPackageUserOverHidden() { 1231 checkVisiblePackageUserOverNonVisible(false /* multiUser*/, PackageRemovalType.HIDE); 1232 checkVisiblePackageUserOverNonVisible(true /* multiUser*/, PackageRemovalType.HIDE); 1233 } 1234 1235 @Test 1236 public void testInstalledPackageUsedOverUninstalled() { 1237 checkVisiblePackageUserOverNonVisible(false /* multiUser*/, PackageRemovalType.UNINSTALL); 1238 checkVisiblePackageUserOverNonVisible(true /* multiUser*/, PackageRemovalType.UNINSTALL); 1239 } 1240 1241 private void checkVisiblePackageUserOverNonVisible(boolean multiUser, 1242 PackageRemovalType removalType) { 1243 assert removalType != PackageRemovalType.DISABLE; 1244 boolean testUninstalled = removalType == PackageRemovalType.UNINSTALL; 1245 boolean testHidden = removalType == PackageRemovalType.HIDE; 1246 String installedPackage = "installedPackage"; 1247 String uninstalledPackage = "uninstalledPackage"; 1248 WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] { 1249 new WebViewProviderInfo(uninstalledPackage, "", true /* available by default */, 1250 false /* fallback */, null), 1251 new WebViewProviderInfo(installedPackage, "", true /* available by default */, 1252 false /* fallback */, null)}; 1253 1254 setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */); 1255 int secondaryUserId = 5; 1256 if (multiUser) { 1257 mTestSystemImpl.addUser(secondaryUserId); 1258 // Install all packages for the primary user. 1259 setEnabledAndValidPackageInfosForUser(TestSystemImpl.PRIMARY_USER_ID, webviewPackages); 1260 mTestSystemImpl.setPackageInfoForUser(secondaryUserId, createPackageInfo( 1261 installedPackage, true /* enabled */, true /* valid */, true /* installed */)); 1262 // Hide or uninstall the primary package for the second user 1263 mTestSystemImpl.setPackageInfo(createPackageInfo(uninstalledPackage, true /* enabled */, 1264 true /* valid */, (testUninstalled ? false : true) /* installed */, 1265 null /* signatures */, 0 /* updateTime */, (testHidden ? true : false))); 1266 } else { 1267 mTestSystemImpl.setPackageInfo(createPackageInfo(installedPackage, true /* enabled */, 1268 true /* valid */, true /* installed */)); 1269 // Hide or uninstall the primary package 1270 mTestSystemImpl.setPackageInfo(createPackageInfo(uninstalledPackage, true /* enabled */, 1271 true /* valid */, (testUninstalled ? false : true) /* installed */, 1272 null /* signatures */, 0 /* updateTime */, (testHidden ? true : false))); 1273 } 1274 1275 runWebViewBootPreparationOnMainSync(); 1276 1277 checkPreparationPhasesForPackage(installedPackage, 1 /* first preparation phase */); 1278 } 1279 1280 @Test 1281 public void testCantSwitchToHiddenPackage () { 1282 checkCantSwitchToNonVisiblePackage(false /* true == uninstalled, false == hidden */); 1283 } 1284 1285 1286 @Test 1287 public void testCantSwitchToUninstalledPackage () { 1288 checkCantSwitchToNonVisiblePackage(true /* true == uninstalled, false == hidden */); 1289 } 1290 1291 /** 1292 * Ensure that we won't prioritize an uninstalled (or hidden) package even if it is user-chosen. 1293 */ 1294 private void checkCantSwitchToNonVisiblePackage(boolean uninstalledNotHidden) { 1295 boolean testUninstalled = uninstalledNotHidden; 1296 boolean testHidden = !uninstalledNotHidden; 1297 String installedPackage = "installedPackage"; 1298 String uninstalledPackage = "uninstalledPackage"; 1299 WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] { 1300 new WebViewProviderInfo(uninstalledPackage, "", true /* available by default */, 1301 false /* fallback */, null), 1302 new WebViewProviderInfo(installedPackage, "", true /* available by default */, 1303 false /* fallback */, null)}; 1304 1305 setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */); 1306 int secondaryUserId = 412; 1307 mTestSystemImpl.addUser(secondaryUserId); 1308 1309 // Let all packages be installed and enabled for the primary user. 1310 setEnabledAndValidPackageInfosForUser(TestSystemImpl.PRIMARY_USER_ID, webviewPackages); 1311 // Only uninstall the 'uninstalled package' for the secondary user. 1312 mTestSystemImpl.setPackageInfoForUser(secondaryUserId, createPackageInfo(installedPackage, 1313 true /* enabled */, true /* valid */, true /* installed */)); 1314 mTestSystemImpl.setPackageInfoForUser(secondaryUserId, createPackageInfo(uninstalledPackage, 1315 true /* enabled */, true /* valid */, !testUninstalled /* installed */, 1316 null /* signatures */, 0 /* updateTime */, testHidden /* hidden */)); 1317 1318 runWebViewBootPreparationOnMainSync(); 1319 1320 checkPreparationPhasesForPackage(installedPackage, 1 /* first preparation phase */); 1321 1322 // ensure that we don't switch to the uninstalled package (it will be used if it becomes 1323 // installed later) 1324 assertEquals(installedPackage, 1325 mWebViewUpdateServiceImpl.changeProviderAndSetting(uninstalledPackage)); 1326 1327 // Ensure both packages are considered valid. 1328 assertEquals(2, mWebViewUpdateServiceImpl.getValidWebViewPackages().length); 1329 1330 1331 // We should only have called onWebViewProviderChanged once (before calling 1332 // changeProviderAndSetting 1333 Mockito.verify(mTestSystemImpl, Mockito.times(1)).onWebViewProviderChanged( 1334 Mockito.argThat(new IsPackageInfoWithName(installedPackage))); 1335 } 1336 1337 @Test 1338 public void testHiddenPackageNotPrioritizedEvenIfChosen() { 1339 checkNonvisiblePackageNotPrioritizedEvenIfChosen( 1340 false /* true == uninstalled, false == hidden */); 1341 } 1342 1343 @Test 1344 public void testUninstalledPackageNotPrioritizedEvenIfChosen() { 1345 checkNonvisiblePackageNotPrioritizedEvenIfChosen( 1346 true /* true == uninstalled, false == hidden */); 1347 } 1348 1349 public void checkNonvisiblePackageNotPrioritizedEvenIfChosen(boolean uninstalledNotHidden) { 1350 boolean testUninstalled = uninstalledNotHidden; 1351 boolean testHidden = !uninstalledNotHidden; 1352 String installedPackage = "installedPackage"; 1353 String uninstalledPackage = "uninstalledPackage"; 1354 WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] { 1355 new WebViewProviderInfo(uninstalledPackage, "", true /* available by default */, 1356 false /* fallback */, null), 1357 new WebViewProviderInfo(installedPackage, "", true /* available by default */, 1358 false /* fallback */, null)}; 1359 1360 setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */); 1361 int secondaryUserId = 4; 1362 mTestSystemImpl.addUser(secondaryUserId); 1363 1364 setEnabledAndValidPackageInfosForUser(TestSystemImpl.PRIMARY_USER_ID, webviewPackages); 1365 mTestSystemImpl.setPackageInfoForUser(secondaryUserId, createPackageInfo(installedPackage, 1366 true /* enabled */, true /* valid */, true /* installed */)); 1367 mTestSystemImpl.setPackageInfoForUser(secondaryUserId, createPackageInfo(uninstalledPackage, 1368 true /* enabled */, true /* valid */, 1369 (testUninstalled ? false : true) /* installed */, null /* signatures */, 1370 0 /* updateTime */, (testHidden ? true : false) /* hidden */)); 1371 1372 // Start with the setting pointing to the uninstalled package 1373 mTestSystemImpl.updateUserSetting(null, uninstalledPackage); 1374 1375 runWebViewBootPreparationOnMainSync(); 1376 1377 checkPreparationPhasesForPackage(installedPackage, 1 /* first preparation phase */); 1378 } 1379 1380 @Test 1381 public void testFallbackEnabledIfPrimaryUninstalledSingleUser() { 1382 checkFallbackEnabledIfPrimaryUninstalled(false /* multiUser */); 1383 } 1384 1385 @Test 1386 public void testFallbackEnabledIfPrimaryUninstalledMultiUser() { 1387 checkFallbackEnabledIfPrimaryUninstalled(true /* multiUser */); 1388 } 1389 1390 /** 1391 * Ensures that fallback becomes enabled at boot if the primary package is uninstalled for some 1392 * user. 1393 */ 1394 private void checkFallbackEnabledIfPrimaryUninstalled(boolean multiUser) { 1395 String primaryPackage = "primary"; 1396 String fallbackPackage = "fallback"; 1397 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 1398 new WebViewProviderInfo( 1399 primaryPackage, "", true /* default available */, false /* fallback */, null), 1400 new WebViewProviderInfo( 1401 fallbackPackage, "", true /* default available */, true /* fallback */, null)}; 1402 setupWithPackages(packages, true /* fallback logic enabled */); 1403 int secondaryUserId = 5; 1404 if (multiUser) { 1405 mTestSystemImpl.addUser(secondaryUserId); 1406 // Install all packages for the primary user. 1407 setEnabledAndValidPackageInfosForUser(TestSystemImpl.PRIMARY_USER_ID, packages); 1408 // Only install fallback package for secondary user. 1409 mTestSystemImpl.setPackageInfoForUser(secondaryUserId, 1410 createPackageInfo(primaryPackage, true /* enabled */, 1411 true /* valid */, false /* installed */)); 1412 mTestSystemImpl.setPackageInfoForUser(secondaryUserId, 1413 createPackageInfo(fallbackPackage, false /* enabled */, 1414 true /* valid */, true /* installed */)); 1415 } else { 1416 mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */, 1417 true /* valid */, false /* installed */)); 1418 mTestSystemImpl.setPackageInfo(createPackageInfo(fallbackPackage, false /* enabled */, 1419 true /* valid */, true /* installed */)); 1420 } 1421 1422 runWebViewBootPreparationOnMainSync(); 1423 // Verify that we enable the fallback package 1424 Mockito.verify(mTestSystemImpl).enablePackageForAllUsers( 1425 Mockito.anyObject(), Mockito.eq(fallbackPackage), Mockito.eq(true) /* enable */); 1426 1427 checkPreparationPhasesForPackage(fallbackPackage, 1 /* first preparation phase */); 1428 } 1429 1430 @Test 1431 public void testPreparationRunsIffNewPackage() { 1432 String primaryPackage = "primary"; 1433 String fallbackPackage = "fallback"; 1434 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 1435 new WebViewProviderInfo( 1436 primaryPackage, "", true /* default available */, false /* fallback */, null), 1437 new WebViewProviderInfo( 1438 fallbackPackage, "", true /* default available */, true /* fallback */, null)}; 1439 setupWithPackages(packages, true /* fallback logic enabled */); 1440 mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */, 1441 true /* valid */, true /* installed */, null /* signatures */, 1442 10 /* lastUpdateTime*/ )); 1443 mTestSystemImpl.setPackageInfo(createPackageInfo(fallbackPackage, true /* enabled */, 1444 true /* valid */, true /* installed */)); 1445 1446 runWebViewBootPreparationOnMainSync(); 1447 1448 checkPreparationPhasesForPackage(primaryPackage, 1 /* first preparation phase */); 1449 Mockito.verify(mTestSystemImpl, Mockito.times(1)).enablePackageForUser( 1450 Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */, 1451 Matchers.anyInt() /* user */); 1452 1453 1454 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, 1455 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0 /* userId */); 1456 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, 1457 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 1 /* userId */); 1458 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, 1459 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 2 /* userId */); 1460 // package still has the same update-time so we shouldn't run preparation here 1461 Mockito.verify(mTestSystemImpl, Mockito.times(1)).onWebViewProviderChanged( 1462 Mockito.argThat(new IsPackageInfoWithName(primaryPackage))); 1463 Mockito.verify(mTestSystemImpl, Mockito.times(1)).enablePackageForUser( 1464 Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */, 1465 Matchers.anyInt() /* user */); 1466 1467 // Ensure we can still load the package 1468 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); 1469 assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status); 1470 assertEquals(primaryPackage, response.packageInfo.packageName); 1471 1472 1473 mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */, 1474 true /* valid */, true /* installed */, null /* signatures */, 1475 20 /* lastUpdateTime*/ )); 1476 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, 1477 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0); 1478 // The package has now changed - ensure that we have run the preparation phase a second time 1479 checkPreparationPhasesForPackage(primaryPackage, 2 /* second preparation phase */); 1480 1481 1482 mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */, 1483 true /* valid */, true /* installed */, null /* signatures */, 1484 50 /* lastUpdateTime*/ )); 1485 // Receive intent for different user 1486 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, 1487 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 2); 1488 1489 checkPreparationPhasesForPackage(primaryPackage, 3 /* third preparation phase */); 1490 } 1491 1492 @Test 1493 public void testGetCurrentWebViewPackage() { 1494 PackageInfo firstPackage = createPackageInfo("first", true /* enabled */, 1495 true /* valid */, true /* installed */); 1496 firstPackage.versionCode = 100; 1497 firstPackage.versionName = "first package version"; 1498 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 1499 new WebViewProviderInfo(firstPackage.packageName, "", true, false, null)}; 1500 setupWithPackages(packages, true); 1501 mTestSystemImpl.setPackageInfo(firstPackage); 1502 1503 runWebViewBootPreparationOnMainSync(); 1504 1505 Mockito.verify(mTestSystemImpl).onWebViewProviderChanged( 1506 Mockito.argThat(new IsPackageInfoWithName(firstPackage.packageName))); 1507 1508 mWebViewUpdateServiceImpl.notifyRelroCreationCompleted(); 1509 1510 // Ensure the API is correct before running waitForAndGetProvider 1511 assertEquals(firstPackage.packageName, 1512 mWebViewUpdateServiceImpl.getCurrentWebViewPackage().packageName); 1513 assertEquals(firstPackage.versionCode, 1514 mWebViewUpdateServiceImpl.getCurrentWebViewPackage().versionCode); 1515 assertEquals(firstPackage.versionName, 1516 mWebViewUpdateServiceImpl.getCurrentWebViewPackage().versionName); 1517 1518 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); 1519 assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status); 1520 assertEquals(firstPackage.packageName, response.packageInfo.packageName); 1521 1522 // Ensure the API is still correct after running waitForAndGetProvider 1523 assertEquals(firstPackage.packageName, 1524 mWebViewUpdateServiceImpl.getCurrentWebViewPackage().packageName); 1525 assertEquals(firstPackage.versionCode, 1526 mWebViewUpdateServiceImpl.getCurrentWebViewPackage().versionCode); 1527 assertEquals(firstPackage.versionName, 1528 mWebViewUpdateServiceImpl.getCurrentWebViewPackage().versionName); 1529 } 1530 1531 @Test 1532 public void testMultiProcessEnabledByDefault() { 1533 String primaryPackage = "primary"; 1534 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 1535 new WebViewProviderInfo( 1536 primaryPackage, "", true /* default available */, false /* fallback */, null)}; 1537 setupWithPackages(packages, true /* fallback logic enabled */, 1 /* numRelros */, 1538 true /* debuggable */, true /* multiprocess by default */); 1539 mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */, 1540 true /* valid */, true /* installed */, null /* signatures */, 1541 10 /* lastUpdateTime*/, false /* not hidden */, 1000 /* versionCode */, 1542 false /* isSystemApp */)); 1543 1544 runWebViewBootPreparationOnMainSync(); 1545 checkPreparationPhasesForPackage(primaryPackage, 1 /* first preparation phase */); 1546 1547 // Check it's on by default 1548 assertTrue(mWebViewUpdateServiceImpl.isMultiProcessEnabled()); 1549 1550 // Test toggling it 1551 mWebViewUpdateServiceImpl.enableMultiProcess(false); 1552 assertFalse(mWebViewUpdateServiceImpl.isMultiProcessEnabled()); 1553 mWebViewUpdateServiceImpl.enableMultiProcess(true); 1554 assertTrue(mWebViewUpdateServiceImpl.isMultiProcessEnabled()); 1555 1556 // Disable, then upgrade provider, which should re-enable it 1557 mWebViewUpdateServiceImpl.enableMultiProcess(false); 1558 mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */, 1559 true /* valid */, true /* installed */, null /* signatures */, 1560 20 /* lastUpdateTime*/, false /* not hidden */, 2000 /* versionCode */, 1561 false /* isSystemApp */)); 1562 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, 1563 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0); 1564 checkPreparationPhasesForPackage(primaryPackage, 2); 1565 assertTrue(mWebViewUpdateServiceImpl.isMultiProcessEnabled()); 1566 } 1567 1568 @Test 1569 public void testMultiProcessDisabledByDefault() { 1570 String primaryPackage = "primary"; 1571 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 1572 new WebViewProviderInfo( 1573 primaryPackage, "", true /* default available */, false /* fallback */, null)}; 1574 setupWithPackages(packages, true /* fallback logic enabled */, 1 /* numRelros */, 1575 true /* debuggable */, false /* not multiprocess by default */); 1576 mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */, 1577 true /* valid */, true /* installed */, null /* signatures */, 1578 10 /* lastUpdateTime*/, false /* not hidden */, 1000 /* versionCode */, 1579 false /* isSystemApp */)); 1580 1581 runWebViewBootPreparationOnMainSync(); 1582 checkPreparationPhasesForPackage(primaryPackage, 1 /* first preparation phase */); 1583 1584 // Check it's off by default 1585 assertFalse(mWebViewUpdateServiceImpl.isMultiProcessEnabled()); 1586 1587 // Test toggling it 1588 mWebViewUpdateServiceImpl.enableMultiProcess(true); 1589 assertTrue(mWebViewUpdateServiceImpl.isMultiProcessEnabled()); 1590 mWebViewUpdateServiceImpl.enableMultiProcess(false); 1591 assertFalse(mWebViewUpdateServiceImpl.isMultiProcessEnabled()); 1592 1593 // Disable, then upgrade provider, which should not re-enable it 1594 mWebViewUpdateServiceImpl.enableMultiProcess(false); 1595 mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */, 1596 true /* valid */, true /* installed */, null /* signatures */, 1597 20 /* lastUpdateTime*/, false /* not hidden */, 2000 /* versionCode */, 1598 false /* isSystemApp */)); 1599 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, 1600 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0); 1601 checkPreparationPhasesForPackage(primaryPackage, 2); 1602 assertFalse(mWebViewUpdateServiceImpl.isMultiProcessEnabled()); 1603 1604 // Enable, then upgrade provider, which should leave it on 1605 mWebViewUpdateServiceImpl.enableMultiProcess(true); 1606 mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */, 1607 true /* valid */, true /* installed */, null /* signatures */, 1608 30 /* lastUpdateTime*/, false /* not hidden */, 3000 /* versionCode */, 1609 false /* isSystemApp */)); 1610 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, 1611 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0); 1612 checkPreparationPhasesForPackage(primaryPackage, 3); 1613 assertTrue(mWebViewUpdateServiceImpl.isMultiProcessEnabled()); 1614 } 1615 1616 /** 1617 * Ensure that packages with a targetSdkVersion targeting the current platform are valid, and 1618 * that packages targeting an older version are not valid. 1619 */ 1620 @Test 1621 public void testTargetSdkVersionValidity() { 1622 PackageInfo newSdkPackage = createPackageInfo("newTargetSdkPackage", 1623 true /* enabled */, true /* valid */, true /* installed */); 1624 newSdkPackage.applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT; 1625 PackageInfo currentSdkPackage = createPackageInfo("currentTargetSdkPackage", 1626 true /* enabled */, true /* valid */, true /* installed */); 1627 currentSdkPackage.applicationInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1+1; 1628 PackageInfo oldSdkPackage = createPackageInfo("oldTargetSdkPackage", 1629 true /* enabled */, true /* valid */, true /* installed */); 1630 oldSdkPackage.applicationInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1; 1631 1632 WebViewProviderInfo newSdkProviderInfo = 1633 new WebViewProviderInfo(newSdkPackage.packageName, "", true, false, null); 1634 WebViewProviderInfo currentSdkProviderInfo = 1635 new WebViewProviderInfo(currentSdkPackage.packageName, "", true, false, null); 1636 WebViewProviderInfo[] packages = new WebViewProviderInfo[] { 1637 new WebViewProviderInfo(oldSdkPackage.packageName, "", true, false, null), 1638 currentSdkProviderInfo, newSdkProviderInfo}; 1639 setupWithPackages(packages, true); 1640; 1641 mTestSystemImpl.setPackageInfo(newSdkPackage); 1642 mTestSystemImpl.setPackageInfo(currentSdkPackage); 1643 mTestSystemImpl.setPackageInfo(oldSdkPackage); 1644 1645 assertArrayEquals(new WebViewProviderInfo[]{currentSdkProviderInfo, newSdkProviderInfo}, 1646 mWebViewUpdateServiceImpl.getValidWebViewPackages()); 1647 1648 runWebViewBootPreparationOnMainSync(); 1649 1650 checkPreparationPhasesForPackage(currentSdkPackage.packageName, 1651 1 /* first preparation phase */); 1652 } 1653} 1654