| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.server.webkit; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| |
| import android.content.Context; |
| import android.content.pm.ApplicationInfo; |
| import android.content.pm.PackageInfo; |
| import android.content.pm.Signature; |
| import android.os.Bundle; |
| import android.support.test.InstrumentationRegistry; |
| import android.support.test.runner.AndroidJUnit4; |
| import android.test.suitebuilder.annotation.MediumTest; |
| import android.util.Base64; |
| import android.webkit.WebViewFactory; |
| import android.webkit.WebViewProviderInfo; |
| import android.webkit.WebViewProviderResponse; |
| |
| import org.hamcrest.Description; |
| |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| |
| import org.mockito.Mockito; |
| import org.mockito.Matchers; |
| import org.mockito.ArgumentMatcher; |
| |
| import java.util.concurrent.CountDownLatch; |
| |
| |
| /** |
| * Tests for WebViewUpdateService |
| */ |
| // Use MediumTest instead of SmallTest as the implementation of WebViewUpdateService |
| // is intended to work on several threads and uses at least one sleep/wait-statement. |
| @RunWith(AndroidJUnit4.class) |
| @MediumTest |
| public class WebViewUpdateServiceTest { |
| private final static String TAG = WebViewUpdateServiceTest.class.getSimpleName(); |
| |
| private WebViewUpdateServiceImpl mWebViewUpdateServiceImpl; |
| private TestSystemImpl mTestSystemImpl; |
| |
| private static final String WEBVIEW_LIBRARY_FLAG = "com.android.webview.WebViewLibrary"; |
| |
| /** |
| * Creates a new instance. |
| */ |
| public WebViewUpdateServiceTest() { |
| } |
| |
| private void setupWithPackages(WebViewProviderInfo[] packages) { |
| setupWithPackages(packages, true); |
| } |
| |
| private void setupWithPackages(WebViewProviderInfo[] packages, |
| boolean fallbackLogicEnabled) { |
| setupWithPackages(packages, fallbackLogicEnabled, 1); |
| } |
| |
| private void setupWithPackages(WebViewProviderInfo[] packages, |
| boolean fallbackLogicEnabled, int numRelros) { |
| setupWithPackages(packages, fallbackLogicEnabled, numRelros, |
| true /* isDebuggable == true -> don't check package signatures */); |
| } |
| |
| private void setupWithPackages(WebViewProviderInfo[] packages, |
| boolean fallbackLogicEnabled, int numRelros, boolean isDebuggable) { |
| TestSystemImpl testing = new TestSystemImpl(packages, fallbackLogicEnabled, numRelros, |
| isDebuggable); |
| mTestSystemImpl = Mockito.spy(testing); |
| mWebViewUpdateServiceImpl = |
| new WebViewUpdateServiceImpl(null /*Context*/, mTestSystemImpl); |
| } |
| |
| private void setEnabledAndValidPackageInfos(WebViewProviderInfo[] providers) { |
| for(WebViewProviderInfo wpi : providers) { |
| mTestSystemImpl.setPackageInfo(createPackageInfo(wpi.packageName, true /* enabled */, |
| true /* valid */, true /* installed */)); |
| } |
| } |
| |
| private void checkCertainPackageUsedAfterWebViewBootPreparation(String expectedProviderName, |
| WebViewProviderInfo[] webviewPackages) { |
| checkCertainPackageUsedAfterWebViewBootPreparation( |
| expectedProviderName, webviewPackages, 1); |
| } |
| |
| private void checkCertainPackageUsedAfterWebViewBootPreparation(String expectedProviderName, |
| WebViewProviderInfo[] webviewPackages, int numRelros) { |
| setupWithPackages(webviewPackages, true, numRelros); |
| // Add (enabled and valid) package infos for each provider |
| setEnabledAndValidPackageInfos(webviewPackages); |
| |
| runWebViewBootPreparationOnMainSync(); |
| |
| Mockito.verify(mTestSystemImpl).onWebViewProviderChanged( |
| Mockito.argThat(new IsPackageInfoWithName(expectedProviderName))); |
| |
| for (int n = 0; n < numRelros; n++) { |
| mWebViewUpdateServiceImpl.notifyRelroCreationCompleted(); |
| } |
| |
| WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); |
| assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status); |
| assertEquals(expectedProviderName, response.packageInfo.packageName); |
| } |
| |
| // For matching the package name of a PackageInfo |
| private class IsPackageInfoWithName extends ArgumentMatcher<PackageInfo> { |
| private final String mPackageName; |
| |
| IsPackageInfoWithName(String name) { |
| mPackageName = name; |
| } |
| |
| @Override |
| public boolean matches(Object p) { |
| return ((PackageInfo) p).packageName.equals(mPackageName); |
| } |
| |
| // Provide a more useful description in case of mismatch |
| @Override |
| public void describeTo (Description description) { |
| description.appendText(String.format("PackageInfo with name '%s'", mPackageName)); |
| } |
| } |
| |
| private static PackageInfo createPackageInfo( |
| String packageName, boolean enabled, boolean valid, boolean installed) { |
| PackageInfo p = new PackageInfo(); |
| p.packageName = packageName; |
| p.applicationInfo = new ApplicationInfo(); |
| p.applicationInfo.enabled = enabled; |
| p.applicationInfo.metaData = new Bundle(); |
| if (installed) { |
| p.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED; |
| } else { |
| p.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED; |
| } |
| if (valid) { |
| // no flag means invalid |
| p.applicationInfo.metaData.putString(WEBVIEW_LIBRARY_FLAG, "blah"); |
| } |
| return p; |
| } |
| |
| private static PackageInfo createPackageInfo(String packageName, boolean enabled, boolean valid, |
| boolean installed, Signature[] signatures, long updateTime) { |
| PackageInfo p = createPackageInfo(packageName, enabled, valid, installed); |
| p.signatures = signatures; |
| p.lastUpdateTime = updateTime; |
| return p; |
| } |
| |
| private static PackageInfo createPackageInfo(String packageName, boolean enabled, boolean valid, |
| boolean installed, Signature[] signatures, long updateTime, boolean hidden) { |
| PackageInfo p = |
| createPackageInfo(packageName, enabled, valid, installed, signatures, updateTime); |
| if (hidden) { |
| p.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN; |
| } else { |
| p.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN; |
| } |
| return p; |
| } |
| |
| private void checkPreparationPhasesForPackage(String expectedPackage, int numPreparation) { |
| // Verify that onWebViewProviderChanged was called for the numPreparation'th time for the |
| // expected package |
| Mockito.verify(mTestSystemImpl, Mockito.times(numPreparation)).onWebViewProviderChanged( |
| Mockito.argThat(new IsPackageInfoWithName(expectedPackage))); |
| |
| mWebViewUpdateServiceImpl.notifyRelroCreationCompleted(); |
| |
| WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); |
| assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status); |
| assertEquals(expectedPackage, response.packageInfo.packageName); |
| } |
| |
| /** |
| * The WebView preparation boot phase is run on the main thread (especially on a thread with a |
| * looper) so to avoid bugs where our tests fail because a looper hasn't been attached to the |
| * thread running prepareWebViewInSystemServer we run it on the main thread. |
| */ |
| private void runWebViewBootPreparationOnMainSync() { |
| InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { |
| @Override |
| public void run() { |
| mWebViewUpdateServiceImpl.prepareWebViewInSystemServer(); |
| } |
| }); |
| } |
| |
| |
| // **************** |
| // Tests |
| // **************** |
| |
| |
| @Test |
| public void testWithSinglePackage() { |
| String testPackageName = "test.package.name"; |
| checkCertainPackageUsedAfterWebViewBootPreparation(testPackageName, |
| new WebViewProviderInfo[] { |
| new WebViewProviderInfo(testPackageName, "", |
| true /*default available*/, false /* fallback */, null)}); |
| } |
| |
| @Test |
| public void testDefaultPackageUsedOverNonDefault() { |
| String defaultPackage = "defaultPackage"; |
| String nonDefaultPackage = "nonDefaultPackage"; |
| WebViewProviderInfo[] packages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo(nonDefaultPackage, "", false, false, null), |
| new WebViewProviderInfo(defaultPackage, "", true, false, null)}; |
| checkCertainPackageUsedAfterWebViewBootPreparation(defaultPackage, packages); |
| } |
| |
| @Test |
| public void testSeveralRelros() { |
| String singlePackage = "singlePackage"; |
| checkCertainPackageUsedAfterWebViewBootPreparation( |
| singlePackage, |
| new WebViewProviderInfo[] { |
| new WebViewProviderInfo(singlePackage, "", true /*def av*/, false, null)}, |
| 2); |
| } |
| |
| // Ensure that package with valid signatures is chosen rather than package with invalid |
| // signatures. |
| @Test |
| public void testWithSignatures() { |
| String validPackage = "valid package"; |
| String invalidPackage = "invalid package"; |
| |
| Signature validSignature = new Signature("11"); |
| Signature invalidExpectedSignature = new Signature("22"); |
| Signature invalidPackageSignature = new Signature("33"); |
| |
| WebViewProviderInfo[] packages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo(invalidPackage, "", true, false, new String[]{ |
| Base64.encodeToString( |
| invalidExpectedSignature.toByteArray(), Base64.DEFAULT)}), |
| new WebViewProviderInfo(validPackage, "", true, false, new String[]{ |
| Base64.encodeToString( |
| validSignature.toByteArray(), Base64.DEFAULT)}) |
| }; |
| setupWithPackages(packages, true /* fallback logic enabled */, 1 /* numRelros */, |
| false /* isDebuggable */); |
| mTestSystemImpl.setPackageInfo(createPackageInfo(invalidPackage, true /* enabled */, |
| true /* valid */, true /* installed */, new Signature[]{invalidPackageSignature} |
| , 0 /* updateTime */)); |
| mTestSystemImpl.setPackageInfo(createPackageInfo(validPackage, true /* enabled */, |
| true /* valid */, true /* installed */, new Signature[]{validSignature} |
| , 0 /* updateTime */)); |
| |
| runWebViewBootPreparationOnMainSync(); |
| |
| |
| checkPreparationPhasesForPackage(validPackage, 1 /* first preparation for this package */); |
| |
| WebViewProviderInfo[] validPackages = mWebViewUpdateServiceImpl.getValidWebViewPackages(); |
| assertEquals(1, validPackages.length); |
| assertEquals(validPackage, validPackages[0].packageName); |
| } |
| |
| @Test |
| public void testFailWaitingForRelro() { |
| WebViewProviderInfo[] packages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo("packagename", "", true, true, null)}; |
| setupWithPackages(packages); |
| setEnabledAndValidPackageInfos(packages); |
| |
| runWebViewBootPreparationOnMainSync(); |
| |
| Mockito.verify(mTestSystemImpl).onWebViewProviderChanged( |
| Mockito.argThat(new IsPackageInfoWithName(packages[0].packageName))); |
| |
| // Never call notifyRelroCreation() |
| |
| WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); |
| assertEquals(WebViewFactory.LIBLOAD_FAILED_WAITING_FOR_RELRO, response.status); |
| } |
| |
| @Test |
| public void testFailListingEmptyWebviewPackages() { |
| WebViewProviderInfo[] packages = new WebViewProviderInfo[0]; |
| setupWithPackages(packages); |
| setEnabledAndValidPackageInfos(packages); |
| |
| runWebViewBootPreparationOnMainSync(); |
| |
| Mockito.verify(mTestSystemImpl, Mockito.never()).onWebViewProviderChanged( |
| Matchers.anyObject()); |
| |
| WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); |
| assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status); |
| } |
| |
| @Test |
| public void testFailListingInvalidWebviewPackage() { |
| WebViewProviderInfo wpi = new WebViewProviderInfo("package", "", true, true, null); |
| WebViewProviderInfo[] packages = new WebViewProviderInfo[] {wpi}; |
| setupWithPackages(packages); |
| mTestSystemImpl.setPackageInfo( |
| createPackageInfo(wpi.packageName, true /* enabled */, false /* valid */, |
| true /* installed */)); |
| |
| runWebViewBootPreparationOnMainSync(); |
| |
| Mockito.verify(mTestSystemImpl, Mockito.never()).onWebViewProviderChanged( |
| Matchers.anyObject()); |
| |
| WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); |
| assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status); |
| |
| // Verify that we can recover from failing to list webview packages. |
| mTestSystemImpl.setPackageInfo( |
| createPackageInfo(wpi.packageName, true /* enabled */, true /* valid */, |
| true /* installed */)); |
| mWebViewUpdateServiceImpl.packageStateChanged(wpi.packageName, |
| WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0); |
| |
| checkPreparationPhasesForPackage(wpi.packageName, 1); |
| } |
| |
| // Test that switching provider using changeProviderAndSetting works. |
| @Test |
| public void testSwitchingProvider() { |
| String firstPackage = "first"; |
| String secondPackage = "second"; |
| WebViewProviderInfo[] packages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo(firstPackage, "", true, false, null), |
| new WebViewProviderInfo(secondPackage, "", true, false, null)}; |
| checkSwitchingProvider(packages, firstPackage, secondPackage); |
| } |
| |
| @Test |
| public void testSwitchingProviderToNonDefault() { |
| String defaultPackage = "defaultPackage"; |
| String nonDefaultPackage = "nonDefaultPackage"; |
| WebViewProviderInfo[] packages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo(defaultPackage, "", true, false, null), |
| new WebViewProviderInfo(nonDefaultPackage, "", false, false, null)}; |
| checkSwitchingProvider(packages, defaultPackage, nonDefaultPackage); |
| } |
| |
| private void checkSwitchingProvider(WebViewProviderInfo[] packages, String initialPackage, |
| String finalPackage) { |
| checkCertainPackageUsedAfterWebViewBootPreparation(initialPackage, packages); |
| |
| mWebViewUpdateServiceImpl.changeProviderAndSetting(finalPackage); |
| checkPreparationPhasesForPackage(finalPackage, 1 /* first preparation for this package */); |
| |
| Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(initialPackage)); |
| } |
| |
| // Change provider during relro creation by using changeProviderAndSetting |
| @Test |
| public void testSwitchingProviderDuringRelroCreation() { |
| checkChangingProviderDuringRelroCreation(true); |
| } |
| |
| // Change provider during relro creation by enabling a provider |
| @Test |
| public void testChangingProviderThroughEnablingDuringRelroCreation() { |
| checkChangingProviderDuringRelroCreation(false); |
| } |
| |
| private void checkChangingProviderDuringRelroCreation(boolean settingsChange) { |
| String firstPackage = "first"; |
| String secondPackage = "second"; |
| WebViewProviderInfo[] packages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo(firstPackage, "", true, false, null), |
| new WebViewProviderInfo(secondPackage, "", true, false, null)}; |
| setupWithPackages(packages); |
| if (settingsChange) { |
| // Have all packages be enabled, so that we can change provider however we want to |
| setEnabledAndValidPackageInfos(packages); |
| } else { |
| // Have all packages be disabled so that we can change one to enabled later |
| for(WebViewProviderInfo wpi : packages) { |
| mTestSystemImpl.setPackageInfo(createPackageInfo(wpi.packageName, |
| false /* enabled */, true /* valid */, true /* installed */)); |
| } |
| } |
| |
| CountDownLatch countdown = new CountDownLatch(1); |
| |
| runWebViewBootPreparationOnMainSync(); |
| |
| Mockito.verify(mTestSystemImpl).onWebViewProviderChanged( |
| Mockito.argThat(new IsPackageInfoWithName(firstPackage))); |
| |
| assertEquals(firstPackage, mWebViewUpdateServiceImpl.getCurrentWebViewPackageName()); |
| |
| new Thread(new Runnable() { |
| @Override |
| public void run() { |
| WebViewProviderResponse threadResponse = |
| mWebViewUpdateServiceImpl.waitForAndGetProvider(); |
| assertEquals(WebViewFactory.LIBLOAD_SUCCESS, threadResponse.status); |
| assertEquals(secondPackage, threadResponse.packageInfo.packageName); |
| // Verify that we killed the first package |
| Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(firstPackage)); |
| countdown.countDown(); |
| } |
| }).start(); |
| try { |
| Thread.sleep(500); // Let the new thread run / be blocked |
| } catch (InterruptedException e) { |
| } |
| |
| if (settingsChange) { |
| mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage); |
| } else { |
| // Switch provider by enabling the second one |
| mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */, |
| true /* valid */, true /* installed */)); |
| mWebViewUpdateServiceImpl.packageStateChanged( |
| secondPackage, WebViewUpdateService.PACKAGE_CHANGED, 0); |
| } |
| mWebViewUpdateServiceImpl.notifyRelroCreationCompleted(); |
| // first package done, should start on second |
| |
| Mockito.verify(mTestSystemImpl).onWebViewProviderChanged( |
| Mockito.argThat(new IsPackageInfoWithName(secondPackage))); |
| |
| mWebViewUpdateServiceImpl.notifyRelroCreationCompleted(); |
| // second package done, the other thread should now be unblocked |
| try { |
| countdown.await(); |
| } catch (InterruptedException e) { |
| } |
| } |
| |
| @Test |
| public void testRunFallbackLogicIfEnabled() { |
| checkFallbackLogicBeingRun(true); |
| } |
| |
| @Test |
| public void testDontRunFallbackLogicIfDisabled() { |
| checkFallbackLogicBeingRun(false); |
| } |
| |
| private void checkFallbackLogicBeingRun(boolean fallbackLogicEnabled) { |
| String primaryPackage = "primary"; |
| String fallbackPackage = "fallback"; |
| WebViewProviderInfo[] packages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo( |
| primaryPackage, "", true /* default available */, false /* fallback */, null), |
| new WebViewProviderInfo( |
| fallbackPackage, "", true /* default available */, true /* fallback */, null)}; |
| setupWithPackages(packages, fallbackLogicEnabled); |
| setEnabledAndValidPackageInfos(packages); |
| |
| runWebViewBootPreparationOnMainSync(); |
| // Verify that we disable the fallback package if fallback logic enabled, and don't disable |
| // the fallback package if that logic is disabled |
| if (fallbackLogicEnabled) { |
| Mockito.verify(mTestSystemImpl).uninstallAndDisablePackageForAllUsers( |
| Matchers.anyObject(), Mockito.eq(fallbackPackage)); |
| } else { |
| Mockito.verify(mTestSystemImpl, Mockito.never()).uninstallAndDisablePackageForAllUsers( |
| Matchers.anyObject(), Matchers.anyObject()); |
| } |
| Mockito.verify(mTestSystemImpl).onWebViewProviderChanged( |
| Mockito.argThat(new IsPackageInfoWithName(primaryPackage))); |
| |
| // Enable fallback package |
| mTestSystemImpl.setPackageInfo(createPackageInfo(fallbackPackage, true /* enabled */, |
| true /* valid */, true /* installed */)); |
| mWebViewUpdateServiceImpl.packageStateChanged( |
| fallbackPackage, WebViewUpdateService.PACKAGE_CHANGED, 0); |
| |
| if (fallbackLogicEnabled) { |
| // Check that we have now disabled the fallback package twice |
| Mockito.verify(mTestSystemImpl, Mockito.times(2)).uninstallAndDisablePackageForAllUsers( |
| Matchers.anyObject(), Mockito.eq(fallbackPackage)); |
| } else { |
| // Check that we still haven't disabled any package |
| Mockito.verify(mTestSystemImpl, Mockito.never()).uninstallAndDisablePackageForAllUsers( |
| Matchers.anyObject(), Matchers.anyObject()); |
| } |
| } |
| |
| /** |
| * Scenario for installing primary package when fallback enabled. |
| * 1. Start with only fallback installed |
| * 2. Install non-fallback |
| * 3. Fallback should be disabled |
| */ |
| @Test |
| public void testInstallingNonFallbackPackage() { |
| String primaryPackage = "primary"; |
| String fallbackPackage = "fallback"; |
| WebViewProviderInfo[] packages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo( |
| primaryPackage, "", true /* default available */, false /* fallback */, null), |
| new WebViewProviderInfo( |
| fallbackPackage, "", true /* default available */, true /* fallback */, null)}; |
| setupWithPackages(packages, true /* isFallbackLogicEnabled */); |
| mTestSystemImpl.setPackageInfo( |
| createPackageInfo(fallbackPackage, true /* enabled */ , true /* valid */, |
| true /* installed */)); |
| |
| runWebViewBootPreparationOnMainSync(); |
| Mockito.verify(mTestSystemImpl, Mockito.never()).uninstallAndDisablePackageForAllUsers( |
| Matchers.anyObject(), Matchers.anyObject()); |
| |
| checkPreparationPhasesForPackage(fallbackPackage, |
| 1 /* first preparation for this package*/); |
| |
| // Install primary package |
| mTestSystemImpl.setPackageInfo( |
| createPackageInfo(primaryPackage, true /* enabled */ , true /* valid */, |
| true /* installed */)); |
| mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, |
| WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0); |
| |
| // Verify fallback disabled, primary package used as provider, and fallback package killed |
| Mockito.verify(mTestSystemImpl).uninstallAndDisablePackageForAllUsers( |
| Matchers.anyObject(), Mockito.eq(fallbackPackage)); |
| checkPreparationPhasesForPackage(primaryPackage, 1 /* first preparation for this package*/); |
| Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(fallbackPackage)); |
| } |
| |
| @Test |
| public void testFallbackChangesEnabledState() { |
| String primaryPackage = "primary"; |
| String fallbackPackage = "fallback"; |
| WebViewProviderInfo[] packages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo( |
| primaryPackage, "", true /* default available */, false /* fallback */, null), |
| new WebViewProviderInfo( |
| fallbackPackage, "", true /* default available */, true /* fallback */, null)}; |
| setupWithPackages(packages, true /* fallbackLogicEnabled */); |
| setEnabledAndValidPackageInfos(packages); |
| |
| runWebViewBootPreparationOnMainSync(); |
| |
| // Verify fallback disabled at boot when primary package enabled |
| Mockito.verify(mTestSystemImpl).enablePackageForUser( |
| Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */, |
| Matchers.anyInt()); |
| |
| checkPreparationPhasesForPackage(primaryPackage, 1); |
| |
| // Disable primary package and ensure fallback becomes enabled and used |
| mTestSystemImpl.setPackageInfo( |
| createPackageInfo(primaryPackage, false /* enabled */, true /* valid */, |
| true /* installed */)); |
| mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, |
| WebViewUpdateService.PACKAGE_CHANGED, 0); |
| |
| Mockito.verify(mTestSystemImpl).enablePackageForUser( |
| Mockito.eq(fallbackPackage), Mockito.eq(true) /* enable */, |
| Matchers.anyInt()); |
| |
| checkPreparationPhasesForPackage(fallbackPackage, 1); |
| |
| |
| // Again enable primary package and verify primary is used and fallback becomes disabled |
| mTestSystemImpl.setPackageInfo( |
| createPackageInfo(primaryPackage, true /* enabled */, true /* valid */, |
| true /* installed */)); |
| mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, |
| WebViewUpdateService.PACKAGE_CHANGED, 0); |
| |
| // Verify fallback is disabled a second time when primary package becomes enabled |
| Mockito.verify(mTestSystemImpl, Mockito.times(2)).enablePackageForUser( |
| Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */, |
| Matchers.anyInt()); |
| |
| checkPreparationPhasesForPackage(primaryPackage, 2); |
| } |
| |
| @Test |
| public void testAddUserWhenFallbackLogicEnabled() { |
| checkAddingNewUser(true); |
| } |
| |
| @Test |
| public void testAddUserWhenFallbackLogicDisabled() { |
| checkAddingNewUser(false); |
| } |
| |
| public void checkAddingNewUser(boolean fallbackLogicEnabled) { |
| String primaryPackage = "primary"; |
| String fallbackPackage = "fallback"; |
| WebViewProviderInfo[] packages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo( |
| primaryPackage, "", true /* default available */, false /* fallback */, null), |
| new WebViewProviderInfo( |
| fallbackPackage, "", true /* default available */, true /* fallback */, null)}; |
| setupWithPackages(packages, fallbackLogicEnabled); |
| setEnabledAndValidPackageInfos(packages); |
| int newUser = 100; |
| mWebViewUpdateServiceImpl.handleNewUser(newUser); |
| if (fallbackLogicEnabled) { |
| // Verify fallback package becomes disabled for new user |
| Mockito.verify(mTestSystemImpl).enablePackageForUser( |
| Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */, |
| Mockito.eq(newUser)); |
| } else { |
| // Verify that we don't disable fallback for new user |
| Mockito.verify(mTestSystemImpl, Mockito.never()).enablePackageForUser( |
| Mockito.anyObject(), Matchers.anyBoolean() /* enable */, |
| Matchers.anyInt() /* user */); |
| } |
| } |
| |
| /** |
| * Timing dependent test where we verify that the list of valid webview packages becoming empty |
| * at a certain point doesn't crash us or break our state. |
| */ |
| @Test |
| public void testNotifyRelroDoesntCrashIfNoPackages() { |
| String firstPackage = "first"; |
| String secondPackage = "second"; |
| WebViewProviderInfo[] packages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo(firstPackage, "", true /* default available */, |
| false /* fallback */, null), |
| new WebViewProviderInfo(secondPackage, "", true /* default available */, |
| false /* fallback */, null)}; |
| setupWithPackages(packages); |
| // Add (enabled and valid) package infos for each provider |
| setEnabledAndValidPackageInfos(packages); |
| |
| runWebViewBootPreparationOnMainSync(); |
| |
| Mockito.verify(mTestSystemImpl).onWebViewProviderChanged( |
| Mockito.argThat(new IsPackageInfoWithName(firstPackage))); |
| |
| // Change provider during relro creation to enter a state where we are |
| // waiting for relro creation to complete just to re-run relro creation. |
| // (so that in next notifyRelroCreationCompleted() call we have to list webview packages) |
| mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage); |
| |
| // Make packages invalid to cause exception to be thrown |
| mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, true /* enabled */, |
| false /* valid */, true /* installed */, null /* signatures */, |
| 0 /* updateTime */)); |
| mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */, |
| false /* valid */, true /* installed */)); |
| |
| // This shouldn't throw an exception! |
| mWebViewUpdateServiceImpl.notifyRelroCreationCompleted(); |
| |
| WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); |
| assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status); |
| |
| // Now make a package valid again and verify that we can switch back to that |
| mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, true /* enabled */, |
| true /* valid */, true /* installed */, null /* signatures */, |
| 1 /* updateTime */ )); |
| |
| mWebViewUpdateServiceImpl.packageStateChanged(firstPackage, |
| WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0); |
| |
| // Ensure we use firstPackage |
| checkPreparationPhasesForPackage(firstPackage, 2 /* second preparation for this package */); |
| } |
| |
| /** |
| * Verify that even if a user-chosen package is removed temporarily we start using it again when |
| * it is added back. |
| */ |
| @Test |
| public void testTempRemovePackageDoesntSwitchProviderPermanently() { |
| String firstPackage = "first"; |
| String secondPackage = "second"; |
| WebViewProviderInfo[] packages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo(firstPackage, "", true /* default available */, |
| false /* fallback */, null), |
| new WebViewProviderInfo(secondPackage, "", true /* default available */, |
| false /* fallback */, null)}; |
| checkCertainPackageUsedAfterWebViewBootPreparation(firstPackage, packages); |
| |
| // Explicitly use the second package |
| mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage); |
| checkPreparationPhasesForPackage(secondPackage, 1 /* first time for this package */); |
| |
| // Remove second package (invalidate it) and verify that first package is used |
| mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */, |
| false /* valid */, true /* installed */)); |
| mWebViewUpdateServiceImpl.packageStateChanged(secondPackage, |
| WebViewUpdateService.PACKAGE_ADDED, 0); |
| checkPreparationPhasesForPackage(firstPackage, 2 /* second time for this package */); |
| |
| // Now make the second package valid again and verify that it is used again |
| mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */, |
| true /* valid */, true /* installed */)); |
| mWebViewUpdateServiceImpl.packageStateChanged(secondPackage, |
| WebViewUpdateService.PACKAGE_ADDED, 0); |
| checkPreparationPhasesForPackage(secondPackage, 2 /* second time for this package */); |
| } |
| |
| /** |
| * Ensure that we update the user-chosen setting across boots if the chosen package is no |
| * longer installed and valid. |
| */ |
| @Test |
| public void testProviderSettingChangedDuringBootIfProviderNotAvailable() { |
| String chosenPackage = "chosenPackage"; |
| String nonChosenPackage = "non-chosenPackage"; |
| WebViewProviderInfo[] packages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo(chosenPackage, "", true /* default available */, |
| false /* fallback */, null), |
| new WebViewProviderInfo(nonChosenPackage, "", true /* default available */, |
| false /* fallback */, null)}; |
| |
| setupWithPackages(packages); |
| // Only 'install' nonChosenPackage |
| mTestSystemImpl.setPackageInfo( |
| createPackageInfo(nonChosenPackage, true /* enabled */, true /* valid */, true /* installed */)); |
| |
| // Set user-chosen package |
| mTestSystemImpl.updateUserSetting(null, chosenPackage); |
| |
| runWebViewBootPreparationOnMainSync(); |
| |
| // Verify that we switch the setting to point to the current package |
| Mockito.verify(mTestSystemImpl).updateUserSetting( |
| Mockito.anyObject(), Mockito.eq(nonChosenPackage)); |
| assertEquals(nonChosenPackage, mTestSystemImpl.getUserChosenWebViewProvider(null)); |
| |
| checkPreparationPhasesForPackage(nonChosenPackage, 1); |
| } |
| |
| @Test |
| public void testRecoverFailedListingWebViewPackagesSettingsChange() { |
| checkRecoverAfterFailListingWebviewPackages(true); |
| } |
| |
| @Test |
| public void testRecoverFailedListingWebViewPackagesAddedPackage() { |
| checkRecoverAfterFailListingWebviewPackages(false); |
| } |
| |
| /** |
| * Test that we can recover correctly from failing to list WebView packages. |
| * settingsChange: whether to fail during changeProviderAndSetting or packageStateChanged |
| */ |
| public void checkRecoverAfterFailListingWebviewPackages(boolean settingsChange) { |
| String firstPackage = "first"; |
| String secondPackage = "second"; |
| WebViewProviderInfo[] packages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo(firstPackage, "", true /* default available */, |
| false /* fallback */, null), |
| new WebViewProviderInfo(secondPackage, "", true /* default available */, |
| false /* fallback */, null)}; |
| checkCertainPackageUsedAfterWebViewBootPreparation(firstPackage, packages); |
| |
| // Make both packages invalid so that we fail listing WebView packages |
| mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, true /* enabled */, |
| false /* valid */, true /* installed */)); |
| mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */, |
| false /* valid */, true /* installed */)); |
| |
| // Change package to hit the webview packages listing problem. |
| if (settingsChange) { |
| mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage); |
| } else { |
| mWebViewUpdateServiceImpl.packageStateChanged(secondPackage, |
| WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0); |
| } |
| |
| WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); |
| assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status); |
| |
| // Make second package valid and verify that we can load it again |
| mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */, |
| true /* valid */, true /* installed */)); |
| |
| mWebViewUpdateServiceImpl.packageStateChanged(secondPackage, |
| WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0); |
| |
| |
| checkPreparationPhasesForPackage(secondPackage, 1); |
| } |
| |
| @Test |
| public void testDontKillIfPackageReplaced() { |
| checkDontKillIfPackageRemoved(true); |
| } |
| |
| @Test |
| public void testDontKillIfPackageRemoved() { |
| checkDontKillIfPackageRemoved(false); |
| } |
| |
| public void checkDontKillIfPackageRemoved(boolean replaced) { |
| String firstPackage = "first"; |
| String secondPackage = "second"; |
| WebViewProviderInfo[] packages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo(firstPackage, "", true /* default available */, |
| false /* fallback */, null), |
| new WebViewProviderInfo(secondPackage, "", true /* default available */, |
| false /* fallback */, null)}; |
| checkCertainPackageUsedAfterWebViewBootPreparation(firstPackage, packages); |
| |
| // Replace or remove the current webview package |
| if (replaced) { |
| mTestSystemImpl.setPackageInfo( |
| createPackageInfo(firstPackage, true /* enabled */, false /* valid */, |
| true /* installed */)); |
| mWebViewUpdateServiceImpl.packageStateChanged(firstPackage, |
| WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0); |
| } else { |
| mTestSystemImpl.removePackageInfo(firstPackage); |
| mWebViewUpdateServiceImpl.packageStateChanged(firstPackage, |
| WebViewUpdateService.PACKAGE_REMOVED, 0); |
| } |
| |
| checkPreparationPhasesForPackage(secondPackage, 1); |
| |
| Mockito.verify(mTestSystemImpl, Mockito.never()).killPackageDependents( |
| Mockito.anyObject()); |
| } |
| |
| @Test |
| public void testKillIfSettingChanged() { |
| String firstPackage = "first"; |
| String secondPackage = "second"; |
| WebViewProviderInfo[] packages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo(firstPackage, "", true /* default available */, |
| false /* fallback */, null), |
| new WebViewProviderInfo(secondPackage, "", true /* default available */, |
| false /* fallback */, null)}; |
| checkCertainPackageUsedAfterWebViewBootPreparation(firstPackage, packages); |
| |
| mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage); |
| |
| checkPreparationPhasesForPackage(secondPackage, 1); |
| |
| Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(firstPackage)); |
| } |
| |
| /** |
| * Test that we kill apps using an old provider when we change the provider setting, even if the |
| * new provider is not the one we intended to change to. |
| */ |
| @Test |
| public void testKillIfChangeProviderIncorrectly() { |
| String firstPackage = "first"; |
| String secondPackage = "second"; |
| String thirdPackage = "third"; |
| WebViewProviderInfo[] packages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo(firstPackage, "", true /* default available */, |
| false /* fallback */, null), |
| new WebViewProviderInfo(secondPackage, "", true /* default available */, |
| false /* fallback */, null), |
| new WebViewProviderInfo(thirdPackage, "", true /* default available */, |
| false /* fallback */, null)}; |
| setupWithPackages(packages); |
| setEnabledAndValidPackageInfos(packages); |
| |
| // Start with the setting pointing to the third package |
| mTestSystemImpl.updateUserSetting(null, thirdPackage); |
| |
| runWebViewBootPreparationOnMainSync(); |
| checkPreparationPhasesForPackage(thirdPackage, 1); |
| |
| mTestSystemImpl.setPackageInfo( |
| createPackageInfo(secondPackage, true /* enabled */, false /* valid */, true /* installed */)); |
| |
| // Try to switch to the invalid second package, this should result in switching to the first |
| // package, since that is more preferred than the third one. |
| assertEquals(firstPackage, |
| mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage)); |
| |
| checkPreparationPhasesForPackage(firstPackage, 1); |
| |
| Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(thirdPackage)); |
| } |
| |
| // Ensure that the update service uses an uninstalled package if that is the only package |
| // available. |
| @Test |
| public void testWithSingleUninstalledPackage() { |
| String testPackageName = "test.package.name"; |
| WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo(testPackageName, "", |
| true /*default available*/, false /* fallback */, null)}; |
| setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */); |
| mTestSystemImpl.setPackageInfo(createPackageInfo(testPackageName, true /* enabled */, |
| true /* valid */, false /* installed */)); |
| |
| runWebViewBootPreparationOnMainSync(); |
| |
| checkPreparationPhasesForPackage(testPackageName, 1 /* first preparation phase */); |
| } |
| |
| @Test |
| public void testNonhiddenPackageUserOverHidden() { |
| checkVisiblePackageUserOverNonVisible(false /* true == uninstalled, false == hidden */); |
| } |
| |
| @Test |
| public void testInstalledPackageUsedOverUninstalled() { |
| checkVisiblePackageUserOverNonVisible(true /* true == uninstalled, false == hidden */); |
| } |
| |
| private void checkVisiblePackageUserOverNonVisible(boolean uninstalledNotHidden) { |
| boolean testUninstalled = uninstalledNotHidden; |
| boolean testHidden = !uninstalledNotHidden; |
| String installedPackage = "installedPackage"; |
| String uninstalledPackage = "uninstalledPackage"; |
| WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo(uninstalledPackage, "", true /* available by default */, |
| false /* fallback */, null), |
| new WebViewProviderInfo(installedPackage, "", true /* available by default */, |
| false /* fallback */, null)}; |
| |
| setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */); |
| mTestSystemImpl.setPackageInfo(createPackageInfo(installedPackage, true /* enabled */, |
| true /* valid */, true /* installed */)); |
| mTestSystemImpl.setPackageInfo(createPackageInfo(uninstalledPackage, true /* enabled */, |
| true /* valid */, (testUninstalled ? false : true) /* installed */, |
| null /* signatures */, 0 /* updateTime */, (testHidden ? true : false))); |
| |
| runWebViewBootPreparationOnMainSync(); |
| |
| checkPreparationPhasesForPackage(installedPackage, 1 /* first preparation phase */); |
| } |
| |
| @Test |
| public void testCantSwitchToHiddenPackage () { |
| checkCantSwitchToNonVisiblePackage(false /* true == uninstalled, false == hidden */); |
| } |
| |
| |
| @Test |
| public void testCantSwitchToUninstalledPackage () { |
| checkCantSwitchToNonVisiblePackage(true /* true == uninstalled, false == hidden */); |
| } |
| |
| /** |
| * Ensure that we won't prioritize an uninstalled (or hidden) package even if it is user-chosen, |
| * and that an uninstalled (or hidden) package is not considered valid (in the |
| * getValidWebViewPackages() API). |
| */ |
| private void checkCantSwitchToNonVisiblePackage(boolean uninstalledNotHidden) { |
| boolean testUninstalled = uninstalledNotHidden; |
| boolean testHidden = !uninstalledNotHidden; |
| String installedPackage = "installedPackage"; |
| String uninstalledPackage = "uninstalledPackage"; |
| WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo(uninstalledPackage, "", true /* available by default */, |
| false /* fallback */, null), |
| new WebViewProviderInfo(installedPackage, "", true /* available by default */, |
| false /* fallback */, null)}; |
| |
| setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */); |
| mTestSystemImpl.setPackageInfo(createPackageInfo(installedPackage, true /* enabled */, |
| true /* valid */, true /* installed */)); |
| mTestSystemImpl.setPackageInfo(createPackageInfo(uninstalledPackage, true /* enabled */, |
| true /* valid */, (testUninstalled ? false : true) /* installed */, |
| null /* signatures */, 0 /* updateTime */, |
| (testHidden ? true : false) /* hidden */)); |
| |
| runWebViewBootPreparationOnMainSync(); |
| |
| checkPreparationPhasesForPackage(installedPackage, 1 /* first preparation phase */); |
| |
| // Ensure that only the installed package is considered valid |
| WebViewProviderInfo[] validPackages = mWebViewUpdateServiceImpl.getValidWebViewPackages(); |
| assertEquals(1, validPackages.length); |
| assertEquals(installedPackage, validPackages[0].packageName); |
| |
| // ensure that we don't switch to the uninstalled package (it will be used if it becomes |
| // installed later) |
| assertEquals(installedPackage, |
| mWebViewUpdateServiceImpl.changeProviderAndSetting(uninstalledPackage)); |
| |
| // We should only have called onWebViewProviderChanged once (before calling |
| // changeProviderAndSetting |
| Mockito.verify(mTestSystemImpl, Mockito.times(1)).onWebViewProviderChanged( |
| Mockito.argThat(new IsPackageInfoWithName(installedPackage))); |
| } |
| |
| @Test |
| public void testHiddenPackageNotPrioritizedEvenIfChosen() { |
| checkNonvisiblePackageNotPrioritizedEvenIfChosen( |
| false /* true == uninstalled, false == hidden */); |
| } |
| |
| @Test |
| public void testUninstalledPackageNotPrioritizedEvenIfChosen() { |
| checkNonvisiblePackageNotPrioritizedEvenIfChosen( |
| true /* true == uninstalled, false == hidden */); |
| } |
| |
| public void checkNonvisiblePackageNotPrioritizedEvenIfChosen(boolean uninstalledNotHidden) { |
| boolean testUninstalled = uninstalledNotHidden; |
| boolean testHidden = !uninstalledNotHidden; |
| String installedPackage = "installedPackage"; |
| String uninstalledPackage = "uninstalledPackage"; |
| WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo(uninstalledPackage, "", true /* available by default */, |
| false /* fallback */, null), |
| new WebViewProviderInfo(installedPackage, "", true /* available by default */, |
| false /* fallback */, null)}; |
| |
| setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */); |
| mTestSystemImpl.setPackageInfo(createPackageInfo(installedPackage, true /* enabled */, |
| true /* valid */, true /* installed */)); |
| mTestSystemImpl.setPackageInfo(createPackageInfo(uninstalledPackage, true /* enabled */, |
| true /* valid */, (testUninstalled ? false : true) /* installed */, |
| null /* signatures */, 0 /* updateTime */, |
| (testHidden ? true : false) /* hidden */)); |
| |
| // Start with the setting pointing to the uninstalled package |
| mTestSystemImpl.updateUserSetting(null, uninstalledPackage); |
| |
| runWebViewBootPreparationOnMainSync(); |
| |
| checkPreparationPhasesForPackage(installedPackage, 1 /* first preparation phase */); |
| } |
| |
| /** |
| * Ensures that fallback becomes enabled if the primary package is uninstalled for the current |
| * user. |
| */ |
| @Test |
| public void testFallbackEnabledIfPrimaryUninstalled() { |
| String primaryPackage = "primary"; |
| String fallbackPackage = "fallback"; |
| WebViewProviderInfo[] packages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo( |
| primaryPackage, "", true /* default available */, false /* fallback */, null), |
| new WebViewProviderInfo( |
| fallbackPackage, "", true /* default available */, true /* fallback */, null)}; |
| setupWithPackages(packages, true /* fallback logic enabled */); |
| mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */, |
| true /* valid */, false /* installed */)); |
| mTestSystemImpl.setPackageInfo(createPackageInfo(fallbackPackage, true /* enabled */, |
| true /* valid */, true /* installed */)); |
| |
| runWebViewBootPreparationOnMainSync(); |
| // Verify that we enable the fallback package |
| Mockito.verify(mTestSystemImpl).enablePackageForAllUsers( |
| Mockito.anyObject(), Mockito.eq(fallbackPackage), Mockito.eq(true) /* enable */); |
| |
| checkPreparationPhasesForPackage(fallbackPackage, 1 /* first preparation phase */); |
| } |
| |
| @Test |
| public void testPreparationRunsIffNewPackage() { |
| String primaryPackage = "primary"; |
| String fallbackPackage = "fallback"; |
| WebViewProviderInfo[] packages = new WebViewProviderInfo[] { |
| new WebViewProviderInfo( |
| primaryPackage, "", true /* default available */, false /* fallback */, null), |
| new WebViewProviderInfo( |
| fallbackPackage, "", true /* default available */, true /* fallback */, null)}; |
| setupWithPackages(packages, true /* fallback logic enabled */); |
| mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */, |
| true /* valid */, true /* installed */, null /* signatures */, |
| 10 /* lastUpdateTime*/ )); |
| mTestSystemImpl.setPackageInfo(createPackageInfo(fallbackPackage, true /* enabled */, |
| true /* valid */, true /* installed */)); |
| |
| runWebViewBootPreparationOnMainSync(); |
| |
| checkPreparationPhasesForPackage(primaryPackage, 1 /* first preparation phase */); |
| Mockito.verify(mTestSystemImpl, Mockito.times(1)).enablePackageForUser( |
| Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */, |
| Matchers.anyInt() /* user */); |
| |
| |
| mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, |
| WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0 /* userId */); |
| mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, |
| WebViewUpdateService.PACKAGE_ADDED_REPLACED, 1 /* userId */); |
| mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, |
| WebViewUpdateService.PACKAGE_ADDED_REPLACED, 2 /* userId */); |
| // package still has the same update-time so we shouldn't run preparation here |
| Mockito.verify(mTestSystemImpl, Mockito.times(1)).onWebViewProviderChanged( |
| Mockito.argThat(new IsPackageInfoWithName(primaryPackage))); |
| Mockito.verify(mTestSystemImpl, Mockito.times(1)).enablePackageForUser( |
| Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */, |
| Matchers.anyInt() /* user */); |
| |
| // Ensure we can still load the package |
| WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); |
| assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status); |
| assertEquals(primaryPackage, response.packageInfo.packageName); |
| |
| |
| mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */, |
| true /* valid */, true /* installed */, null /* signatures */, |
| 20 /* lastUpdateTime*/ )); |
| mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, |
| WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0); |
| // The package has now changed - ensure that we have run the preparation phase a second time |
| checkPreparationPhasesForPackage(primaryPackage, 2 /* second preparation phase */); |
| |
| |
| mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */, |
| true /* valid */, true /* installed */, null /* signatures */, |
| 50 /* lastUpdateTime*/ )); |
| // Receive intent for different user |
| mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, |
| WebViewUpdateService.PACKAGE_ADDED_REPLACED, 2); |
| |
| checkPreparationPhasesForPackage(primaryPackage, 3 /* third preparation phase */); |
| } |
| } |