@capacitor/ios 8.4.3-nightly-20260730T154011.0 → 8.4.3

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.
@@ -4,7 +4,7 @@ import Foundation
4
4
  public class ApplicationDelegateProxy: NSObject, UIApplicationDelegate {
5
5
  public static let shared = ApplicationDelegateProxy()
6
6
 
7
- public internal(set) var lastURL: URL?
7
+ public private(set) var lastURL: URL?
8
8
 
9
9
  public func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
10
10
  NotificationCenter.default.post(name: .capacitorOpenURL, object: [
@@ -18,10 +18,6 @@ extension Notification.Name {
18
18
  public static let capacitorStatusBarTapped = Notification.Name(rawValue: "CapacitorStatusBarTappedNotification")
19
19
  public static let capacitorViewDidAppear = Notification.Name(rawValue: "CapacitorViewDidAppear")
20
20
  public static let capacitorViewWillTransition = Notification.Name(rawValue: "CapacitorViewWillTransition")
21
- public static let capacitorSceneWillConnect = Notification.Name(rawValue: "CapacitorSceneWillConnect")
22
- public static let capacitorSceneOpenURL = Notification.Name(rawValue: "CapacitorSceneOpenURLNotification")
23
- public static let capacitorSceneOpenUniversalLink =
24
- Notification.Name(rawValue: "CapacitorSceneOpenUniversalLinkNotification")
25
21
  }
26
22
 
27
23
  @objc extension NSNotification {
@@ -34,9 +30,6 @@ extension Notification.Name {
34
30
  public static let capacitorStatusBarTapped = Notification.Name.capacitorStatusBarTapped
35
31
  public static let capacitorViewDidAppear = Notification.Name.capacitorViewDidAppear
36
32
  public static let capacitorViewWillTransition = Notification.Name.capacitorViewWillTransition
37
- public static let capacitorSceneWillConnect = Notification.Name.capacitorSceneWillConnect
38
- public static let capacitorSceneOpenURL = Notification.Name.capacitorSceneOpenURL
39
- public static let capacitorSceneOpenUniversalLink = Notification.Name.capacitorSceneOpenUniversalLink
40
33
  }
41
34
 
42
35
  /**
@@ -93,6 +93,10 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
93
93
  }
94
94
  }
95
95
  }
96
+ @available(*, deprecated, message: "obsolete")
97
+ var tmpWindow: UIWindow?
98
+ @available(*, deprecated, message: "obsolete")
99
+ static let tmpVCAppeared = Notification(name: Notification.Name(rawValue: "tmpViewControllerAppeared"))
96
100
  public static let capacitorSite = "https://capacitorjs.com/"
97
101
  public static let fileStartIdentifier = "/_capacitor_file_"
98
102
  public static let httpInterceptorStartIdentifier = "/_capacitor_http_interceptor_"
@@ -213,12 +217,16 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
213
217
  super.init()
214
218
 
215
219
  self.webViewDelegationHandler.bridge = self
220
+ self.webViewAssetHandler.setConfiguration(configuration)
216
221
 
217
222
  exportCoreJS(localUrl: configuration.localURL.absoluteString)
218
223
  registerPlugins()
219
224
  setupCordovaCompatibility()
220
225
  exportMiscJS()
221
226
  canInjectJS = false
227
+ observers.append(NotificationCenter.default.addObserver(forName: type(of: self).tmpVCAppeared.name, object: .none, queue: .none) { [weak self] _ in
228
+ self?.tmpWindow = nil
229
+ })
222
230
 
223
231
  self.setupWebDebugging(configuration: configuration)
224
232
  }
@@ -263,16 +271,11 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
263
271
  exportCordovaJS()
264
272
  registerCordovaPlugins()
265
273
  } else {
266
- observers.append(NotificationCenter.default.addObserver(forName: UIScene.willEnterForegroundNotification, object: nil, queue: OperationQueue.main) { [weak self] notification in
267
- if let scene = notification.object as? UIWindowScene, scene === self?.viewController?.view.window?.windowScene {
268
- self?.triggerDocumentJSEvent(eventName: "resume")
269
- }
270
-
274
+ observers.append(NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: OperationQueue.main) { [weak self] (_) in
275
+ self?.triggerDocumentJSEvent(eventName: "resume")
271
276
  })
272
- observers.append(NotificationCenter.default.addObserver(forName: UIScene.didEnterBackgroundNotification, object: nil, queue: OperationQueue.main) { [weak self] notification in
273
- if let scene = notification.object as? UIWindowScene, scene === self?.viewController?.view.window?.windowScene {
274
- self?.triggerDocumentJSEvent(eventName: "pause")
275
- }
277
+ observers.append(NotificationCenter.default.addObserver(forName: UIApplication.didEnterBackgroundNotification, object: nil, queue: OperationQueue.main) { [weak self] (_) in
278
+ self?.triggerDocumentJSEvent(eventName: "pause")
276
279
  })
277
280
  }
278
281
  }
@@ -0,0 +1,8 @@
1
+ import UIKit
2
+
3
+ internal class TmpViewController: UIViewController {
4
+ override func viewDidAppear(_ animated: Bool) {
5
+ super.viewDidAppear(animated)
6
+ NotificationCenter.default.post(CapacitorBridge.tmpVCAppeared)
7
+ }
8
+ }
@@ -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] {
@@ -74,6 +74,12 @@ open class WebViewDelegationHandler: NSObject, WKNavigationDelegate, WKUIDelegat
74
74
  return
75
75
  }
76
76
 
77
+ // The proxy returns a remote body at the app origin, so block it before plugins can allow it.
78
+ if navURL.path.starts(with: CapacitorBridge.httpInterceptorStartIdentifier) {
79
+ decisionHandler(.cancel)
80
+ return
81
+ }
82
+
77
83
  // first, give plugins the chance to handle the decision
78
84
  for pluginObject in bridge.plugins {
79
85
  let plugin = pluginObject.value
@@ -107,7 +113,7 @@ open class WebViewDelegationHandler: NSObject, WKNavigationDelegate, WKUIDelegat
107
113
 
108
114
  if !isApplicationNavigation, toplevelNavigation {
109
115
  // disallow and let the system handle it
110
- if webView.window?.windowScene?.activationState == .foregroundActive {
116
+ if UIApplication.shared.applicationState == .active {
111
117
  UIApplication.shared.open(navURL, options: [:], completionHandler: nil)
112
118
  }
113
119
  decisionHandler(.cancel)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capacitor/ios",
3
- "version": "8.4.3-nightly-20260730T154011.0",
3
+ "version": "8.4.3",
4
4
  "description": "Capacitor: Cross-platform apps with JavaScript and the web",
5
5
  "homepage": "https://capacitorjs.com",
6
6
  "author": "Ionic Team <hi@ionic.io> (https://ionic.io)",
@@ -25,7 +25,7 @@
25
25
  "xc:build:CapacitorCordova": "cd CapacitorCordova && xcodebuild && cd .."
26
26
  },
27
27
  "peerDependencies": {
28
- "@capacitor/core": "^8.4.0-nightly-20260730T154011.0"
28
+ "@capacitor/core": "^8.4.0"
29
29
  },
30
30
  "publishConfig": {
31
31
  "access": "public"
@@ -1,87 +0,0 @@
1
- //
2
- // CAPSceneDelegateProxy.swift
3
- // Capacitor
4
- //
5
- // Created by Joseph Orlando Pender on 6/10/26.
6
- // Copyright © 2026 Drifty Co. All rights reserved.
7
- //
8
-
9
- import Foundation
10
-
11
- @objc(CAPSceneDelegateProxy)
12
- public class SceneDelegateProxy: NSObject, UISceneDelegate {
13
- public static let shared = SceneDelegateProxy()
14
-
15
- public private(set) var lastURL: URL?
16
-
17
- public func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
18
- NotificationCenter.default.post(name: .capacitorSceneWillConnect, object: scene)
19
-
20
- // Plugins haven't loaded yet on a cold start, so notifications posted here are
21
- // missed. Deliver them on the first capacitorViewDidAppear, once plugins are
22
- // registered.
23
- var token: NSObjectProtocol?
24
- token = NotificationCenter.default.addObserver(forName: .capacitorViewDidAppear, object: nil, queue: .main) { _ in
25
- if let token {
26
- NotificationCenter.default.removeObserver(token)
27
- }
28
- if !connectionOptions.urlContexts.isEmpty {
29
- self.scene(scene, openURLContexts: connectionOptions.urlContexts)
30
- }
31
- for userActivity in connectionOptions.userActivities {
32
- self.scene(scene, continue: userActivity)
33
- }
34
- }
35
- }
36
-
37
- public func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
38
- for context in URLContexts {
39
- lastURL = context.url
40
- ApplicationDelegateProxy.shared.lastURL = context.url
41
- let options = Self.openURLOptions(from: context.options)
42
-
43
- // Capacitor 8 backwards compat
44
- NotificationCenter.default.post(name: .capacitorOpenURL, object: [
45
- "url": context.url,
46
- "options": options
47
- ])
48
-
49
- NotificationCenter.default.post(name: NSNotification.Name.CDVPluginHandleOpenURL, object: context.url)
50
-
51
- NotificationCenter.default.post(name: .capacitorSceneOpenURL, object: scene, userInfo: [
52
- "url": context.url,
53
- "options": options
54
- ])
55
- }
56
- }
57
-
58
- public func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
59
- guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
60
- let url = userActivity.webpageURL else {
61
- return
62
- }
63
- lastURL = url
64
- ApplicationDelegateProxy.shared.lastURL = url
65
-
66
- // Capacitor 8 backwards compat
67
- NotificationCenter.default.post(name: .capacitorOpenUniversalLink, object: [
68
- "url": url
69
- ])
70
-
71
- NotificationCenter.default.post(name: .capacitorSceneOpenUniversalLink, object: scene, userInfo: [
72
- "url": url
73
- ])
74
- }
75
-
76
- private static func openURLOptions(from sceneOptions: UIScene.OpenURLOptions) -> [UIApplication.OpenURLOptionsKey: Any] {
77
- var options: [UIApplication.OpenURLOptionsKey: Any] = [:]
78
- if let sourceApplication = sceneOptions.sourceApplication {
79
- options[.sourceApplication] = sourceApplication
80
- }
81
- if let annotation = sceneOptions.annotation {
82
- options[.annotation] = annotation
83
- }
84
- options[.openInPlace] = sceneOptions.openInPlace
85
- return options
86
- }
87
- }