Merge "Migrate away from WebView fallback logic."
This commit is contained in:
committed by
Android (Google) Code Review
commit
d5cfd7f985
@@ -77,11 +77,6 @@ interface IWebViewUpdateService {
|
||||
@UnsupportedAppUsage
|
||||
boolean isFallbackPackage(String packageName);
|
||||
|
||||
/**
|
||||
* Enable or disable the WebView package fallback mechanism.
|
||||
*/
|
||||
void enableFallbackLogic(boolean enable);
|
||||
|
||||
/**
|
||||
* Used by Settings to determine whether multiprocess is enabled.
|
||||
*/
|
||||
|
||||
@@ -19,19 +19,15 @@ package com.android.server.webkit;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.AppGlobals;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.IPackageDeleteObserver;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.database.ContentObserver;
|
||||
import android.os.Build;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings.Global;
|
||||
import android.provider.Settings;
|
||||
import android.util.AndroidRuntimeException;
|
||||
import android.util.Log;
|
||||
@@ -42,12 +38,12 @@ import android.webkit.WebViewZygote;
|
||||
|
||||
import com.android.internal.util.XmlUtils;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
/**
|
||||
* Default implementation for the WebView preparation Utility interface.
|
||||
* @hide
|
||||
@@ -77,7 +73,6 @@ public class SystemImpl implements SystemInterface {
|
||||
private SystemImpl() {
|
||||
int numFallbackPackages = 0;
|
||||
int numAvailableByDefaultPackages = 0;
|
||||
int numAvByDefaultAndNotFallback = 0;
|
||||
XmlResourceParser parser = null;
|
||||
List<WebViewProviderInfo> webViewProviders = new ArrayList<WebViewProviderInfo>();
|
||||
try {
|
||||
@@ -121,9 +116,6 @@ public class SystemImpl implements SystemInterface {
|
||||
}
|
||||
if (currentProvider.availableByDefault) {
|
||||
numAvailableByDefaultPackages++;
|
||||
if (!currentProvider.isFallback) {
|
||||
numAvByDefaultAndNotFallback++;
|
||||
}
|
||||
}
|
||||
webViewProviders.add(currentProvider);
|
||||
}
|
||||
@@ -140,10 +132,6 @@ public class SystemImpl implements SystemInterface {
|
||||
throw new AndroidRuntimeException("There must be at least one WebView package "
|
||||
+ "that is available by default");
|
||||
}
|
||||
if (numAvByDefaultAndNotFallback == 0) {
|
||||
throw new AndroidRuntimeException("There must be at least one WebView package "
|
||||
+ "that is available by default and not a fallback");
|
||||
}
|
||||
mWebViewProviderPackages =
|
||||
webViewProviders.toArray(new WebViewProviderInfo[webViewProviders.size()]);
|
||||
}
|
||||
@@ -221,23 +209,6 @@ public class SystemImpl implements SystemInterface {
|
||||
Settings.Global.WEBVIEW_FALLBACK_LOGIC_ENABLED, enable ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninstallAndDisablePackageForAllUsers(Context context, String packageName) {
|
||||
enablePackageForAllUsers(context, packageName, false);
|
||||
try {
|
||||
PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
|
||||
ApplicationInfo applicationInfo = pm.getApplicationInfo(packageName, 0);
|
||||
if (applicationInfo != null && applicationInfo.isUpdatedSystemApp()) {
|
||||
pm.deletePackage(packageName, new IPackageDeleteObserver.Stub() {
|
||||
public void packageDeleted(String packageName, int returnCode) {
|
||||
enablePackageForAllUsers(context, packageName, false);
|
||||
}
|
||||
}, PackageManager.DELETE_SYSTEM_APP | PackageManager.DELETE_ALL_USERS);
|
||||
}
|
||||
} catch (NameNotFoundException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enablePackageForAllUsers(Context context, String packageName, boolean enable) {
|
||||
UserManager userManager = (UserManager)context.getSystemService(Context.USER_SERVICE);
|
||||
@@ -246,8 +217,7 @@ public class SystemImpl implements SystemInterface {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enablePackageForUser(String packageName, boolean enable, int userId) {
|
||||
private void enablePackageForUser(String packageName, boolean enable, int userId) {
|
||||
try {
|
||||
AppGlobals.getPackageManager().setApplicationEnabledSetting(
|
||||
packageName,
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.android.server.webkit;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.database.ContentObserver;
|
||||
import android.webkit.UserPackage;
|
||||
import android.webkit.WebViewProviderInfo;
|
||||
|
||||
@@ -45,9 +44,7 @@ public interface SystemInterface {
|
||||
public boolean isFallbackLogicEnabled();
|
||||
public void enableFallbackLogic(boolean enable);
|
||||
|
||||
public void uninstallAndDisablePackageForAllUsers(Context context, String packageName);
|
||||
public void enablePackageForAllUsers(Context context, String packageName, boolean enable);
|
||||
public void enablePackageForUser(String packageName, boolean enable, int userId);
|
||||
|
||||
public boolean systemIsDebuggable();
|
||||
public PackageInfo getPackageInfoForProvider(WebViewProviderInfo configInfo)
|
||||
|
||||
@@ -242,28 +242,7 @@ public class WebViewUpdateService extends SystemService {
|
||||
|
||||
@Override // Binder call
|
||||
public boolean isFallbackPackage(String packageName) {
|
||||
return WebViewUpdateService.this.mImpl.isFallbackPackage(packageName);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void enableFallbackLogic(boolean enable) {
|
||||
if (getContext().checkCallingPermission(
|
||||
android.Manifest.permission.WRITE_SECURE_SETTINGS)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
String msg = "Permission Denial: enableFallbackLogic() from pid="
|
||||
+ Binder.getCallingPid()
|
||||
+ ", uid=" + Binder.getCallingUid()
|
||||
+ " requires " + android.Manifest.permission.WRITE_SECURE_SETTINGS;
|
||||
Slog.w(TAG, msg);
|
||||
throw new SecurityException(msg);
|
||||
}
|
||||
|
||||
long callingId = Binder.clearCallingIdentity();
|
||||
try {
|
||||
WebViewUpdateService.this.mImpl.enableFallbackLogic(enable);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(callingId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
|
||||
@@ -16,48 +16,36 @@
|
||||
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.UserHandle;
|
||||
import android.util.Slog;
|
||||
import android.webkit.UserPackage;
|
||||
import android.webkit.WebViewProviderInfo;
|
||||
import android.webkit.WebViewProviderResponse;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.Integer;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Implementation of the WebViewUpdateService.
|
||||
* This class doesn't depend on the android system like the actual Service does and can be used
|
||||
* directly by tests (as long as they implement a SystemInterface).
|
||||
*
|
||||
* This class implements two main features - handling WebView fallback packages and keeping track
|
||||
* of, and preparing, the current WebView implementation. The fallback mechanism is meant to be
|
||||
* uncoupled from the rest of the WebView preparation and does not store any state. The code for
|
||||
* choosing and preparing a WebView implementation needs to keep track of a couple of different
|
||||
* things such as what package is used as WebView implementation.
|
||||
* This class keeps track of and prepares the current WebView implementation, and needs to keep
|
||||
* track of a couple of different things such as what package is used as WebView implementation.
|
||||
*
|
||||
* The public methods in this class are accessed from WebViewUpdateService either on the UI thread
|
||||
* or on one of multiple Binder threads. This means that the code in this class needs to be
|
||||
* thread-safe. The fallback mechanism shares (almost) no information between threads which makes
|
||||
* it easier to argue about thread-safety (in theory, if timed badly, the fallback mechanism can
|
||||
* incorrectly enable/disable a fallback package but that fault will be corrected when we later
|
||||
* receive an intent for that enabling/disabling). On the other hand, the WebView preparation code
|
||||
* shares state between threads meaning that code that chooses a new WebView implementation or
|
||||
* checks which implementation is being used needs to hold a lock.
|
||||
* or on one of multiple Binder threads. The WebView preparation code shares state between threads
|
||||
* meaning that code that chooses a new WebView implementation or checks which implementation is
|
||||
* being used needs to hold a lock.
|
||||
*
|
||||
* The WebViewUpdateService can be accessed in a couple of different ways.
|
||||
* 1. It is started from the SystemServer at boot - at that point we just initiate some state such
|
||||
* as the WebView preparation class.
|
||||
* 2. The SystemServer calls WebViewUpdateService.prepareWebViewInSystemServer. This happens at boot
|
||||
* and the WebViewUpdateService should not have been accessed before this call. In this call we
|
||||
* enable/disable fallback packages and then choose WebView implementation for the first time.
|
||||
* migrate away from the old fallback logic if necessary and then choose WebView implementation for
|
||||
* the first time.
|
||||
* 3. The update service listens for Intents related to package installs and removals. These intents
|
||||
* are received and processed on the UI thread. Each intent can result in enabling/disabling
|
||||
* fallback packages and changing WebView implementation.
|
||||
* are received and processed on the UI thread. Each intent can result in changing WebView
|
||||
* implementation.
|
||||
* 4. The update service can be reached through Binder calls which are handled on specific binder
|
||||
* threads. These calls can be made from any process. Generally they are used for changing WebView
|
||||
* implementation (from Settings), getting information about the current WebView implementation (for
|
||||
@@ -86,35 +74,15 @@ public class WebViewUpdateServiceImpl {
|
||||
// We don't early out here in different cases where we could potentially early-out (e.g. if
|
||||
// we receive PACKAGE_CHANGED for another user than the system user) since that would
|
||||
// complicate this logic further and open up for more edge cases.
|
||||
updateFallbackStateOnPackageChange(packageName, changedState);
|
||||
mWebViewUpdater.packageStateChanged(packageName, changedState);
|
||||
}
|
||||
|
||||
void prepareWebViewInSystemServer() {
|
||||
updateFallbackStateOnBoot();
|
||||
migrateFallbackStateOnBoot();
|
||||
mWebViewUpdater.prepareWebViewInSystemServer();
|
||||
mSystemInterface.notifyZygote(isMultiProcessEnabled());
|
||||
}
|
||||
|
||||
private boolean existsValidNonFallbackProvider(WebViewProviderInfo[] providers) {
|
||||
for (WebViewProviderInfo provider : providers) {
|
||||
if (provider.availableByDefault && !provider.isFallback) {
|
||||
// userPackages can contain null objects.
|
||||
List<UserPackage> userPackages =
|
||||
mSystemInterface.getPackageInfoForProviderAllUsers(mContext, provider);
|
||||
if (WebViewUpdater.isInstalledAndEnabledForAllUsers(userPackages) &&
|
||||
// Checking validity of the package for the system user (rather than all
|
||||
// users) since package validity depends not on the user but on the package
|
||||
// itself.
|
||||
mWebViewUpdater.isValidProvider(provider,
|
||||
userPackages.get(UserHandle.USER_SYSTEM).getPackageInfo())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void handleNewUser(int userId) {
|
||||
// The system user is always started at boot, and by that point we have already run one
|
||||
// round of the package-changing logic (through prepareWebViewInSystemServer()), so early
|
||||
@@ -128,14 +96,11 @@ public class WebViewUpdateServiceImpl {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a user was added or removed to ensure fallback logic and WebView preparation are
|
||||
* triggered. This has to be done since the WebView package we use depends on the enabled-state
|
||||
* Called when a user was added or removed to ensure WebView preparation is triggered.
|
||||
* This has to be done since the WebView package we use depends on the enabled-state
|
||||
* of packages for all users (so adding or removing a user might cause us to change package).
|
||||
*/
|
||||
private void handleUserChange() {
|
||||
if (mSystemInterface.isFallbackLogicEnabled()) {
|
||||
updateFallbackState(mSystemInterface.getWebViewPackages());
|
||||
}
|
||||
// Potentially trigger package-changing logic.
|
||||
mWebViewUpdater.updateCurrentWebViewPackage(null);
|
||||
}
|
||||
@@ -164,60 +129,22 @@ public class WebViewUpdateServiceImpl {
|
||||
return mWebViewUpdater.getCurrentWebViewPackage();
|
||||
}
|
||||
|
||||
void enableFallbackLogic(boolean enable) {
|
||||
mSystemInterface.enableFallbackLogic(enable);
|
||||
}
|
||||
|
||||
private void updateFallbackStateOnBoot() {
|
||||
if (!mSystemInterface.isFallbackLogicEnabled()) return;
|
||||
|
||||
WebViewProviderInfo[] webviewProviders = mSystemInterface.getWebViewPackages();
|
||||
updateFallbackState(webviewProviders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the enabled-state of our fallback package, i.e. if there exists some non-fallback
|
||||
* package that is valid (and available by default) then disable the fallback package,
|
||||
* otherwise, enable the fallback package.
|
||||
* If the fallback logic is enabled, re-enable any fallback package for all users, then
|
||||
* disable the fallback logic.
|
||||
*
|
||||
* This migrates away from the old fallback mechanism to the new state where packages are never
|
||||
* automatically enableenableisabled.
|
||||
*/
|
||||
private void updateFallbackStateOnPackageChange(String changedPackage, int changedState) {
|
||||
private void migrateFallbackStateOnBoot() {
|
||||
if (!mSystemInterface.isFallbackLogicEnabled()) return;
|
||||
|
||||
WebViewProviderInfo[] webviewProviders = mSystemInterface.getWebViewPackages();
|
||||
|
||||
// A package was changed / updated / downgraded, early out if it is not one of the
|
||||
// webview packages that are available by default.
|
||||
boolean changedPackageAvailableByDefault = false;
|
||||
for (WebViewProviderInfo provider : webviewProviders) {
|
||||
if (provider.packageName.equals(changedPackage)) {
|
||||
if (provider.availableByDefault) {
|
||||
changedPackageAvailableByDefault = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!changedPackageAvailableByDefault) return;
|
||||
updateFallbackState(webviewProviders);
|
||||
}
|
||||
|
||||
private void updateFallbackState(WebViewProviderInfo[] webviewProviders) {
|
||||
// If there exists a valid and enabled non-fallback package - disable the fallback
|
||||
// package, otherwise, enable it.
|
||||
WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewProviders);
|
||||
if (fallbackProvider == null) return;
|
||||
boolean existsValidNonFallbackProvider = existsValidNonFallbackProvider(webviewProviders);
|
||||
|
||||
List<UserPackage> userPackages =
|
||||
mSystemInterface.getPackageInfoForProviderAllUsers(mContext, fallbackProvider);
|
||||
if (existsValidNonFallbackProvider && !isDisabledForAllUsers(userPackages)) {
|
||||
mSystemInterface.uninstallAndDisablePackageForAllUsers(mContext,
|
||||
fallbackProvider.packageName);
|
||||
} else if (!existsValidNonFallbackProvider
|
||||
&& !WebViewUpdater.isInstalledAndEnabledForAllUsers(userPackages)) {
|
||||
// Enable the fallback package for all users.
|
||||
mSystemInterface.enablePackageForAllUsers(mContext,
|
||||
fallbackProvider.packageName, true);
|
||||
if (fallbackProvider != null) {
|
||||
mSystemInterface.enablePackageForAllUsers(mContext, fallbackProvider.packageName, true);
|
||||
}
|
||||
mSystemInterface.enableFallbackLogic(false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,15 +159,6 @@ public class WebViewUpdateServiceImpl {
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean isFallbackPackage(String packageName) {
|
||||
if (packageName == null || !mSystemInterface.isFallbackLogicEnabled()) return false;
|
||||
|
||||
WebViewProviderInfo[] webviewPackages = mSystemInterface.getWebViewPackages();
|
||||
WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewPackages);
|
||||
return (fallbackProvider != null
|
||||
&& packageName.equals(fallbackProvider.packageName));
|
||||
}
|
||||
|
||||
boolean isMultiProcessEnabled() {
|
||||
int settingValue = mSystemInterface.getMultiProcessSetting(mContext);
|
||||
if (mSystemInterface.isMultiProcessDefaultEnabled()) {
|
||||
@@ -262,15 +180,6 @@ public class WebViewUpdateServiceImpl {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isDisabledForAllUsers(List<UserPackage> userPackages) {
|
||||
for (UserPackage userPackage : userPackages) {
|
||||
if (userPackage.getPackageInfo() != null && userPackage.isEnabledPackage()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump the state of this Service.
|
||||
*/
|
||||
|
||||
@@ -37,10 +37,6 @@ class WebViewUpdateServiceShellCommand extends ShellCommand {
|
||||
final PrintWriter pw = getOutPrintWriter();
|
||||
try {
|
||||
switch(cmd) {
|
||||
case "enable-redundant-packages":
|
||||
return enableFallbackLogic(false);
|
||||
case "disable-redundant-packages":
|
||||
return enableFallbackLogic(true);
|
||||
case "set-webview-implementation":
|
||||
return setWebViewImplementation();
|
||||
case "enable-multiprocess":
|
||||
@@ -56,13 +52,6 @@ class WebViewUpdateServiceShellCommand extends ShellCommand {
|
||||
return -1;
|
||||
}
|
||||
|
||||
private int enableFallbackLogic(boolean enable) throws RemoteException {
|
||||
final PrintWriter pw = getOutPrintWriter();
|
||||
mInterface.enableFallbackLogic(enable);
|
||||
pw.println("Success");
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int setWebViewImplementation() throws RemoteException {
|
||||
final PrintWriter pw = getOutPrintWriter();
|
||||
String shellChosenPackage = getNextArg();
|
||||
@@ -104,13 +93,6 @@ class WebViewUpdateServiceShellCommand extends ShellCommand {
|
||||
pw.println(" help");
|
||||
pw.println(" Print this help text.");
|
||||
pw.println("");
|
||||
pw.println(" enable-redundant-packages");
|
||||
pw.println(" Allow a fallback package to be installed and enabled even when a");
|
||||
pw.println(" more-preferred package is available. This command is useful when testing");
|
||||
pw.println(" fallback packages.");
|
||||
pw.println(" disable-redundant-packages");
|
||||
pw.println(" Disallow installing and enabling fallback packages when a more-preferred");
|
||||
pw.println(" package is available.");
|
||||
helpSetWebViewImplementation();
|
||||
pw.println(" enable-multiprocess");
|
||||
pw.println(" Enable multi-process mode for WebView");
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.Signature;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Base64;
|
||||
import android.util.Slog;
|
||||
import android.webkit.UserPackage;
|
||||
import android.webkit.WebViewFactory;
|
||||
@@ -29,7 +28,6 @@ import android.webkit.WebViewProviderResponse;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -140,13 +138,17 @@ class WebViewUpdater {
|
||||
try {
|
||||
synchronized(mLock) {
|
||||
mCurrentWebViewPackage = findPreferredWebViewPackage();
|
||||
// Don't persist the user-chosen setting across boots if the package being
|
||||
// chosen is not used (could be disabled or uninstalled) so that the user won't
|
||||
// be surprised by the device switching to using a certain webview package,
|
||||
// that was uninstalled/disabled a long time ago, if it is installed/enabled
|
||||
// again.
|
||||
mSystemInterface.updateUserSetting(mContext,
|
||||
mCurrentWebViewPackage.packageName);
|
||||
String userSetting = mSystemInterface.getUserChosenWebViewProvider(mContext);
|
||||
if (userSetting != null
|
||||
&& !userSetting.equals(mCurrentWebViewPackage.packageName)) {
|
||||
// Don't persist the user-chosen setting across boots if the package being
|
||||
// chosen is not used (could be disabled or uninstalled) so that the user won't
|
||||
// be surprised by the device switching to using a certain webview package,
|
||||
// that was uninstalled/disabled a long time ago, if it is installed/enabled
|
||||
// again.
|
||||
mSystemInterface.updateUserSetting(mContext,
|
||||
mCurrentWebViewPackage.packageName);
|
||||
}
|
||||
onWebViewProviderChanged(mCurrentWebViewPackage);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
@@ -470,9 +472,9 @@ class WebViewUpdater {
|
||||
|
||||
/**
|
||||
* Gets the minimum version code allowed for a valid provider. It is the minimum versionCode
|
||||
* of all available-by-default and non-fallback WebView provider packages. If there is no
|
||||
* such WebView provider package on the system, then return -1, which means all positive
|
||||
* versionCode WebView packages are accepted.
|
||||
* of all available-by-default WebView provider packages. If there is no such WebView provider
|
||||
* package on the system, then return -1, which means all positive versionCode WebView packages
|
||||
* are accepted.
|
||||
*
|
||||
* Note that this is a private method in WebViewUpdater that handles a variable
|
||||
* (mMinimumVersionCode) which is shared between threads. Furthermore, this method does not
|
||||
@@ -485,7 +487,7 @@ class WebViewUpdater {
|
||||
|
||||
long minimumVersionCode = -1;
|
||||
for (WebViewProviderInfo provider : mSystemInterface.getWebViewPackages()) {
|
||||
if (provider.availableByDefault && !provider.isFallback) {
|
||||
if (provider.availableByDefault) {
|
||||
try {
|
||||
long versionCode =
|
||||
mSystemInterface.getFactoryPackageVersion(provider.packageName);
|
||||
|
||||
@@ -87,11 +87,6 @@ public class TestSystemImpl implements SystemInterface {
|
||||
mFallbackLogicEnabled = enable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninstallAndDisablePackageForAllUsers(Context context, String packageName) {
|
||||
enablePackageForAllUsers(context, packageName, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enablePackageForAllUsers(Context context, String packageName, boolean enable) {
|
||||
for(int userId : mUsers) {
|
||||
@@ -99,8 +94,7 @@ public class TestSystemImpl implements SystemInterface {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enablePackageForUser(String packageName, boolean enable, int userId) {
|
||||
private void enablePackageForUser(String packageName, boolean enable, int userId) {
|
||||
Map<Integer, PackageInfo> userPackages = mPackages.get(packageName);
|
||||
if (userPackages == null) {
|
||||
throw new IllegalArgumentException("There is no package called " + packageName);
|
||||
|
||||
@@ -41,7 +41,6 @@ import org.mockito.ArgumentMatcher;
|
||||
import org.mockito.Matchers;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.lang.Integer;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
/**
|
||||
@@ -68,27 +67,32 @@ public class WebViewUpdateServiceTest {
|
||||
}
|
||||
|
||||
private void setupWithPackages(WebViewProviderInfo[] packages) {
|
||||
setupWithPackages(packages, true);
|
||||
setupWithAllParameters(packages, false /* fallbackLogicEnabled */, 1 /* numRelros */,
|
||||
true /* isDebuggable */, false /* multiProcessDefault */);
|
||||
}
|
||||
|
||||
private void setupWithPackages(WebViewProviderInfo[] packages,
|
||||
boolean fallbackLogicEnabled) {
|
||||
setupWithPackages(packages, fallbackLogicEnabled, 1);
|
||||
private void setupWithPackagesAndFallbackLogic(WebViewProviderInfo[] packages) {
|
||||
setupWithAllParameters(packages, true /* fallbackLogicEnabled */, 1 /* numRelros */,
|
||||
true /* isDebuggable */, false /* multiProcessDefault */);
|
||||
}
|
||||
|
||||
private void setupWithPackages(WebViewProviderInfo[] packages,
|
||||
boolean fallbackLogicEnabled, int numRelros) {
|
||||
setupWithPackages(packages, fallbackLogicEnabled, numRelros,
|
||||
true /* isDebuggable == true -> don't check package signatures */);
|
||||
private void setupWithPackagesAndRelroCount(WebViewProviderInfo[] packages, int numRelros) {
|
||||
setupWithAllParameters(packages, false /* fallbackLogicEnabled */, numRelros,
|
||||
true /* isDebuggable */, false /* multiProcessDefault */);
|
||||
}
|
||||
|
||||
private void setupWithPackages(WebViewProviderInfo[] packages,
|
||||
boolean fallbackLogicEnabled, int numRelros, boolean isDebuggable) {
|
||||
setupWithPackages(packages, fallbackLogicEnabled, numRelros, isDebuggable,
|
||||
false /* multiProcessDefault */);
|
||||
private void setupWithPackagesNonDebuggable(WebViewProviderInfo[] packages) {
|
||||
setupWithAllParameters(packages, false /* fallbackLogicEnabled */, 1 /* numRelros */,
|
||||
false /* isDebuggable */, false /* multiProcessDefault */);
|
||||
}
|
||||
|
||||
private void setupWithPackages(WebViewProviderInfo[] packages,
|
||||
private void setupWithPackagesAndMultiProcess(WebViewProviderInfo[] packages,
|
||||
boolean multiProcessDefault) {
|
||||
setupWithAllParameters(packages, false /* fallbackLogicEnabled */, 1 /* numRelros */,
|
||||
true /* isDebuggable */, multiProcessDefault);
|
||||
}
|
||||
|
||||
private void setupWithAllParameters(WebViewProviderInfo[] packages,
|
||||
boolean fallbackLogicEnabled, int numRelros, boolean isDebuggable,
|
||||
boolean multiProcessDefault) {
|
||||
TestSystemImpl testing = new TestSystemImpl(packages, fallbackLogicEnabled, numRelros,
|
||||
@@ -119,7 +123,7 @@ public class WebViewUpdateServiceTest {
|
||||
|
||||
private void checkCertainPackageUsedAfterWebViewBootPreparation(String expectedProviderName,
|
||||
WebViewProviderInfo[] webviewPackages, int numRelros) {
|
||||
setupWithPackages(webviewPackages, true, numRelros);
|
||||
setupWithPackagesAndRelroCount(webviewPackages, numRelros);
|
||||
// Add (enabled and valid) package infos for each provider
|
||||
setEnabledAndValidPackageInfos(webviewPackages);
|
||||
|
||||
@@ -289,8 +293,7 @@ public class WebViewUpdateServiceTest {
|
||||
Base64.encodeToString(
|
||||
validSignature.toByteArray(), Base64.DEFAULT)})
|
||||
};
|
||||
setupWithPackages(packages, true /* fallback logic enabled */, 1 /* numRelros */,
|
||||
false /* isDebuggable */);
|
||||
setupWithPackagesNonDebuggable(packages);
|
||||
mTestSystemImpl.setPackageInfo(createPackageInfo(invalidPackage, true /* enabled */,
|
||||
true /* valid */, true /* installed */, new Signature[]{invalidPackageSignature}
|
||||
, 0 /* updateTime */));
|
||||
@@ -510,82 +513,75 @@ public class WebViewUpdateServiceTest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario for testing migrating away from the fallback logic.
|
||||
* We start with a primary package that's a disabled fallback, and an enabled secondary,
|
||||
* so that the fallback being re-enabled will cause a provider switch, as that covers
|
||||
* the most complex case.
|
||||
*/
|
||||
@Test
|
||||
public void testRunFallbackLogicIfEnabled() {
|
||||
checkFallbackLogicBeingRun(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDontRunFallbackLogicIfDisabled() {
|
||||
checkFallbackLogicBeingRun(false);
|
||||
}
|
||||
|
||||
private void checkFallbackLogicBeingRun(boolean fallbackLogicEnabled) {
|
||||
public void testFallbackLogicMigration() {
|
||||
String primaryPackage = "primary";
|
||||
String fallbackPackage = "fallback";
|
||||
String secondaryPackage = "secondary";
|
||||
WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
|
||||
new WebViewProviderInfo(
|
||||
primaryPackage, "", true /* default available */, false /* fallback */, null),
|
||||
primaryPackage, "", true /* default available */, true /* fallback */, null),
|
||||
new WebViewProviderInfo(
|
||||
fallbackPackage, "", true /* default available */, true /* fallback */, null)};
|
||||
setupWithPackages(packages, fallbackLogicEnabled);
|
||||
setEnabledAndValidPackageInfos(packages);
|
||||
secondaryPackage, "", true /* default available */, false /* fallback */,
|
||||
null)};
|
||||
setupWithPackagesAndFallbackLogic(packages);
|
||||
mTestSystemImpl.setPackageInfo(
|
||||
createPackageInfo(primaryPackage, false /* enabled */ , true /* valid */,
|
||||
true /* installed */));
|
||||
mTestSystemImpl.setPackageInfo(
|
||||
createPackageInfo(secondaryPackage, true /* enabled */ , true /* valid */,
|
||||
true /* installed */));
|
||||
|
||||
// Check that the boot time logic re-enables and chooses the primary, and disables the
|
||||
// fallback logic.
|
||||
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)));
|
||||
Mockito.verify(mTestSystemImpl).enablePackageForAllUsers(
|
||||
Matchers.anyObject(), Mockito.eq(primaryPackage), Mockito.eq(true));
|
||||
checkPreparationPhasesForPackage(primaryPackage, 1);
|
||||
assertFalse(mTestSystemImpl.isFallbackLogicEnabled());
|
||||
|
||||
// Enable fallback package
|
||||
mTestSystemImpl.setPackageInfo(createPackageInfo(fallbackPackage, true /* enabled */,
|
||||
// Disable primary again
|
||||
mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, false /* enabled */,
|
||||
true /* valid */, true /* installed */));
|
||||
mWebViewUpdateServiceImpl.packageStateChanged(
|
||||
fallbackPackage, WebViewUpdateService.PACKAGE_CHANGED, TestSystemImpl.PRIMARY_USER_ID);
|
||||
mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
|
||||
WebViewUpdateService.PACKAGE_CHANGED, TestSystemImpl.PRIMARY_USER_ID);
|
||||
checkPreparationPhasesForPackage(secondaryPackage, 1);
|
||||
|
||||
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());
|
||||
}
|
||||
// Run boot logic again and check that we didn't re-enable the primary a second time.
|
||||
runWebViewBootPreparationOnMainSync();
|
||||
Mockito.verify(mTestSystemImpl, Mockito.times(1)).enablePackageForAllUsers(
|
||||
Matchers.anyObject(), Mockito.eq(primaryPackage), Mockito.eq(true));
|
||||
checkPreparationPhasesForPackage(secondaryPackage, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario for installing primary package when fallback enabled.
|
||||
* 1. Start with only fallback installed
|
||||
* 2. Install non-fallback
|
||||
* 3. Fallback should be disabled
|
||||
* Scenario for installing primary package when secondary in use.
|
||||
* 1. Start with only secondary installed
|
||||
* 2. Install primary
|
||||
* 3. Primary should be used
|
||||
*/
|
||||
@Test
|
||||
public void testInstallingNonFallbackPackage() {
|
||||
public void testInstallingPrimaryPackage() {
|
||||
String primaryPackage = "primary";
|
||||
String fallbackPackage = "fallback";
|
||||
String secondaryPackage = "secondary";
|
||||
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 */);
|
||||
secondaryPackage, "", true /* default available */, false /* fallback */,
|
||||
null)};
|
||||
setupWithPackages(packages);
|
||||
mTestSystemImpl.setPackageInfo(
|
||||
createPackageInfo(fallbackPackage, true /* enabled */ , true /* valid */,
|
||||
createPackageInfo(secondaryPackage, true /* enabled */ , true /* valid */,
|
||||
true /* installed */));
|
||||
|
||||
runWebViewBootPreparationOnMainSync();
|
||||
Mockito.verify(mTestSystemImpl, Mockito.never()).uninstallAndDisablePackageForAllUsers(
|
||||
Matchers.anyObject(), Matchers.anyObject());
|
||||
|
||||
checkPreparationPhasesForPackage(fallbackPackage,
|
||||
checkPreparationPhasesForPackage(secondaryPackage,
|
||||
1 /* first preparation for this package*/);
|
||||
|
||||
// Install primary package
|
||||
@@ -595,24 +591,22 @@ public class WebViewUpdateServiceTest {
|
||||
mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
|
||||
WebViewUpdateService.PACKAGE_ADDED_REPLACED, TestSystemImpl.PRIMARY_USER_ID);
|
||||
|
||||
// Verify fallback disabled, primary package used as provider, and fallback package killed
|
||||
Mockito.verify(mTestSystemImpl).uninstallAndDisablePackageForAllUsers(
|
||||
Matchers.anyObject(), Mockito.eq(fallbackPackage));
|
||||
// Verify primary package used as provider, and secondary package killed
|
||||
checkPreparationPhasesForPackage(primaryPackage, 1 /* first preparation for this package*/);
|
||||
Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(fallbackPackage));
|
||||
Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(secondaryPackage));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFallbackChangesEnabledStateSingleUser() {
|
||||
public void testRemovingPrimarySelectsSecondarySingleUser() {
|
||||
for (PackageRemovalType removalType : REMOVAL_TYPES) {
|
||||
checkFallbackChangesEnabledState(false /* multiUser */, removalType);
|
||||
checkRemovingPrimarySelectsSecondary(false /* multiUser */, removalType);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFallbackChangesEnabledStateMultiUser() {
|
||||
public void testRemovingPrimarySelectsSecondaryMultiUser() {
|
||||
for (PackageRemovalType removalType : REMOVAL_TYPES) {
|
||||
checkFallbackChangesEnabledState(true /* multiUser */, removalType);
|
||||
checkRemovingPrimarySelectsSecondary(true /* multiUser */, removalType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -626,16 +620,17 @@ public class WebViewUpdateServiceTest {
|
||||
|
||||
private PackageRemovalType[] REMOVAL_TYPES = PackageRemovalType.class.getEnumConstants();
|
||||
|
||||
public void checkFallbackChangesEnabledState(boolean multiUser,
|
||||
public void checkRemovingPrimarySelectsSecondary(boolean multiUser,
|
||||
PackageRemovalType removalType) {
|
||||
String primaryPackage = "primary";
|
||||
String fallbackPackage = "fallback";
|
||||
String secondaryPackage = "secondary";
|
||||
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 */);
|
||||
secondaryPackage, "", true /* default available */, false /* fallback */,
|
||||
null)};
|
||||
setupWithPackages(packages);
|
||||
int secondaryUserId = 10;
|
||||
int userIdToChangePackageFor = multiUser ? secondaryUserId : TestSystemImpl.PRIMARY_USER_ID;
|
||||
if (multiUser) {
|
||||
@@ -645,18 +640,12 @@ public class WebViewUpdateServiceTest {
|
||||
setEnabledAndValidPackageInfosForUser(TestSystemImpl.PRIMARY_USER_ID, packages);
|
||||
|
||||
runWebViewBootPreparationOnMainSync();
|
||||
|
||||
// Verify fallback disabled at boot when primary package enabled
|
||||
checkEnablePackageForUserCalled(fallbackPackage, false, multiUser
|
||||
? new int[] {TestSystemImpl.PRIMARY_USER_ID, secondaryUserId}
|
||||
: new int[] {TestSystemImpl.PRIMARY_USER_ID}, 1 /* numUsages */);
|
||||
|
||||
checkPreparationPhasesForPackage(primaryPackage, 1);
|
||||
|
||||
boolean enabled = !(removalType == PackageRemovalType.DISABLE);
|
||||
boolean installed = !(removalType == PackageRemovalType.UNINSTALL);
|
||||
boolean hidden = (removalType == PackageRemovalType.HIDE);
|
||||
// Disable primary package and ensure fallback becomes enabled and used
|
||||
// Disable primary package and ensure secondary becomes used
|
||||
mTestSystemImpl.setPackageInfoForUser(userIdToChangePackageFor,
|
||||
createPackageInfo(primaryPackage, enabled /* enabled */, true /* valid */,
|
||||
installed /* installed */, null /* signature */, 0 /* updateTime */,
|
||||
@@ -665,15 +654,9 @@ public class WebViewUpdateServiceTest {
|
||||
removalType == PackageRemovalType.DISABLE
|
||||
? WebViewUpdateService.PACKAGE_CHANGED : WebViewUpdateService.PACKAGE_REMOVED,
|
||||
userIdToChangePackageFor); // USER ID
|
||||
checkPreparationPhasesForPackage(secondaryPackage, 1);
|
||||
|
||||
checkEnablePackageForUserCalled(fallbackPackage, true, multiUser
|
||||
? new int[] {TestSystemImpl.PRIMARY_USER_ID, secondaryUserId}
|
||||
: new int[] {TestSystemImpl.PRIMARY_USER_ID}, 1 /* numUsages */);
|
||||
|
||||
checkPreparationPhasesForPackage(fallbackPackage, 1);
|
||||
|
||||
|
||||
// Again enable primary package and verify primary is used and fallback becomes disabled
|
||||
// Again enable primary package and verify primary is used
|
||||
mTestSystemImpl.setPackageInfoForUser(userIdToChangePackageFor,
|
||||
createPackageInfo(primaryPackage, true /* enabled */, true /* valid */,
|
||||
true /* installed */));
|
||||
@@ -681,60 +664,9 @@ public class WebViewUpdateServiceTest {
|
||||
removalType == PackageRemovalType.DISABLE
|
||||
? WebViewUpdateService.PACKAGE_CHANGED : WebViewUpdateService.PACKAGE_ADDED,
|
||||
userIdToChangePackageFor);
|
||||
|
||||
// Verify fallback is disabled a second time when primary package becomes enabled
|
||||
checkEnablePackageForUserCalled(fallbackPackage, false, multiUser
|
||||
? new int[] {TestSystemImpl.PRIMARY_USER_ID, secondaryUserId}
|
||||
: new int[] {TestSystemImpl.PRIMARY_USER_ID}, 2 /* numUsages */);
|
||||
|
||||
checkPreparationPhasesForPackage(primaryPackage, 2);
|
||||
}
|
||||
|
||||
private void checkEnablePackageForUserCalled(String packageName, boolean expectEnabled,
|
||||
int[] userIds, int numUsages) {
|
||||
for (int userId : userIds) {
|
||||
Mockito.verify(mTestSystemImpl, Mockito.times(numUsages)).enablePackageForUser(
|
||||
Mockito.eq(packageName), Mockito.eq(expectEnabled), Mockito.eq(userId));
|
||||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
setEnabledAndValidPackageInfosForUser(TestSystemImpl.PRIMARY_USER_ID, packages);
|
||||
int newUser = 100;
|
||||
mTestSystemImpl.addUser(newUser);
|
||||
setEnabledAndValidPackageInfosForUser(newUser, packages);
|
||||
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 */);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that adding a new user for which the current WebView package is uninstalled causes a
|
||||
* change of WebView provider.
|
||||
@@ -742,13 +674,14 @@ public class WebViewUpdateServiceTest {
|
||||
@Test
|
||||
public void testAddingNewUserWithUninstalledPackage() {
|
||||
String primaryPackage = "primary";
|
||||
String fallbackPackage = "fallback";
|
||||
String secondaryPackage = "secondary";
|
||||
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 */);
|
||||
secondaryPackage, "", true /* default available */, false /* fallback */,
|
||||
null)};
|
||||
setupWithPackages(packages);
|
||||
setEnabledAndValidPackageInfosForUser(TestSystemImpl.PRIMARY_USER_ID, packages);
|
||||
int newUser = 100;
|
||||
mTestSystemImpl.addUser(newUser);
|
||||
@@ -757,18 +690,10 @@ public class WebViewUpdateServiceTest {
|
||||
createPackageInfo(primaryPackage, true /* enabled */, true /* valid */,
|
||||
false /* installed */));
|
||||
mTestSystemImpl.setPackageInfoForUser(newUser,
|
||||
createPackageInfo(fallbackPackage, false /* enabled */, true /* valid */,
|
||||
createPackageInfo(secondaryPackage, true /* enabled */, true /* valid */,
|
||||
true /* installed */));
|
||||
mWebViewUpdateServiceImpl.handleNewUser(newUser);
|
||||
// Verify fallback package doesn't become disabled for the primary user.
|
||||
Mockito.verify(mTestSystemImpl, Mockito.never()).enablePackageForUser(
|
||||
Mockito.anyObject(), Mockito.eq(false) /* enable */,
|
||||
Mockito.eq(TestSystemImpl.PRIMARY_USER_ID) /* user */);
|
||||
// Verify that we enable the fallback package for the secondary user.
|
||||
Mockito.verify(mTestSystemImpl, Mockito.times(1)).enablePackageForUser(
|
||||
Mockito.eq(fallbackPackage), Mockito.eq(true) /* enable */,
|
||||
Mockito.eq(newUser) /* user */);
|
||||
checkPreparationPhasesForPackage(fallbackPackage, 1 /* numRelros */);
|
||||
checkPreparationPhasesForPackage(secondaryPackage, 1 /* numRelros */);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -874,7 +799,8 @@ public class WebViewUpdateServiceTest {
|
||||
setupWithPackages(packages);
|
||||
// Only 'install' nonChosenPackage
|
||||
mTestSystemImpl.setPackageInfo(
|
||||
createPackageInfo(nonChosenPackage, true /* enabled */, true /* valid */, true /* installed */));
|
||||
createPackageInfo(nonChosenPackage, true /* enabled */, true /* valid */,
|
||||
true /* installed */));
|
||||
|
||||
// Set user-chosen package
|
||||
mTestSystemImpl.updateUserSetting(null, chosenPackage);
|
||||
@@ -1024,7 +950,8 @@ public class WebViewUpdateServiceTest {
|
||||
checkPreparationPhasesForPackage(thirdPackage, 1);
|
||||
|
||||
mTestSystemImpl.setPackageInfo(
|
||||
createPackageInfo(secondPackage, true /* enabled */, false /* valid */, true /* installed */));
|
||||
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.
|
||||
@@ -1084,40 +1011,17 @@ public class WebViewUpdateServiceTest {
|
||||
100000 /* candidate version */, false /* expected validity */);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimumSystemVersionUsedFallbackIgnored() {
|
||||
checkPackageVersions(new int[]{300000, 400000, 500000, 600000, 700000} /* system versions */,
|
||||
200000 /* candidate version */, false /* expected validity */, true /* add fallback */,
|
||||
100000 /* fallback version */, false /* expected validity of fallback */);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFallbackValid() {
|
||||
checkPackageVersions(new int[]{300000, 400000, 500000, 600000, 700000} /* system versions */,
|
||||
200000/* candidate version */, false /* expected validity */, true /* add fallback */,
|
||||
300000 /* fallback version */, true /* expected validity of fallback */);
|
||||
}
|
||||
|
||||
private void checkPackageVersions(int[] systemVersions, int candidateVersion,
|
||||
boolean candidateShouldBeValid) {
|
||||
checkPackageVersions(systemVersions, candidateVersion, candidateShouldBeValid,
|
||||
false, 0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for checking that package version restriction works as it should.
|
||||
* I.e. that a package with lower version than the system-default is not valid and that a
|
||||
* package with greater than or equal version code is considered valid.
|
||||
*/
|
||||
private void checkPackageVersions(int[] systemVersions, int candidateVersion,
|
||||
boolean candidateShouldBeValid, boolean addFallback, int fallbackVersion,
|
||||
boolean fallbackShouldBeValid) {
|
||||
boolean candidateShouldBeValid) {
|
||||
int numSystemPackages = systemVersions.length;
|
||||
int numFallbackPackages = (addFallback ? 1 : 0);
|
||||
int numPackages = systemVersions.length + 1 + numFallbackPackages;
|
||||
int numPackages = systemVersions.length + 1;
|
||||
String candidatePackage = "candidatePackage";
|
||||
String systemPackage = "systemPackage";
|
||||
String fallbackPackage = "fallbackPackage";
|
||||
|
||||
// Each package needs a valid signature since we set isDebuggable to false
|
||||
Signature signature = new Signature("11");
|
||||
@@ -1126,8 +1030,7 @@ public class WebViewUpdateServiceTest {
|
||||
|
||||
// Set up config
|
||||
// 1. candidatePackage
|
||||
// 2-N. default available non-fallback packages
|
||||
// N+1. default available fallback package
|
||||
// 2-N. default available packages
|
||||
WebViewProviderInfo[] packages = new WebViewProviderInfo[numPackages];
|
||||
packages[0] = new WebViewProviderInfo(candidatePackage, "",
|
||||
false /* available by default */, false /* fallback */,
|
||||
@@ -1137,14 +1040,7 @@ public class WebViewUpdateServiceTest {
|
||||
true /* available by default */, false /* fallback */,
|
||||
new String[]{encodedSignatureString});
|
||||
}
|
||||
if (addFallback) {
|
||||
packages[packages.length-1] = new WebViewProviderInfo(fallbackPackage, "",
|
||||
true /* available by default */, true /* fallback */,
|
||||
new String[]{encodedSignatureString});
|
||||
}
|
||||
|
||||
setupWithPackages(packages, true /* fallback logic enabled */, 1 /* numRelros */,
|
||||
false /* isDebuggable */);
|
||||
setupWithPackagesNonDebuggable(packages);
|
||||
|
||||
// Set package infos
|
||||
mTestSystemImpl.setPackageInfo(
|
||||
@@ -1157,12 +1053,6 @@ public class WebViewUpdateServiceTest {
|
||||
true /* installed */, new Signature[]{signature}, 0 /* updateTime */,
|
||||
false /* hidden */, systemVersions[n-1], true /* isSystemApp */));
|
||||
}
|
||||
if (addFallback) {
|
||||
mTestSystemImpl.setPackageInfo(
|
||||
createPackageInfo(fallbackPackage, true /* enabled */, true /* valid */,
|
||||
true /* installed */, new Signature[]{signature}, 0 /* updateTime */,
|
||||
false /* hidden */, fallbackVersion, true /* isSystemApp */));
|
||||
}
|
||||
|
||||
WebViewProviderInfo[] validPackages = mWebViewUpdateServiceImpl.getValidWebViewPackages();
|
||||
int expectedNumValidPackages = numSystemPackages;
|
||||
@@ -1175,15 +1065,6 @@ public class WebViewUpdateServiceTest {
|
||||
}
|
||||
}
|
||||
|
||||
if (fallbackShouldBeValid) {
|
||||
expectedNumValidPackages += numFallbackPackages;
|
||||
} else {
|
||||
// Ensure the fallback package is not one of the valid packages
|
||||
for(int n = 0; n < validPackages.length; n++) {
|
||||
assertFalse(fallbackPackage.equals(validPackages[n].packageName));
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals(expectedNumValidPackages, validPackages.length);
|
||||
|
||||
runWebViewBootPreparationOnMainSync();
|
||||
@@ -1212,7 +1093,7 @@ public class WebViewUpdateServiceTest {
|
||||
WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] {
|
||||
new WebViewProviderInfo(testPackageName, "",
|
||||
true /*default available*/, false /* fallback */, null)};
|
||||
setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */);
|
||||
setupWithPackages(webviewPackages);
|
||||
mTestSystemImpl.setPackageInfo(createPackageInfo(testPackageName, true /* enabled */,
|
||||
true /* valid */, false /* installed */));
|
||||
|
||||
@@ -1250,7 +1131,7 @@ public class WebViewUpdateServiceTest {
|
||||
new WebViewProviderInfo(installedPackage, "", true /* available by default */,
|
||||
false /* fallback */, null)};
|
||||
|
||||
setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */);
|
||||
setupWithPackages(webviewPackages);
|
||||
int secondaryUserId = 5;
|
||||
if (multiUser) {
|
||||
mTestSystemImpl.addUser(secondaryUserId);
|
||||
@@ -1301,7 +1182,7 @@ public class WebViewUpdateServiceTest {
|
||||
new WebViewProviderInfo(installedPackage, "", true /* available by default */,
|
||||
false /* fallback */, null)};
|
||||
|
||||
setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */);
|
||||
setupWithPackages(webviewPackages);
|
||||
int secondaryUserId = 412;
|
||||
mTestSystemImpl.addUser(secondaryUserId);
|
||||
|
||||
@@ -1356,7 +1237,7 @@ public class WebViewUpdateServiceTest {
|
||||
new WebViewProviderInfo(installedPackage, "", true /* available by default */,
|
||||
false /* fallback */, null)};
|
||||
|
||||
setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */);
|
||||
setupWithPackages(webviewPackages);
|
||||
int secondaryUserId = 4;
|
||||
mTestSystemImpl.addUser(secondaryUserId);
|
||||
|
||||
@@ -1376,79 +1257,26 @@ public class WebViewUpdateServiceTest {
|
||||
checkPreparationPhasesForPackage(installedPackage, 1 /* first preparation phase */);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFallbackEnabledIfPrimaryUninstalledSingleUser() {
|
||||
checkFallbackEnabledIfPrimaryUninstalled(false /* multiUser */);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFallbackEnabledIfPrimaryUninstalledMultiUser() {
|
||||
checkFallbackEnabledIfPrimaryUninstalled(true /* multiUser */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that fallback becomes enabled at boot if the primary package is uninstalled for some
|
||||
* user.
|
||||
*/
|
||||
private void checkFallbackEnabledIfPrimaryUninstalled(boolean multiUser) {
|
||||
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 */);
|
||||
int secondaryUserId = 5;
|
||||
if (multiUser) {
|
||||
mTestSystemImpl.addUser(secondaryUserId);
|
||||
// Install all packages for the primary user.
|
||||
setEnabledAndValidPackageInfosForUser(TestSystemImpl.PRIMARY_USER_ID, packages);
|
||||
// Only install fallback package for secondary user.
|
||||
mTestSystemImpl.setPackageInfoForUser(secondaryUserId,
|
||||
createPackageInfo(primaryPackage, true /* enabled */,
|
||||
true /* valid */, false /* installed */));
|
||||
mTestSystemImpl.setPackageInfoForUser(secondaryUserId,
|
||||
createPackageInfo(fallbackPackage, false /* enabled */,
|
||||
true /* valid */, true /* installed */));
|
||||
} else {
|
||||
mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */,
|
||||
true /* valid */, false /* installed */));
|
||||
mTestSystemImpl.setPackageInfo(createPackageInfo(fallbackPackage, false /* 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";
|
||||
String secondaryPackage = "secondary";
|
||||
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 */);
|
||||
secondaryPackage, "", true /* default available */, false /* fallback */,
|
||||
null)};
|
||||
setupWithPackages(packages);
|
||||
mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */,
|
||||
true /* valid */, true /* installed */, null /* signatures */,
|
||||
10 /* lastUpdateTime*/ ));
|
||||
mTestSystemImpl.setPackageInfo(createPackageInfo(fallbackPackage, true /* enabled */,
|
||||
mTestSystemImpl.setPackageInfo(createPackageInfo(secondaryPackage, 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 */);
|
||||
@@ -1459,9 +1287,6 @@ public class WebViewUpdateServiceTest {
|
||||
// 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();
|
||||
@@ -1496,7 +1321,7 @@ public class WebViewUpdateServiceTest {
|
||||
firstPackage.versionName = "first package version";
|
||||
WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
|
||||
new WebViewProviderInfo(firstPackage.packageName, "", true, false, null)};
|
||||
setupWithPackages(packages, true);
|
||||
setupWithPackages(packages);
|
||||
mTestSystemImpl.setPackageInfo(firstPackage);
|
||||
|
||||
runWebViewBootPreparationOnMainSync();
|
||||
@@ -1542,9 +1367,7 @@ public class WebViewUpdateServiceTest {
|
||||
WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
|
||||
new WebViewProviderInfo(
|
||||
primaryPackage, "", true /* default available */, false /* fallback */, null)};
|
||||
setupWithPackages(packages, true /* fallback logic enabled */, 1 /* numRelros */,
|
||||
true /* debuggable */,
|
||||
enabledByDefault /* not multiprocess by default */);
|
||||
setupWithPackagesAndMultiProcess(packages, enabledByDefault);
|
||||
mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */,
|
||||
true /* valid */, true /* installed */, null /* signatures */,
|
||||
10 /* lastUpdateTime*/, false /* not hidden */, 1000 /* versionCode */,
|
||||
@@ -1599,8 +1422,7 @@ public class WebViewUpdateServiceTest {
|
||||
WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
|
||||
new WebViewProviderInfo(
|
||||
primaryPackage, "", true /* default available */, false /* fallback */, null)};
|
||||
setupWithPackages(packages, true /* fallback logic enabled */, 1 /* numRelros */,
|
||||
true /* debuggable */, enabledByDefault /* multiprocess by default */);
|
||||
setupWithPackagesAndMultiProcess(packages, enabledByDefault);
|
||||
mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */,
|
||||
true /* valid */, true /* installed */, null /* signatures */,
|
||||
10 /* lastUpdateTime*/, false /* not hidden */, 1000 /* versionCode */,
|
||||
@@ -1638,7 +1460,7 @@ public class WebViewUpdateServiceTest {
|
||||
WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
|
||||
new WebViewProviderInfo(oldSdkPackage.packageName, "", true, false, null),
|
||||
currentSdkProviderInfo, newSdkProviderInfo};
|
||||
setupWithPackages(packages, true);
|
||||
setupWithPackages(packages);
|
||||
;
|
||||
mTestSystemImpl.setPackageInfo(newSdkPackage);
|
||||
mTestSystemImpl.setPackageInfo(currentSdkPackage);
|
||||
|
||||
Reference in New Issue
Block a user