@capacitor-plus/ios 8.5.3 → 8.6.2

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
- if let scene = notification.object as? UIWindowScene, scene === self?.viewController?.view.window?.windowScene {
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
- if let scene = notification.object as? UIWindowScene, scene === self?.viewController?.view.window?.windowScene {
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
- handleCapacitorHttpRequest(urlSchemeTask, localUrl, false)
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
- "Access-Control-Allow-Origin": self.serverUrl?.absoluteString ?? "",
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.5.3",
3
+ "version": "8.6.2",
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.5.0",
29
- "@capacitor/core": "^8.5.0"
28
+ "@capacitor-plus/core": "^8.6.0",
29
+ "@capacitor/core": "^8.6.0"
30
30
  },
31
31
  "publishConfig": {
32
32
  "access": "public"