Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 564c2fd5 authored by Gustav Sennton's avatar Gustav Sennton
Browse files

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
parent 9deb6b5a
Loading
Loading
Loading
Loading
+10 −0
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.content.pm.UserInfo;
import android.os.Build;
import android.os.UserManager;
import android.os.UserManager;


import java.util.ArrayList;
import java.util.ArrayList;
@@ -77,6 +78,15 @@ public class UserPackage {
                        & ApplicationInfo.PRIVATE_FLAG_HIDDEN) == 0));
                        & 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() {
    public UserInfo getUserInfo() {
        return mUserInfo;
        return mUserInfo;
    }
    }
+8 −22
Original line number Original line Diff line number Diff line
@@ -147,16 +147,8 @@ public final class WebViewFactory {
     */
     */
    public static Class<WebViewFactoryProvider> getWebViewProviderClass(ClassLoader clazzLoader)
    public static Class<WebViewFactoryProvider> getWebViewProviderClass(ClassLoader clazzLoader)
            throws ClassNotFoundException {
            throws ClassNotFoundException {
        try {
        return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY,
        return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY,
                true, clazzLoader);
                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);
        }
    }
    }


    /**
    /**
@@ -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 {
                try {
                    if (staticFactory != null) {
                    sProviderInstance = (WebViewFactoryProvider)
                    sProviderInstance = (WebViewFactoryProvider)
                            staticFactory.invoke(null, new WebViewDelegate());
                            staticFactory.invoke(null, new WebViewDelegate());
                    } else {
                        sProviderInstance = providerClass.getConstructor(WebViewDelegate.class)
                                .newInstance(new WebViewDelegate());
                    }
                    if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance);
                    if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance);
                    return sProviderInstance;
                    return sProviderInstance;
                } catch (Exception e) {
                } catch (Exception e) {
@@ -384,8 +371,7 @@ public final class WebViewFactory {
                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()");
                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()");
                try {
                try {
                    return getWebViewProviderClass(clazzLoader);
                    return getWebViewProviderClass(clazzLoader);
                }
                } finally {
                finally {
                    Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
                    Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
                }
                }
            } catch (ClassNotFoundException e) {
            } catch (ClassNotFoundException e) {
+4 −0
Original line number Original line Diff line number Diff line
@@ -630,6 +630,10 @@ public class WebViewUpdateServiceImpl {
         */
         */
        public boolean isValidProvider(WebViewProviderInfo configInfo,
        public boolean isValidProvider(WebViewProviderInfo configInfo,
                PackageInfo packageInfo) {
                PackageInfo packageInfo) {
            // Ensure the provider targets this framework release (or a later one).
            if (!UserPackage.hasCorrectTargetSdkVersion(packageInfo)) {
                return false;
            }
            if (!versionCodeGE(packageInfo.versionCode, getMinimumVersionCode())
            if (!versionCodeGE(packageInfo.versionCode, getMinimumVersionCode())
                    && !mSystemInterface.systemIsDebuggable()) {
                    && !mSystemInterface.systemIsDebuggable()) {
                // Webview providers may be downgraded arbitrarily low, prevent that by enforcing
                // Webview providers may be downgraded arbitrarily low, prevent that by enforcing
+42 −0
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


package com.android.server.webkit;
package com.android.server.webkit;


import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertTrue;
@@ -24,6 +25,7 @@ import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInfo;
import android.content.pm.Signature;
import android.content.pm.Signature;
import android.os.Build;
import android.os.Bundle;
import android.os.Bundle;
import android.support.test.InstrumentationRegistry;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.runner.AndroidJUnit4;
@@ -174,6 +176,8 @@ public class WebViewUpdateServiceTest {
            // no flag means invalid
            // no flag means invalid
            p.applicationInfo.metaData.putString(WEBVIEW_LIBRARY_FLAG, "blah");
            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;
        return p;
    }
    }


@@ -1614,4 +1618,42 @@ public class WebViewUpdateServiceTest {
        checkPreparationPhasesForPackage(primaryPackage, 3);
        checkPreparationPhasesForPackage(primaryPackage, 3);
        assertTrue(mWebViewUpdateServiceImpl.isMultiProcessEnabled());
        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 */);
    }
}
}