@capacitor-plus/ios 8.5.3 → 8.6.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.
|
@@ -213,6 +213,7 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
|
|
|
213
213
|
super.init()
|
|
214
214
|
|
|
215
215
|
self.webViewDelegationHandler.bridge = self
|
|
216
|
+
self.webViewAssetHandler.setConfiguration(configuration)
|
|
216
217
|
|
|
217
218
|
exportCoreJS(localUrl: configuration.localURL.absoluteString)
|
|
218
219
|
registerPlugins()
|
|
@@ -272,19 +273,35 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
|
|
|
272
273
|
self?.triggerDocumentJSEvent(eventName: "pause")
|
|
273
274
|
})
|
|
274
275
|
observers.append(NotificationCenter.default.addObserver(forName: UIScene.willEnterForegroundNotification, object: nil, queue: OperationQueue.main) { [weak self] notification in
|
|
275
|
-
|
|
276
|
-
self?.triggerDocumentJSEvent(eventName: "resume")
|
|
277
|
-
}
|
|
278
|
-
|
|
276
|
+
self?.triggerSceneLifecycleJSEvent("resume", for: notification)
|
|
279
277
|
})
|
|
280
278
|
observers.append(NotificationCenter.default.addObserver(forName: UIScene.didEnterBackgroundNotification, object: nil, queue: OperationQueue.main) { [weak self] notification in
|
|
281
|
-
|
|
282
|
-
self?.triggerDocumentJSEvent(eventName: "pause")
|
|
283
|
-
}
|
|
279
|
+
self?.triggerSceneLifecycleJSEvent("pause", for: notification)
|
|
284
280
|
})
|
|
285
281
|
}
|
|
286
282
|
}
|
|
287
283
|
|
|
284
|
+
/**
|
|
285
|
+
Forward a scene lifecycle transition to the page as a document event, but only once
|
|
286
|
+
the page exists to receive it.
|
|
287
|
+
|
|
288
|
+
On a cold start `UIScene.willEnterForegroundNotification` is posted while the initial
|
|
289
|
+
load is still in flight, before `window.Capacitor` has been defined. Evaluating
|
|
290
|
+
`triggerEvent` at that point throws inside the web view and surfaces as a
|
|
291
|
+
"JS Eval error" in the log. The same happens when the web content process was
|
|
292
|
+
terminated and the page is being reloaded. In both cases the page is about to load
|
|
293
|
+
from scratch, so there is nothing for it to resume or pause; the event is dropped
|
|
294
|
+
rather than deferred, because a "resume" delivered right after a fresh load would
|
|
295
|
+
make the page react to a transition it never went through.
|
|
296
|
+
*/
|
|
297
|
+
private func triggerSceneLifecycleJSEvent(_ eventName: String, for notification: Notification) {
|
|
298
|
+
guard let scene = notification.object as? UIWindowScene,
|
|
299
|
+
scene === viewController?.view.window?.windowScene else {
|
|
300
|
+
return
|
|
301
|
+
}
|
|
302
|
+
eval(js: "window.Capacitor?.triggerEvent && window.Capacitor.triggerEvent('\(eventName)', 'document')")
|
|
303
|
+
}
|
|
304
|
+
|
|
288
305
|
/**
|
|
289
306
|
Export the core Cordova JS runtime
|
|
290
307
|
*/
|
|
@@ -6,6 +6,7 @@ import UniformTypeIdentifiers
|
|
|
6
6
|
open class WebViewAssetHandler: NSObject, WKURLSchemeHandler {
|
|
7
7
|
private var router: Router
|
|
8
8
|
private var serverUrl: URL?
|
|
9
|
+
private var configuration: InstanceConfiguration?
|
|
9
10
|
|
|
10
11
|
public init(router: Router) {
|
|
11
12
|
self.router = router
|
|
@@ -20,6 +21,10 @@ open class WebViewAssetHandler: NSObject, WKURLSchemeHandler {
|
|
|
20
21
|
self.serverUrl = serverUrl
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
open func setConfiguration(_ configuration: InstanceConfiguration?) {
|
|
25
|
+
self.configuration = configuration
|
|
26
|
+
}
|
|
27
|
+
|
|
23
28
|
private func isUsingLiveReload(_ localUrl: URL) -> Bool {
|
|
24
29
|
return self.serverUrl != nil && self.serverUrl?.scheme != localUrl.scheme
|
|
25
30
|
}
|
|
@@ -31,7 +36,13 @@ open class WebViewAssetHandler: NSObject, WKURLSchemeHandler {
|
|
|
31
36
|
let localUrl = URL.init(string: url.absoluteString)!
|
|
32
37
|
|
|
33
38
|
if url.path.starts(with: CapacitorBridge.httpInterceptorStartIdentifier) {
|
|
34
|
-
|
|
39
|
+
// Only serve the proxy when CapacitorHttp is on. A scheme task can't tell a document from
|
|
40
|
+
// a subresource, so keeping documents out relies on the check in decidePolicyFor.
|
|
41
|
+
if configuration?.getPluginConfig("CapacitorHttp").getBoolean("enabled", false) == true {
|
|
42
|
+
handleCapacitorHttpRequest(urlSchemeTask, localUrl, false)
|
|
43
|
+
} else {
|
|
44
|
+
urlSchemeTask.didFailWithError(URLError(.unsupportedURL))
|
|
45
|
+
}
|
|
35
46
|
return
|
|
36
47
|
}
|
|
37
48
|
|
|
@@ -152,12 +163,13 @@ open class WebViewAssetHandler: NSObject, WKURLSchemeHandler {
|
|
|
152
163
|
let existingHeaders = response.allHeaderFields
|
|
153
164
|
var newHeaders: [AnyHashable: Any] = [:]
|
|
154
165
|
|
|
166
|
+
// Nothing should render this. If anything does, sandbox keeps it inert.
|
|
167
|
+
newHeaders["Content-Security-Policy"] = "sandbox; frame-ancestors 'none'"
|
|
168
|
+
|
|
155
169
|
// if using live reload, then set CORS headers
|
|
156
170
|
if self.isUsingLiveReload(url) {
|
|
157
|
-
newHeaders =
|
|
158
|
-
|
|
159
|
-
"Access-Control-Allow-Methods": "GET, HEAD, OPTIONS, TRACE"
|
|
160
|
-
]
|
|
171
|
+
newHeaders["Access-Control-Allow-Origin"] = self.serverUrl?.absoluteString ?? ""
|
|
172
|
+
newHeaders["Access-Control-Allow-Methods"] = "GET, HEAD, OPTIONS, TRACE"
|
|
161
173
|
}
|
|
162
174
|
|
|
163
175
|
if let mergedHeaders = existingHeaders.merging(newHeaders, uniquingKeysWith: { (_, newHeaders) in newHeaders }) as? [String: String] {
|
|
@@ -64,6 +64,35 @@ open class WebViewDelegationHandler: NSObject, WKNavigationDelegate, WKUIDelegat
|
|
|
64
64
|
decisionHandler(.grant)
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
private static func effectivePort(for url: URL) -> Int? {
|
|
68
|
+
if let port = url.port {
|
|
69
|
+
return port
|
|
70
|
+
}
|
|
71
|
+
switch url.scheme?.lowercased() {
|
|
72
|
+
case "https":
|
|
73
|
+
return 443
|
|
74
|
+
case "http":
|
|
75
|
+
return 80
|
|
76
|
+
default:
|
|
77
|
+
return nil
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private static func matchesOrigin(_ url: URL, _ origin: URL) -> Bool {
|
|
82
|
+
guard url.scheme == origin.scheme, url.host == origin.host else {
|
|
83
|
+
return false
|
|
84
|
+
}
|
|
85
|
+
return effectivePort(for: url) == effectivePort(for: origin)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/// Test seam: avoids subclassing `WKNavigationAction` in unit tests.
|
|
89
|
+
static func shouldBlockHttpInterceptorNavigation(for url: URL, serverURL: URL, localURL: URL) -> Bool {
|
|
90
|
+
guard url.path.starts(with: CapacitorBridge.httpInterceptorStartIdentifier) else {
|
|
91
|
+
return false
|
|
92
|
+
}
|
|
93
|
+
return matchesOrigin(url, serverURL) || matchesOrigin(url, localURL)
|
|
94
|
+
}
|
|
95
|
+
|
|
67
96
|
open func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
|
|
68
97
|
// post a notification for any listeners
|
|
69
98
|
NotificationCenter.default.post(name: .capacitorDecidePolicyForNavigationAction, object: navigationAction)
|
|
@@ -74,6 +103,16 @@ open class WebViewDelegationHandler: NSObject, WKNavigationDelegate, WKUIDelegat
|
|
|
74
103
|
return
|
|
75
104
|
}
|
|
76
105
|
|
|
106
|
+
// The proxy returns a remote body at the app origin, so block it before plugins can allow it.
|
|
107
|
+
if Self.shouldBlockHttpInterceptorNavigation(
|
|
108
|
+
for: navURL,
|
|
109
|
+
serverURL: bridge.config.serverURL,
|
|
110
|
+
localURL: bridge.config.localURL
|
|
111
|
+
) {
|
|
112
|
+
decisionHandler(.cancel)
|
|
113
|
+
return
|
|
114
|
+
}
|
|
115
|
+
|
|
77
116
|
// first, give plugins the chance to handle the decision
|
|
78
117
|
for pluginObject in bridge.plugins {
|
|
79
118
|
let plugin = pluginObject.value
|
|
@@ -417,12 +417,6 @@ var nativeBridge = (function (exports) {
|
|
|
417
417
|
}
|
|
418
418
|
};
|
|
419
419
|
const platform = getPlatformId(win);
|
|
420
|
-
if (platform == 'android' && typeof win.CapacitorSystemBarsAndroidInterface !== 'undefined') {
|
|
421
|
-
// add DOM ready listener for System Bars
|
|
422
|
-
document.addEventListener('DOMContentLoaded', function () {
|
|
423
|
-
win.CapacitorSystemBarsAndroidInterface.onDOMReady();
|
|
424
|
-
});
|
|
425
|
-
}
|
|
426
420
|
if (platform == 'android' || platform == 'ios') {
|
|
427
421
|
// patch document.cookie on Android/iOS
|
|
428
422
|
win.CapacitorCookiesDescriptor =
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capacitor-plus/ios",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.6.1",
|
|
4
4
|
"description": "Capacitor+: Enhanced Capacitor with automated upstream sync - Cross-platform apps with JavaScript and the web",
|
|
5
5
|
"homepage": "https://capgo.app/docs/plugins/capacitor-plus/",
|
|
6
6
|
"author": "Capgo Team <support@capgo.app> (https://capgo.app)",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"xc:build:CapacitorCordova": "cd CapacitorCordova && xcodebuild && cd .."
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
|
-
"@capacitor-plus/core": "^8.
|
|
29
|
-
"@capacitor/core": "^8.
|
|
28
|
+
"@capacitor-plus/core": "^8.6.0",
|
|
29
|
+
"@capacitor/core": "^8.6.0"
|
|
30
30
|
},
|
|
31
31
|
"publishConfig": {
|
|
32
32
|
"access": "public"
|