| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.minting; | 5 package org.chromium.minting; |
| 6 | 6 |
| 7 import android.app.Service; | 7 import android.app.Service; |
| 8 import android.content.Context; | 8 import android.content.Context; |
| 9 import android.content.Intent; | 9 import android.content.Intent; |
| 10 import android.content.SharedPreferences; | 10 import android.content.SharedPreferences; |
| 11 import android.content.pm.PackageInfo; | 11 import android.content.pm.PackageInfo; |
| 12 import android.content.pm.PackageManager; | 12 import android.content.pm.PackageManager; |
| 13 import android.os.Bundle; | 13 import android.os.Bundle; |
| 14 import android.os.IBinder; | 14 import android.os.IBinder; |
| 15 import android.util.Log; | 15 import android.util.Log; |
| 16 | 16 |
| 17 import org.chromium.minting.lib.common.WebAPKUtils; | 17 import org.chromium.minting.lib.common.WebApkUtils; |
| 18 | 18 |
| 19 import java.io.File; | 19 import java.io.File; |
| 20 import java.lang.reflect.Constructor; | 20 import java.lang.reflect.Constructor; |
| 21 import java.util.Scanner; | 21 import java.util.Scanner; |
| 22 | 22 |
| 23 /** | 23 /** |
| 24 * Shell class for services provided by Web APK to Chrome. Extracts code with im
plementation of | 24 * Shell class for services provided by Web APK to Chrome. Extracts code with im
plementation of |
| 25 * services from .dex file in Chrome APK. | 25 * services from .dex file in Chrome APK. |
| 26 */ | 26 */ |
| 27 public class MintingServiceFactory extends Service { | 27 public class WebApkServiceFactory extends Service { |
| 28 private static final String TAG = "cr.MintingServiceFactory"; | 28 private static final String TAG = "cr.WebApkServiceFactory"; |
| 29 | 29 |
| 30 /** | 30 /** |
| 31 * Name of the class with IBinder API implementation. | 31 * Name of the class with IBinder API implementation. |
| 32 */ | 32 */ |
| 33 private static final String MINTED_SERVICE_IMPL_CLASS_NAME = | 33 private static final String MINTED_SERVICE_IMPL_CLASS_NAME = |
| 34 "org.chromium.minting.libs.runtime_library.MintedServiceImpl"; | 34 "org.chromium.minting.libs.runtime_library.WebApkServiceImpl"; |
| 35 | 35 |
| 36 private static final String KEY_APP_ICON_ID = "app_icon_id"; | 36 private static final String KEY_APP_ICON_ID = "app_icon_id"; |
| 37 private static final String KEY_EXPECTED_HOST_BROWSER = "expected_host_brows
er"; | 37 private static final String KEY_EXPECTED_HOST_BROWSER = "expected_host_brows
er"; |
| 38 | 38 |
| 39 /** | 39 /** |
| 40 * Name of the shared preferences file. | 40 * Name of the shared preferences file. |
| 41 */ | 41 */ |
| 42 private static final String PREF_FILE_NAME = "MINT_PREFS"; | 42 private static final String PREF_FILE_NAME = "MINT_PREFS"; |
| 43 | 43 |
| 44 /** | 44 /** |
| 45 * Name of the shared preference for Chrome's version code. | 45 * Name of the shared preference for Chrome's version code. |
| 46 */ | 46 */ |
| 47 private static final String REMOTE_VERSION_CODE_PREF = | 47 private static final String REMOTE_VERSION_CODE_PREF = |
| 48 "minting_service_factory_remote_version_code"; | 48 "minting_service_factory_remote_version_code"; |
| 49 | 49 |
| 50 /** | 50 /** |
| 51 * Name of the shared preference for the version number of the dynamically l
oaded dex. | 51 * Name of the shared preference for the version number of the dynamically l
oaded dex. |
| 52 */ | 52 */ |
| 53 private static final String RUNTIME_DEX_VERSION_PREF = | 53 private static final String RUNTIME_DEX_VERSION_PREF = |
| 54 "minting_service_factory_runtime_dex_version"; | 54 "minting_service_factory_runtime_dex_version"; |
| 55 | 55 |
| 56 /* | 56 /* |
| 57 * ClassLoader for loading {@link MINTED_SERVICE_IMPL_CLASS_NAME}. Static so
that all | 57 * ClassLoader for loading {@link MINTED_SERVICE_IMPL_CLASS_NAME}. Static so
that all |
| 58 * {@link MintingServiceFactory} service instatiations use the same ClassLoa
der during the app's | 58 * {@link WebApkServiceFactory} service instatiations use the same ClassLoad
er during the app's |
| 59 * lifetime. | 59 * lifetime. |
| 60 */ | 60 */ |
| 61 private static ClassLoader sClassLoader; | 61 private static ClassLoader sClassLoader; |
| 62 | 62 |
| 63 @Override | 63 @Override |
| 64 public IBinder onBind(Intent intent) { | 64 public IBinder onBind(Intent intent) { |
| 65 if (sClassLoader == null) { | 65 if (sClassLoader == null) { |
| 66 sClassLoader = createClassLoader(this); | 66 sClassLoader = createClassLoader(this); |
| 67 if (sClassLoader == null) { | 67 if (sClassLoader == null) { |
| 68 Log.w(TAG, "Unable to create ClassLoader."); | 68 Log.w(TAG, "Unable to create ClassLoader."); |
| 69 return null; | 69 return null; |
| 70 } | 70 } |
| 71 } | 71 } |
| 72 | 72 |
| 73 try { | 73 try { |
| 74 Class<?> mintedServiceImplClass = | 74 Class<?> mintedServiceImplClass = |
| 75 sClassLoader.loadClass(MINTED_SERVICE_IMPL_CLASS_NAME); | 75 sClassLoader.loadClass(MINTED_SERVICE_IMPL_CLASS_NAME); |
| 76 Constructor<?> mintedServiceImplConstructor = | 76 Constructor<?> mintedServiceImplConstructor = |
| 77 mintedServiceImplClass.getConstructor(Context.class, Bundle.
class); | 77 mintedServiceImplClass.getConstructor(Context.class, Bundle.
class); |
| 78 String expectedHostPackageName = WebAPKUtils.getHostBrowserPackageNa
me(this); | 78 String expectedHostPackageName = WebApkUtils.getHostBrowserPackageNa
me(this); |
| 79 Bundle bundle = new Bundle(); | 79 Bundle bundle = new Bundle(); |
| 80 bundle.putInt(KEY_APP_ICON_ID, R.drawable.app_icon); | 80 bundle.putInt(KEY_APP_ICON_ID, R.drawable.app_icon); |
| 81 bundle.putString(KEY_EXPECTED_HOST_BROWSER, expectedHostPackageName)
; | 81 bundle.putString(KEY_EXPECTED_HOST_BROWSER, expectedHostPackageName)
; |
| 82 return (IBinder) mintedServiceImplConstructor.newInstance(new Object
[] {this, bundle}); | 82 return (IBinder) mintedServiceImplConstructor.newInstance(new Object
[] {this, bundle}); |
| 83 } catch (Exception e) { | 83 } catch (Exception e) { |
| 84 Log.w(TAG, "Unable to create MintedServiceImpl."); | 84 Log.w(TAG, "Unable to create WebApkServiceImpl."); |
| 85 e.printStackTrace(); | 85 e.printStackTrace(); |
| 86 return null; | 86 return null; |
| 87 } | 87 } |
| 88 } | 88 } |
| 89 | 89 |
| 90 /** | 90 /** |
| 91 * Creates ClassLoader for loading {@link MINTED_SERVICE_IMPL_CLASS_NAME}. | 91 * Creates ClassLoader for loading {@link MINTED_SERVICE_IMPL_CLASS_NAME}. |
| 92 * @param context WebAPK's context. | 92 * @param context WebAPK's context. |
| 93 * @return The ClassLoader. | 93 * @return The ClassLoader. |
| 94 */ | 94 */ |
| 95 private static ClassLoader createClassLoader(Context context) { | 95 private static ClassLoader createClassLoader(Context context) { |
| 96 Context remoteContext = WebAPKUtils.getHostBrowserContext(context); | 96 Context remoteContext = WebApkUtils.getHostBrowserContext(context); |
| 97 if (remoteContext == null) { | 97 if (remoteContext == null) { |
| 98 Log.w(TAG, "Failed to get remote context."); | 98 Log.w(TAG, "Failed to get remote context."); |
| 99 return null; | 99 return null; |
| 100 } | 100 } |
| 101 | 101 |
| 102 SharedPreferences preferences = context.getSharedPreferences(PREF_FILE_N
AME, MODE_PRIVATE); | 102 SharedPreferences preferences = context.getSharedPreferences(PREF_FILE_N
AME, MODE_PRIVATE); |
| 103 | 103 |
| 104 int runtimeDexVersion = preferences.getInt(RUNTIME_DEX_VERSION_PREF, -1)
; | 104 int runtimeDexVersion = preferences.getInt(RUNTIME_DEX_VERSION_PREF, -1)
; |
| 105 int newRuntimeDexVersion = checkForNewRuntimeDexVersion(preferences, rem
oteContext); | 105 int newRuntimeDexVersion = checkForNewRuntimeDexVersion(preferences, rem
oteContext); |
| 106 if (newRuntimeDexVersion == -1) { | 106 if (newRuntimeDexVersion == -1) { |
| 107 newRuntimeDexVersion = runtimeDexVersion; | 107 newRuntimeDexVersion = runtimeDexVersion; |
| 108 } | 108 } |
| 109 File localDexDir = context.getDir("dex", Context.MODE_PRIVATE); | 109 File localDexDir = context.getDir("dex", Context.MODE_PRIVATE); |
| 110 if (newRuntimeDexVersion != runtimeDexVersion) { | 110 if (newRuntimeDexVersion != runtimeDexVersion) { |
| 111 Log.w(TAG, "Delete cached dex files."); | 111 Log.w(TAG, "Delete cached dex files."); |
| 112 DexLoader.deleteCachedDexes(localDexDir); | 112 DexLoader.deleteCachedDexes(localDexDir); |
| 113 } | 113 } |
| 114 | 114 |
| 115 String dexAssetName = WebAPKUtils.getRuntimeDexName(newRuntimeDexVersion
); | 115 String dexAssetName = WebApkUtils.getRuntimeDexName(newRuntimeDexVersion
); |
| 116 File remoteDexFile = | 116 File remoteDexFile = |
| 117 new File(remoteContext.getDir("dex", Context.MODE_PRIVATE), dexA
ssetName); | 117 new File(remoteContext.getDir("dex", Context.MODE_PRIVATE), dexA
ssetName); |
| 118 return DexLoader.load(remoteContext, dexAssetName, MINTED_SERVICE_IMPL_C
LASS_NAME, | 118 return DexLoader.load(remoteContext, dexAssetName, MINTED_SERVICE_IMPL_C
LASS_NAME, |
| 119 remoteDexFile, localDexDir); | 119 remoteDexFile, localDexDir); |
| 120 } | 120 } |
| 121 | 121 |
| 122 /** | 122 /** |
| 123 * Checks if there is a new "runtime dex" version number. If there is a new
version number, | 123 * Checks if there is a new "runtime dex" version number. If there is a new
version number, |
| 124 * updates SharedPreferences. | 124 * updates SharedPreferences. |
| 125 * @param preferences WebAPK's SharedPreferences. | 125 * @param preferences WebAPK's SharedPreferences. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 * @param assetName The name of the asset. | 159 * @param assetName The name of the asset. |
| 160 */ | 160 */ |
| 161 private static int readAssetContentsToInt(Context context, String assetName)
{ | 161 private static int readAssetContentsToInt(Context context, String assetName)
{ |
| 162 try (Scanner scanner = new Scanner(context.getAssets().open(assetName)))
{ | 162 try (Scanner scanner = new Scanner(context.getAssets().open(assetName)))
{ |
| 163 return scanner.nextInt(); | 163 return scanner.nextInt(); |
| 164 } catch (Exception e) { | 164 } catch (Exception e) { |
| 165 return -1; | 165 return -1; |
| 166 } | 166 } |
| 167 } | 167 } |
| 168 } | 168 } |
| OLD | NEW |