@capgo/capacitor-updater 7.51.20 → 7.51.23
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/README.md +1 -1
- package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdaterPlugin.java +20 -4
- package/android/src/main/java/ee/forgr/capacitor_updater/CapgoUpdater.java +135 -35
- package/android/src/main/java/ee/forgr/capacitor_updater/CryptoCipher.java +51 -18
- package/android/src/main/java/ee/forgr/capacitor_updater/DownloadService.java +106 -29
- package/android/src/main/java/ee/forgr/capacitor_updater/Logger.java +12 -1
- package/android/src/main/java/ee/forgr/capacitor_updater/ShakeMenu.java +4 -4
- package/dist/esm/history.js +7 -7
- package/dist/esm/history.js.map +1 -1
- package/dist/plugin.cjs.js +7 -7
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +7 -7
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/CapacitorUpdaterPlugin/CapacitorUpdaterPlugin.swift +218 -94
- package/ios/Sources/CapacitorUpdaterPlugin/CapgoUpdater.swift +177 -32
- package/ios/Sources/CapacitorUpdaterPlugin/CryptoCipher.swift +9 -1
- package/ios/Sources/CapacitorUpdaterPlugin/ShakeMenu.swift +4 -1
- package/package.json +6 -8
|
@@ -96,7 +96,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
96
96
|
deinit {
|
|
97
97
|
implementation.shutdown()
|
|
98
98
|
}
|
|
99
|
-
private let pluginVersion: String = "7.51.
|
|
99
|
+
private let pluginVersion: String = "7.51.23"
|
|
100
100
|
private let launchStartedAtMs = Int64(Date().timeIntervalSince1970 * 1000)
|
|
101
101
|
static let updateUrlDefault = "https://plugin.capgo.app/updates"
|
|
102
102
|
static let statsUrlDefault = "https://plugin.capgo.app/stats"
|
|
@@ -582,8 +582,10 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
582
582
|
var dest: URL
|
|
583
583
|
if BundleInfo.ID_BUILTIN == id {
|
|
584
584
|
dest = Bundle.main.resourceURL!.appendingPathComponent("public")
|
|
585
|
+
} else if let bundleDir = try? self.implementation.getBundleDirectory(id: id) {
|
|
586
|
+
dest = bundleDir
|
|
585
587
|
} else {
|
|
586
|
-
dest =
|
|
588
|
+
dest = Bundle.main.resourceURL!.appendingPathComponent("public")
|
|
587
589
|
}
|
|
588
590
|
|
|
589
591
|
if !FileManager.default.fileExists(atPath: dest.path) {
|
|
@@ -1611,7 +1613,19 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1611
1613
|
throw makePreviewError("Invalid download URL")
|
|
1612
1614
|
}
|
|
1613
1615
|
|
|
1616
|
+
if !self.implementation.publicKey.isEmpty && !CryptoCipher.isValidSessionKey(sessionKey) {
|
|
1617
|
+
self.logger.error("Public key present but no valid session key provided")
|
|
1618
|
+
self.implementation.sendStats(action: "session_key_required", versionName: version)
|
|
1619
|
+
throw makePreviewError("Session key required when public key is present")
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1614
1622
|
var checksum = rawChecksum
|
|
1623
|
+
if manifestEntries == nil && checksum.isEmpty {
|
|
1624
|
+
self.logger.error("No checksum provided")
|
|
1625
|
+
self.implementation.sendStats(action: "checksum_required", versionName: version)
|
|
1626
|
+
throw makePreviewError("Checksum required")
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1615
1629
|
let next: BundleInfo
|
|
1616
1630
|
if let manifestEntries = manifestEntries {
|
|
1617
1631
|
next = try self.implementation.downloadManifest(manifest: manifestEntries, version: version, sessionKey: sessionKey)
|
|
@@ -1619,29 +1633,20 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1619
1633
|
next = try self.implementation.download(url: url, version: version, sessionKey: sessionKey)
|
|
1620
1634
|
}
|
|
1621
1635
|
|
|
1622
|
-
if
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
self.
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
CryptoCipher.logChecksumInfo(label: "Expected checksum", hexChecksum: checksum)
|
|
1636
|
-
if (checksum != "" || self.implementation.publicKey != "") && next.getChecksum() != checksum {
|
|
1637
|
-
self.logger.error("Error checksum \(next.getChecksum()) \(checksum)")
|
|
1638
|
-
self.implementation.sendStats(action: "checksum_fail", versionName: next.getVersionName())
|
|
1639
|
-
let id = next.getId()
|
|
1640
|
-
let resDel = self.implementation.delete(id: id)
|
|
1641
|
-
if !resDel {
|
|
1642
|
-
self.logger.error("Delete failed, id \(id) doesn't exist")
|
|
1636
|
+
if manifestEntries == nil {
|
|
1637
|
+
checksum = try CryptoCipher.decryptChecksum(checksum: checksum, publicKey: self.implementation.publicKey)
|
|
1638
|
+
CryptoCipher.logChecksumInfo(label: "Bundle checksum", hexChecksum: next.getChecksum())
|
|
1639
|
+
CryptoCipher.logChecksumInfo(label: "Expected checksum", hexChecksum: checksum)
|
|
1640
|
+
if next.getChecksum() != checksum {
|
|
1641
|
+
self.logger.error("Error checksum \(next.getChecksum()) \(checksum)")
|
|
1642
|
+
self.implementation.sendStats(action: "checksum_fail", versionName: next.getVersionName())
|
|
1643
|
+
let id = next.getId()
|
|
1644
|
+
let resDel = self.implementation.delete(id: id)
|
|
1645
|
+
if !resDel {
|
|
1646
|
+
self.logger.error("Delete failed, id \(id) doesn't exist")
|
|
1647
|
+
}
|
|
1648
|
+
throw ObjectSavableError.checksum
|
|
1643
1649
|
}
|
|
1644
|
-
throw ObjectSavableError.checksum
|
|
1645
1650
|
}
|
|
1646
1651
|
|
|
1647
1652
|
self.logger.info("Good checksum \(next.getChecksum()) \(checksum)")
|
|
@@ -1693,8 +1698,10 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1693
1698
|
let id = self.implementation.getCurrentBundleId()
|
|
1694
1699
|
if BundleInfo.ID_BUILTIN == id {
|
|
1695
1700
|
return Bundle.main.resourceURL!.appendingPathComponent("public")
|
|
1701
|
+
} else if let bundleDir = try? self.implementation.getBundleDirectory(id: id) {
|
|
1702
|
+
return bundleDir
|
|
1696
1703
|
} else {
|
|
1697
|
-
return
|
|
1704
|
+
return Bundle.main.resourceURL!.appendingPathComponent("public")
|
|
1698
1705
|
}
|
|
1699
1706
|
}
|
|
1700
1707
|
|
|
@@ -3498,13 +3505,10 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
3498
3505
|
}
|
|
3499
3506
|
|
|
3500
3507
|
private func performHideSplashscreen() {
|
|
3501
|
-
self.cancelSplashscreenTimeout()
|
|
3502
3508
|
self.removeSplashscreenLoader()
|
|
3503
3509
|
self.splashscreenInvocationToken += 1
|
|
3504
|
-
self.
|
|
3505
|
-
|
|
3506
|
-
callbackId: "autoHideSplashscreen",
|
|
3507
|
-
options: self.splashscreenOptions(methodName: "hide"),
|
|
3510
|
+
self.invokeSplashscreenAction(
|
|
3511
|
+
.hide,
|
|
3508
3512
|
retriesRemaining: self.splashscreenMaxRetries,
|
|
3509
3513
|
requestToken: self.splashscreenInvocationToken
|
|
3510
3514
|
)
|
|
@@ -3524,10 +3528,8 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
3524
3528
|
self.cancelSplashscreenTimeout()
|
|
3525
3529
|
self.autoSplashscreenTimedOut = false
|
|
3526
3530
|
self.splashscreenInvocationToken += 1
|
|
3527
|
-
self.
|
|
3528
|
-
|
|
3529
|
-
callbackId: "autoShowSplashscreen",
|
|
3530
|
-
options: self.splashscreenOptions(methodName: "show"),
|
|
3531
|
+
self.invokeSplashscreenAction(
|
|
3532
|
+
.show,
|
|
3531
3533
|
retriesRemaining: self.splashscreenMaxRetries,
|
|
3532
3534
|
requestToken: self.splashscreenInvocationToken
|
|
3533
3535
|
)
|
|
@@ -3537,7 +3539,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
3537
3539
|
}
|
|
3538
3540
|
|
|
3539
3541
|
private func splashscreenOptions(methodName: String) -> [String: Any] {
|
|
3540
|
-
methodName == "show" ? ["autoHide": false] : [:]
|
|
3542
|
+
methodName == "show" ? ["autoHide": false, "fadeInDuration": 0] : [:]
|
|
3541
3543
|
}
|
|
3542
3544
|
|
|
3543
3545
|
private func splashscreenCompletedMessage(methodName: String) -> String {
|
|
@@ -3556,20 +3558,59 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
3556
3558
|
self.splashscreenInvocationToken += 1
|
|
3557
3559
|
}
|
|
3558
3560
|
|
|
3559
|
-
private
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3561
|
+
private enum SplashscreenAction {
|
|
3562
|
+
case show
|
|
3563
|
+
case hide
|
|
3564
|
+
|
|
3565
|
+
var methodName: String {
|
|
3566
|
+
switch self {
|
|
3567
|
+
case .show:
|
|
3568
|
+
return "show"
|
|
3569
|
+
case .hide:
|
|
3570
|
+
return "hide"
|
|
3571
|
+
}
|
|
3572
|
+
}
|
|
3573
|
+
|
|
3574
|
+
var unavailableMessageVerb: String {
|
|
3575
|
+
switch self {
|
|
3576
|
+
case .show:
|
|
3577
|
+
return "showing"
|
|
3578
|
+
case .hide:
|
|
3579
|
+
return "hiding"
|
|
3580
|
+
}
|
|
3581
|
+
}
|
|
3567
3582
|
}
|
|
3568
3583
|
|
|
3569
|
-
private func
|
|
3570
|
-
methodName:
|
|
3571
|
-
|
|
3572
|
-
|
|
3584
|
+
private func splashscreenOptionsJSON(methodName: String) -> String {
|
|
3585
|
+
let options = self.splashscreenOptions(methodName: methodName)
|
|
3586
|
+
guard !options.isEmpty,
|
|
3587
|
+
let data = try? JSONSerialization.data(withJSONObject: options),
|
|
3588
|
+
let json = String(data: data, encoding: .utf8) else {
|
|
3589
|
+
return "{}"
|
|
3590
|
+
}
|
|
3591
|
+
return json
|
|
3592
|
+
}
|
|
3593
|
+
|
|
3594
|
+
private func splashscreenPluginExposesMethod(_ methodName: String, on plugin: CAPPlugin) -> Bool {
|
|
3595
|
+
guard let bridgedPlugin = plugin as? CAPBridgedPlugin else {
|
|
3596
|
+
return false
|
|
3597
|
+
}
|
|
3598
|
+
return bridgedPlugin.pluginMethods.contains { $0.name == methodName }
|
|
3599
|
+
}
|
|
3600
|
+
|
|
3601
|
+
private func splashscreenBridgeScript(for action: SplashscreenAction) -> String {
|
|
3602
|
+
let optionsJSON = self.splashscreenOptionsJSON(methodName: action.methodName)
|
|
3603
|
+
return """
|
|
3604
|
+
var cap = window.Capacitor;
|
|
3605
|
+
if (!cap || typeof cap.nativePromise !== 'function') {
|
|
3606
|
+
throw new Error('Capacitor bridge not ready');
|
|
3607
|
+
}
|
|
3608
|
+
return await cap.nativePromise('\(self.splashscreenPluginName)', '\(action.methodName)', \(optionsJSON));
|
|
3609
|
+
"""
|
|
3610
|
+
}
|
|
3611
|
+
|
|
3612
|
+
private func invokeSplashscreenAction(
|
|
3613
|
+
_ action: SplashscreenAction,
|
|
3573
3614
|
retriesRemaining: Int,
|
|
3574
3615
|
requestToken: Int
|
|
3575
3616
|
) {
|
|
@@ -3578,22 +3619,18 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
3578
3619
|
}
|
|
3579
3620
|
|
|
3580
3621
|
guard let bridge = self.bridge else {
|
|
3581
|
-
self.
|
|
3582
|
-
|
|
3583
|
-
callbackId: callbackId,
|
|
3584
|
-
options: options,
|
|
3622
|
+
self.retrySplashscreenAction(
|
|
3623
|
+
action,
|
|
3585
3624
|
retriesRemaining: retriesRemaining,
|
|
3586
3625
|
requestToken: requestToken,
|
|
3587
|
-
message: "Bridge not available for \(
|
|
3626
|
+
message: "Bridge not available for \(action.unavailableMessageVerb) splashscreen with autoSplashscreen"
|
|
3588
3627
|
)
|
|
3589
3628
|
return
|
|
3590
3629
|
}
|
|
3591
3630
|
|
|
3592
3631
|
guard let splashScreenPlugin = bridge.plugin(withName: self.splashscreenPluginName) else {
|
|
3593
|
-
self.
|
|
3594
|
-
|
|
3595
|
-
callbackId: callbackId,
|
|
3596
|
-
options: options,
|
|
3632
|
+
self.retrySplashscreenAction(
|
|
3633
|
+
action,
|
|
3597
3634
|
retriesRemaining: retriesRemaining,
|
|
3598
3635
|
requestToken: requestToken,
|
|
3599
3636
|
message: "autoSplashscreen: SplashScreen plugin not found. Install @capacitor/splash-screen plugin."
|
|
@@ -3601,37 +3638,86 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
3601
3638
|
return
|
|
3602
3639
|
}
|
|
3603
3640
|
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3641
|
+
guard self.splashscreenPluginExposesMethod(action.methodName, on: splashScreenPlugin) else {
|
|
3642
|
+
self.retrySplashscreenAction(
|
|
3643
|
+
action,
|
|
3644
|
+
retriesRemaining: retriesRemaining,
|
|
3645
|
+
requestToken: requestToken,
|
|
3646
|
+
message: "autoSplashscreen: SplashScreen plugin does not expose \(action.methodName)(). Make sure @capacitor/splash-screen plugin is properly installed."
|
|
3647
|
+
)
|
|
3648
|
+
return
|
|
3649
|
+
}
|
|
3650
|
+
|
|
3651
|
+
guard let webView = bridge.webView else {
|
|
3652
|
+
self.retrySplashscreenAction(
|
|
3653
|
+
action,
|
|
3610
3654
|
retriesRemaining: retriesRemaining,
|
|
3611
3655
|
requestToken: requestToken,
|
|
3612
|
-
message: "
|
|
3656
|
+
message: "WebView not available for \(action.unavailableMessageVerb) splashscreen with autoSplashscreen"
|
|
3613
3657
|
)
|
|
3614
3658
|
return
|
|
3615
3659
|
}
|
|
3616
3660
|
|
|
3617
|
-
let
|
|
3618
|
-
|
|
3619
|
-
|
|
3661
|
+
let script = self.splashscreenBridgeScript(for: action)
|
|
3662
|
+
let runInvocation = { [weak self] in
|
|
3663
|
+
guard let self = self, requestToken == self.splashscreenInvocationToken else {
|
|
3664
|
+
return
|
|
3665
|
+
}
|
|
3666
|
+
webView.callAsyncJavaScript(
|
|
3667
|
+
script,
|
|
3668
|
+
arguments: [:],
|
|
3669
|
+
in: nil,
|
|
3670
|
+
in: .page
|
|
3671
|
+
) { [weak self] (result: Result<Any, Error>) in
|
|
3672
|
+
guard let self = self, requestToken == self.splashscreenInvocationToken else {
|
|
3673
|
+
return
|
|
3674
|
+
}
|
|
3675
|
+
if case .failure(let error) = result {
|
|
3676
|
+
self.retrySplashscreenAction(
|
|
3677
|
+
action,
|
|
3678
|
+
retriesRemaining: retriesRemaining,
|
|
3679
|
+
requestToken: requestToken,
|
|
3680
|
+
message: "Failed to invoke SplashScreen \(action.methodName) via Capacitor bridge: \(error.localizedDescription)"
|
|
3681
|
+
)
|
|
3682
|
+
return
|
|
3683
|
+
}
|
|
3684
|
+
if action == .hide {
|
|
3685
|
+
self.cancelSplashscreenTimeout()
|
|
3686
|
+
}
|
|
3687
|
+
self.logger.info("Called SplashScreen \(action.methodName) method")
|
|
3688
|
+
self.logger.info(self.splashscreenCompletedMessage(methodName: action.methodName))
|
|
3689
|
+
}
|
|
3690
|
+
}
|
|
3691
|
+
|
|
3692
|
+
if Thread.isMainThread {
|
|
3693
|
+
runInvocation()
|
|
3694
|
+
} else {
|
|
3695
|
+
DispatchQueue.main.async(execute: runInvocation)
|
|
3696
|
+
}
|
|
3620
3697
|
}
|
|
3621
3698
|
|
|
3622
|
-
private func
|
|
3623
|
-
|
|
3624
|
-
callbackId: String,
|
|
3625
|
-
options: [String: Any],
|
|
3699
|
+
private func retrySplashscreenAction(
|
|
3700
|
+
_ action: SplashscreenAction,
|
|
3626
3701
|
retriesRemaining: Int,
|
|
3627
3702
|
requestToken: Int,
|
|
3628
3703
|
message: String
|
|
3629
3704
|
) {
|
|
3630
3705
|
guard retriesRemaining > 0 else {
|
|
3631
|
-
if
|
|
3706
|
+
if action == .show {
|
|
3632
3707
|
self.logger.warn(message)
|
|
3633
|
-
|
|
3634
|
-
|
|
3708
|
+
return
|
|
3709
|
+
}
|
|
3710
|
+
|
|
3711
|
+
self.logger.error("\(message). Scheduling another hide retry.")
|
|
3712
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(self.splashscreenRetryDelayMilliseconds)) { [weak self] in
|
|
3713
|
+
guard let self = self, requestToken == self.splashscreenInvocationToken else {
|
|
3714
|
+
return
|
|
3715
|
+
}
|
|
3716
|
+
self.invokeSplashscreenAction(
|
|
3717
|
+
action,
|
|
3718
|
+
retriesRemaining: self.splashscreenMaxRetries,
|
|
3719
|
+
requestToken: requestToken
|
|
3720
|
+
)
|
|
3635
3721
|
}
|
|
3636
3722
|
return
|
|
3637
3723
|
}
|
|
@@ -3641,10 +3727,8 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
3641
3727
|
guard let self = self, requestToken == self.splashscreenInvocationToken else {
|
|
3642
3728
|
return
|
|
3643
3729
|
}
|
|
3644
|
-
self.
|
|
3645
|
-
|
|
3646
|
-
callbackId: callbackId,
|
|
3647
|
-
options: options,
|
|
3730
|
+
self.invokeSplashscreenAction(
|
|
3731
|
+
action,
|
|
3648
3732
|
retriesRemaining: retriesRemaining - 1,
|
|
3649
3733
|
requestToken: requestToken
|
|
3650
3734
|
)
|
|
@@ -4097,6 +4181,22 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
4097
4181
|
self.updateUrl = updateUrl
|
|
4098
4182
|
}
|
|
4099
4183
|
|
|
4184
|
+
func downloadBundleForTesting(
|
|
4185
|
+
urlString: String,
|
|
4186
|
+
version: String,
|
|
4187
|
+
sessionKey: String,
|
|
4188
|
+
checksum: String,
|
|
4189
|
+
manifestEntries: [ManifestEntry]?
|
|
4190
|
+
) throws -> BundleInfo {
|
|
4191
|
+
try downloadBundle(
|
|
4192
|
+
urlString: urlString,
|
|
4193
|
+
version: version,
|
|
4194
|
+
sessionKey: sessionKey,
|
|
4195
|
+
checksum: checksum,
|
|
4196
|
+
manifestEntries: manifestEntries
|
|
4197
|
+
)
|
|
4198
|
+
}
|
|
4199
|
+
|
|
4100
4200
|
func setAutoUpdateModeForTesting(_ autoUpdateMode: String) {
|
|
4101
4201
|
self.autoUpdateMode = Self.normalizedAutoUpdateMode(autoUpdateMode)
|
|
4102
4202
|
self.autoUpdate = Self.isAutoUpdateModeEnabled(self.autoUpdateMode)
|
|
@@ -4432,6 +4532,17 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
4432
4532
|
if latestVersionName != "" && current.getVersionName() != latestVersionName {
|
|
4433
4533
|
do {
|
|
4434
4534
|
self.logger.info("New bundle: \(latestVersionName) found. Current is: \(current.getVersionName()). \(messageUpdate)")
|
|
4535
|
+
if !self.implementation.publicKey.isEmpty && !CryptoCipher.isValidSessionKey(sessionKey) {
|
|
4536
|
+
self.logger.error("Public key present but no valid session key provided")
|
|
4537
|
+
self.implementation.sendStats(action: "session_key_required", versionName: latestVersionName)
|
|
4538
|
+
self.endBackGroundTaskWithNotif(
|
|
4539
|
+
msg: "Session key required when public key is present",
|
|
4540
|
+
latestVersionName: latestVersionName,
|
|
4541
|
+
current: current,
|
|
4542
|
+
plannedDirectUpdate: plannedDirectUpdate
|
|
4543
|
+
)
|
|
4544
|
+
return
|
|
4545
|
+
}
|
|
4435
4546
|
var nextImpl = self.implementation.getBundleInfoByVersionName(version: latestVersionName)
|
|
4436
4547
|
let needsDownload = nextImpl.map(Self.shouldRetryDownloadForExistingBundle) ?? true
|
|
4437
4548
|
if needsDownload {
|
|
@@ -4449,6 +4560,17 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
4449
4560
|
if res.manifest != nil {
|
|
4450
4561
|
nextImpl = try self.implementation.downloadManifest(manifest: res.manifest!, version: latestVersionName, sessionKey: sessionKey, link: res.link, comment: res.comment)
|
|
4451
4562
|
} else {
|
|
4563
|
+
if res.checksum.isEmpty {
|
|
4564
|
+
self.logger.error("No checksum provided")
|
|
4565
|
+
self.implementation.sendStats(action: "checksum_required", versionName: latestVersionName)
|
|
4566
|
+
self.endBackGroundTaskWithNotif(
|
|
4567
|
+
msg: "Checksum required",
|
|
4568
|
+
latestVersionName: latestVersionName,
|
|
4569
|
+
current: current,
|
|
4570
|
+
plannedDirectUpdate: plannedDirectUpdate
|
|
4571
|
+
)
|
|
4572
|
+
return
|
|
4573
|
+
}
|
|
4452
4574
|
nextImpl = try self.implementation.download(url: downloadUrl, version: latestVersionName, sessionKey: sessionKey, link: res.link, comment: res.comment)
|
|
4453
4575
|
}
|
|
4454
4576
|
}
|
|
@@ -4477,24 +4599,26 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
4477
4599
|
self.endBackGroundTask()
|
|
4478
4600
|
return
|
|
4479
4601
|
}
|
|
4480
|
-
res.
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4602
|
+
if res.manifest == nil {
|
|
4603
|
+
res.checksum = try CryptoCipher.decryptChecksum(checksum: res.checksum, publicKey: self.implementation.publicKey)
|
|
4604
|
+
CryptoCipher.logChecksumInfo(label: "Bundle checksum", hexChecksum: next.getChecksum())
|
|
4605
|
+
CryptoCipher.logChecksumInfo(label: "Expected checksum", hexChecksum: res.checksum)
|
|
4606
|
+
if next.getChecksum() != res.checksum {
|
|
4607
|
+
self.logger.error("Error checksum \(next.getChecksum()) \(res.checksum)")
|
|
4608
|
+
self.implementation.sendStats(action: "checksum_fail", versionName: next.getVersionName())
|
|
4609
|
+
let id = next.getId()
|
|
4610
|
+
let resDel = self.implementation.delete(id: id)
|
|
4611
|
+
if !resDel {
|
|
4612
|
+
self.logger.error("Delete failed, id \(id) doesn't exist")
|
|
4613
|
+
}
|
|
4614
|
+
self.endBackGroundTaskWithNotif(
|
|
4615
|
+
msg: "Error checksum",
|
|
4616
|
+
latestVersionName: latestVersionName,
|
|
4617
|
+
current: current,
|
|
4618
|
+
plannedDirectUpdate: plannedDirectUpdate
|
|
4619
|
+
)
|
|
4620
|
+
return
|
|
4490
4621
|
}
|
|
4491
|
-
self.endBackGroundTaskWithNotif(
|
|
4492
|
-
msg: "Error checksum",
|
|
4493
|
-
latestVersionName: latestVersionName,
|
|
4494
|
-
current: current,
|
|
4495
|
-
plannedDirectUpdate: plannedDirectUpdate
|
|
4496
|
-
)
|
|
4497
|
-
return
|
|
4498
4622
|
}
|
|
4499
4623
|
if self.shouldBlockAutoUpdateForPreviewSession() {
|
|
4500
4624
|
self.clearDownloadInProgressState()
|