Merge "Add initial unit tests for WebViewUpdateService." into nyc-dev

am: ce2cb76

* commit 'ce2cb7630c94c4d394f3a12ab5fd5475f61e343c':
  Add initial unit tests for WebViewUpdateService.

Change-Id: I303ed7db8d03183891912ff979c39dae4f1ae16d
This commit is contained in:
Gustav Sennton
2016-04-12 15:29:07 +00:00
committed by android-build-merger
3 changed files with 736 additions and 2 deletions

View File

@@ -119,6 +119,8 @@ public class WebViewUpdateServiceImpl {
}
private void updateFallbackStateOnBoot() {
if (!mSystemInterface.isFallbackLogicEnabled()) return;
WebViewProviderInfo[] webviewProviders = mSystemInterface.getWebViewPackages();
updateFallbackState(webviewProviders, true);
}
@@ -497,8 +499,15 @@ public class WebViewUpdateServiceImpl {
mWebViewPackageDirty = false;
// If we have changed provider since we started the relro creation we need to
// redo the whole process using the new package instead.
PackageInfo newPackage = findPreferredWebViewPackage();
onWebViewProviderChanged(newPackage);
try {
PackageInfo newPackage = findPreferredWebViewPackage();
onWebViewProviderChanged(newPackage);
} catch (WebViewFactory.MissingWebViewPackageException e) {
// If we can't find any valid WebView package we are now in a state where
// mAnyWebViewInstalled is false, so loading WebView will be blocked and we
// should simply wait until we receive an intent declaring a new package was
// installed.
}
} else {
mLock.notifyAll();
}

View File

@@ -0,0 +1,112 @@
/*
* 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 android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.webkit.WebViewProviderInfo;
import java.util.HashMap;
public class TestSystemImpl implements SystemInterface {
private String mUserProvider = "";
private final WebViewProviderInfo[] mPackageConfigs;
HashMap<String, PackageInfo> mPackages = new HashMap();
private boolean mFallbackLogicEnabled;
private final int mNumRelros;
private final boolean mIsDebuggable;
public TestSystemImpl(WebViewProviderInfo[] packageConfigs, boolean fallbackLogicEnabled,
int numRelros, boolean isDebuggable) {
mPackageConfigs = packageConfigs;
mFallbackLogicEnabled = fallbackLogicEnabled;
mNumRelros = numRelros;
mIsDebuggable = isDebuggable;
}
@Override
public WebViewProviderInfo[] getWebViewPackages() {
return mPackageConfigs;
}
@Override
public int onWebViewProviderChanged(PackageInfo packageInfo) {
return mNumRelros;
}
@Override
public String getUserChosenWebViewProvider(Context context) { return mUserProvider; }
@Override
public void updateUserSetting(Context context, String newProviderName) {
mUserProvider = newProviderName;
}
@Override
public void killPackageDependents(String packageName) {}
@Override
public boolean isFallbackLogicEnabled() {
return mFallbackLogicEnabled;
}
@Override
public void enableFallbackLogic(boolean enable) {
mFallbackLogicEnabled = enable;
}
@Override
public void uninstallAndDisablePackageForAllUsers(Context context, String packageName) {
enablePackageForAllUsers(context, packageName, false);
}
@Override
public void enablePackageForAllUsers(Context context, String packageName, boolean enable) {
enablePackageForUser(packageName, enable, 0);
}
@Override
public void enablePackageForUser(String packageName, boolean enable, int userId) {
PackageInfo packageInfo = mPackages.get(packageName);
if (packageInfo == null) {
throw new IllegalArgumentException("There is no package called " + packageName);
}
packageInfo.applicationInfo.enabled = enable;
setPackageInfo(packageInfo);
}
@Override
public boolean systemIsDebuggable() { return mIsDebuggable; }
@Override
public PackageInfo getPackageInfoForProvider(WebViewProviderInfo info) throws
NameNotFoundException {
PackageInfo ret = mPackages.get(info.packageName);
if (ret == null) throw new NameNotFoundException(info.packageName);
return ret;
}
public void setPackageInfo(PackageInfo pi) {
mPackages.put(pi.packageName, pi);
}
@Override
public int getFactoryPackageVersion(String packageName) {
return 0;
}
}

View File

@@ -0,0 +1,613 @@
/*
* 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 android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.Signature;
import android.os.Bundle;
import android.util.Base64;
import android.test.AndroidTestCase;
import android.webkit.WebViewFactory;
import android.webkit.WebViewProviderInfo;
import android.webkit.WebViewProviderResponse;
import java.util.concurrent.CountDownLatch;
import org.hamcrest.Description;
import org.mockito.Mockito;
import org.mockito.Matchers;
import org.mockito.ArgumentMatcher;
/**
* Tests for WebViewUpdateService
*/
public class WebViewUpdateServiceTest extends AndroidTestCase {
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";
@Override
protected void setUp() throws Exception {
super.setUp();
}
/**
* 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 */));
}
}
private void checkCertainPackageUsedAfterWebViewPreparation(String expectedProviderName,
WebViewProviderInfo[] webviewPackages) {
checkCertainPackageUsedAfterWebViewPreparation(expectedProviderName, webviewPackages, 1);
}
private void checkCertainPackageUsedAfterWebViewPreparation(String expectedProviderName,
WebViewProviderInfo[] webviewPackages, int numRelros) {
setupWithPackages(webviewPackages, true, numRelros);
// Add (enabled and valid) package infos for each provider
setEnabledAndValidPackageInfos(webviewPackages);
mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
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) {
PackageInfo p = new PackageInfo();
p.packageName = packageName;
p.applicationInfo = new ApplicationInfo();
p.applicationInfo.enabled = enabled;
p.applicationInfo.metaData = new Bundle();
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, Signature[] signatures) {
PackageInfo p = createPackageInfo(packageName, enabled, valid);
p.signatures = signatures;
return p;
}
// ****************
// Tests
// ****************
public void testWithSinglePackage() {
String testPackageName = "test.package.name";
checkCertainPackageUsedAfterWebViewPreparation(testPackageName,
new WebViewProviderInfo[] {
new WebViewProviderInfo(testPackageName, "",
true /*default available*/, false /* fallback */, null)});
}
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)};
checkCertainPackageUsedAfterWebViewPreparation(defaultPackage, packages);
}
public void testSeveralRelros() {
String singlePackage = "singlePackage";
checkCertainPackageUsedAfterWebViewPreparation(
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.
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 */, new Signature[]{invalidPackageSignature}));
mTestSystemImpl.setPackageInfo(createPackageInfo(validPackage, true /* enabled */,
true /* valid */, new Signature[]{validSignature}));
mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
Mockito.argThat(new IsPackageInfoWithName(validPackage)));
mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status);
assertEquals(validPackage, response.packageInfo.packageName);
WebViewProviderInfo[] validPackages = mWebViewUpdateServiceImpl.getValidWebViewPackages();
assertEquals(1, validPackages.length);
assertEquals(validPackage, validPackages[0].packageName);
}
public void testFailWaitingForRelro() {
WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
new WebViewProviderInfo("packagename", "", true, true, null)};
setupWithPackages(packages);
setEnabledAndValidPackageInfos(packages);
mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
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);
}
public void testFailListingEmptyWebviewPackages() {
WebViewProviderInfo[] packages = new WebViewProviderInfo[0];
setupWithPackages(packages);
setEnabledAndValidPackageInfos(packages);
mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
Mockito.verify(mTestSystemImpl, Mockito.never()).onWebViewProviderChanged(
Matchers.anyObject());
WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status);
}
public void testFailListingInvalidWebviewPackage() {
WebViewProviderInfo wpi = new WebViewProviderInfo("", "", true, true, null);
WebViewProviderInfo[] packages = new WebViewProviderInfo[] {wpi};
setupWithPackages(packages);
mTestSystemImpl.setPackageInfo(createPackageInfo(wpi.packageName, true, false));
mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status);
}
// Test that switching provider using changeProviderAndSetting works.
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);
}
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) {
checkCertainPackageUsedAfterWebViewPreparation(initialPackage, packages);
mWebViewUpdateServiceImpl.changeProviderAndSetting(finalPackage);
Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
Mockito.argThat(new IsPackageInfoWithName(finalPackage)));
mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
WebViewProviderResponse secondResponse = mWebViewUpdateServiceImpl.waitForAndGetProvider();
assertEquals(WebViewFactory.LIBLOAD_SUCCESS, secondResponse.status);
assertEquals(finalPackage, secondResponse.packageInfo.packageName);
Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(initialPackage));
}
// Change provider during relro creation by using changeProviderAndSetting
public void testSwitchingProviderDuringRelroCreation() {
checkChangingProviderDuringRelroCreation(true);
}
// Change provider during relro creation by enabling a provider
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 */));
}
}
CountDownLatch countdown = new CountDownLatch(1);
mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
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(1000); // 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 */));
mWebViewUpdateServiceImpl.packageStateChanged(
secondPackage, WebViewUpdateService.PACKAGE_CHANGED);
}
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) {
}
}
public void testRunFallbackLogicIfEnabled() {
checkFallbackLogicBeingRun(true);
}
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);
mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
// 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 */));
mWebViewUpdateServiceImpl.packageStateChanged(
fallbackPackage, WebViewUpdateService.PACKAGE_CHANGED);
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
*/
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 */));
mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
Mockito.verify(mTestSystemImpl, Mockito.never()).uninstallAndDisablePackageForAllUsers(
Matchers.anyObject(), Matchers.anyObject());
Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
Mockito.argThat(new IsPackageInfoWithName(fallbackPackage)));
mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status);
assertEquals(fallbackPackage, response.packageInfo.packageName);
// Install primary package
mTestSystemImpl.setPackageInfo(
createPackageInfo(primaryPackage, true /* enabled */ , true /* valid */));
mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
WebViewUpdateService.PACKAGE_ADDED);
// Verify fallback disabled and primary package used as provider
Mockito.verify(mTestSystemImpl).uninstallAndDisablePackageForAllUsers(
Matchers.anyObject(), Mockito.eq(fallbackPackage));
Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
Mockito.argThat(new IsPackageInfoWithName(primaryPackage)));
// Finish the webview preparation and ensure primary package used and fallback killed
mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status);
assertEquals(primaryPackage, response.packageInfo.packageName);
Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(fallbackPackage));
}
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);
mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
// Verify fallback disabled at boot when primary package enabled
Mockito.verify(mTestSystemImpl).enablePackageForUser(
Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */,
Matchers.anyInt());
mTestSystemImpl.setPackageInfo(
createPackageInfo(primaryPackage, false /* enabled */, true /* valid */));
mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
WebViewUpdateService.PACKAGE_CHANGED);
// Verify fallback becomes enabled when primary package becomes disabled
Mockito.verify(mTestSystemImpl).enablePackageForUser(
Mockito.eq(fallbackPackage), Mockito.eq(true) /* enable */,
Matchers.anyInt());
mTestSystemImpl.setPackageInfo(
createPackageInfo(primaryPackage, true /* enabled */, true /* valid */));
mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
WebViewUpdateService.PACKAGE_CHANGED);
// 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());
}
public void testAddUserWhenFallbackLogicEnabled() {
checkAddingNewUser(true);
}
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.
*/
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);
mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
Mockito.argThat(new IsPackageInfoWithName(firstPackage)));
mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage);
// Make packages invalid to cause exception to be thrown
mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, true /* enabled */,
false /* valid */));
mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
false /* valid */));
// 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 */));
mWebViewUpdateServiceImpl.packageStateChanged(firstPackage,
WebViewUpdateService.PACKAGE_ADDED);
// Second time we call onWebViewProviderChanged for firstPackage
Mockito.verify(mTestSystemImpl, Mockito.times(2)).onWebViewProviderChanged(
Mockito.argThat(new IsPackageInfoWithName(firstPackage)));
mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status);
assertEquals(firstPackage, response.packageInfo.packageName);
}
// TODO (gsennton) add more tests for ensuring killPackageDependents is called / not called
}