diff options
| author | 2013-06-12 16:02:03 +0100 | |
|---|---|---|
| committer | 2013-06-19 15:03:08 +0100 | |
| commit | 03ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8 (patch) | |
| tree | 5ab5fa849c46fbb9fb773b303d9e136906fac8bc | |
| parent | 4b77dbb2068b357a09db86102a391d27ffd84a19 (diff) | |
Enable preloading of the appropriate WebView.
Allow the appropriate WebView to be preloaded in the zygote by
constructing the currently selected WebViewFactoryProvider when the
WebViewFactory is preloaded. At runtime, if the preloaded provider is
still the current selection, the preloaded instance is used, otherwise
the provider is loaded at that time.
This change also removes "graceful" fallback from the experimental
WebView to the classic implementation: if the option to use the
experimental WebView is selected and it could not be loaded
successfully at the time a WebView is created, an exception will be
thrown, rather than allowing execution to continue with the classic
implementation, as the fallback may mislead developers who do not
examine logcat output in detail.
Change-Id: I0cd01c784d7048abeac55ab5863ca16b8fd9ecf2
| -rw-r--r-- | core/java/android/webkit/WebViewClassic.java | 14 | ||||
| -rw-r--r-- | core/java/android/webkit/WebViewFactory.java | 79 | ||||
| -rw-r--r-- | preloaded-classes | 3 |
3 files changed, 59 insertions, 37 deletions
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java index a324502f4471..3afab0982078 100644 --- a/core/java/android/webkit/WebViewClassic.java +++ b/core/java/android/webkit/WebViewClassic.java @@ -66,6 +66,7 @@ import android.text.Editable; import android.text.InputType; import android.text.Selection; import android.text.TextUtils; +import android.util.AndroidRuntimeException; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; @@ -1293,6 +1294,19 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc // WebViewProvider bindings static class Factory implements WebViewFactoryProvider, WebViewFactoryProvider.Statics { + Factory() { + // Touch JniUtil and WebViewCore in case this is being called from + // WebViewFactory.Preloader, to ensure that the JNI libraries that they use are + // preloaded in the zygote. + try { + Class.forName("android.webkit.JniUtil"); + Class.forName("android.webkit.WebViewCore"); + } catch (ClassNotFoundException e) { + Log.e(LOGTAG, "failed to load JNI libraries"); + throw new AndroidRuntimeException(e); + } + } + @Override public String findAddress(String addr) { return WebViewClassic.findAddress(addr); diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java index ea5187a483c3..2ee0961a6582 100644 --- a/core/java/android/webkit/WebViewFactory.java +++ b/core/java/android/webkit/WebViewFactory.java @@ -19,10 +19,9 @@ package android.webkit; import android.os.Build; import android.os.StrictMode; import android.os.SystemProperties; +import android.util.AndroidRuntimeException; import android.util.Log; -import dalvik.system.PathClassLoader; - /** * Top level factory, used creating all the main WebView implementation classes. * @@ -45,6 +44,17 @@ public final class WebViewFactory { private static final boolean DEBUG = false; + private static class Preloader { + static WebViewFactoryProvider sPreloadedProvider; + static { + try { + sPreloadedProvider = getFactoryClass().newInstance(); + } catch (Exception e) { + Log.w(LOGTAG, "error preloading provider", e); + } + } + } + // Cache the factory both for efficiency, and ensure any one process gets all webviews from the // same provider. private static WebViewFactoryProvider sProviderInstance; @@ -67,32 +77,39 @@ public final class WebViewFactory { // us honest and minimize usage of WebViewClassic internals when binding the proxy. if (sProviderInstance != null) return sProviderInstance; - if (isExperimentalWebViewEnabled()) { - StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); - try { - sProviderInstance = getFactoryByName(CHROMIUM_WEBVIEW_FACTORY); - if (DEBUG) Log.v(LOGTAG, "Loaded Chromium provider: " + sProviderInstance); - } finally { - StrictMode.setThreadPolicy(oldPolicy); - } + Class<WebViewFactoryProvider> providerClass; + try { + providerClass = getFactoryClass(); + } catch (ClassNotFoundException e) { + Log.e(LOGTAG, "error loading provider", e); + throw new AndroidRuntimeException(e); } - if (sProviderInstance == null) { - if (DEBUG) Log.v(LOGTAG, "Falling back to default provider: " - + DEFAULT_WEBVIEW_FACTORY); - sProviderInstance = getFactoryByName(DEFAULT_WEBVIEW_FACTORY); - if (sProviderInstance == null) { - if (DEBUG) Log.v(LOGTAG, "Falling back to explicit linkage"); - sProviderInstance = new WebViewClassic.Factory(); - } + // This implicitly loads Preloader even if it wasn't preloaded at boot. + if (Preloader.sPreloadedProvider != null && + Preloader.sPreloadedProvider.getClass() == providerClass) { + sProviderInstance = Preloader.sPreloadedProvider; + if (DEBUG) Log.v(LOGTAG, "Using preloaded provider: " + sProviderInstance); + return sProviderInstance; + } + + // The preloaded provider isn't the one we wanted; construct our own. + StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); + try { + sProviderInstance = providerClass.newInstance(); + if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance); + return sProviderInstance; + } catch (Exception e) { + Log.e(LOGTAG, "error instantiating provider", e); + throw new AndroidRuntimeException(e); + } finally { + StrictMode.setThreadPolicy(oldPolicy); } - return sProviderInstance; } } - // For debug builds, we allow a system property to specify that we should use the - // experimtanl Chromium powered WebView. This enables us to switch between - // implementations at runtime. For user (release) builds, don't allow this. + // We allow a system property to specify that we should use the experimental Chromium powered + // WebView. This enables us to switch between implementations at runtime. private static boolean isExperimentalWebViewEnabled() { if (!isExperimentalWebViewAvailable()) return false; boolean use_experimental_webview = SystemProperties.getBoolean( @@ -108,19 +125,11 @@ public final class WebViewFactory { return use_experimental_webview; } - private static WebViewFactoryProvider getFactoryByName(String providerName) { - try { - if (DEBUG) Log.v(LOGTAG, "attempt to load class " + providerName); - Class<?> c = Class.forName(providerName); - if (DEBUG) Log.v(LOGTAG, "instantiating factory"); - return (WebViewFactoryProvider) c.newInstance(); - } catch (ClassNotFoundException e) { - Log.e(LOGTAG, "error loading " + providerName, e); - } catch (IllegalAccessException e) { - Log.e(LOGTAG, "error loading " + providerName, e); - } catch (InstantiationException e) { - Log.e(LOGTAG, "error loading " + providerName, e); + private static Class<WebViewFactoryProvider> getFactoryClass() throws ClassNotFoundException { + if (isExperimentalWebViewEnabled()) { + return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY); + } else { + return (Class<WebViewFactoryProvider>) Class.forName(DEFAULT_WEBVIEW_FACTORY); } - return null; } } diff --git a/preloaded-classes b/preloaded-classes index 2aa610a362e9..45d27eeddbb4 100644 --- a/preloaded-classes +++ b/preloaded-classes @@ -1220,7 +1220,6 @@ android.webkit.HTML5Audio android.webkit.HTML5VideoViewProxy android.webkit.JWebCoreJavaBridge android.webkit.JavascriptInterface -android.webkit.JniUtil android.webkit.L10nUtils android.webkit.MockGeolocation android.webkit.OverScrollGlow @@ -1269,7 +1268,6 @@ android.webkit.WebViewClassic$TitleBarDelegate android.webkit.WebViewClassic$TrustStorageListener android.webkit.WebViewClassic$ViewSizeData android.webkit.WebViewClient -android.webkit.WebViewCore android.webkit.WebViewCore$AutoFillData android.webkit.WebViewCore$DrawData android.webkit.WebViewCore$EventHub @@ -1283,6 +1281,7 @@ android.webkit.WebViewDatabase android.webkit.WebViewDatabaseClassic android.webkit.WebViewDatabaseClassic$1 android.webkit.WebViewFactory +android.webkit.WebViewFactory$Preloader android.webkit.WebViewFactoryProvider android.webkit.WebViewFactoryProvider$Statics android.webkit.WebViewInputDispatcher |