@hot-updater/react-native 1.0.0-rc.4 → 1.0.0-rc.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +13 -2
- package/android/proguard-rules.pro +8 -2
- package/android/src/bridge/BridgeReactInstance.kt +38 -0
- package/android/src/bridgeless/BridgeReactInstance.kt +24 -0
- package/android/src/main/java/com/hotupdater/ActivityStartGate.kt +94 -0
- package/android/src/main/java/com/hotupdater/BuiltInAssetResolver.kt +286 -0
- package/android/src/main/java/com/hotupdater/BundleFileStorageService.kt +1064 -844
- package/android/src/main/java/com/hotupdater/BundleMetadata.kt +50 -11
- package/android/src/main/java/com/hotupdater/FileManagerService.kt +45 -0
- package/android/src/main/java/com/hotupdater/HotUpdaterException.kt +287 -22
- package/android/src/main/java/com/hotupdater/HotUpdaterImpl.kt +46 -30
- package/android/src/main/java/com/hotupdater/HotUpdaterRecoveryManager.kt +75 -192
- package/android/src/main/java/com/hotupdater/HotUpdaterRecoveryState.kt +64 -0
- package/android/src/main/java/com/hotupdater/InstallIdentityService.kt +37 -0
- package/android/src/main/java/com/hotupdater/KeyValueStorageService.kt +86 -0
- package/android/src/main/java/com/hotupdater/NetworkState.kt +31 -0
- package/android/src/main/java/com/hotupdater/NoBackupStorage.kt +17 -0
- package/android/src/main/java/com/hotupdater/OkHttpDownloadService.kt +127 -50
- package/android/src/main/java/com/hotupdater/ReactNativeValueConverters.kt +34 -0
- package/android/src/main/java/com/hotupdater/TarArchiveInputStream.kt +214 -375
- package/android/src/main/java/com/hotupdater/TarBrArchiveExtractor.kt +119 -0
- package/android/src/newarch/HotUpdater.kt +7 -9
- package/android/src/newarch/HotUpdaterModule.kt +109 -84
- package/android/src/newarch/JavaScriptExceptionHooks.kt +48 -0
- package/android/src/newarch/ReactIntegrationManager.kt +6 -32
- package/android/src/oldarch/HotUpdater.kt +7 -9
- package/android/src/oldarch/HotUpdaterModule.kt +98 -74
- package/android/src/oldarch/HotUpdaterSpec.kt +4 -6
- package/android/src/oldarch/JavaScriptExceptionHooks.kt +71 -0
- package/ios/HotUpdater/Internal/BrotliFileDecompressor.swift +167 -0
- package/ios/HotUpdater/Internal/BuiltInAssetResolver.swift +196 -0
- package/ios/HotUpdater/Internal/BundleFileStorageService.swift +1032 -1116
- package/ios/HotUpdater/Internal/BundleMetadata.swift +61 -54
- package/ios/HotUpdater/Internal/FileManagerService.swift +48 -0
- package/ios/HotUpdater/Internal/FileUtilities.swift +64 -0
- package/ios/HotUpdater/Internal/HotUpdater-Bridging-Header.h +0 -1
- package/ios/HotUpdater/Internal/HotUpdater.mm +32 -67
- package/ios/HotUpdater/Internal/HotUpdaterImpl.swift +229 -73
- package/ios/HotUpdater/Internal/KeyValueStorageService.swift +71 -0
- package/ios/HotUpdater/Internal/NotificationExtension.swift +0 -2
- package/ios/HotUpdater/Internal/TarArchiveExtractor.swift +182 -311
- package/ios/HotUpdater/Internal/URLSessionDownloadService.swift +119 -71
- package/ios/HotUpdater/Internal/UpdateFailure.swift +390 -0
- package/ios/HotUpdater/Recovery/HotUpdaterRecovery.h +16 -0
- package/ios/HotUpdater/Recovery/HotUpdaterRecovery.mm +83 -0
- package/ios/HotUpdater/Recovery/HotUpdaterRecoveryHooks.mm +49 -0
- package/lib/commonjs/appReady.js +96 -0
- package/lib/commonjs/appReady.js.map +1 -0
- package/lib/commonjs/checkForUpdate.js +121 -69
- package/lib/commonjs/checkForUpdate.js.map +1 -1
- package/lib/commonjs/clientPlugin.js +13 -0
- package/lib/commonjs/clientPlugin.js.map +1 -0
- package/lib/commonjs/error.js +5 -14
- package/lib/commonjs/error.js.map +1 -1
- package/lib/commonjs/fetchJSON.js +16 -27
- package/lib/commonjs/fetchJSON.js.map +1 -1
- package/lib/commonjs/fetchUpdateResponse.js +60 -0
- package/lib/commonjs/fetchUpdateResponse.js.map +1 -0
- package/lib/commonjs/httpClient.js +64 -95
- package/lib/commonjs/httpClient.js.map +1 -1
- package/lib/commonjs/index.js +355 -324
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/init.types.js +6 -0
- package/lib/commonjs/init.types.js.map +1 -0
- package/lib/commonjs/native.js +77 -63
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/pluginHost.js +41 -0
- package/lib/commonjs/pluginHost.js.map +1 -0
- package/lib/commonjs/releaseCatalogCache.js +36 -87
- package/lib/commonjs/releaseCatalogCache.js.map +1 -1
- package/lib/commonjs/sdkVersion.js +1 -1
- package/lib/commonjs/sdkVersion.js.map +1 -1
- package/lib/commonjs/specs/NativeHotUpdater.js.map +1 -1
- package/lib/commonjs/store.js +3 -10
- package/lib/commonjs/store.js.map +1 -1
- package/lib/commonjs/updateError.js +145 -0
- package/lib/commonjs/updateError.js.map +1 -0
- package/lib/commonjs/wrap.js +46 -38
- package/lib/commonjs/wrap.js.map +1 -1
- package/lib/module/appReady.js +90 -0
- package/lib/module/appReady.js.map +1 -0
- package/lib/module/checkForUpdate.js +114 -64
- package/lib/module/checkForUpdate.js.map +1 -1
- package/lib/module/clientPlugin.js +4 -0
- package/lib/module/clientPlugin.js.map +1 -0
- package/lib/module/error.js +5 -14
- package/lib/module/error.js.map +1 -1
- package/lib/module/fetchJSON.js +14 -26
- package/lib/module/fetchJSON.js.map +1 -1
- package/lib/module/fetchUpdateResponse.js +55 -0
- package/lib/module/fetchUpdateResponse.js.map +1 -0
- package/lib/module/httpClient.js +63 -94
- package/lib/module/httpClient.js.map +1 -1
- package/lib/module/index.js +335 -327
- package/lib/module/index.js.map +1 -1
- package/lib/module/init.types.js +4 -0
- package/lib/module/init.types.js.map +1 -0
- package/lib/module/native.js +70 -56
- package/lib/module/native.js.map +1 -1
- package/lib/module/pluginHost.js +36 -0
- package/lib/module/pluginHost.js.map +1 -0
- package/lib/module/releaseCatalogCache.js +32 -82
- package/lib/module/releaseCatalogCache.js.map +1 -1
- package/lib/module/sdkVersion.js +1 -1
- package/lib/module/sdkVersion.js.map +1 -1
- package/lib/module/specs/NativeHotUpdater.js.map +1 -1
- package/lib/module/store.js +3 -10
- package/lib/module/store.js.map +1 -1
- package/lib/module/updateError.js +139 -0
- package/lib/module/updateError.js.map +1 -0
- package/lib/module/wrap.js +47 -38
- package/lib/module/wrap.js.map +1 -1
- package/lib/typescript/commonjs/appReady.d.ts +30 -0
- package/lib/typescript/commonjs/appReady.d.ts.map +1 -0
- package/lib/typescript/commonjs/checkForUpdate.d.ts +20 -6
- package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/commonjs/clientPlugin.d.ts +2 -0
- package/lib/typescript/commonjs/clientPlugin.d.ts.map +1 -0
- package/lib/typescript/commonjs/error.d.ts +5 -14
- package/lib/typescript/commonjs/error.d.ts.map +1 -1
- package/lib/typescript/commonjs/fetchJSON.d.ts +5 -5
- package/lib/typescript/commonjs/fetchJSON.d.ts.map +1 -1
- package/lib/typescript/commonjs/fetchUpdateResponse.d.ts +14 -0
- package/lib/typescript/commonjs/fetchUpdateResponse.d.ts.map +1 -0
- package/lib/typescript/commonjs/httpClient.d.ts +5 -34
- package/lib/typescript/commonjs/httpClient.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +124 -116
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/init.types.d.ts +21 -0
- package/lib/typescript/commonjs/init.types.d.ts.map +1 -0
- package/lib/typescript/commonjs/native.d.ts +32 -25
- package/lib/typescript/commonjs/native.d.ts.map +1 -1
- package/lib/typescript/commonjs/pluginHost.d.ts +8 -0
- package/lib/typescript/commonjs/pluginHost.d.ts.map +1 -0
- package/lib/typescript/commonjs/releaseCatalogCache.d.ts +8 -14
- package/lib/typescript/commonjs/releaseCatalogCache.d.ts.map +1 -1
- package/lib/typescript/commonjs/sdkVersion.d.ts +1 -1
- package/lib/typescript/commonjs/sdkVersion.d.ts.map +1 -1
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts +35 -47
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/commonjs/store.d.ts +1 -3
- package/lib/typescript/commonjs/store.d.ts.map +1 -1
- package/lib/typescript/commonjs/types.d.ts +1 -1
- package/lib/typescript/commonjs/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/updateError.d.ts +26 -0
- package/lib/typescript/commonjs/updateError.d.ts.map +1 -0
- package/lib/typescript/commonjs/wrap.d.ts +2 -3
- package/lib/typescript/commonjs/wrap.d.ts.map +1 -1
- package/lib/typescript/commonjs/wrap.types.d.ts +13 -41
- package/lib/typescript/commonjs/wrap.types.d.ts.map +1 -1
- package/lib/typescript/module/appReady.d.ts +30 -0
- package/lib/typescript/module/appReady.d.ts.map +1 -0
- package/lib/typescript/module/checkForUpdate.d.ts +20 -6
- package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/module/clientPlugin.d.ts +2 -0
- package/lib/typescript/module/clientPlugin.d.ts.map +1 -0
- package/lib/typescript/module/error.d.ts +5 -14
- package/lib/typescript/module/error.d.ts.map +1 -1
- package/lib/typescript/module/fetchJSON.d.ts +5 -5
- package/lib/typescript/module/fetchJSON.d.ts.map +1 -1
- package/lib/typescript/module/fetchUpdateResponse.d.ts +14 -0
- package/lib/typescript/module/fetchUpdateResponse.d.ts.map +1 -0
- package/lib/typescript/module/httpClient.d.ts +5 -34
- package/lib/typescript/module/httpClient.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +124 -116
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/init.types.d.ts +21 -0
- package/lib/typescript/module/init.types.d.ts.map +1 -0
- package/lib/typescript/module/native.d.ts +32 -25
- package/lib/typescript/module/native.d.ts.map +1 -1
- package/lib/typescript/module/pluginHost.d.ts +8 -0
- package/lib/typescript/module/pluginHost.d.ts.map +1 -0
- package/lib/typescript/module/releaseCatalogCache.d.ts +8 -14
- package/lib/typescript/module/releaseCatalogCache.d.ts.map +1 -1
- package/lib/typescript/module/sdkVersion.d.ts +1 -1
- package/lib/typescript/module/sdkVersion.d.ts.map +1 -1
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts +35 -47
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/module/store.d.ts +1 -3
- package/lib/typescript/module/store.d.ts.map +1 -1
- package/lib/typescript/module/types.d.ts +1 -1
- package/lib/typescript/module/types.d.ts.map +1 -1
- package/lib/typescript/module/updateError.d.ts +26 -0
- package/lib/typescript/module/updateError.d.ts.map +1 -0
- package/lib/typescript/module/wrap.d.ts +2 -3
- package/lib/typescript/module/wrap.d.ts.map +1 -1
- package/lib/typescript/module/wrap.types.d.ts +13 -41
- package/lib/typescript/module/wrap.types.d.ts.map +1 -1
- package/package.json +8 -4
- package/src/appReady.ts +147 -0
- package/src/checkForUpdate.ts +156 -89
- package/src/clientPlugin.ts +21 -0
- package/src/error.ts +5 -15
- package/src/fetchJSON.ts +14 -30
- package/src/fetchUpdateResponse.ts +60 -0
- package/src/httpClient.ts +89 -160
- package/src/index.ts +413 -425
- package/src/init.types.ts +24 -0
- package/src/native.ts +101 -105
- package/src/pluginHost.ts +52 -0
- package/src/releaseCatalogCache.ts +43 -172
- package/src/sdkVersion.ts +1 -1
- package/src/specs/NativeHotUpdater.ts +34 -48
- package/src/store.ts +2 -23
- package/src/types.ts +1 -1
- package/src/updateError.ts +167 -0
- package/src/wrap.tsx +60 -43
- package/src/wrap.types.ts +18 -46
- package/android/src/main/java/com/hotupdater/DecompressService.kt +0 -89
- package/android/src/main/java/com/hotupdater/DecompressionStrategy.kt +0 -26
- package/android/src/main/java/com/hotupdater/TarBrDecompressionStrategy.kt +0 -117
- package/android/src/main/java/com/hotupdater/TarGzDecompressionStrategy.kt +0 -117
- package/android/src/main/java/com/hotupdater/ZipDecompressionStrategy.kt +0 -192
- package/android/src/test/java/com/hotupdater/BsdiffPatchTest.kt +0 -46
- package/android/src/test/java/com/hotupdater/BundleFileStorageServiceTest.kt +0 -799
- package/android/src/test/java/com/hotupdater/HotUpdaterImplTest.kt +0 -273
- package/android/src/test/java/com/hotupdater/NativeConfigUtilsTest.kt +0 -20
- package/android/src/test/java/com/hotupdater/OkHttpDownloadServiceTest.kt +0 -111
- package/android/src/test/java/com/hotupdater/RelativePathResolverTest.kt +0 -41
- package/android/src/test/java/com/hotupdater/ReleaseCatalogCacheServiceTest.kt +0 -118
- package/android/src/test/java/com/hotupdater/TarArchiveInputStreamTest.kt +0 -68
- package/ios/HotUpdater/Internal/ArchiveExtractionUtilities.swift +0 -178
- package/ios/HotUpdater/Internal/DecompressService.swift +0 -112
- package/ios/HotUpdater/Internal/DecompressionStrategy.swift +0 -22
- package/ios/HotUpdater/Internal/StreamingTarArchiveExtractor.swift +0 -370
- package/ios/HotUpdater/Internal/TarBrDecompressionStrategy.swift +0 -39
- package/ios/HotUpdater/Internal/TarGzDecompressionStrategy.swift +0 -59
- package/ios/HotUpdater/Internal/ZipArchiveExtractor.swift +0 -482
- package/ios/HotUpdater/Internal/ZipDecompressionStrategy.swift +0 -56
- package/lib/commonjs/catalogCacheNative.spec.js +0 -31
- package/lib/commonjs/catalogCacheNative.spec.js.map +0 -1
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js +0 -616
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js.map +0 -1
- package/lib/commonjs/httpClient.spec.js +0 -102
- package/lib/commonjs/httpClient.spec.js.map +0 -1
- package/lib/commonjs/index.spec.js +0 -302
- package/lib/commonjs/index.spec.js.map +0 -1
- package/lib/commonjs/iosInterop.spec.js +0 -18
- package/lib/commonjs/iosInterop.spec.js.map +0 -1
- package/lib/commonjs/native.spec.js +0 -883
- package/lib/commonjs/native.spec.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js +0 -218
- package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.js +0 -133
- package/lib/commonjs/notifyAppReadyInsights.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.spec.js +0 -246
- package/lib/commonjs/notifyAppReadyInsights.spec.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.test-utils.js +0 -24
- package/lib/commonjs/notifyAppReadyInsights.test-utils.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.transport.spec.js +0 -117
- package/lib/commonjs/notifyAppReadyInsights.transport.spec.js.map +0 -1
- package/lib/commonjs/releaseCatalogCache.spec.js +0 -195
- package/lib/commonjs/releaseCatalogCache.spec.js.map +0 -1
- package/lib/commonjs/releaseCatalogCacheNativeContract.spec.js +0 -64
- package/lib/commonjs/releaseCatalogCacheNativeContract.spec.js.map +0 -1
- package/lib/commonjs/store.notification.spec.js +0 -76
- package/lib/commonjs/store.notification.spec.js.map +0 -1
- package/lib/commonjs/store.spec.js +0 -316
- package/lib/commonjs/store.spec.js.map +0 -1
- package/lib/commonjs/wrap.spec.js +0 -329
- package/lib/commonjs/wrap.spec.js.map +0 -1
- package/lib/module/catalogCacheNative.spec.js +0 -31
- package/lib/module/catalogCacheNative.spec.js.map +0 -1
- package/lib/module/checkForUpdate.releaseCatalog.spec.js +0 -615
- package/lib/module/checkForUpdate.releaseCatalog.spec.js.map +0 -1
- package/lib/module/httpClient.spec.js +0 -102
- package/lib/module/httpClient.spec.js.map +0 -1
- package/lib/module/index.spec.js +0 -301
- package/lib/module/index.spec.js.map +0 -1
- package/lib/module/iosInterop.spec.js +0 -18
- package/lib/module/iosInterop.spec.js.map +0 -1
- package/lib/module/native.spec.js +0 -882
- package/lib/module/native.spec.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.boundary.spec.js +0 -217
- package/lib/module/notifyAppReadyInsights.boundary.spec.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.js +0 -128
- package/lib/module/notifyAppReadyInsights.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.spec.js +0 -245
- package/lib/module/notifyAppReadyInsights.spec.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.test-utils.js +0 -18
- package/lib/module/notifyAppReadyInsights.test-utils.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.transport.spec.js +0 -116
- package/lib/module/notifyAppReadyInsights.transport.spec.js.map +0 -1
- package/lib/module/releaseCatalogCache.spec.js +0 -195
- package/lib/module/releaseCatalogCache.spec.js.map +0 -1
- package/lib/module/releaseCatalogCacheNativeContract.spec.js +0 -64
- package/lib/module/releaseCatalogCacheNativeContract.spec.js.map +0 -1
- package/lib/module/store.notification.spec.js +0 -77
- package/lib/module/store.notification.spec.js.map +0 -1
- package/lib/module/store.spec.js +0 -315
- package/lib/module/store.spec.js.map +0 -1
- package/lib/module/wrap.spec.js +0 -330
- package/lib/module/wrap.spec.js.map +0 -1
- package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts +0 -13
- package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts.map +0 -1
- package/lib/typescript/commonjs/notifyAppReadyInsights.test-utils.d.ts +0 -8
- package/lib/typescript/commonjs/notifyAppReadyInsights.test-utils.d.ts.map +0 -1
- package/lib/typescript/module/notifyAppReadyInsights.d.ts +0 -13
- package/lib/typescript/module/notifyAppReadyInsights.d.ts.map +0 -1
- package/lib/typescript/module/notifyAppReadyInsights.test-utils.d.ts +0 -8
- package/lib/typescript/module/notifyAppReadyInsights.test-utils.d.ts.map +0 -1
- package/src/catalogCacheNative.spec.ts +0 -63
- package/src/checkForUpdate.releaseCatalog.spec.ts +0 -612
- package/src/httpClient.spec.ts +0 -132
- package/src/index.spec.ts +0 -337
- package/src/iosInterop.spec.ts +0 -30
- package/src/native.spec.ts +0 -945
- package/src/notifyAppReadyInsights.boundary.spec.ts +0 -234
- package/src/notifyAppReadyInsights.spec.ts +0 -243
- package/src/notifyAppReadyInsights.test-utils.ts +0 -31
- package/src/notifyAppReadyInsights.transport.spec.ts +0 -130
- package/src/notifyAppReadyInsights.ts +0 -194
- package/src/releaseCatalogCache.spec.ts +0 -282
- package/src/releaseCatalogCacheNativeContract.spec.ts +0 -80
- package/src/store.notification.spec.ts +0 -92
- package/src/store.spec.ts +0 -372
- package/src/wrap.spec.ts +0 -406
|
@@ -21,6 +21,7 @@ data class BundleMetadata(
|
|
|
21
21
|
val pendingUpdateStrategy: String? = null,
|
|
22
22
|
val pendingTransition: PendingSelectionTransition? = null,
|
|
23
23
|
val verificationPending: Boolean = false,
|
|
24
|
+
val launchInProgress: Boolean = false,
|
|
24
25
|
val highestSeenCatalogs: Map<String, CatalogHighWater> = emptyMap(),
|
|
25
26
|
val currentSelectionContexts: Map<String, String> = emptyMap(),
|
|
26
27
|
val updatedAt: Long = System.currentTimeMillis(),
|
|
@@ -71,6 +72,7 @@ data class BundleMetadata(
|
|
|
71
72
|
pendingTransition =
|
|
72
73
|
json.optJSONObject("pendingTransition")?.let(PendingSelectionTransition::fromJson),
|
|
73
74
|
verificationPending = json.optBoolean("verificationPending", false),
|
|
75
|
+
launchInProgress = json.optBoolean("launchInProgress", false),
|
|
74
76
|
highestSeenCatalogs = highestSeenCatalogs,
|
|
75
77
|
currentSelectionContexts = currentSelectionContexts,
|
|
76
78
|
updatedAt = json.optLong("updatedAt", System.currentTimeMillis()),
|
|
@@ -121,6 +123,7 @@ data class BundleMetadata(
|
|
|
121
123
|
put("pendingUpdateStrategy", pendingUpdateStrategy ?: JSONObject.NULL)
|
|
122
124
|
put("pendingTransition", pendingTransition?.toJson() ?: JSONObject.NULL)
|
|
123
125
|
put("verificationPending", verificationPending)
|
|
126
|
+
put("launchInProgress", launchInProgress)
|
|
124
127
|
put(
|
|
125
128
|
"highestSeenCatalogs",
|
|
126
129
|
JSONObject().apply {
|
|
@@ -293,12 +296,44 @@ data class CrashedBundleEntry(
|
|
|
293
296
|
}
|
|
294
297
|
}
|
|
295
298
|
|
|
299
|
+
/**
|
|
300
|
+
* A bundle whose launch ended before first content without a crash, waiting
|
|
301
|
+
* for its one retry. Such a launch cannot tell a hang from a user leaving
|
|
302
|
+
* early, so the bundle is offered again instead of entering crash history.
|
|
303
|
+
* A second unfinished launch of it adds it there.
|
|
304
|
+
*
|
|
305
|
+
* [retryReady] turns true once a later launch shows content. The retry
|
|
306
|
+
* starts with the next process, so the session that recovered never reloads
|
|
307
|
+
* into the same bundle.
|
|
308
|
+
*/
|
|
309
|
+
data class InterruptedLaunch(
|
|
310
|
+
val bundleId: String,
|
|
311
|
+
val retryReady: Boolean = false,
|
|
312
|
+
) {
|
|
313
|
+
companion object {
|
|
314
|
+
fun fromJson(json: JSONObject): InterruptedLaunch? =
|
|
315
|
+
json.optNullableString("bundleId")?.let { bundleId ->
|
|
316
|
+
InterruptedLaunch(
|
|
317
|
+
bundleId = bundleId,
|
|
318
|
+
retryReady = json.optBoolean("retryReady", false),
|
|
319
|
+
)
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
fun toJson(): JSONObject =
|
|
324
|
+
JSONObject().apply {
|
|
325
|
+
put("bundleId", bundleId)
|
|
326
|
+
put("retryReady", retryReady)
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
296
330
|
/**
|
|
297
331
|
* History of crashed bundles
|
|
298
332
|
*/
|
|
299
333
|
data class CrashedHistory(
|
|
300
334
|
val bundles: MutableList<CrashedBundleEntry> = mutableListOf(),
|
|
301
335
|
val maxHistorySize: Int = DEFAULT_MAX_HISTORY_SIZE,
|
|
336
|
+
var interruptedLaunch: InterruptedLaunch? = null,
|
|
302
337
|
) {
|
|
303
338
|
companion object {
|
|
304
339
|
private const val TAG = "CrashedHistory"
|
|
@@ -314,6 +349,7 @@ data class CrashedHistory(
|
|
|
314
349
|
return CrashedHistory(
|
|
315
350
|
bundles = bundles,
|
|
316
351
|
maxHistorySize = json.optInt("maxHistorySize", DEFAULT_MAX_HISTORY_SIZE),
|
|
352
|
+
interruptedLaunch = json.optJSONObject("interruptedLaunch")?.let(InterruptedLaunch::fromJson),
|
|
317
353
|
)
|
|
318
354
|
}
|
|
319
355
|
|
|
@@ -339,6 +375,7 @@ data class CrashedHistory(
|
|
|
339
375
|
bundles.forEach { bundlesArray.put(it.toJson()) }
|
|
340
376
|
put("bundles", bundlesArray)
|
|
341
377
|
put("maxHistorySize", maxHistorySize)
|
|
378
|
+
interruptedLaunch?.let { put("interruptedLaunch", it.toJson()) }
|
|
342
379
|
}
|
|
343
380
|
|
|
344
381
|
fun saveToFile(file: File): Boolean =
|
|
@@ -386,6 +423,7 @@ data class CrashedHistory(
|
|
|
386
423
|
|
|
387
424
|
fun clear() {
|
|
388
425
|
bundles.clear()
|
|
426
|
+
interruptedLaunch = null
|
|
389
427
|
}
|
|
390
428
|
}
|
|
391
429
|
|
|
@@ -394,6 +432,13 @@ data class PendingCrashRecovery(
|
|
|
394
432
|
val shouldRollback: Boolean,
|
|
395
433
|
) {
|
|
396
434
|
companion object {
|
|
435
|
+
internal fun loadFromFile(file: File): PendingCrashRecovery? =
|
|
436
|
+
try {
|
|
437
|
+
fromJson(JSONObject(file.readText()))
|
|
438
|
+
} catch (_: Exception) {
|
|
439
|
+
null
|
|
440
|
+
}
|
|
441
|
+
|
|
397
442
|
fun fromJson(json: JSONObject): PendingCrashRecovery =
|
|
398
443
|
PendingCrashRecovery(
|
|
399
444
|
launchedBundleId =
|
|
@@ -469,21 +514,17 @@ data class LaunchReport(
|
|
|
469
514
|
}
|
|
470
515
|
}
|
|
471
516
|
|
|
517
|
+
/**
|
|
518
|
+
* The persisted install id. See [InstallIdentityService].
|
|
519
|
+
*/
|
|
472
520
|
data class InstallationIdentity(
|
|
473
521
|
val installId: String,
|
|
474
|
-
val userId: String? = null,
|
|
475
|
-
val username: String? = null,
|
|
476
522
|
) {
|
|
477
523
|
companion object {
|
|
478
524
|
private const val TAG = "InstallationIdentity"
|
|
479
|
-
const val IDENTITY_FILENAME = "identity.json"
|
|
525
|
+
const val IDENTITY_FILENAME = "install-identity.json"
|
|
480
526
|
|
|
481
|
-
fun fromJson(json: JSONObject): InstallationIdentity =
|
|
482
|
-
InstallationIdentity(
|
|
483
|
-
installId = json.getString("installId"),
|
|
484
|
-
userId = json.optNullableString("userId"),
|
|
485
|
-
username = json.optNullableString("username"),
|
|
486
|
-
)
|
|
527
|
+
fun fromJson(json: JSONObject): InstallationIdentity = InstallationIdentity(installId = json.getString("installId"))
|
|
487
528
|
|
|
488
529
|
fun loadFromFile(file: File): InstallationIdentity? =
|
|
489
530
|
try {
|
|
@@ -501,8 +542,6 @@ data class InstallationIdentity(
|
|
|
501
542
|
fun toJson(): JSONObject =
|
|
502
543
|
JSONObject().apply {
|
|
503
544
|
put("installId", installId)
|
|
504
|
-
put("userId", userId ?: JSONObject.NULL)
|
|
505
|
-
put("username", username ?: JSONObject.NULL)
|
|
506
545
|
}
|
|
507
546
|
|
|
508
547
|
fun saveToFile(file: File): Boolean =
|
|
@@ -2,6 +2,51 @@ package com.hotupdater
|
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
4
|
import java.io.File
|
|
5
|
+
import java.io.FileOutputStream
|
|
6
|
+
import java.io.IOException
|
|
7
|
+
import java.io.OutputStream
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* An I/O failure writing to local storage, as opposed to a failure reading or
|
|
11
|
+
* decoding the data being written.
|
|
12
|
+
*/
|
|
13
|
+
class LocalStorageException(
|
|
14
|
+
cause: IOException,
|
|
15
|
+
) : IOException(cause.message, cause)
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* An output stream to a local file whose I/O failures, including opening the
|
|
19
|
+
* file, surface as [LocalStorageException].
|
|
20
|
+
*/
|
|
21
|
+
internal class LocalStorageOutputStream private constructor(
|
|
22
|
+
private val output: OutputStream,
|
|
23
|
+
) : OutputStream() {
|
|
24
|
+
companion object {
|
|
25
|
+
fun open(file: File): LocalStorageOutputStream = LocalStorageOutputStream(storageOperation { FileOutputStream(file) })
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
override fun write(byte: Int) = storageOperation { output.write(byte) }
|
|
29
|
+
|
|
30
|
+
override fun write(
|
|
31
|
+
buffer: ByteArray,
|
|
32
|
+
offset: Int,
|
|
33
|
+
length: Int,
|
|
34
|
+
) = storageOperation { output.write(buffer, offset, length) }
|
|
35
|
+
|
|
36
|
+
override fun flush() = storageOperation { output.flush() }
|
|
37
|
+
|
|
38
|
+
override fun close() = storageOperation { output.close() }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Runs a local file operation, reporting its I/O failure as [LocalStorageException]. */
|
|
42
|
+
internal inline fun <T> storageOperation(block: () -> T): T =
|
|
43
|
+
try {
|
|
44
|
+
block()
|
|
45
|
+
} catch (error: LocalStorageException) {
|
|
46
|
+
throw error
|
|
47
|
+
} catch (error: IOException) {
|
|
48
|
+
throw LocalStorageException(error)
|
|
49
|
+
}
|
|
5
50
|
|
|
6
51
|
/**
|
|
7
52
|
* Interface for file system operations
|
|
@@ -1,41 +1,275 @@
|
|
|
1
1
|
package com.hotupdater
|
|
2
2
|
|
|
3
|
+
import java.io.IOException
|
|
4
|
+
import java.io.InterruptedIOException
|
|
5
|
+
import java.net.MalformedURLException
|
|
6
|
+
import java.net.SocketException
|
|
7
|
+
import java.net.UnknownHostException
|
|
8
|
+
import javax.net.ssl.SSLException
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Where an update failed: [DOWNLOAD] covers transferring and verifying the
|
|
12
|
+
* update's files, [INSTALL] producing the bundle on disk.
|
|
13
|
+
* Values match `UpdateErrorStage` in packages/react-native/src/clientPlugin.ts.
|
|
14
|
+
*/
|
|
15
|
+
enum class UpdateFailureStage(
|
|
16
|
+
val value: String,
|
|
17
|
+
) {
|
|
18
|
+
DOWNLOAD("download"),
|
|
19
|
+
INSTALL("install"),
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Why an update failed.
|
|
24
|
+
* Values match `UpdateErrorReason` in packages/react-native/src/clientPlugin.ts.
|
|
25
|
+
*/
|
|
26
|
+
enum class UpdateFailureReason(
|
|
27
|
+
val value: String,
|
|
28
|
+
) {
|
|
29
|
+
NETWORK("network"),
|
|
30
|
+
HTTP("http"),
|
|
31
|
+
INVALID_RESPONSE("invalid_response"),
|
|
32
|
+
HASH_MISMATCH("hash_mismatch"),
|
|
33
|
+
SIGNATURE("signature"),
|
|
34
|
+
PATCH("patch"),
|
|
35
|
+
EXTRACT("extract"),
|
|
36
|
+
STORAGE("storage"),
|
|
37
|
+
UNKNOWN("unknown"),
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** What was being fetched or applied when an update failed. */
|
|
41
|
+
enum class UpdateFailureResource(
|
|
42
|
+
val value: String,
|
|
43
|
+
) {
|
|
44
|
+
MANIFEST("manifest"),
|
|
45
|
+
FILE("file"),
|
|
46
|
+
PATCH("patch"),
|
|
47
|
+
ARCHIVE("archive"),
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Why no HTTP response arrived, for a [UpdateFailureReason.NETWORK] failure. */
|
|
51
|
+
enum class UpdateFailureTransport(
|
|
52
|
+
val value: String,
|
|
53
|
+
) {
|
|
54
|
+
TIMEOUT("timeout"),
|
|
55
|
+
DNS("dns"),
|
|
56
|
+
TLS("tls"),
|
|
57
|
+
CONNECTION("connection"),
|
|
58
|
+
OFFLINE("offline"),
|
|
59
|
+
CANCELLED("cancelled"),
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The classification an `updateBundle` rejection carries as `userInfo`.
|
|
64
|
+
* [httpStatus] and [originCode] are reported only for
|
|
65
|
+
* [UpdateFailureReason.HTTP], and [transport] only for
|
|
66
|
+
* [UpdateFailureReason.NETWORK].
|
|
67
|
+
*/
|
|
68
|
+
data class UpdateFailure(
|
|
69
|
+
val stage: UpdateFailureStage,
|
|
70
|
+
val reason: UpdateFailureReason,
|
|
71
|
+
val httpStatus: Int? = null,
|
|
72
|
+
val resource: UpdateFailureResource? = null,
|
|
73
|
+
val transport: UpdateFailureTransport? = null,
|
|
74
|
+
/** The storage origin's XML error `<Code>`, such as `AccessDenied`. */
|
|
75
|
+
val originCode: String? = null,
|
|
76
|
+
) {
|
|
77
|
+
/**
|
|
78
|
+
* The rejection's `userInfo`:
|
|
79
|
+
* `{ stage, reason, resource?, httpStatus?, transport?, originCode? }`.
|
|
80
|
+
*/
|
|
81
|
+
fun toUserInfo(): Map<String, Any> =
|
|
82
|
+
buildMap {
|
|
83
|
+
put("stage", stage.value)
|
|
84
|
+
put("reason", reason.value)
|
|
85
|
+
resource?.let { put("resource", it.value) }
|
|
86
|
+
if (reason == UpdateFailureReason.HTTP) {
|
|
87
|
+
httpStatus?.let { put("httpStatus", it) }
|
|
88
|
+
originCode?.let { put("originCode", it) }
|
|
89
|
+
}
|
|
90
|
+
if (reason == UpdateFailureReason.NETWORK) {
|
|
91
|
+
transport?.let { put("transport", it.value) }
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
companion object {
|
|
96
|
+
fun download(reason: UpdateFailureReason) = UpdateFailure(UpdateFailureStage.DOWNLOAD, reason)
|
|
97
|
+
|
|
98
|
+
fun install(reason: UpdateFailureReason) = UpdateFailure(UpdateFailureStage.INSTALL, reason)
|
|
99
|
+
|
|
100
|
+
fun http(
|
|
101
|
+
status: Int,
|
|
102
|
+
originCode: String? = null,
|
|
103
|
+
) = UpdateFailure(UpdateFailureStage.DOWNLOAD, UpdateFailureReason.HTTP, status, originCode = originCode)
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Classifies the error a download returned. OkHttp rejects a URL it
|
|
107
|
+
* cannot request with IllegalArgumentException, an invalid response.
|
|
108
|
+
* [isOffline] is asked only after a failed host lookup.
|
|
109
|
+
*/
|
|
110
|
+
fun ofDownloadError(
|
|
111
|
+
error: Throwable?,
|
|
112
|
+
isOffline: () -> Boolean = { false },
|
|
113
|
+
): UpdateFailure =
|
|
114
|
+
when (error) {
|
|
115
|
+
is HttpStatusException -> {
|
|
116
|
+
http(error.statusCode, error.originCode)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
is LocalStorageException -> {
|
|
120
|
+
install(UpdateFailureReason.STORAGE)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
is MalformedURLException -> {
|
|
124
|
+
download(UpdateFailureReason.INVALID_RESPONSE)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// The body ended early; the connection itself did not fail.
|
|
128
|
+
is IncompleteDownloadException -> {
|
|
129
|
+
download(UpdateFailureReason.NETWORK)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
is IOException -> {
|
|
133
|
+
UpdateFailure(
|
|
134
|
+
UpdateFailureStage.DOWNLOAD,
|
|
135
|
+
UpdateFailureReason.NETWORK,
|
|
136
|
+
transport = transportOf(error, isOffline),
|
|
137
|
+
)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
is IllegalArgumentException -> {
|
|
141
|
+
download(UpdateFailureReason.INVALID_RESPONSE)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
else -> {
|
|
145
|
+
download(UpdateFailureReason.UNKNOWN)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Why a request got no response, or null when the error does not say.
|
|
151
|
+
* An [InterruptedIOException] is a socket or OkHttp call timeout, a
|
|
152
|
+
* [SocketException] a refused, unreachable, or reset connection, and
|
|
153
|
+
* OkHttp reports a canceled call as an IOException "Canceled".
|
|
154
|
+
*/
|
|
155
|
+
private fun transportOf(
|
|
156
|
+
error: IOException,
|
|
157
|
+
isOffline: () -> Boolean,
|
|
158
|
+
): UpdateFailureTransport? =
|
|
159
|
+
when {
|
|
160
|
+
error is SSLException -> UpdateFailureTransport.TLS
|
|
161
|
+
error is InterruptedIOException -> UpdateFailureTransport.TIMEOUT
|
|
162
|
+
error is UnknownHostException -> if (isOffline()) UpdateFailureTransport.OFFLINE else UpdateFailureTransport.DNS
|
|
163
|
+
error is SocketException -> UpdateFailureTransport.CONNECTION
|
|
164
|
+
error.message == "Canceled" -> UpdateFailureTransport.CANCELLED
|
|
165
|
+
else -> null
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Classifies a failed hash or signature check of a downloaded file. */
|
|
169
|
+
fun ofVerificationError(error: Throwable?): UpdateFailure =
|
|
170
|
+
when (error) {
|
|
171
|
+
is SignatureVerificationException.FileHashMismatch -> download(UpdateFailureReason.HASH_MISMATCH)
|
|
172
|
+
is SignatureVerificationException.FileReadFailed -> install(UpdateFailureReason.STORAGE)
|
|
173
|
+
else -> download(UpdateFailureReason.SIGNATURE)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Classifies an error the pipeline did not anticipate: a malformed URL
|
|
178
|
+
* is an invalid response, any other I/O error a local storage failure,
|
|
179
|
+
* and anything else unknown in [stage].
|
|
180
|
+
*/
|
|
181
|
+
fun ofUnexpectedError(
|
|
182
|
+
error: Throwable,
|
|
183
|
+
stage: UpdateFailureStage,
|
|
184
|
+
): UpdateFailure =
|
|
185
|
+
when (error) {
|
|
186
|
+
is MalformedURLException -> download(UpdateFailureReason.INVALID_RESPONSE)
|
|
187
|
+
is IOException -> install(UpdateFailureReason.STORAGE)
|
|
188
|
+
else -> UpdateFailure(stage, UpdateFailureReason.UNKNOWN)
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* The Release catalog selection changed while its bundle was being installed.
|
|
195
|
+
* The update was superseded, so this rejection is not an update failure.
|
|
196
|
+
*/
|
|
197
|
+
class StaleReleaseSelectionException : IllegalStateException("Release catalog selection is stale")
|
|
198
|
+
|
|
3
199
|
/**
|
|
4
200
|
* Exception class for Hot Updater errors
|
|
5
201
|
* Matches error codes defined in packages/react-native/src/errors.ts
|
|
202
|
+
*
|
|
203
|
+
* [failure] classifies an update failure for JS. It is null for a rejection
|
|
204
|
+
* that is not an update failure, such as a bundle in the crashed history.
|
|
6
205
|
*/
|
|
7
206
|
class HotUpdaterException(
|
|
8
207
|
val code: String,
|
|
9
208
|
message: String,
|
|
10
209
|
cause: Throwable? = null,
|
|
210
|
+
val failure: UpdateFailure? = null,
|
|
11
211
|
) : Exception(message, cause) {
|
|
212
|
+
/**
|
|
213
|
+
* This failure with [resource] as what was being fetched or applied,
|
|
214
|
+
* unless it already names one or is not an update failure.
|
|
215
|
+
*/
|
|
216
|
+
fun withResource(resource: UpdateFailureResource?): HotUpdaterException {
|
|
217
|
+
val failure = failure
|
|
218
|
+
if (resource == null || failure == null || failure.resource != null) {
|
|
219
|
+
return this
|
|
220
|
+
}
|
|
221
|
+
return HotUpdaterException(code, message.orEmpty(), cause, failure.copy(resource = resource)).also {
|
|
222
|
+
it.stackTrace = stackTrace
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
12
226
|
companion object {
|
|
227
|
+
private val invalidResponse = UpdateFailure.download(UpdateFailureReason.INVALID_RESPONSE)
|
|
228
|
+
private val signatureFailure = UpdateFailure.download(UpdateFailureReason.SIGNATURE)
|
|
229
|
+
private val storageFailure = UpdateFailure.install(UpdateFailureReason.STORAGE)
|
|
230
|
+
|
|
13
231
|
// Parameter validation errors
|
|
14
232
|
fun missingBundleId() =
|
|
15
233
|
HotUpdaterException(
|
|
16
234
|
"MISSING_BUNDLE_ID",
|
|
17
235
|
"Missing or empty 'bundleId'",
|
|
236
|
+
failure = invalidResponse,
|
|
18
237
|
)
|
|
19
238
|
|
|
20
|
-
fun
|
|
239
|
+
fun invalidManifestParams() =
|
|
21
240
|
HotUpdaterException(
|
|
22
|
-
"
|
|
23
|
-
"
|
|
241
|
+
"INVALID_MANIFEST",
|
|
242
|
+
"Manifest URL, hash, and assets are required",
|
|
243
|
+
failure = invalidResponse.copy(resource = UpdateFailureResource.MANIFEST),
|
|
24
244
|
)
|
|
25
245
|
|
|
246
|
+
fun invalidFileUrl(
|
|
247
|
+
parameter: String,
|
|
248
|
+
url: String,
|
|
249
|
+
resource: UpdateFailureResource,
|
|
250
|
+
) = HotUpdaterException(
|
|
251
|
+
"INVALID_FILE_URL",
|
|
252
|
+
"Invalid '$parameter' provided: $url",
|
|
253
|
+
failure = invalidResponse.copy(resource = resource),
|
|
254
|
+
)
|
|
255
|
+
|
|
26
256
|
// Bundle storage errors
|
|
27
257
|
fun directoryCreationFailed() =
|
|
28
258
|
HotUpdaterException(
|
|
29
259
|
"DIRECTORY_CREATION_FAILED",
|
|
30
260
|
"Failed to create bundle directory",
|
|
261
|
+
failure = storageFailure,
|
|
31
262
|
)
|
|
32
263
|
|
|
33
|
-
fun downloadFailed(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
264
|
+
fun downloadFailed(
|
|
265
|
+
cause: Throwable? = null,
|
|
266
|
+
failure: UpdateFailure = UpdateFailure.ofDownloadError(cause),
|
|
267
|
+
) = HotUpdaterException(
|
|
268
|
+
"DOWNLOAD_FAILED",
|
|
269
|
+
"Failed to download bundle",
|
|
270
|
+
cause,
|
|
271
|
+
failure,
|
|
272
|
+
)
|
|
39
273
|
|
|
40
274
|
fun incompleteDownload(
|
|
41
275
|
expectedSize: Long,
|
|
@@ -43,19 +277,14 @@ class HotUpdaterException(
|
|
|
43
277
|
) = HotUpdaterException(
|
|
44
278
|
"INCOMPLETE_DOWNLOAD",
|
|
45
279
|
"Download incomplete: received $actualSize bytes, expected $expectedSize bytes",
|
|
280
|
+
failure = UpdateFailure.download(UpdateFailureReason.NETWORK),
|
|
46
281
|
)
|
|
47
282
|
|
|
48
|
-
fun extractionFormatError(cause: Throwable? = null) =
|
|
49
|
-
HotUpdaterException(
|
|
50
|
-
"EXTRACTION_FORMAT_ERROR",
|
|
51
|
-
"The downloaded bundle file is not a valid compressed archive",
|
|
52
|
-
cause,
|
|
53
|
-
)
|
|
54
|
-
|
|
55
283
|
fun invalidBundle() =
|
|
56
284
|
HotUpdaterException(
|
|
57
285
|
"INVALID_BUNDLE",
|
|
58
286
|
"Bundle missing required platform files (index.ios.bundle or index.android.bundle)",
|
|
287
|
+
failure = invalidResponse,
|
|
59
288
|
)
|
|
60
289
|
|
|
61
290
|
fun insufficientDiskSpace(
|
|
@@ -64,19 +293,24 @@ class HotUpdaterException(
|
|
|
64
293
|
) = HotUpdaterException(
|
|
65
294
|
"INSUFFICIENT_DISK_SPACE",
|
|
66
295
|
"Insufficient disk space: need $required bytes, available $available bytes",
|
|
296
|
+
failure = storageFailure,
|
|
67
297
|
)
|
|
68
298
|
|
|
69
|
-
fun signatureVerificationFailed(
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
299
|
+
fun signatureVerificationFailed(
|
|
300
|
+
cause: Throwable? = null,
|
|
301
|
+
failure: UpdateFailure = UpdateFailure.ofVerificationError(cause),
|
|
302
|
+
) = HotUpdaterException(
|
|
303
|
+
"SIGNATURE_VERIFICATION_FAILED",
|
|
304
|
+
"Bundle signature verification failed",
|
|
305
|
+
cause,
|
|
306
|
+
failure,
|
|
307
|
+
)
|
|
75
308
|
|
|
76
309
|
fun moveOperationFailed() =
|
|
77
310
|
HotUpdaterException(
|
|
78
311
|
"MOVE_OPERATION_FAILED",
|
|
79
312
|
"Failed to move bundle files",
|
|
313
|
+
failure = storageFailure,
|
|
80
314
|
)
|
|
81
315
|
|
|
82
316
|
fun bundleInCrashedHistory(bundleId: String) =
|
|
@@ -90,30 +324,35 @@ class HotUpdaterException(
|
|
|
90
324
|
HotUpdaterException(
|
|
91
325
|
"PUBLIC_KEY_NOT_CONFIGURED",
|
|
92
326
|
"Public key not configured for signature verification",
|
|
327
|
+
failure = signatureFailure,
|
|
93
328
|
)
|
|
94
329
|
|
|
95
330
|
fun invalidPublicKeyFormat() =
|
|
96
331
|
HotUpdaterException(
|
|
97
332
|
"INVALID_PUBLIC_KEY_FORMAT",
|
|
98
333
|
"Invalid public key format",
|
|
334
|
+
failure = signatureFailure,
|
|
99
335
|
)
|
|
100
336
|
|
|
101
337
|
fun fileHashMismatch() =
|
|
102
338
|
HotUpdaterException(
|
|
103
339
|
"FILE_HASH_MISMATCH",
|
|
104
340
|
"File hash verification failed",
|
|
341
|
+
failure = UpdateFailure.download(UpdateFailureReason.HASH_MISMATCH),
|
|
105
342
|
)
|
|
106
343
|
|
|
107
344
|
fun fileReadFailed() =
|
|
108
345
|
HotUpdaterException(
|
|
109
346
|
"FILE_READ_FAILED",
|
|
110
347
|
"Failed to read file for verification",
|
|
348
|
+
failure = storageFailure,
|
|
111
349
|
)
|
|
112
350
|
|
|
113
351
|
fun unsignedNotAllowed() =
|
|
114
352
|
HotUpdaterException(
|
|
115
353
|
"UNSIGNED_NOT_ALLOWED",
|
|
116
354
|
"Unsigned bundles are not allowed",
|
|
355
|
+
failure = signatureFailure,
|
|
117
356
|
)
|
|
118
357
|
|
|
119
358
|
fun securityFrameworkError(cause: Throwable? = null) =
|
|
@@ -121,6 +360,7 @@ class HotUpdaterException(
|
|
|
121
360
|
"SECURITY_FRAMEWORK_ERROR",
|
|
122
361
|
"Security framework error occurred",
|
|
123
362
|
cause,
|
|
363
|
+
failure = signatureFailure,
|
|
124
364
|
)
|
|
125
365
|
|
|
126
366
|
// Internal errors
|
|
@@ -130,5 +370,30 @@ class HotUpdaterException(
|
|
|
130
370
|
"An unknown error occurred",
|
|
131
371
|
cause,
|
|
132
372
|
)
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* A local storage failure while producing the bundle. It keeps the
|
|
376
|
+
* `UNKNOWN_ERROR` code these failures have always been rejected with.
|
|
377
|
+
*/
|
|
378
|
+
fun storageFailed(message: String) =
|
|
379
|
+
HotUpdaterException(
|
|
380
|
+
"UNKNOWN_ERROR",
|
|
381
|
+
message,
|
|
382
|
+
failure = storageFailure,
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Wraps an error the update pipeline did not anticipate in the
|
|
387
|
+
* `UNKNOWN_ERROR` rejection it has always produced, adding [failure].
|
|
388
|
+
*/
|
|
389
|
+
fun unexpected(
|
|
390
|
+
cause: Throwable,
|
|
391
|
+
failure: UpdateFailure,
|
|
392
|
+
) = HotUpdaterException(
|
|
393
|
+
"UNKNOWN_ERROR",
|
|
394
|
+
cause.message ?: "An unknown error occurred",
|
|
395
|
+
cause,
|
|
396
|
+
failure,
|
|
397
|
+
)
|
|
133
398
|
}
|
|
134
399
|
}
|