@capgo/capacitor-updater 8.51.23 → 8.51.24

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.
@@ -146,7 +146,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
146
146
  static final int APPLICATION_EXIT_REASON_USER_REQUESTED = 10;
147
147
  static final int APPLICATION_EXIT_REASON_DEPENDENCY_DIED = 12;
148
148
 
149
- private final String pluginVersion = "8.51.23";
149
+ private final String pluginVersion = "8.51.24";
150
150
  private static final String DELAY_CONDITION_PREFERENCES = "";
151
151
 
152
152
  private SharedPreferences.Editor editor;
@@ -5,15 +5,24 @@ import android.util.Log;
5
5
  import androidx.annotation.NonNull;
6
6
  import androidx.annotation.Nullable;
7
7
  import com.getcapacitor.*;
8
+ import java.nio.ByteBuffer;
9
+ import java.nio.CharBuffer;
10
+ import java.nio.charset.CharsetEncoder;
11
+ import java.nio.charset.CoderResult;
12
+ import java.nio.charset.CodingErrorAction;
13
+ import java.nio.charset.StandardCharsets;
8
14
  import java.util.ArrayList;
9
15
  import java.util.Arrays;
10
16
  import java.util.Date;
11
17
  import java.util.Locale;
12
18
  import java.util.Map;
13
19
  import org.jetbrains.annotations.Contract;
20
+ import org.json.JSONObject;
14
21
 
15
22
  public class Logger {
16
23
 
24
+ static final int MAX_WEBVIEW_LOG_PAYLOAD_CHARS = 4096;
25
+
17
26
  private Bridge bridge;
18
27
 
19
28
  public enum LogLevel {
@@ -250,13 +259,63 @@ public class Logger {
250
259
 
251
260
  // Send to JavaScript if webView is available
252
261
  if (bridge != null && bridge.getWebView() != null) {
253
- bridge.eval(
254
- "console." + level.name() + "(\"[" + tag.replace("\"", "\\\"") + "] " + formattedMessage.replace("\"", "\\\"") + "\")",
255
- null
256
- );
262
+ String script = buildWebViewConsoleScript(level, tag, formattedMessage);
263
+ if (script != null) {
264
+ bridge.eval(script, null);
265
+ }
266
+ }
267
+ }
268
+
269
+ @Nullable
270
+ static String consoleMethodForLevel(@NonNull LogLevel level) {
271
+ switch (level) {
272
+ case error:
273
+ return "error";
274
+ case warn:
275
+ return "warn";
276
+ case info:
277
+ return "info";
278
+ case debug:
279
+ return "debug";
280
+ default:
281
+ return null;
257
282
  }
258
283
  }
259
284
 
285
+ @NonNull
286
+ static String toJsStringLiteral(@NonNull String value) {
287
+ return JSONObject.quote(value);
288
+ }
289
+
290
+ @NonNull
291
+ static String capWebViewLogPayload(@NonNull String payload) {
292
+ CharsetEncoder encoder = StandardCharsets.UTF_8.newEncoder()
293
+ .onMalformedInput(CodingErrorAction.REPLACE)
294
+ .onUnmappableCharacter(CodingErrorAction.REPLACE);
295
+ ByteBuffer bytes = ByteBuffer.allocate(MAX_WEBVIEW_LOG_PAYLOAD_CHARS);
296
+ CharBuffer chars = CharBuffer.wrap(payload);
297
+ CoderResult result = encoder.encode(chars, bytes, true);
298
+ if (result.isUnderflow()) {
299
+ result = encoder.flush(bytes);
300
+ }
301
+ if (result.isUnderflow()) {
302
+ return payload;
303
+ }
304
+
305
+ return new String(bytes.array(), 0, bytes.position(), StandardCharsets.UTF_8) + "...";
306
+ }
307
+
308
+ @Nullable
309
+ static String buildWebViewConsoleScript(@NonNull LogLevel level, @NonNull String tag, @NonNull String formattedMessage) {
310
+ String consoleMethod = consoleMethodForLevel(level);
311
+ if (consoleMethod == null) {
312
+ return null;
313
+ }
314
+
315
+ String payload = capWebViewLogPayload("[" + tag + "] " + formattedMessage);
316
+ return "console." + consoleMethod + "(" + toJsStringLiteral(payload) + ")";
317
+ }
318
+
260
319
  public void dir(Object value) {
261
320
  String message;
262
321
 
@@ -96,7 +96,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
96
96
  deinit {
97
97
  implementation.shutdown()
98
98
  }
99
- private let pluginVersion: String = "8.51.23"
99
+ private let pluginVersion: String = "8.51.24"
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"
@@ -4,6 +4,8 @@ import os.log
4
4
  import WebKit
5
5
 
6
6
  public class Logger {
7
+ static let maxWebViewLogPayloadChars = 4096
8
+
7
9
  public enum LogLevel: Int {
8
10
  case silent = 0
9
11
  case error
@@ -199,17 +201,85 @@ public class Logger {
199
201
  // This will never fail, but we have to keep swift happy
200
202
  if let label = _labels[level] {
201
203
  log(atLevel: level, label: label, tag: tag, message: message)
202
- if let webView = self.webView {
204
+ if let webView = self.webView, let script = buildWebViewConsoleScript(level: level, label: label, tag: tag, message: message) {
203
205
  DispatchQueue.main.async {
204
- let combined = "\(label) \(self.tag) : \(message)"
205
- let jsArg = self.toJSStringLiteral(combined)
206
- webView.evaluateJavaScript("console.\(level.asString())(\(jsArg))", completionHandler: nil)
206
+ webView.evaluateJavaScript(script, completionHandler: nil)
207
207
  }
208
208
  }
209
209
  }
210
210
  }
211
211
 
212
- private func toJSStringLiteral(_ value: String) -> String {
212
+ func consoleMethodName(for level: LogLevel) -> String? {
213
+ switch level {
214
+ case .error:
215
+ return "error"
216
+ case .warn:
217
+ return "warn"
218
+ case .info:
219
+ return "info"
220
+ case .debug:
221
+ return "debug"
222
+ case .silent:
223
+ return nil
224
+ }
225
+ }
226
+
227
+ private func utf8SequenceLength(_ lead: UInt8) -> Int {
228
+ if (lead & 0x80) == 0 {
229
+ return 1
230
+ }
231
+ if (lead & 0xE0) == 0xC0 {
232
+ return 2
233
+ }
234
+ if (lead & 0xF0) == 0xE0 {
235
+ return 3
236
+ }
237
+ if (lead & 0xF8) == 0xF0 {
238
+ return 4
239
+ }
240
+ return 0
241
+ }
242
+
243
+ func capWebViewLogPayload(_ payload: String) -> String {
244
+ let suffix = "..."
245
+ let maxPayloadBytes = Logger.maxWebViewLogPayloadChars
246
+ let payloadBytes = Array(payload.utf8.prefix(maxPayloadBytes + 1))
247
+ if payloadBytes.count <= maxPayloadBytes {
248
+ return payload
249
+ }
250
+
251
+ var end = maxPayloadBytes
252
+ while end > 0 && (payloadBytes[end - 1] & 0xC0) == 0x80 {
253
+ end -= 1
254
+ }
255
+ while end > 0 {
256
+ let leadIndex = end - 1
257
+ let lead = payloadBytes[leadIndex]
258
+ let seqLength = utf8SequenceLength(lead)
259
+ if seqLength == 0 {
260
+ end -= 1
261
+ continue
262
+ }
263
+ if leadIndex + seqLength <= maxPayloadBytes {
264
+ end = leadIndex + seqLength
265
+ break
266
+ }
267
+ end -= 1
268
+ }
269
+
270
+ return String(decoding: payloadBytes[0..<end], as: UTF8.self) + suffix
271
+ }
272
+
273
+ func buildWebViewConsoleScript(level: LogLevel, label: String, tag: String, message: String) -> String? {
274
+ guard let consoleMethod = consoleMethodName(for: level) else {
275
+ return nil
276
+ }
277
+
278
+ let payload = capWebViewLogPayload("\(label) \(tag) : \(message)")
279
+ return "console.\(consoleMethod)(\(toJSStringLiteral(payload)))"
280
+ }
281
+
282
+ func toJSStringLiteral(_ value: String) -> String {
213
283
  // Prefer JSON encoding to produce a valid JS string literal
214
284
  if let data = try? JSONEncoder().encode(value),
215
285
  let encoded = String(data: data, encoding: .utf8) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-updater",
3
- "version": "8.51.23",
3
+ "version": "8.51.24",
4
4
  "license": "MPL-2.0",
5
5
  "description": "Live update for capacitor apps",
6
6
  "main": "dist/plugin.cjs.js",