From 2ed6fee15c85ff991f64ecfa8c1c4738e0fdf9b6 Mon Sep 17 00:00:00 2001 From: Gustav Sennton Date: Tue, 3 Mar 2015 15:12:34 +0000 Subject: [PATCH] Load WebView from one out of a list of packages. Use a priority list of WebView packages instead of a single package to determine which package to load WebView from. This to allow a future version of Chrome to provide the WebView implementation. Change-Id: I42e900f0e63152188ebfcff9e39e0d9a99bc6c90 --- core/java/android/webkit/WebViewFactory.java | 71 +++++++++++++++---- core/res/res/values/config.xml | 6 +- core/res/res/values/symbols.xml | 2 +- .../server/webkit/WebViewUpdateService.java | 21 +++++- 4 files changed, 80 insertions(+), 20 deletions(-) diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java index cafe05309efb4..4d8dce1f121e2 100644 --- a/core/java/android/webkit/WebViewFactory.java +++ b/core/java/android/webkit/WebViewFactory.java @@ -76,9 +76,54 @@ public final class WebViewFactory { private static boolean sAddressSpaceReserved = false; private static PackageInfo sPackageInfo; + /** @hide */ + public static String[] getWebViewPackageNames() { + return AppGlobals.getInitialApplication().getResources().getStringArray( + com.android.internal.R.array.config_webViewPackageNames); + } + + // TODO (gsennton) remove when committing webview xts test change public static String getWebViewPackageName() { - return AppGlobals.getInitialApplication().getString( - com.android.internal.R.string.config_webViewPackageName); + String[] webViewPackageNames = getWebViewPackageNames(); + return webViewPackageNames[webViewPackageNames.length-1]; + } + + /** + * Return the package info of the first package in the webview priority list that contains + * webview. + * + * @hide + */ + public static PackageInfo findPreferredWebViewPackage() { + PackageManager pm = AppGlobals.getInitialApplication().getPackageManager(); + + for (String packageName : getWebViewPackageNames()) { + try { + PackageInfo packageInfo = pm.getPackageInfo(packageName, + PackageManager.GET_META_DATA); + ApplicationInfo applicationInfo = packageInfo.applicationInfo; + + // If the correct flag is set the package contains webview. + if (getWebViewLibrary(applicationInfo) != null) { + return packageInfo; + } + } catch (PackageManager.NameNotFoundException e) { + } + } + throw new AndroidRuntimeException("Could not find a loadable WebView package"); + } + + private static ApplicationInfo getWebViewApplicationInfo() { + if (sPackageInfo == null) + return findPreferredWebViewPackage().applicationInfo; + else + return sPackageInfo.applicationInfo; + } + + private static String getWebViewLibrary(ApplicationInfo ai) { + if (ai.metaData != null) + return ai.metaData.getString("com.android.webview.WebViewLibrary"); + return null; } public static PackageInfo getLoadedPackageInfo() { @@ -99,6 +144,11 @@ 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); @@ -137,15 +187,10 @@ public final class WebViewFactory { private static Class getFactoryClass() throws ClassNotFoundException { Application initialApplication = AppGlobals.getInitialApplication(); try { - // First fetch the package info so we can log the webview package version. - String packageName = getWebViewPackageName(); - sPackageInfo = initialApplication.getPackageManager().getPackageInfo(packageName, 0); - Log.i(LOGTAG, "Loading " + packageName + " version " + sPackageInfo.versionName + - " (code " + sPackageInfo.versionCode + ")"); - // Construct a package context to load the Java code into the current app. - Context webViewContext = initialApplication.createPackageContext(packageName, - Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); + Context webViewContext = initialApplication.createPackageContext( + sPackageInfo.packageName, + Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); initialApplication.getAssets().addAssetPath( webViewContext.getApplicationInfo().sourceDir); ClassLoader clazzLoader = webViewContext.getClassLoader(); @@ -272,10 +317,8 @@ public final class WebViewFactory { private static String[] getWebViewNativeLibraryPaths() throws PackageManager.NameNotFoundException { - final String NATIVE_LIB_FILE_NAME = "libwebviewchromium.so"; - - PackageManager pm = AppGlobals.getInitialApplication().getPackageManager(); - ApplicationInfo ai = pm.getApplicationInfo(getWebViewPackageName(), 0); + ApplicationInfo ai = getWebViewApplicationInfo(); + final String NATIVE_LIB_FILE_NAME = getWebViewLibrary(ai); String path32; String path64; diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 6d9bbae78586b..26ac9e91af0d9 100755 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1961,8 +1961,10 @@ string that's stored in 8-bit unpacked format) characters.--> false - - com.android.webview + + + com.android.webview + diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java index d4c5f8716c0e3..ac79b36f70053 100644 --- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java +++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java @@ -40,6 +40,8 @@ public class WebViewUpdateService extends SystemService { private boolean mRelroReady32Bit = false; private boolean mRelroReady64Bit = false; + private String oldWebViewPackageName = null; + private BroadcastReceiver mWebViewUpdatedReceiver; public WebViewUpdateService(Context context) { @@ -51,9 +53,22 @@ public class WebViewUpdateService extends SystemService { mWebViewUpdatedReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - String webviewPackage = "package:" + WebViewFactory.getWebViewPackageName(); - if (webviewPackage.equals(intent.getDataString())) { - onWebViewUpdateInstalled(); + + for (String packageName : WebViewFactory.getWebViewPackageNames()) { + String webviewPackage = "package:" + packageName; + + if (webviewPackage.equals(intent.getDataString())) { + String usedPackageName = + WebViewFactory.findPreferredWebViewPackage().packageName; + // Only trigger update actions if the updated package is the one that + // will be used, or the one that was in use before the update. + if (packageName.equals(usedPackageName) || + packageName.equals(oldWebViewPackageName)) { + onWebViewUpdateInstalled(); + oldWebViewPackageName = usedPackageName; + } + return; + } } } };