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

Commit a8366e78 authored by Gustav Sennton's avatar Gustav Sennton
Browse files

Fix loading of null webview if there is no webview package.

In the change in go/ag/672863 we throw an AndroidRuntimeException
instead of a PackageManager.NameNotFoundException when no webview
package exists. This should break devices not using webview since
the NameNotFoundException is used to detect webview not being present
(so that the null webview can be loaded instead). In this patch we
create a new type of exception and look for that one instead when we
want to determine whether the device should or should not have webview
installed.

Change-Id: Ia75dec718d7a5b2c3517671c54be3950badb8bba
parent 8a2c92c8
Loading
Loading
Loading
Loading
+50 −35
Original line number Diff line number Diff line
@@ -76,6 +76,11 @@ public final class WebViewFactory {
    private static boolean sAddressSpaceReserved = false;
    private static PackageInfo sPackageInfo;

    private static class MissingWebViewPackageException extends AndroidRuntimeException {
        public MissingWebViewPackageException(String message) { super(message); }
        public MissingWebViewPackageException(Exception e) { super(e); }
    }

    /** @hide */
    public static String[] getWebViewPackageNames() {
        return AppGlobals.getInitialApplication().getResources().getStringArray(
@@ -110,9 +115,10 @@ public final class WebViewFactory {
            } catch (PackageManager.NameNotFoundException e) {
            }
        }
        throw new AndroidRuntimeException("Could not find a loadable WebView package");
        throw new MissingWebViewPackageException("Could not find a loadable WebView package");
    }

    // throws MissingWebViewPackageException
    private static ApplicationInfo getWebViewApplicationInfo() {
        if (sPackageInfo == null)
            return findPreferredWebViewPackage().applicationInfo;
@@ -144,25 +150,7 @@ public final class WebViewFactory {

            Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getProvider()");
            try {
                // First fetch the package info so we can log the webview package version.
                sPackageInfo = findPreferredWebViewPackage();
                Log.i(LOGTAG, "Loading " + sPackageInfo.packageName + " version " +
                    sPackageInfo.versionName + " (code " + sPackageInfo.versionCode + ")");

                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()");
                loadNativeLibrary();
                Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);

                Class<WebViewFactoryProvider> providerClass;
                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getFactoryClass()");
                try {
                    providerClass = getFactoryClass();
                } catch (ClassNotFoundException e) {
                    Log.e(LOGTAG, "error loading provider", e);
                    throw new AndroidRuntimeException(e);
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
                }
                Class<WebViewFactoryProvider> providerClass = getProviderClass();

                StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "providerClass.newInstance()");
@@ -184,7 +172,44 @@ public final class WebViewFactory {
        }
    }

    private static Class<WebViewFactoryProvider> getFactoryClass() throws ClassNotFoundException {
    private static Class<WebViewFactoryProvider> getProviderClass() {
        try {
            // First fetch the package info so we can log the webview package version.
            sPackageInfo = findPreferredWebViewPackage();
            Log.i(LOGTAG, "Loading " + sPackageInfo.packageName + " version " +
                sPackageInfo.versionName + " (code " + sPackageInfo.versionCode + ")");

            Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()");
            loadNativeLibrary();
            Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);

            Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getChromiumProviderClass()");
            try {
                return getChromiumProviderClass();
            } catch (ClassNotFoundException e) {
                Log.e(LOGTAG, "error loading provider", e);
                throw new AndroidRuntimeException(e);
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
            }
        } catch (MissingWebViewPackageException e) {
            // If the package doesn't exist, then try loading the null WebView instead.
            // If that succeeds, then this is a device without WebView support; if it fails then
            // swallow the failure, complain that the real WebView is missing and rethrow the
            // original exception.
            try {
                return (Class<WebViewFactoryProvider>) Class.forName(NULL_WEBVIEW_FACTORY);
            } catch (ClassNotFoundException e2) {
                // Ignore.
            }
            Log.e(LOGTAG, "Chromium WebView package does not exist", e);
            throw new AndroidRuntimeException(e);
        }
    }

    // throws MissingWebViewPackageException
    private static Class<WebViewFactoryProvider> getChromiumProviderClass()
            throws ClassNotFoundException {
        Application initialApplication = AppGlobals.getInitialApplication();
        try {
            // Construct a package context to load the Java code into the current app.
@@ -202,17 +227,7 @@ public final class WebViewFactory {
                Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
            }
        } catch (PackageManager.NameNotFoundException e) {
            // If the package doesn't exist, then try loading the null WebView instead.
            // If that succeeds, then this is a device without WebView support; if it fails then
            // swallow the failure, complain that the real WebView is missing and rethrow the
            // original exception.
            try {
                return (Class<WebViewFactoryProvider>) Class.forName(NULL_WEBVIEW_FACTORY);
            } catch (ClassNotFoundException e2) {
                // Ignore.
            }
            Log.e(LOGTAG, "Chromium WebView package does not exist", e);
            throw new AndroidRuntimeException(e);
            throw new MissingWebViewPackageException(e);
        }
    }

@@ -315,8 +330,8 @@ public final class WebViewFactory {
        prepareWebViewInSystemServer(nativeLibs);
    }

    private static String[] getWebViewNativeLibraryPaths()
            throws PackageManager.NameNotFoundException {
    // throws MissingWebViewPackageException
    private static String[] getWebViewNativeLibraryPaths() {
        ApplicationInfo ai = getWebViewApplicationInfo();
        final String NATIVE_LIB_FILE_NAME = getWebViewLibrary(ai);

@@ -443,7 +458,7 @@ public final class WebViewFactory {
            } else if (DEBUG) {
                Log.v(LOGTAG, "loaded with relro file");
            }
        } catch (PackageManager.NameNotFoundException e) {
        } catch (MissingWebViewPackageException e) {
            Log.e(LOGTAG, "Failed to list WebView package libraries for loadNativeLibrary", e);
        }
    }