Make sure we cannot use packages targeting pre-O as WebView packages.

Using a WebView package targeting a release before O as WebView provider
on O will cause crashes (because of incompatibility issues), this CL
makes us interpret a package targeting a pre-O release as being invalid
on O.

Also remove the code that lets us fall back to loading the old
WebViewChromiumFactoryProvider (pre-O) class.

Bug: 34773740
Bug: 34180497
Test: Ensure WebView provider with targetSdkVersion="O" shows up in the
WebView Implementation Dev Setting, ensure targetSdkVersion=25 doesn't
show up.
Test: Add WVUS unit test to ensure a packages with targetSdkVersion < 26
are considered invalid, and > 26 are valid. Run WVUS unit tests.

Change-Id: I4d80d46019e2522bc3fc6068712d28eedb31fcce
This commit is contained in:
Gustav Sennton
2017-01-30 18:08:01 +00:00
parent 9deb6b5a3a
commit 564c2fd5db
4 changed files with 64 additions and 22 deletions

View File

@@ -20,6 +20,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.os.Build;
import android.os.UserManager;
import java.util.ArrayList;
@@ -77,6 +78,15 @@ public class UserPackage {
& ApplicationInfo.PRIVATE_FLAG_HIDDEN) == 0));
}
/**
* Returns whether the package represented by {@param packageInfo} targets a sdk version
* supported by the current framework version.
*/
public static boolean hasCorrectTargetSdkVersion(PackageInfo packageInfo) {
// TODO(gsennton) use Build.VERSION_CODES.O when that has been updated.
return packageInfo.applicationInfo.targetSdkVersion > Build.VERSION_CODES.N_MR1;
}
public UserInfo getUserInfo() {
return mUserInfo;
}

View File

@@ -145,18 +145,10 @@ public final class WebViewFactory {
/**
* @hide
*/
public static Class<WebViewFactoryProvider> getWebViewProviderClass( ClassLoader clazzLoader)
throws ClassNotFoundException{
try {
return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY,
true, clazzLoader);
} catch (ClassNotFoundException e) {
// TODO: This loads the provider which is not built for O, should be removed
// before the release.
return (Class<WebViewFactoryProvider>) Class.forName(
"com.android.webview.chromium.WebViewChromiumFactoryProvider",
true, clazzLoader);
}
public static Class<WebViewFactoryProvider> getWebViewProviderClass(ClassLoader clazzLoader)
throws ClassNotFoundException {
return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY,
true, clazzLoader);
}
/**
@@ -225,15 +217,10 @@ public final class WebViewFactory {
}
}
Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "providerClass.newInstance()");
Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactoryProvider invocation");
try {
if (staticFactory != null) {
sProviderInstance = (WebViewFactoryProvider)
staticFactory.invoke(null, new WebViewDelegate());
} else {
sProviderInstance = providerClass.getConstructor(WebViewDelegate.class)
.newInstance(new WebViewDelegate());
}
sProviderInstance = (WebViewFactoryProvider)
staticFactory.invoke(null, new WebViewDelegate());
if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance);
return sProviderInstance;
} catch (Exception e) {
@@ -384,8 +371,7 @@ public final class WebViewFactory {
Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()");
try {
return getWebViewProviderClass(clazzLoader);
}
finally {
} finally {
Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
}
} catch (ClassNotFoundException e) {

View File

@@ -630,6 +630,10 @@ public class WebViewUpdateServiceImpl {
*/
public boolean isValidProvider(WebViewProviderInfo configInfo,
PackageInfo packageInfo) {
// Ensure the provider targets this framework release (or a later one).
if (!UserPackage.hasCorrectTargetSdkVersion(packageInfo)) {
return false;
}
if (!versionCodeGE(packageInfo.versionCode, getMinimumVersionCode())
&& !mSystemInterface.systemIsDebuggable()) {
// Webview providers may be downgraded arbitrarily low, prevent that by enforcing

View File

@@ -16,6 +16,7 @@
package com.android.server.webkit;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -24,6 +25,7 @@ import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.Signature;
import android.os.Build;
import android.os.Bundle;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
@@ -174,6 +176,8 @@ public class WebViewUpdateServiceTest {
// no flag means invalid
p.applicationInfo.metaData.putString(WEBVIEW_LIBRARY_FLAG, "blah");
}
// Default to this package being valid in terms of targetSdkVersion.
p.applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
return p;
}
@@ -1614,4 +1618,42 @@ public class WebViewUpdateServiceTest {
checkPreparationPhasesForPackage(primaryPackage, 3);
assertTrue(mWebViewUpdateServiceImpl.isMultiProcessEnabled());
}
/**
* Ensure that packages with a targetSdkVersion targeting the current platform are valid, and
* that packages targeting an older version are not valid.
*/
@Test
public void testTargetSdkVersionValidity() {
PackageInfo newSdkPackage = createPackageInfo("newTargetSdkPackage",
true /* enabled */, true /* valid */, true /* installed */);
newSdkPackage.applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
PackageInfo currentSdkPackage = createPackageInfo("currentTargetSdkPackage",
true /* enabled */, true /* valid */, true /* installed */);
currentSdkPackage.applicationInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1+1;
PackageInfo oldSdkPackage = createPackageInfo("oldTargetSdkPackage",
true /* enabled */, true /* valid */, true /* installed */);
oldSdkPackage.applicationInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1;
WebViewProviderInfo newSdkProviderInfo =
new WebViewProviderInfo(newSdkPackage.packageName, "", true, false, null);
WebViewProviderInfo currentSdkProviderInfo =
new WebViewProviderInfo(currentSdkPackage.packageName, "", true, false, null);
WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
new WebViewProviderInfo(oldSdkPackage.packageName, "", true, false, null),
currentSdkProviderInfo, newSdkProviderInfo};
setupWithPackages(packages, true);
;
mTestSystemImpl.setPackageInfo(newSdkPackage);
mTestSystemImpl.setPackageInfo(currentSdkPackage);
mTestSystemImpl.setPackageInfo(oldSdkPackage);
assertArrayEquals(new WebViewProviderInfo[]{currentSdkProviderInfo, newSdkProviderInfo},
mWebViewUpdateServiceImpl.getValidWebViewPackages());
runWebViewBootPreparationOnMainSync();
checkPreparationPhasesForPackage(currentSdkPackage.packageName,
1 /* first preparation phase */);
}
}