@capgo/capacitor-updater 7.2.21 → 7.4.0
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 +22 -16
- package/android/src/main/java/ee/forgr/capacitor_updater/BundleInfo.java +48 -26
- package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdaterPlugin.java +165 -135
- package/android/src/main/java/ee/forgr/capacitor_updater/CapgoUpdater.java +85 -51
- package/android/src/main/java/ee/forgr/capacitor_updater/CryptoCipherV2.java +13 -8
- package/android/src/main/java/ee/forgr/capacitor_updater/DelayUpdateUtils.java +43 -40
- package/android/src/main/java/ee/forgr/capacitor_updater/DownloadService.java +24 -20
- package/android/src/main/java/ee/forgr/capacitor_updater/DownloadWorkerManager.java +8 -4
- package/android/src/main/java/ee/forgr/capacitor_updater/Logger.java +338 -0
- package/dist/docs.json +64 -30
- package/dist/esm/definitions.d.ts +13 -0
- package/dist/esm/definitions.js.map +1 -1
- package/ios/Plugin/AES.swift +5 -3
- package/ios/Plugin/CapacitorUpdaterPlugin.swift +125 -93
- package/ios/Plugin/CapgoUpdater.swift +70 -68
- package/ios/Plugin/CryptoCipherV2.swift +31 -26
- package/ios/Plugin/DelayUpdateUtils.swift +26 -24
- package/ios/Plugin/Logger.swift +289 -0
- package/ios/Plugin/UserDefaultsExtension.swift +0 -2
- package/package.json +1 -1
|
@@ -14,6 +14,8 @@ import Version
|
|
|
14
14
|
*/
|
|
15
15
|
@objc(CapacitorUpdaterPlugin)
|
|
16
16
|
public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
17
|
+
private let logger = Logger(withTag: "✨ CapgoUpdater")
|
|
18
|
+
|
|
17
19
|
public let identifier = "CapacitorUpdaterPlugin"
|
|
18
20
|
public let jsName = "CapacitorUpdater"
|
|
19
21
|
public let pluginMethods: [CAPPluginMethod] = [
|
|
@@ -45,7 +47,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
45
47
|
CAPPluginMethod(name: "getNextBundle", returnType: CAPPluginReturnPromise)
|
|
46
48
|
]
|
|
47
49
|
public var implementation = CapgoUpdater()
|
|
48
|
-
private let PLUGIN_VERSION: String = "7.
|
|
50
|
+
private let PLUGIN_VERSION: String = "7.4.0"
|
|
49
51
|
static let updateUrlDefault = "https://plugin.capgo.app/updates"
|
|
50
52
|
static let statsUrlDefault = "https://plugin.capgo.app/stats"
|
|
51
53
|
static let channelUrlDefault = "https://plugin.capgo.app/channel_self"
|
|
@@ -70,27 +72,35 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
70
72
|
private var delayUpdateUtils: DelayUpdateUtils!
|
|
71
73
|
|
|
72
74
|
override public func load() {
|
|
75
|
+
let disableJSLogging = getConfig().getBoolean("disableJSLogging", false)
|
|
76
|
+
// Set webView for logging to JavaScript console
|
|
77
|
+
if ((self.bridge?.webView) != nil) && !disableJSLogging {
|
|
78
|
+
logger.setWebView(webView: (self.bridge?.webView)!)
|
|
79
|
+
logger.info("WebView set successfully for logging")
|
|
80
|
+
} else {
|
|
81
|
+
logger.error("Failed to get webView for logging")
|
|
82
|
+
}
|
|
73
83
|
#if targetEnvironment(simulator)
|
|
74
|
-
|
|
75
|
-
|
|
84
|
+
logger.info("::::: SIMULATOR :::::")
|
|
85
|
+
logger.info("Application directory: \(NSHomeDirectory())")
|
|
76
86
|
#endif
|
|
77
87
|
|
|
78
88
|
self.semaphoreUp()
|
|
79
89
|
self.implementation.deviceID = (UserDefaults.standard.string(forKey: "appUUID") ?? UUID().uuidString).lowercased()
|
|
80
90
|
UserDefaults.standard.set( self.implementation.deviceID, forKey: "appUUID")
|
|
81
91
|
UserDefaults.standard.synchronize()
|
|
82
|
-
|
|
92
|
+
logger.info("init for device \(self.implementation.deviceID)")
|
|
83
93
|
guard let versionName = getConfig().getString("version", Bundle.main.versionName) else {
|
|
84
|
-
|
|
94
|
+
logger.error("Cannot get version name")
|
|
85
95
|
// crash the app
|
|
86
96
|
fatalError("Cannot get version name")
|
|
87
97
|
}
|
|
88
98
|
do {
|
|
89
99
|
currentVersionNative = try Version(versionName)
|
|
90
100
|
} catch {
|
|
91
|
-
|
|
101
|
+
logger.error("Cannot parse versionName \(versionName)")
|
|
92
102
|
}
|
|
93
|
-
|
|
103
|
+
logger.info("version native \(self.currentVersionNative.description)")
|
|
94
104
|
implementation.versionBuild = getConfig().getString("version", Bundle.main.versionName)!
|
|
95
105
|
autoDeleteFailed = getConfig().getBoolean("autoDeleteFailed", true)
|
|
96
106
|
autoDeletePrevious = getConfig().getBoolean("autoDeletePrevious", true)
|
|
@@ -112,10 +122,14 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
112
122
|
implementation.notifyDownloadRaw = notifyDownload
|
|
113
123
|
implementation.PLUGIN_VERSION = self.PLUGIN_VERSION
|
|
114
124
|
|
|
125
|
+
// Set logger for shared classes
|
|
126
|
+
implementation.setLogger(logger)
|
|
127
|
+
CryptoCipherV2.setLogger(logger)
|
|
128
|
+
|
|
115
129
|
// Initialize DelayUpdateUtils
|
|
116
130
|
self.delayUpdateUtils = DelayUpdateUtils(currentVersionNative: currentVersionNative, installNext: { [weak self] in
|
|
117
131
|
self?.installNext()
|
|
118
|
-
})
|
|
132
|
+
}, logger: logger)
|
|
119
133
|
let config = (self.bridge?.viewController as? CAPBridgeViewController)?.instanceDescriptor().legacyConfig
|
|
120
134
|
implementation.appId = Bundle.main.infoDictionary?["CFBundleIdentifier"] as? String ?? ""
|
|
121
135
|
implementation.appId = config?["appId"] as? String ?? implementation.appId
|
|
@@ -123,7 +137,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
123
137
|
if implementation.appId == "" {
|
|
124
138
|
fatalError("appId is missing in capacitor.config.json or plugin config, and cannot be retrieved from the native app, please add it globally or in the plugin config")
|
|
125
139
|
}
|
|
126
|
-
|
|
140
|
+
logger.info("appId \(implementation.appId)")
|
|
127
141
|
implementation.statsUrl = getConfig().getString("statsUrl", CapacitorUpdaterPlugin.statsUrlDefault)!
|
|
128
142
|
implementation.channelUrl = getConfig().getString("channelUrl", CapacitorUpdaterPlugin.channelUrlDefault)!
|
|
129
143
|
implementation.defaultChannel = getConfig().getString("defaultChannel", "")!
|
|
@@ -141,7 +155,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
141
155
|
// According to martin it is not possible to use serverBasePath on ios in a way that allows us to store the bundle once
|
|
142
156
|
|
|
143
157
|
if !self.initialLoad() {
|
|
144
|
-
|
|
158
|
+
logger.error("unable to force reload, the plugin might fallback to the builtin version")
|
|
145
159
|
}
|
|
146
160
|
|
|
147
161
|
let nc = NotificationCenter.default
|
|
@@ -164,11 +178,11 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
164
178
|
}
|
|
165
179
|
|
|
166
180
|
if !FileManager.default.fileExists(atPath: dest.path) {
|
|
167
|
-
|
|
181
|
+
logger.error("Initial load fail - file at path \(dest.path) doesn't exist. Defaulting to buildin!! \(id)")
|
|
168
182
|
dest = Bundle.main.resourceURL!.appendingPathComponent("public")
|
|
169
183
|
}
|
|
170
184
|
|
|
171
|
-
|
|
185
|
+
logger.info("Initial load \(id)")
|
|
172
186
|
// We don't use the viewcontroller here as it does not work during the initial load state
|
|
173
187
|
bridge.setServerBasePath(dest.path)
|
|
174
188
|
return true
|
|
@@ -194,16 +208,16 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
194
208
|
do {
|
|
195
209
|
LatestVersionNative = try Version(UserDefaults.standard.string(forKey: "LatestVersionNative") ?? "0.0.0")
|
|
196
210
|
} catch {
|
|
197
|
-
|
|
211
|
+
logger.error("Cannot get version native \(currentVersionNative)")
|
|
198
212
|
}
|
|
199
213
|
if LatestVersionNative != "0.0.0" && self.currentVersionNative.description != LatestVersionNative.description {
|
|
200
214
|
_ = self._reset(toLastSuccessful: false)
|
|
201
215
|
let res = implementation.list()
|
|
202
216
|
res.forEach { version in
|
|
203
|
-
|
|
217
|
+
logger.info("Deleting obsolete bundle: \(version.getId())")
|
|
204
218
|
let res = implementation.delete(id: version.getId())
|
|
205
219
|
if !res {
|
|
206
|
-
|
|
220
|
+
logger.error("Delete failed, id \(version.getId()) doesn't exist")
|
|
207
221
|
}
|
|
208
222
|
}
|
|
209
223
|
}
|
|
@@ -224,12 +238,12 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
224
238
|
|
|
225
239
|
@objc func setUpdateUrl(_ call: CAPPluginCall) {
|
|
226
240
|
if !getConfig().getBoolean("allowModifyUrl", false) {
|
|
227
|
-
|
|
241
|
+
logger.error("setUpdateUrl called without allowModifyUrl")
|
|
228
242
|
call.reject("setUpdateUrl called without allowModifyUrl set allowModifyUrl in your config to true to allow it")
|
|
229
243
|
return
|
|
230
244
|
}
|
|
231
245
|
guard let url = call.getString("url") else {
|
|
232
|
-
|
|
246
|
+
logger.error("setUpdateUrl called without url")
|
|
233
247
|
call.reject("setUpdateUrl called without url")
|
|
234
248
|
return
|
|
235
249
|
}
|
|
@@ -239,12 +253,12 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
239
253
|
|
|
240
254
|
@objc func setStatsUrl(_ call: CAPPluginCall) {
|
|
241
255
|
if !getConfig().getBoolean("allowModifyUrl", false) {
|
|
242
|
-
|
|
256
|
+
logger.error("setStatsUrl called without allowModifyUrl")
|
|
243
257
|
call.reject("setStatsUrl called without allowModifyUrl set allowModifyUrl in your config to true to allow it")
|
|
244
258
|
return
|
|
245
259
|
}
|
|
246
260
|
guard let url = call.getString("url") else {
|
|
247
|
-
|
|
261
|
+
logger.error("setStatsUrl called without url")
|
|
248
262
|
call.reject("setStatsUrl called without url")
|
|
249
263
|
return
|
|
250
264
|
}
|
|
@@ -254,12 +268,12 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
254
268
|
|
|
255
269
|
@objc func setChannelUrl(_ call: CAPPluginCall) {
|
|
256
270
|
if !getConfig().getBoolean("allowModifyUrl", false) {
|
|
257
|
-
|
|
271
|
+
logger.error("setChannelUrl called without allowModifyUrl")
|
|
258
272
|
call.reject("setChannelUrl called without allowModifyUrl set allowModifyUrl in your config to true to allow it")
|
|
259
273
|
return
|
|
260
274
|
}
|
|
261
275
|
guard let url = call.getString("url") else {
|
|
262
|
-
|
|
276
|
+
logger.error("setChannelUrl called without url")
|
|
263
277
|
call.reject("setChannelUrl called without url")
|
|
264
278
|
return
|
|
265
279
|
}
|
|
@@ -281,52 +295,70 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
281
295
|
|
|
282
296
|
@objc func download(_ call: CAPPluginCall) {
|
|
283
297
|
guard let urlString = call.getString("url") else {
|
|
284
|
-
|
|
298
|
+
logger.error("Download called without url")
|
|
285
299
|
call.reject("Download called without url")
|
|
286
300
|
return
|
|
287
301
|
}
|
|
288
302
|
guard let version = call.getString("version") else {
|
|
289
|
-
|
|
303
|
+
logger.error("Download called without version")
|
|
290
304
|
call.reject("Download called without version")
|
|
291
305
|
return
|
|
292
306
|
}
|
|
293
307
|
|
|
294
308
|
let sessionKey = call.getString("sessionKey", "")
|
|
295
309
|
var checksum = call.getString("checksum", "")
|
|
310
|
+
let manifestArray = call.getArray("manifest")
|
|
296
311
|
let url = URL(string: urlString)
|
|
297
|
-
|
|
312
|
+
logger.info("Downloading \(String(describing: url))")
|
|
298
313
|
DispatchQueue.global(qos: .background).async {
|
|
299
314
|
do {
|
|
300
|
-
let next
|
|
315
|
+
let next: BundleInfo
|
|
316
|
+
if let manifestArray = manifestArray {
|
|
317
|
+
// Convert JSArray to [ManifestEntry]
|
|
318
|
+
var manifestEntries: [ManifestEntry] = []
|
|
319
|
+
for item in manifestArray {
|
|
320
|
+
if let manifestDict = item as? [String: Any] {
|
|
321
|
+
let entry = ManifestEntry(
|
|
322
|
+
file_name: manifestDict["file_name"] as? String,
|
|
323
|
+
file_hash: manifestDict["file_hash"] as? String,
|
|
324
|
+
download_url: manifestDict["download_url"] as? String
|
|
325
|
+
)
|
|
326
|
+
manifestEntries.append(entry)
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
next = try self.implementation.downloadManifest(manifest: manifestEntries, version: version, sessionKey: sessionKey)
|
|
330
|
+
} else {
|
|
331
|
+
next = try self.implementation.download(url: url!, version: version, sessionKey: sessionKey)
|
|
332
|
+
}
|
|
301
333
|
// If public key is present but no checksum provided, refuse installation
|
|
302
334
|
if self.implementation.publicKey != "" && checksum == "" {
|
|
303
|
-
|
|
335
|
+
self.logger.error("Public key present but no checksum provided")
|
|
304
336
|
self.implementation.sendStats(action: "checksum_required", versionName: next.getVersionName())
|
|
305
337
|
let id = next.getId()
|
|
306
338
|
let resDel = self.implementation.delete(id: id)
|
|
307
339
|
if !resDel {
|
|
308
|
-
|
|
340
|
+
self.logger.error("Delete failed, id \(id) doesn't exist")
|
|
309
341
|
}
|
|
310
342
|
throw ObjectSavableError.checksum
|
|
311
343
|
}
|
|
312
344
|
|
|
313
345
|
checksum = try CryptoCipherV2.decryptChecksum(checksum: checksum, publicKey: self.implementation.publicKey)
|
|
314
346
|
if (checksum != "" || self.implementation.publicKey != "") && next.getChecksum() != checksum {
|
|
315
|
-
|
|
347
|
+
self.logger.error("Error checksum \(next.getChecksum()) \(checksum)")
|
|
316
348
|
self.implementation.sendStats(action: "checksum_fail", versionName: next.getVersionName())
|
|
317
349
|
let id = next.getId()
|
|
318
350
|
let resDel = self.implementation.delete(id: id)
|
|
319
351
|
if !resDel {
|
|
320
|
-
|
|
352
|
+
self.logger.error("Delete failed, id \(id) doesn't exist")
|
|
321
353
|
}
|
|
322
354
|
throw ObjectSavableError.checksum
|
|
323
355
|
} else {
|
|
324
|
-
|
|
356
|
+
self.logger.info("Good checksum \(next.getChecksum()) \(checksum)")
|
|
325
357
|
}
|
|
326
358
|
self.notifyListeners("updateAvailable", data: ["bundle": next.toJSON()])
|
|
327
359
|
call.resolve(next.toJSON())
|
|
328
360
|
} catch {
|
|
329
|
-
|
|
361
|
+
self.logger.error("Failed to download from: \(String(describing: url)) \(error.localizedDescription)")
|
|
330
362
|
self.notifyListeners("downloadFailed", data: ["version": version])
|
|
331
363
|
self.implementation.sendStats(action: "download_fail")
|
|
332
364
|
call.reject("Failed to download from: \(url!)", error.localizedDescription)
|
|
@@ -344,16 +376,16 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
344
376
|
} else {
|
|
345
377
|
dest = self.implementation.getBundleDirectory(id: id)
|
|
346
378
|
}
|
|
347
|
-
|
|
379
|
+
logger.info("Reloading \(id)")
|
|
348
380
|
if let vc = bridge.viewController as? CAPBridgeViewController {
|
|
349
381
|
guard let capBridge = vc.bridge else {
|
|
350
|
-
|
|
382
|
+
logger.error("Cannot get capBridge")
|
|
351
383
|
return false
|
|
352
384
|
}
|
|
353
385
|
if keepUrlPathAfterReload {
|
|
354
386
|
DispatchQueue.main.async {
|
|
355
387
|
guard let url = vc.webView?.url else {
|
|
356
|
-
|
|
388
|
+
self.logger.error("vc.webView?.url is null?")
|
|
357
389
|
return
|
|
358
390
|
}
|
|
359
391
|
capBridge.setServerBasePath(dest.path)
|
|
@@ -379,20 +411,20 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
379
411
|
if self._reload() {
|
|
380
412
|
call.resolve()
|
|
381
413
|
} else {
|
|
382
|
-
|
|
414
|
+
logger.error("Reload failed")
|
|
383
415
|
call.reject("Reload failed")
|
|
384
416
|
}
|
|
385
417
|
}
|
|
386
418
|
|
|
387
419
|
@objc func next(_ call: CAPPluginCall) {
|
|
388
420
|
guard let id = call.getString("id") else {
|
|
389
|
-
|
|
421
|
+
logger.error("Next called without id")
|
|
390
422
|
call.reject("Next called without id")
|
|
391
423
|
return
|
|
392
424
|
}
|
|
393
|
-
|
|
425
|
+
logger.info("Setting next active id \(id)")
|
|
394
426
|
if !self.implementation.setNextBundle(next: id) {
|
|
395
|
-
|
|
427
|
+
logger.error("Set next version failed. id \(id) does not exist.")
|
|
396
428
|
call.reject("Set next version failed. id \(id) does not exist.")
|
|
397
429
|
} else {
|
|
398
430
|
call.resolve(self.implementation.getBundleInfo(id: id).toJSON())
|
|
@@ -401,14 +433,14 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
401
433
|
|
|
402
434
|
@objc func set(_ call: CAPPluginCall) {
|
|
403
435
|
guard let id = call.getString("id") else {
|
|
404
|
-
|
|
436
|
+
logger.error("Set called without id")
|
|
405
437
|
call.reject("Set called without id")
|
|
406
438
|
return
|
|
407
439
|
}
|
|
408
440
|
let res = implementation.set(id: id)
|
|
409
|
-
|
|
441
|
+
logger.info("Set active bundle: \(id)")
|
|
410
442
|
if !res {
|
|
411
|
-
|
|
443
|
+
logger.info("Bundle successfully set to: \(id) ")
|
|
412
444
|
call.reject("Update failed, id \(id) doesn't exist")
|
|
413
445
|
} else {
|
|
414
446
|
self.reload(call)
|
|
@@ -417,7 +449,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
417
449
|
|
|
418
450
|
@objc func delete(_ call: CAPPluginCall) {
|
|
419
451
|
guard let id = call.getString("id") else {
|
|
420
|
-
|
|
452
|
+
logger.error("Delete called without version")
|
|
421
453
|
call.reject("Delete called without id")
|
|
422
454
|
return
|
|
423
455
|
}
|
|
@@ -425,7 +457,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
425
457
|
if res {
|
|
426
458
|
call.resolve()
|
|
427
459
|
} else {
|
|
428
|
-
|
|
460
|
+
logger.error("Delete failed, id \(id) doesn't exist or it cannot be deleted (perhaps it is the 'next' bundle)")
|
|
429
461
|
call.reject("Delete failed, id \(id) does not exist or it cannot be deleted (perhaps it is the 'next' bundle)")
|
|
430
462
|
}
|
|
431
463
|
}
|
|
@@ -464,7 +496,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
464
496
|
call.reject(res.error)
|
|
465
497
|
} else {
|
|
466
498
|
if self._isAutoUpdateEnabled() && triggerAutoUpdate {
|
|
467
|
-
|
|
499
|
+
self.logger.info("Calling autoupdater after channel change!")
|
|
468
500
|
self.backgroundDownload()
|
|
469
501
|
}
|
|
470
502
|
call.resolve(res.toDict())
|
|
@@ -474,7 +506,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
474
506
|
|
|
475
507
|
@objc func setChannel(_ call: CAPPluginCall) {
|
|
476
508
|
guard let channel = call.getString("channel") else {
|
|
477
|
-
|
|
509
|
+
logger.error("setChannel called without channel")
|
|
478
510
|
call.reject("setChannel called without channel")
|
|
479
511
|
return
|
|
480
512
|
}
|
|
@@ -485,7 +517,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
485
517
|
call.reject(res.error)
|
|
486
518
|
} else {
|
|
487
519
|
if self._isAutoUpdateEnabled() && triggerAutoUpdate {
|
|
488
|
-
|
|
520
|
+
self.logger.info("Calling autoupdater after channel change!")
|
|
489
521
|
self.backgroundDownload()
|
|
490
522
|
}
|
|
491
523
|
call.resolve(res.toDict())
|
|
@@ -505,7 +537,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
505
537
|
}
|
|
506
538
|
@objc func setCustomId(_ call: CAPPluginCall) {
|
|
507
539
|
guard let customId = call.getString("customId") else {
|
|
508
|
-
|
|
540
|
+
logger.error("setCustomId called without customId")
|
|
509
541
|
call.reject("setCustomId called without customId")
|
|
510
542
|
return
|
|
511
543
|
}
|
|
@@ -521,11 +553,11 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
521
553
|
// If developer wants to reset to the last successful bundle, and that bundle is not
|
|
522
554
|
// the built-in bundle, set it as the bundle to use and reload.
|
|
523
555
|
if toLastSuccessful && !fallback.isBuiltin() {
|
|
524
|
-
|
|
556
|
+
logger.info("Resetting to: \(fallback.toString())")
|
|
525
557
|
return self.implementation.set(bundle: fallback) && self._reload()
|
|
526
558
|
}
|
|
527
559
|
|
|
528
|
-
|
|
560
|
+
logger.info("Resetting to builtin version")
|
|
529
561
|
|
|
530
562
|
// Otherwise, reset back to the built-in bundle and reload.
|
|
531
563
|
self.implementation.reset()
|
|
@@ -540,8 +572,8 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
540
572
|
if self._reset(toLastSuccessful: toLastSuccessful) {
|
|
541
573
|
call.resolve()
|
|
542
574
|
} else {
|
|
543
|
-
|
|
544
|
-
call.reject("
|
|
575
|
+
logger.error("Reset failed")
|
|
576
|
+
call.reject("Reset failed")
|
|
545
577
|
}
|
|
546
578
|
}
|
|
547
579
|
|
|
@@ -557,13 +589,13 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
557
589
|
self.semaphoreDown()
|
|
558
590
|
let bundle = self.implementation.getCurrentBundle()
|
|
559
591
|
self.implementation.setSuccess(bundle: bundle, autoDeletePrevious: self.autoDeletePrevious)
|
|
560
|
-
|
|
592
|
+
logger.info("Current bundle loaded successfully. ['notifyAppReady()' was called] \(bundle.toString())")
|
|
561
593
|
call.resolve(["bundle": bundle.toJSON()])
|
|
562
594
|
}
|
|
563
595
|
|
|
564
596
|
@objc func setMultiDelay(_ call: CAPPluginCall) {
|
|
565
597
|
guard let delayConditionList = call.getValue("delayConditions") else {
|
|
566
|
-
|
|
598
|
+
logger.error("setMultiDelay called without delayCondition")
|
|
567
599
|
call.reject("setMultiDelay called without delayCondition")
|
|
568
600
|
return
|
|
569
601
|
}
|
|
@@ -609,7 +641,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
609
641
|
private func _isAutoUpdateEnabled() -> Bool {
|
|
610
642
|
let instanceDescriptor = (self.bridge?.viewController as? CAPBridgeViewController)?.instanceDescriptor()
|
|
611
643
|
if instanceDescriptor?.serverURL != nil {
|
|
612
|
-
|
|
644
|
+
logger.warn("AutoUpdate is automatic disabled when serverUrl is set.")
|
|
613
645
|
}
|
|
614
646
|
return self.autoUpdate && self.updateUrl != "" && instanceDescriptor?.serverURL == nil
|
|
615
647
|
}
|
|
@@ -633,7 +665,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
633
665
|
self.appReadyCheck = DispatchWorkItem(block: {
|
|
634
666
|
self.DeferredNotifyAppReadyCheck()
|
|
635
667
|
})
|
|
636
|
-
|
|
668
|
+
logger.info("Wait for \(self.appReadyTimeout) ms, then check for notifyAppReady")
|
|
637
669
|
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(self.appReadyTimeout), execute: self.appReadyCheck!)
|
|
638
670
|
}
|
|
639
671
|
|
|
@@ -641,15 +673,15 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
641
673
|
// Automatically roll back to fallback version if notifyAppReady has not been called yet
|
|
642
674
|
let current: BundleInfo = self.implementation.getCurrentBundle()
|
|
643
675
|
if current.isBuiltin() {
|
|
644
|
-
|
|
676
|
+
logger.info("Built-in bundle is active. We skip the check for notifyAppReady.")
|
|
645
677
|
return
|
|
646
678
|
}
|
|
647
679
|
|
|
648
|
-
|
|
680
|
+
logger.info("Current bundle is: \(current.toString())")
|
|
649
681
|
|
|
650
682
|
if BundleStatus.SUCCESS.localizedString != current.getStatus() {
|
|
651
|
-
|
|
652
|
-
|
|
683
|
+
logger.error("notifyAppReady was not called, roll back current bundle: \(current.toString())")
|
|
684
|
+
logger.error("Did you forget to call 'notifyAppReady()' in your Capacitor App code?")
|
|
653
685
|
self.notifyListeners("updateFailed", data: [
|
|
654
686
|
"bundle": current.toJSON()
|
|
655
687
|
])
|
|
@@ -657,16 +689,16 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
657
689
|
self.implementation.setError(bundle: current)
|
|
658
690
|
_ = self._reset(toLastSuccessful: true)
|
|
659
691
|
if self.autoDeleteFailed && !current.isBuiltin() {
|
|
660
|
-
|
|
692
|
+
logger.info("Deleting failing bundle: \(current.toString())")
|
|
661
693
|
let res = self.implementation.delete(id: current.getId(), removeInfo: false)
|
|
662
694
|
if !res {
|
|
663
|
-
|
|
695
|
+
logger.info("Delete version deleted: \(current.toString())")
|
|
664
696
|
} else {
|
|
665
|
-
|
|
697
|
+
logger.error("Failed to delete failed bundle: \(current.toString())")
|
|
666
698
|
}
|
|
667
699
|
}
|
|
668
700
|
} else {
|
|
669
|
-
|
|
701
|
+
logger.info("notifyAppReady was called. This is fine: \(current.toString())")
|
|
670
702
|
}
|
|
671
703
|
}
|
|
672
704
|
|
|
@@ -681,7 +713,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
681
713
|
}
|
|
682
714
|
|
|
683
715
|
func sendReadyToJs(current: BundleInfo, msg: String) {
|
|
684
|
-
|
|
716
|
+
logger.info("sendReadyToJs")
|
|
685
717
|
DispatchQueue.global().async {
|
|
686
718
|
self.semaphoreWait(waitTime: self.appReadyTimeout)
|
|
687
719
|
self.notifyListeners("appReady", data: ["bundle": current.toJSON(), "status": msg])
|
|
@@ -695,14 +727,14 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
695
727
|
}
|
|
696
728
|
self.notifyListeners("noNeedUpdate", data: ["bundle": current.toJSON()])
|
|
697
729
|
self.sendReadyToJs(current: current, msg: msg)
|
|
698
|
-
|
|
730
|
+
logger.info("endBackGroundTaskWithNotif \(msg) current: \(current.getVersionName()) latestVersionName: \(latestVersionName)")
|
|
699
731
|
self.endBackGroundTask()
|
|
700
732
|
}
|
|
701
733
|
|
|
702
734
|
func backgroundDownload() {
|
|
703
735
|
let messageUpdate = self.directUpdate ? "Update will occur now." : "Update will occur next time app moves to background."
|
|
704
736
|
guard let url = URL(string: self.updateUrl) else {
|
|
705
|
-
|
|
737
|
+
logger.error("Error no url or wrong format")
|
|
706
738
|
return
|
|
707
739
|
}
|
|
708
740
|
DispatchQueue.global(qos: .background).async {
|
|
@@ -710,12 +742,12 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
710
742
|
// End the task if time expires.
|
|
711
743
|
self.endBackGroundTask()
|
|
712
744
|
}
|
|
713
|
-
|
|
745
|
+
self.logger.info("Check for update via \(self.updateUrl)")
|
|
714
746
|
let res = self.implementation.getLatest(url: url, channel: nil)
|
|
715
747
|
let current = self.implementation.getCurrentBundle()
|
|
716
748
|
|
|
717
749
|
if (res.message) != nil {
|
|
718
|
-
|
|
750
|
+
self.logger.info("API message: \(res.message ?? "")")
|
|
719
751
|
if res.major == true {
|
|
720
752
|
self.notifyListeners("majorAvailable", data: ["version": res.version])
|
|
721
753
|
}
|
|
@@ -723,13 +755,13 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
723
755
|
return
|
|
724
756
|
}
|
|
725
757
|
if res.version == "builtin" {
|
|
726
|
-
|
|
758
|
+
self.logger.info("Latest version is builtin")
|
|
727
759
|
if self.directUpdate {
|
|
728
|
-
|
|
760
|
+
self.logger.info("Direct update to builtin version")
|
|
729
761
|
_ = self._reset(toLastSuccessful: false)
|
|
730
762
|
self.endBackGroundTaskWithNotif(msg: "Updated to builtin version", latestVersionName: res.version, current: self.implementation.getCurrentBundle(), error: false)
|
|
731
763
|
} else {
|
|
732
|
-
|
|
764
|
+
self.logger.info("Setting next bundle to builtin")
|
|
733
765
|
_ = self.implementation.setNextBundle(next: BundleInfo.ID_BUILTIN)
|
|
734
766
|
self.endBackGroundTaskWithNotif(msg: "Next update will be to builtin version", latestVersionName: res.version, current: current, error: false)
|
|
735
767
|
}
|
|
@@ -737,23 +769,23 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
737
769
|
}
|
|
738
770
|
let sessionKey = res.sessionKey ?? ""
|
|
739
771
|
guard let downloadUrl = URL(string: res.url) else {
|
|
740
|
-
|
|
772
|
+
self.logger.error("Error no url or wrong format")
|
|
741
773
|
self.endBackGroundTaskWithNotif(msg: "Error no url or wrong format", latestVersionName: res.version, current: current)
|
|
742
774
|
return
|
|
743
775
|
}
|
|
744
776
|
let latestVersionName = res.version
|
|
745
777
|
if latestVersionName != "" && current.getVersionName() != latestVersionName {
|
|
746
778
|
do {
|
|
747
|
-
|
|
779
|
+
self.logger.info("New bundle: \(latestVersionName) found. Current is: \(current.getVersionName()). \(messageUpdate)")
|
|
748
780
|
var nextImpl = self.implementation.getBundleInfoByVersionName(version: latestVersionName)
|
|
749
781
|
if nextImpl == nil || nextImpl?.isDeleted() == true {
|
|
750
782
|
if nextImpl?.isDeleted() == true {
|
|
751
|
-
|
|
783
|
+
self.logger.info("Latest bundle already exists and will be deleted, download will overwrite it.")
|
|
752
784
|
let res = self.implementation.delete(id: nextImpl!.getId(), removeInfo: true)
|
|
753
785
|
if res {
|
|
754
|
-
|
|
786
|
+
self.logger.info("Failed bundle deleted: \(nextImpl!.toString())")
|
|
755
787
|
} else {
|
|
756
|
-
|
|
788
|
+
self.logger.error("Failed to delete failed bundle: \(nextImpl!.toString())")
|
|
757
789
|
}
|
|
758
790
|
}
|
|
759
791
|
if res.manifest != nil {
|
|
@@ -763,23 +795,23 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
763
795
|
}
|
|
764
796
|
}
|
|
765
797
|
guard let next = nextImpl else {
|
|
766
|
-
|
|
798
|
+
self.logger.error("Error downloading file")
|
|
767
799
|
self.endBackGroundTaskWithNotif(msg: "Error downloading file", latestVersionName: latestVersionName, current: current)
|
|
768
800
|
return
|
|
769
801
|
}
|
|
770
802
|
if next.isErrorStatus() {
|
|
771
|
-
|
|
803
|
+
self.logger.error("Latest bundle already exists and is in error state. Aborting update.")
|
|
772
804
|
self.endBackGroundTaskWithNotif(msg: "Latest version is in error state. Aborting update.", latestVersionName: latestVersionName, current: current)
|
|
773
805
|
return
|
|
774
806
|
}
|
|
775
807
|
res.checksum = try CryptoCipherV2.decryptChecksum(checksum: res.checksum, publicKey: self.implementation.publicKey)
|
|
776
808
|
if res.checksum != "" && next.getChecksum() != res.checksum && res.manifest == nil {
|
|
777
|
-
|
|
809
|
+
self.logger.error("Error checksum \(next.getChecksum()) \(res.checksum)")
|
|
778
810
|
self.implementation.sendStats(action: "checksum_fail", versionName: next.getVersionName())
|
|
779
811
|
let id = next.getId()
|
|
780
812
|
let resDel = self.implementation.delete(id: id)
|
|
781
813
|
if !resDel {
|
|
782
|
-
|
|
814
|
+
self.logger.error("Delete failed, id \(id) doesn't exist")
|
|
783
815
|
}
|
|
784
816
|
self.endBackGroundTaskWithNotif(msg: "Error checksum", latestVersionName: latestVersionName, current: current)
|
|
785
817
|
return
|
|
@@ -792,7 +824,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
792
824
|
return DelayCondition(kind: kind, value: value)
|
|
793
825
|
}
|
|
794
826
|
if !delayConditionList.isEmpty {
|
|
795
|
-
|
|
827
|
+
self.logger.info("Update delayed until delay conditions met")
|
|
796
828
|
self.endBackGroundTaskWithNotif(msg: "Update delayed until delay conditions met", latestVersionName: latestVersionName, current: next, error: false)
|
|
797
829
|
return
|
|
798
830
|
}
|
|
@@ -806,13 +838,13 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
806
838
|
}
|
|
807
839
|
return
|
|
808
840
|
} catch {
|
|
809
|
-
|
|
841
|
+
self.logger.error("Error downloading file \(error.localizedDescription)")
|
|
810
842
|
let current: BundleInfo = self.implementation.getCurrentBundle()
|
|
811
843
|
self.endBackGroundTaskWithNotif(msg: "Error downloading file", latestVersionName: latestVersionName, current: current)
|
|
812
844
|
return
|
|
813
845
|
}
|
|
814
846
|
} else {
|
|
815
|
-
|
|
847
|
+
self.logger.info("No need to update, \(current.getId()) is the latest bundle.")
|
|
816
848
|
self.endBackGroundTaskWithNotif(msg: "No need to update, \(current.getId()) is the latest bundle.", latestVersionName: latestVersionName, current: current, error: false)
|
|
817
849
|
return
|
|
818
850
|
}
|
|
@@ -820,7 +852,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
820
852
|
}
|
|
821
853
|
|
|
822
854
|
@objc func appKilled() {
|
|
823
|
-
|
|
855
|
+
logger.info("onActivityDestroyed: all activity destroyed")
|
|
824
856
|
self.delayUpdateUtils.checkCancelDelay(source: .killed)
|
|
825
857
|
}
|
|
826
858
|
|
|
@@ -832,19 +864,19 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
832
864
|
return DelayCondition(kind: kind, value: value)
|
|
833
865
|
}
|
|
834
866
|
if !delayConditionList.isEmpty {
|
|
835
|
-
|
|
867
|
+
logger.info("Update delayed until delay conditions met")
|
|
836
868
|
return
|
|
837
869
|
}
|
|
838
870
|
let current: BundleInfo = self.implementation.getCurrentBundle()
|
|
839
871
|
let next: BundleInfo? = self.implementation.getNextBundle()
|
|
840
872
|
|
|
841
873
|
if next != nil && !next!.isErrorStatus() && next!.getVersionName() != current.getVersionName() {
|
|
842
|
-
|
|
874
|
+
logger.info("Next bundle is: \(next!.toString())")
|
|
843
875
|
if self.implementation.set(bundle: next!) && self._reload() {
|
|
844
|
-
|
|
876
|
+
logger.info("Updated to bundle: \(next!.toString())")
|
|
845
877
|
_ = self.implementation.setNextBundle(next: Optional<String>.none)
|
|
846
878
|
} else {
|
|
847
|
-
|
|
879
|
+
logger.error("Update to bundle: \(next!.toString()) Failed!")
|
|
848
880
|
}
|
|
849
881
|
}
|
|
850
882
|
}
|
|
@@ -874,12 +906,12 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
874
906
|
self.delayUpdateUtils.unsetBackgroundTimestamp()
|
|
875
907
|
if backgroundWork != nil && taskRunning {
|
|
876
908
|
backgroundWork!.cancel()
|
|
877
|
-
|
|
909
|
+
logger.info("Background Timer Task canceled, Activity resumed before timer completes")
|
|
878
910
|
}
|
|
879
911
|
if self._isAutoUpdateEnabled() {
|
|
880
912
|
self.backgroundDownload()
|
|
881
913
|
} else {
|
|
882
|
-
|
|
914
|
+
logger.info("Auto update is disabled")
|
|
883
915
|
self.sendReadyToJs(current: current, msg: "disabled")
|
|
884
916
|
}
|
|
885
917
|
self.checkAppReady()
|
|
@@ -890,7 +922,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
890
922
|
return
|
|
891
923
|
}
|
|
892
924
|
guard let url = URL(string: self.updateUrl) else {
|
|
893
|
-
|
|
925
|
+
logger.error("Error no url or wrong format")
|
|
894
926
|
return
|
|
895
927
|
}
|
|
896
928
|
let timer = Timer.scheduledTimer(withTimeInterval: TimeInterval(periodCheckDelay), repeats: true) { _ in
|
|
@@ -899,7 +931,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
899
931
|
let current = self.implementation.getCurrentBundle()
|
|
900
932
|
|
|
901
933
|
if res.version != current.getVersionName() {
|
|
902
|
-
|
|
934
|
+
self.logger.info("New version found: \(res.version)")
|
|
903
935
|
self.backgroundDownload()
|
|
904
936
|
}
|
|
905
937
|
}
|
|
@@ -910,7 +942,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
910
942
|
@objc func appMovedToBackground() {
|
|
911
943
|
let current: BundleInfo = self.implementation.getCurrentBundle()
|
|
912
944
|
self.implementation.sendStats(action: "app_moved_to_background", versionName: current.getVersionName())
|
|
913
|
-
|
|
945
|
+
logger.info("Check for pending update")
|
|
914
946
|
|
|
915
947
|
// Set background timestamp
|
|
916
948
|
let backgroundTimestamp = Int64(Date().timeIntervalSince1970 * 1000) // Convert to milliseconds
|