| Index: chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserClassLoader.java
|
| diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserClassLoader.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserClassLoader.java
|
| index c727d2edc46fa830acc1c43d3a438c3cf0dc5ce2..2b16dd749c02958e0d857a5ce59ced9a8ebb7a29 100644
|
| --- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserClassLoader.java
|
| +++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserClassLoader.java
|
| @@ -6,7 +6,6 @@ package org.chromium.webapk.shell_apk;
|
|
|
| import android.content.Context;
|
| import android.content.SharedPreferences;
|
| -import android.content.pm.PackageInfo;
|
| import android.content.pm.PackageManager;
|
| import android.os.Looper;
|
| import android.util.Log;
|
| @@ -41,6 +40,8 @@ public class HostBrowserClassLoader {
|
|
|
| /*
|
| * ClassLoader for WebAPK dex. Static so that the same ClassLoader is used for app's lifetime.
|
| + * The ClassLoader is re-created if the host browser is upgraded while the WebAPK is still
|
| + * running.
|
| */
|
| private static ClassLoader sClassLoader;
|
|
|
| @@ -52,8 +53,15 @@ public class HostBrowserClassLoader {
|
| */
|
| public static ClassLoader getClassLoaderInstance(Context context, String canaryClassName) {
|
| assertRunningOnUiThread();
|
| - if (sClassLoader == null) {
|
| - sClassLoader = createClassLoader(context, canaryClassName);
|
| + Context remoteContext = WebApkUtils.getHostBrowserContext(context);
|
| + if (remoteContext == null) {
|
| + Log.w(TAG, "Failed to get remote context.");
|
| + return null;
|
| + }
|
| +
|
| + if (sClassLoader == null || !canReuseClassLoaderInstance(context, remoteContext)) {
|
| + sClassLoader =
|
| + createClassLoader(context, remoteContext, new DexLoader(), canaryClassName);
|
| }
|
| return sClassLoader;
|
| }
|
| @@ -61,16 +69,13 @@ public class HostBrowserClassLoader {
|
| /**
|
| * Creates ClassLoader for WebAPK dex.
|
| * @param context WebAPK's context.
|
| + * @param remoteContext Host browser's context.
|
| * @param canaryClassName Class to load to check that ClassLoader is valid.
|
| + * @param dexLoader DexLoader for creating ClassLoader.
|
| * @return The ClassLoader.
|
| */
|
| - private static ClassLoader createClassLoader(Context context, String canaryClassName) {
|
| - Context remoteContext = WebApkUtils.getHostBrowserContext(context);
|
| - if (remoteContext == null) {
|
| - Log.w(TAG, "Failed to get remote context.");
|
| - return null;
|
| - }
|
| -
|
| + public static ClassLoader createClassLoader(
|
| + Context context, Context remoteContext, DexLoader dexLoader, String canaryClassName) {
|
| SharedPreferences preferences =
|
| context.getSharedPreferences(PREF_PACKAGE, Context.MODE_PRIVATE);
|
|
|
| @@ -82,14 +87,27 @@ public class HostBrowserClassLoader {
|
| File localDexDir = context.getDir("dex", Context.MODE_PRIVATE);
|
| if (newRuntimeDexVersion != runtimeDexVersion) {
|
| Log.w(TAG, "Delete cached dex files.");
|
| - DexLoader.deleteCachedDexes(localDexDir);
|
| + dexLoader.deleteCachedDexes(localDexDir);
|
| }
|
|
|
| String dexAssetName = WebApkVersionUtils.getRuntimeDexName(newRuntimeDexVersion);
|
| File remoteDexFile =
|
| new File(remoteContext.getDir("dex", Context.MODE_PRIVATE), dexAssetName);
|
| - return DexLoader.load(remoteContext, dexAssetName, canaryClassName,
|
| - remoteDexFile, localDexDir);
|
| + return dexLoader.load(
|
| + remoteContext, dexAssetName, canaryClassName, remoteDexFile, localDexDir);
|
| + }
|
| +
|
| + /**
|
| + * Returns whether {@link sClassLoader} can be reused.
|
| + */
|
| + public static boolean canReuseClassLoaderInstance(Context context, Context remoteContext) {
|
| + // WebAPK may still be running when the host browser gets upgraded. Prevent ClassLoader from
|
| + // getting reused in this scenario.
|
| + SharedPreferences preferences =
|
| + context.getSharedPreferences(PREF_PACKAGE, Context.MODE_PRIVATE);
|
| + int cachedRemoteVersionCode = preferences.getInt(REMOTE_VERSION_CODE_PREF, -1);
|
| + int remoteVersionCode = getVersionCode(remoteContext);
|
| + return remoteVersionCode == cachedRemoteVersionCode;
|
| }
|
|
|
| /**
|
| @@ -104,29 +122,35 @@ public class HostBrowserClassLoader {
|
| // The "runtime dex" version only changes when {@link remoteContext}'s APK version code
|
| // changes. Checking the APK's version code is less expensive than reading from the APK's
|
| // assets.
|
| - PackageInfo remotePackageInfo = null;
|
| - try {
|
| - remotePackageInfo = remoteContext.getPackageManager().getPackageInfo(
|
| - remoteContext.getPackageName(), 0);
|
| - } catch (PackageManager.NameNotFoundException e) {
|
| - Log.e(TAG, "Failed to get remote package info.");
|
| - return -1;
|
| - }
|
| -
|
| + int remoteVersionCode = getVersionCode(remoteContext);
|
| int cachedRemoteVersionCode = preferences.getInt(REMOTE_VERSION_CODE_PREF, -1);
|
| - if (cachedRemoteVersionCode == remotePackageInfo.versionCode) {
|
| + if (cachedRemoteVersionCode == remoteVersionCode) {
|
| return -1;
|
| }
|
|
|
| int runtimeDexVersion = readAssetContentsToInt(remoteContext, "webapk_dex_version.txt");
|
| SharedPreferences.Editor editor = preferences.edit();
|
| - editor.putInt(REMOTE_VERSION_CODE_PREF, remotePackageInfo.versionCode);
|
| + editor.putInt(REMOTE_VERSION_CODE_PREF, remoteVersionCode);
|
| editor.putInt(RUNTIME_DEX_VERSION_PREF, runtimeDexVersion);
|
| editor.apply();
|
| return runtimeDexVersion;
|
| }
|
|
|
| /**
|
| + * Returns version code of {@link context}'s APK.
|
| + */
|
| + private static int getVersionCode(Context context) {
|
| + try {
|
| + return context.getPackageManager()
|
| + .getPackageInfo(context.getPackageName(), 0)
|
| + .versionCode;
|
| + } catch (PackageManager.NameNotFoundException e) {
|
| + Log.e(TAG, "Failed to get remote package info.");
|
| + }
|
| + return -1;
|
| + }
|
| +
|
| + /**
|
| * Returns the first integer in an asset file's contents.
|
| * @param context
|
| * @param assetName The name of the asset.
|
|
|