@capgo/capacitor-webview-crash 8.0.1
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/CapgoCapacitorWebViewCrash.podspec +17 -0
- package/LICENSE +373 -0
- package/Package.swift +28 -0
- package/README.md +257 -0
- package/android/build.gradle +59 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/app/capgo/webviewcrash/WebViewCrash.java +58 -0
- package/android/src/main/java/app/capgo/webviewcrash/WebViewCrashPlugin.java +104 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +251 -0
- package/dist/esm/definitions.d.ts +84 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +17 -0
- package/dist/esm/web.js +75 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +89 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +92 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/WebViewCrashPlugin/WebViewCrash.swift +105 -0
- package/ios/Sources/WebViewCrashPlugin/WebViewCrashPlugin.swift +62 -0
- package/ios/Tests/WebViewCrashPluginTests/WebViewCrashPluginTests.swift +12 -0
- package/package.json +92 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C,MAAM,OAAO,eAAgB,SAAQ,SAAS;IAA9C;;QACU,4BAAuB,GAAG,KAAK,CAAC;IA4E1C,CAAC;IA1EC,KAAK,CAAC,mBAAmB;QACvB,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,qBAAqB;QACzB,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAC9B,IAAI,CAAC,uBAAuB,GAAG,KAAK,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,qBAAqB;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACpC,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,CAAC,uBAAuB,GAAG,KAAK,CAAC;QACrC,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAC9B,OAAO,EAAE,KAAK,EAAE,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,SAAiB,EAAE,YAAqC;QACxE,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QAChE,IAAI,SAAS,KAAK,eAAe,CAAC,SAAS,EAAE,CAAC;YAC5C,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAChC,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,sBAAsB;QAC5B,IAAI,IAAI,CAAC,uBAAuB,EAAE,CAAC;YACjC,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC1C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO;QACT,CAAC;QAED,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC;QACpC,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACzD,CAAC;IAEO,cAAc;;QACpB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,OAAO;YACL,QAAQ,EAAE,KAAK;YACf,SAAS;YACT,YAAY,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE;YAC/C,MAAM,EAAE,WAAW;YACnB,GAAG,EAAE,MAAA,UAAU,CAAC,QAAQ,0CAAE,IAAI;YAC9B,QAAQ,EAAE,QAAQ;SACnB,CAAC;IACJ,CAAC;IAEO,oBAAoB;;QAC1B,MAAM,GAAG,GAAG,MAAA,UAAU,CAAC,YAAY,0CAAE,OAAO,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;QACzE,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAqB,CAAC;QAC7C,CAAC;QAAC,WAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAEO,qBAAqB,CAAC,KAAuB;;QACnD,MAAA,UAAU,CAAC,YAAY,0CAAE,OAAO,CAAC,eAAe,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IACtF,CAAC;IAEO,sBAAsB;;QAC5B,MAAA,UAAU,CAAC,YAAY,0CAAE,UAAU,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;IAClE,CAAC;;AAEuB,yBAAS,GAAG,2BAA2B,AAA9B,CAA+B;AACxC,0BAAU,GAAG,6BAA6B,AAAhC,CAAiC","sourcesContent":["import type { PluginListenerHandle } from '@capacitor/core';\nimport { WebPlugin } from '@capacitor/core';\n\nimport type { PendingCrashInfoResult, WebViewCrashInfo, WebViewCrashPlugin } from './definitions';\n\nexport class WebViewCrashWeb extends WebPlugin implements WebViewCrashPlugin {\n private didDispatchPendingEvent = false;\n\n async getPendingCrashInfo(): Promise<PendingCrashInfoResult> {\n return { value: this.readPendingCrashInfo() };\n }\n\n async clearPendingCrashInfo(): Promise<void> {\n this.removePendingCrashInfo();\n this.didDispatchPendingEvent = false;\n }\n\n async simulateCrashRecovery(): Promise<PendingCrashInfoResult> {\n const value = this.buildCrashInfo();\n this.writePendingCrashInfo(value);\n this.didDispatchPendingEvent = false;\n this.flushPendingCrashEvent();\n return { value };\n }\n\n async addListener(eventName: string, listenerFunc: (...args: any[]) => any): Promise<PluginListenerHandle> {\n const handle = await super.addListener(eventName, listenerFunc);\n if (eventName === WebViewCrashWeb.eventName) {\n this.flushPendingCrashEvent();\n }\n return handle;\n }\n\n private flushPendingCrashEvent(): void {\n if (this.didDispatchPendingEvent) {\n return;\n }\n\n const value = this.readPendingCrashInfo();\n if (!value) {\n return;\n }\n\n this.didDispatchPendingEvent = true;\n this.notifyListeners(WebViewCrashWeb.eventName, value);\n }\n\n private buildCrashInfo(): WebViewCrashInfo {\n const timestamp = Date.now();\n return {\n platform: 'web',\n timestamp,\n timestampISO: new Date(timestamp).toISOString(),\n reason: 'simulated',\n url: globalThis.location?.href,\n appState: 'active',\n };\n }\n\n private readPendingCrashInfo(): WebViewCrashInfo | null {\n const raw = globalThis.localStorage?.getItem(WebViewCrashWeb.storageKey);\n if (!raw) {\n return null;\n }\n\n try {\n return JSON.parse(raw) as WebViewCrashInfo;\n } catch {\n return null;\n }\n }\n\n private writePendingCrashInfo(value: WebViewCrashInfo): void {\n globalThis.localStorage?.setItem(WebViewCrashWeb.storageKey, JSON.stringify(value));\n }\n\n private removePendingCrashInfo(): void {\n globalThis.localStorage?.removeItem(WebViewCrashWeb.storageKey);\n }\n\n private static readonly eventName = 'webViewRestoredAfterCrash';\n private static readonly storageKey = 'capgo.webview-crash.pending';\n}\n"]}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@capacitor/core');
|
|
4
|
+
|
|
5
|
+
const WebViewCrash = core.registerPlugin('WebViewCrash', {
|
|
6
|
+
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.WebViewCrashWeb()),
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
class WebViewCrashWeb extends core.WebPlugin {
|
|
10
|
+
constructor() {
|
|
11
|
+
super(...arguments);
|
|
12
|
+
this.didDispatchPendingEvent = false;
|
|
13
|
+
}
|
|
14
|
+
async getPendingCrashInfo() {
|
|
15
|
+
return { value: this.readPendingCrashInfo() };
|
|
16
|
+
}
|
|
17
|
+
async clearPendingCrashInfo() {
|
|
18
|
+
this.removePendingCrashInfo();
|
|
19
|
+
this.didDispatchPendingEvent = false;
|
|
20
|
+
}
|
|
21
|
+
async simulateCrashRecovery() {
|
|
22
|
+
const value = this.buildCrashInfo();
|
|
23
|
+
this.writePendingCrashInfo(value);
|
|
24
|
+
this.didDispatchPendingEvent = false;
|
|
25
|
+
this.flushPendingCrashEvent();
|
|
26
|
+
return { value };
|
|
27
|
+
}
|
|
28
|
+
async addListener(eventName, listenerFunc) {
|
|
29
|
+
const handle = await super.addListener(eventName, listenerFunc);
|
|
30
|
+
if (eventName === WebViewCrashWeb.eventName) {
|
|
31
|
+
this.flushPendingCrashEvent();
|
|
32
|
+
}
|
|
33
|
+
return handle;
|
|
34
|
+
}
|
|
35
|
+
flushPendingCrashEvent() {
|
|
36
|
+
if (this.didDispatchPendingEvent) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const value = this.readPendingCrashInfo();
|
|
40
|
+
if (!value) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
this.didDispatchPendingEvent = true;
|
|
44
|
+
this.notifyListeners(WebViewCrashWeb.eventName, value);
|
|
45
|
+
}
|
|
46
|
+
buildCrashInfo() {
|
|
47
|
+
var _a;
|
|
48
|
+
const timestamp = Date.now();
|
|
49
|
+
return {
|
|
50
|
+
platform: 'web',
|
|
51
|
+
timestamp,
|
|
52
|
+
timestampISO: new Date(timestamp).toISOString(),
|
|
53
|
+
reason: 'simulated',
|
|
54
|
+
url: (_a = globalThis.location) === null || _a === void 0 ? void 0 : _a.href,
|
|
55
|
+
appState: 'active',
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
readPendingCrashInfo() {
|
|
59
|
+
var _a;
|
|
60
|
+
const raw = (_a = globalThis.localStorage) === null || _a === void 0 ? void 0 : _a.getItem(WebViewCrashWeb.storageKey);
|
|
61
|
+
if (!raw) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
return JSON.parse(raw);
|
|
66
|
+
}
|
|
67
|
+
catch (_b) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
writePendingCrashInfo(value) {
|
|
72
|
+
var _a;
|
|
73
|
+
(_a = globalThis.localStorage) === null || _a === void 0 ? void 0 : _a.setItem(WebViewCrashWeb.storageKey, JSON.stringify(value));
|
|
74
|
+
}
|
|
75
|
+
removePendingCrashInfo() {
|
|
76
|
+
var _a;
|
|
77
|
+
(_a = globalThis.localStorage) === null || _a === void 0 ? void 0 : _a.removeItem(WebViewCrashWeb.storageKey);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
WebViewCrashWeb.eventName = 'webViewRestoredAfterCrash';
|
|
81
|
+
WebViewCrashWeb.storageKey = 'capgo.webview-crash.pending';
|
|
82
|
+
|
|
83
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
84
|
+
__proto__: null,
|
|
85
|
+
WebViewCrashWeb: WebViewCrashWeb
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
exports.WebViewCrash = WebViewCrash;
|
|
89
|
+
//# sourceMappingURL=plugin.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst WebViewCrash = registerPlugin('WebViewCrash', {\n web: () => import('./web').then((m) => new m.WebViewCrashWeb()),\n});\nexport * from './definitions';\nexport { WebViewCrash };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class WebViewCrashWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.didDispatchPendingEvent = false;\n }\n async getPendingCrashInfo() {\n return { value: this.readPendingCrashInfo() };\n }\n async clearPendingCrashInfo() {\n this.removePendingCrashInfo();\n this.didDispatchPendingEvent = false;\n }\n async simulateCrashRecovery() {\n const value = this.buildCrashInfo();\n this.writePendingCrashInfo(value);\n this.didDispatchPendingEvent = false;\n this.flushPendingCrashEvent();\n return { value };\n }\n async addListener(eventName, listenerFunc) {\n const handle = await super.addListener(eventName, listenerFunc);\n if (eventName === WebViewCrashWeb.eventName) {\n this.flushPendingCrashEvent();\n }\n return handle;\n }\n flushPendingCrashEvent() {\n if (this.didDispatchPendingEvent) {\n return;\n }\n const value = this.readPendingCrashInfo();\n if (!value) {\n return;\n }\n this.didDispatchPendingEvent = true;\n this.notifyListeners(WebViewCrashWeb.eventName, value);\n }\n buildCrashInfo() {\n var _a;\n const timestamp = Date.now();\n return {\n platform: 'web',\n timestamp,\n timestampISO: new Date(timestamp).toISOString(),\n reason: 'simulated',\n url: (_a = globalThis.location) === null || _a === void 0 ? void 0 : _a.href,\n appState: 'active',\n };\n }\n readPendingCrashInfo() {\n var _a;\n const raw = (_a = globalThis.localStorage) === null || _a === void 0 ? void 0 : _a.getItem(WebViewCrashWeb.storageKey);\n if (!raw) {\n return null;\n }\n try {\n return JSON.parse(raw);\n }\n catch (_b) {\n return null;\n }\n }\n writePendingCrashInfo(value) {\n var _a;\n (_a = globalThis.localStorage) === null || _a === void 0 ? void 0 : _a.setItem(WebViewCrashWeb.storageKey, JSON.stringify(value));\n }\n removePendingCrashInfo() {\n var _a;\n (_a = globalThis.localStorage) === null || _a === void 0 ? void 0 : _a.removeItem(WebViewCrashWeb.storageKey);\n }\n}\nWebViewCrashWeb.eventName = 'webViewRestoredAfterCrash';\nWebViewCrashWeb.storageKey = 'capgo.webview-crash.pending';\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
var capacitorWebViewCrash = (function (exports, core) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const WebViewCrash = core.registerPlugin('WebViewCrash', {
|
|
5
|
+
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.WebViewCrashWeb()),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
class WebViewCrashWeb extends core.WebPlugin {
|
|
9
|
+
constructor() {
|
|
10
|
+
super(...arguments);
|
|
11
|
+
this.didDispatchPendingEvent = false;
|
|
12
|
+
}
|
|
13
|
+
async getPendingCrashInfo() {
|
|
14
|
+
return { value: this.readPendingCrashInfo() };
|
|
15
|
+
}
|
|
16
|
+
async clearPendingCrashInfo() {
|
|
17
|
+
this.removePendingCrashInfo();
|
|
18
|
+
this.didDispatchPendingEvent = false;
|
|
19
|
+
}
|
|
20
|
+
async simulateCrashRecovery() {
|
|
21
|
+
const value = this.buildCrashInfo();
|
|
22
|
+
this.writePendingCrashInfo(value);
|
|
23
|
+
this.didDispatchPendingEvent = false;
|
|
24
|
+
this.flushPendingCrashEvent();
|
|
25
|
+
return { value };
|
|
26
|
+
}
|
|
27
|
+
async addListener(eventName, listenerFunc) {
|
|
28
|
+
const handle = await super.addListener(eventName, listenerFunc);
|
|
29
|
+
if (eventName === WebViewCrashWeb.eventName) {
|
|
30
|
+
this.flushPendingCrashEvent();
|
|
31
|
+
}
|
|
32
|
+
return handle;
|
|
33
|
+
}
|
|
34
|
+
flushPendingCrashEvent() {
|
|
35
|
+
if (this.didDispatchPendingEvent) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const value = this.readPendingCrashInfo();
|
|
39
|
+
if (!value) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
this.didDispatchPendingEvent = true;
|
|
43
|
+
this.notifyListeners(WebViewCrashWeb.eventName, value);
|
|
44
|
+
}
|
|
45
|
+
buildCrashInfo() {
|
|
46
|
+
var _a;
|
|
47
|
+
const timestamp = Date.now();
|
|
48
|
+
return {
|
|
49
|
+
platform: 'web',
|
|
50
|
+
timestamp,
|
|
51
|
+
timestampISO: new Date(timestamp).toISOString(),
|
|
52
|
+
reason: 'simulated',
|
|
53
|
+
url: (_a = globalThis.location) === null || _a === void 0 ? void 0 : _a.href,
|
|
54
|
+
appState: 'active',
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
readPendingCrashInfo() {
|
|
58
|
+
var _a;
|
|
59
|
+
const raw = (_a = globalThis.localStorage) === null || _a === void 0 ? void 0 : _a.getItem(WebViewCrashWeb.storageKey);
|
|
60
|
+
if (!raw) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
return JSON.parse(raw);
|
|
65
|
+
}
|
|
66
|
+
catch (_b) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
writePendingCrashInfo(value) {
|
|
71
|
+
var _a;
|
|
72
|
+
(_a = globalThis.localStorage) === null || _a === void 0 ? void 0 : _a.setItem(WebViewCrashWeb.storageKey, JSON.stringify(value));
|
|
73
|
+
}
|
|
74
|
+
removePendingCrashInfo() {
|
|
75
|
+
var _a;
|
|
76
|
+
(_a = globalThis.localStorage) === null || _a === void 0 ? void 0 : _a.removeItem(WebViewCrashWeb.storageKey);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
WebViewCrashWeb.eventName = 'webViewRestoredAfterCrash';
|
|
80
|
+
WebViewCrashWeb.storageKey = 'capgo.webview-crash.pending';
|
|
81
|
+
|
|
82
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
83
|
+
__proto__: null,
|
|
84
|
+
WebViewCrashWeb: WebViewCrashWeb
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
exports.WebViewCrash = WebViewCrash;
|
|
88
|
+
|
|
89
|
+
return exports;
|
|
90
|
+
|
|
91
|
+
})({}, capacitorExports);
|
|
92
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst WebViewCrash = registerPlugin('WebViewCrash', {\n web: () => import('./web').then((m) => new m.WebViewCrashWeb()),\n});\nexport * from './definitions';\nexport { WebViewCrash };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class WebViewCrashWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.didDispatchPendingEvent = false;\n }\n async getPendingCrashInfo() {\n return { value: this.readPendingCrashInfo() };\n }\n async clearPendingCrashInfo() {\n this.removePendingCrashInfo();\n this.didDispatchPendingEvent = false;\n }\n async simulateCrashRecovery() {\n const value = this.buildCrashInfo();\n this.writePendingCrashInfo(value);\n this.didDispatchPendingEvent = false;\n this.flushPendingCrashEvent();\n return { value };\n }\n async addListener(eventName, listenerFunc) {\n const handle = await super.addListener(eventName, listenerFunc);\n if (eventName === WebViewCrashWeb.eventName) {\n this.flushPendingCrashEvent();\n }\n return handle;\n }\n flushPendingCrashEvent() {\n if (this.didDispatchPendingEvent) {\n return;\n }\n const value = this.readPendingCrashInfo();\n if (!value) {\n return;\n }\n this.didDispatchPendingEvent = true;\n this.notifyListeners(WebViewCrashWeb.eventName, value);\n }\n buildCrashInfo() {\n var _a;\n const timestamp = Date.now();\n return {\n platform: 'web',\n timestamp,\n timestampISO: new Date(timestamp).toISOString(),\n reason: 'simulated',\n url: (_a = globalThis.location) === null || _a === void 0 ? void 0 : _a.href,\n appState: 'active',\n };\n }\n readPendingCrashInfo() {\n var _a;\n const raw = (_a = globalThis.localStorage) === null || _a === void 0 ? void 0 : _a.getItem(WebViewCrashWeb.storageKey);\n if (!raw) {\n return null;\n }\n try {\n return JSON.parse(raw);\n }\n catch (_b) {\n return null;\n }\n }\n writePendingCrashInfo(value) {\n var _a;\n (_a = globalThis.localStorage) === null || _a === void 0 ? void 0 : _a.setItem(WebViewCrashWeb.storageKey, JSON.stringify(value));\n }\n removePendingCrashInfo() {\n var _a;\n (_a = globalThis.localStorage) === null || _a === void 0 ? void 0 : _a.removeItem(WebViewCrashWeb.storageKey);\n }\n}\nWebViewCrashWeb.eventName = 'webViewRestoredAfterCrash';\nWebViewCrashWeb.storageKey = 'capgo.webview-crash.pending';\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import Capacitor
|
|
2
|
+
import Foundation
|
|
3
|
+
import ObjectiveC.runtime
|
|
4
|
+
import UIKit
|
|
5
|
+
import WebKit
|
|
6
|
+
|
|
7
|
+
enum WebViewCrashBridge {
|
|
8
|
+
static let eventName = "webViewRestoredAfterCrash"
|
|
9
|
+
|
|
10
|
+
static func pendingResult(_ value: [String: Any]?) -> [String: Any] {
|
|
11
|
+
[
|
|
12
|
+
"value": value ?? NSNull()
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
enum WebViewCrashStore {
|
|
18
|
+
private static let pendingCrashKey = "CapgoWebViewCrash.pendingInfo"
|
|
19
|
+
private static let timestampFormatter = ISO8601DateFormatter()
|
|
20
|
+
|
|
21
|
+
static func read() -> [String: Any]? {
|
|
22
|
+
UserDefaults.standard.dictionary(forKey: pendingCrashKey)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static func write(_ value: [String: Any]) {
|
|
26
|
+
UserDefaults.standard.set(value, forKey: pendingCrashKey)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
static func clear() {
|
|
30
|
+
UserDefaults.standard.removeObject(forKey: pendingCrashKey)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static func buildCrashInfo(platform: String, reason: String, url: String?, appState: String? = nil) -> [String: Any] {
|
|
34
|
+
let date = Date()
|
|
35
|
+
let timestamp = Int(date.timeIntervalSince1970 * 1000)
|
|
36
|
+
var value: [String: Any] = [
|
|
37
|
+
"platform": platform,
|
|
38
|
+
"timestamp": timestamp,
|
|
39
|
+
"timestampISO": timestampFormatter.string(from: date),
|
|
40
|
+
"reason": reason
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
if let url, !url.isEmpty {
|
|
44
|
+
value["url"] = url
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if let appState {
|
|
48
|
+
value["appState"] = appState
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return value
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
enum WebViewCrashSwizzler {
|
|
56
|
+
private static var didInstall = false
|
|
57
|
+
|
|
58
|
+
static func installIfNeeded() {
|
|
59
|
+
guard !didInstall else {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
let originalSelector = #selector(WebViewDelegationHandler.webViewWebContentProcessDidTerminate(_:))
|
|
64
|
+
let swizzledSelector = #selector(WebViewDelegationHandler.capgo_webViewCrash_webViewWebContentProcessDidTerminate(_:))
|
|
65
|
+
|
|
66
|
+
guard
|
|
67
|
+
let originalMethod = class_getInstanceMethod(WebViewDelegationHandler.self, originalSelector),
|
|
68
|
+
let swizzledMethod = class_getInstanceMethod(WebViewDelegationHandler.self, swizzledSelector)
|
|
69
|
+
else {
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
method_exchangeImplementations(originalMethod, swizzledMethod)
|
|
74
|
+
didInstall = true
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private extension WebViewDelegationHandler {
|
|
79
|
+
@objc func capgo_webViewCrash_webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
|
|
80
|
+
let crashInfo = WebViewCrashStore.buildCrashInfo(
|
|
81
|
+
platform: "ios",
|
|
82
|
+
reason: "webContentProcessDidTerminate",
|
|
83
|
+
url: webView.url?.absoluteString,
|
|
84
|
+
appState: UIApplication.shared.applicationState.capgoWebViewCrashValue
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
WebViewCrashStore.write(crashInfo)
|
|
88
|
+
capgo_webViewCrash_webViewWebContentProcessDidTerminate(webView)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
extension UIApplication.State {
|
|
93
|
+
var capgoWebViewCrashValue: String {
|
|
94
|
+
switch self {
|
|
95
|
+
case .active:
|
|
96
|
+
return "active"
|
|
97
|
+
case .inactive:
|
|
98
|
+
return "inactive"
|
|
99
|
+
case .background:
|
|
100
|
+
return "background"
|
|
101
|
+
@unknown default:
|
|
102
|
+
return "unknown"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import Capacitor
|
|
2
|
+
import Foundation
|
|
3
|
+
import UIKit
|
|
4
|
+
|
|
5
|
+
@objc(WebViewCrashPlugin)
|
|
6
|
+
public class WebViewCrashPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
7
|
+
public let identifier = "WebViewCrashPlugin"
|
|
8
|
+
public let jsName = "WebViewCrash"
|
|
9
|
+
public let pluginMethods: [CAPPluginMethod] = [
|
|
10
|
+
CAPPluginMethod(name: "getPendingCrashInfo", returnType: CAPPluginReturnPromise),
|
|
11
|
+
CAPPluginMethod(name: "clearPendingCrashInfo", returnType: CAPPluginReturnPromise),
|
|
12
|
+
CAPPluginMethod(name: "simulateCrashRecovery", returnType: CAPPluginReturnPromise)
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
private var didDispatchPendingEvent = false
|
|
16
|
+
|
|
17
|
+
override public func load() {
|
|
18
|
+
WebViewCrashSwizzler.installIfNeeded()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@objc override public func addListener(_ call: CAPPluginCall) {
|
|
22
|
+
super.addListener(call)
|
|
23
|
+
|
|
24
|
+
if call.getString("eventName") == WebViewCrashBridge.eventName {
|
|
25
|
+
dispatchPendingCrashIfNeeded()
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@objc func getPendingCrashInfo(_ call: CAPPluginCall) {
|
|
30
|
+
call.resolve(WebViewCrashBridge.pendingResult(WebViewCrashStore.read()))
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@objc func clearPendingCrashInfo(_ call: CAPPluginCall) {
|
|
34
|
+
WebViewCrashStore.clear()
|
|
35
|
+
didDispatchPendingEvent = false
|
|
36
|
+
call.resolve()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@objc func simulateCrashRecovery(_ call: CAPPluginCall) {
|
|
40
|
+
let crashInfo = WebViewCrashStore.buildCrashInfo(
|
|
41
|
+
platform: "ios",
|
|
42
|
+
reason: "simulated",
|
|
43
|
+
url: bridge?.webView?.url?.absoluteString,
|
|
44
|
+
appState: UIApplication.shared.applicationState.capgoWebViewCrashValue
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
WebViewCrashStore.write(crashInfo)
|
|
48
|
+
didDispatchPendingEvent = false
|
|
49
|
+
dispatchPendingCrashIfNeeded()
|
|
50
|
+
|
|
51
|
+
call.resolve(WebViewCrashBridge.pendingResult(crashInfo))
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private func dispatchPendingCrashIfNeeded() {
|
|
55
|
+
guard !didDispatchPendingEvent, let crashInfo = WebViewCrashStore.read() else {
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
didDispatchPendingEvent = true
|
|
60
|
+
notifyListeners(WebViewCrashBridge.eventName, data: crashInfo)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import XCTest
|
|
2
|
+
@testable import WebViewCrashPlugin
|
|
3
|
+
|
|
4
|
+
final class WebViewCrashPluginTests: XCTestCase {
|
|
5
|
+
func testPluginMetadata() {
|
|
6
|
+
let plugin = WebViewCrashPlugin()
|
|
7
|
+
|
|
8
|
+
XCTAssertEqual(plugin.identifier, "WebViewCrashPlugin")
|
|
9
|
+
XCTAssertEqual(plugin.jsName, "WebViewCrash")
|
|
10
|
+
XCTAssertEqual(plugin.pluginMethods.count, 3)
|
|
11
|
+
}
|
|
12
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@capgo/capacitor-webview-crash",
|
|
3
|
+
"version": "8.0.1",
|
|
4
|
+
"description": "Capacitor plugin for detecting WebView crash recovery and informing the next JS runtime.",
|
|
5
|
+
"main": "dist/plugin.cjs.js",
|
|
6
|
+
"module": "dist/esm/index.js",
|
|
7
|
+
"types": "dist/esm/index.d.ts",
|
|
8
|
+
"unpkg": "dist/plugin.js",
|
|
9
|
+
"files": [
|
|
10
|
+
"android/src/main/",
|
|
11
|
+
"android/build.gradle",
|
|
12
|
+
"dist/",
|
|
13
|
+
"ios/Sources",
|
|
14
|
+
"ios/Tests",
|
|
15
|
+
"Package.swift",
|
|
16
|
+
"CapgoCapacitorWebViewCrash.podspec"
|
|
17
|
+
],
|
|
18
|
+
"author": "Martin Donadieu <martin@capgo.app>",
|
|
19
|
+
"license": "MPL-2.0",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/Cap-go/capacitor-webview-crash.git"
|
|
23
|
+
},
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/Cap-go/capacitor-webview-crash/issues"
|
|
26
|
+
},
|
|
27
|
+
"homepage": "https://capgo.app/docs/plugins/webview-crash/",
|
|
28
|
+
"keywords": [
|
|
29
|
+
"capacitor",
|
|
30
|
+
"plugin",
|
|
31
|
+
"webview-crash",
|
|
32
|
+
"crash-recovery",
|
|
33
|
+
"ios",
|
|
34
|
+
"android",
|
|
35
|
+
"capgo"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"verify": "bun run verify:ios && bun run verify:android && bun run verify:web",
|
|
39
|
+
"verify:ios": "xcodebuild -scheme CapgoCapacitorWebViewCrash -destination generic/platform=iOS",
|
|
40
|
+
"verify:android": "cd android && ./gradlew clean build test && cd ..",
|
|
41
|
+
"verify:web": "bun run build && bun test",
|
|
42
|
+
"test": "bun test",
|
|
43
|
+
"lint": "bun run eslint && bun run prettier -- --check && bun run swiftlint -- lint",
|
|
44
|
+
"fmt": "bun run eslint -- --fix && bun run prettier -- --write && bun run swiftlint -- --fix --format",
|
|
45
|
+
"eslint": "eslint . --ext .ts",
|
|
46
|
+
"prettier": "prettier-pretty-check \"**/*.{css,html,ts,js,java,json,md}\" --plugin=prettier-plugin-java",
|
|
47
|
+
"swiftlint": "node-swiftlint",
|
|
48
|
+
"docgen": "docgen --api WebViewCrashPlugin --output-readme README.md --output-json dist/docs.json",
|
|
49
|
+
"build": "bun run clean && bun run docgen && tsc && rollup -c rollup.config.mjs",
|
|
50
|
+
"clean": "rimraf ./dist",
|
|
51
|
+
"watch": "tsc --watch",
|
|
52
|
+
"prepublishOnly": "bun run build",
|
|
53
|
+
"check:wiring": "node scripts/check-capacitor-plugin-wiring.mjs"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@capacitor/android": "^8.0.0",
|
|
57
|
+
"@capacitor/cli": "^8.0.0",
|
|
58
|
+
"@capacitor/core": "^8.0.0",
|
|
59
|
+
"@capacitor/docgen": "^0.3.1",
|
|
60
|
+
"@capacitor/ios": "^8.0.0",
|
|
61
|
+
"@ionic/eslint-config": "^0.4.0",
|
|
62
|
+
"@ionic/prettier-config": "^4.0.0",
|
|
63
|
+
"@ionic/swiftlint-config": "^2.0.0",
|
|
64
|
+
"@types/node": "^24.10.1",
|
|
65
|
+
"eslint": "^8.57.1",
|
|
66
|
+
"eslint-plugin-import": "^2.31.0",
|
|
67
|
+
"husky": "^9.1.7",
|
|
68
|
+
"prettier": "^3.6.2",
|
|
69
|
+
"prettier-pretty-check": "^0.2.0",
|
|
70
|
+
"prettier-plugin-java": "^2.7.7",
|
|
71
|
+
"rimraf": "^6.1.0",
|
|
72
|
+
"rollup": "^4.53.2",
|
|
73
|
+
"swiftlint": "^2.0.0",
|
|
74
|
+
"typescript": "^5.9.3"
|
|
75
|
+
},
|
|
76
|
+
"peerDependencies": {
|
|
77
|
+
"@capacitor/core": ">=8.0.0"
|
|
78
|
+
},
|
|
79
|
+
"prettier": "@ionic/prettier-config",
|
|
80
|
+
"swiftlint": "@ionic/swiftlint-config",
|
|
81
|
+
"eslintConfig": {
|
|
82
|
+
"extends": "@ionic/eslint-config/recommended"
|
|
83
|
+
},
|
|
84
|
+
"capacitor": {
|
|
85
|
+
"ios": {
|
|
86
|
+
"src": "ios"
|
|
87
|
+
},
|
|
88
|
+
"android": {
|
|
89
|
+
"src": "android"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|