@capacitor/ios 9.0.0-alpha.5 → 9.0.0-alpha.7

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.
Files changed (111) hide show
  1. package/Capacitor.podspec +10 -4
  2. package/CapacitorCordova.podspec +6 -5
  3. package/{Capacitor → Sources}/Capacitor/CAPApplicationDelegateProxy.swift +1 -1
  4. package/{Capacitor → Sources}/Capacitor/CAPBridgeProtocol.swift +0 -57
  5. package/{Capacitor → Sources}/Capacitor/CAPInstanceConfiguration.swift +0 -15
  6. package/{Capacitor → Sources}/Capacitor/CAPNotifications.swift +8 -36
  7. package/Sources/Capacitor/CAPPlugin+Bridge.swift +108 -0
  8. package/{Capacitor → Sources}/Capacitor/CAPPluginCall.swift +0 -13
  9. package/Sources/Capacitor/CAPSceneDelegateProxy.swift +204 -0
  10. package/{Capacitor → Sources}/Capacitor/CapacitorBridge.swift +37 -78
  11. package/Sources/Capacitor/CapacitorObjCExports.swift +11 -0
  12. package/{Capacitor → Sources}/Capacitor/JS.swift +9 -20
  13. package/{Capacitor → Sources}/Capacitor/JSExport.swift +6 -2
  14. package/Sources/Capacitor/JSResultSerialization.swift +56 -0
  15. package/{Capacitor → Sources}/Capacitor/NotificationRouter.swift +9 -0
  16. package/Sources/Capacitor/PluginCallResult.swift +17 -0
  17. package/{Capacitor → Sources}/Capacitor/Plugins/CapacitorUrlRequest.swift +2 -11
  18. package/{Capacitor → Sources}/Capacitor/WebViewAssetHandler.swift +17 -5
  19. package/{Capacitor → Sources}/Capacitor/WebViewDelegationHandler.swift +7 -1
  20. package/{Capacitor → Sources}/Capacitor/assets/native-bridge.js +0 -6
  21. package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/CapacitorCordova}/Plugin.swift +5 -0
  22. package/{Capacitor/Capacitor → Sources/CapacitorObjC}/CAPInstanceConfiguration.m +9 -1
  23. package/{Capacitor/Capacitor → Sources/CapacitorObjC}/CAPInstanceDescriptor.m +0 -1
  24. package/Sources/CapacitorObjC/CAPPlugin.m +100 -0
  25. package/Sources/CapacitorObjC/CAPPluginCallResult.m +29 -0
  26. package/{Capacitor/Capacitor → Sources/CapacitorObjC}/CAPPluginMethod.m +0 -1
  27. package/{Capacitor → Sources/CapacitorObjC/include}/Capacitor/CAPPlugin.h +3 -20
  28. package/{Capacitor → Sources/CapacitorObjC/include}/Capacitor/CAPPluginCall.h +1 -2
  29. package/Sources/CapacitorObjC/include/Capacitor/CAPPluginCallResult.h +28 -0
  30. package/Sources/CapacitorObjCShims/include/Capacitor/Capacitor-Swift.h +9 -0
  31. package/{Capacitor → Sources/CapacitorObjCShims/include}/Capacitor/Capacitor.h +8 -0
  32. package/package.json +6 -7
  33. package/Capacitor/Capacitor/CAPBridge.swift +0 -25
  34. package/Capacitor/Capacitor/CAPFile.swift +0 -14
  35. package/Capacitor/Capacitor/CAPPlugin.m +0 -180
  36. package/Capacitor/Capacitor/Info.plist +0 -24
  37. package/Capacitor/Capacitor/PluginCallResult.swift +0 -106
  38. package/CapacitorCordova/CapacitorCordova/Info.plist +0 -26
  39. /package/{Capacitor → Sources}/Capacitor/AppUUID.swift +0 -0
  40. /package/{Capacitor → Sources}/Capacitor/Array+Capacitor.swift +0 -0
  41. /package/{Capacitor → Sources}/Capacitor/CAPBridgeDelegate.swift +0 -0
  42. /package/{Capacitor → Sources}/Capacitor/CAPBridgeViewController.swift +0 -0
  43. /package/{Capacitor → Sources}/Capacitor/CAPBridgedPlugin+getMethod.swift +0 -0
  44. /package/{Capacitor → Sources}/Capacitor/CAPInstanceDescriptor.swift +0 -0
  45. /package/{Capacitor → Sources}/Capacitor/CAPInstancePlugin.swift +0 -0
  46. /package/{Capacitor → Sources}/Capacitor/CAPLog.swift +0 -0
  47. /package/{Capacitor → Sources}/Capacitor/CAPPlugin+LoadInstance.swift +0 -0
  48. /package/{Capacitor → Sources}/Capacitor/CAPPluginMethod.swift +0 -0
  49. /package/{Capacitor → Sources}/Capacitor/CapacitorExtension.swift +0 -0
  50. /package/{Capacitor → Sources}/Capacitor/Codable/JSValueDecoder.swift +0 -0
  51. /package/{Capacitor → Sources}/Capacitor/Codable/JSValueEncoder.swift +0 -0
  52. /package/{Capacitor → Sources}/Capacitor/Data+Capacitor.swift +0 -0
  53. /package/{Capacitor → Sources}/Capacitor/DocLinks.swift +0 -0
  54. /package/{Capacitor → Sources}/Capacitor/JSTypes.swift +0 -0
  55. /package/{Capacitor → Sources}/Capacitor/KeyPath.swift +0 -0
  56. /package/{Capacitor → Sources}/Capacitor/KeyValueStore.swift +0 -0
  57. /package/{Capacitor → Sources}/Capacitor/NotificationHandlerProtocol.swift +0 -0
  58. /package/{Capacitor → Sources}/Capacitor/PluginConfig.swift +0 -0
  59. /package/{Capacitor → Sources}/Capacitor/Plugins/CapacitorCookieManager.swift +0 -0
  60. /package/{Capacitor → Sources}/Capacitor/Plugins/CapacitorCookies.swift +0 -0
  61. /package/{Capacitor → Sources}/Capacitor/Plugins/CapacitorHttp.swift +0 -0
  62. /package/{Capacitor → Sources}/Capacitor/Plugins/Console.swift +0 -0
  63. /package/{Capacitor → Sources}/Capacitor/Plugins/HttpRequestHandler.swift +0 -0
  64. /package/{Capacitor → Sources}/Capacitor/Plugins/SystemBars.swift +0 -0
  65. /package/{Capacitor → Sources}/Capacitor/Plugins/WebView.swift +0 -0
  66. /package/{Capacitor → Sources}/Capacitor/PrivacyInfo.xcprivacy +0 -0
  67. /package/{Capacitor → Sources}/Capacitor/Router.swift +0 -0
  68. /package/{Capacitor → Sources}/Capacitor/UIColor.swift +0 -0
  69. /package/{Capacitor → Sources}/Capacitor/WKWebView+Capacitor.swift +0 -0
  70. /package/{Capacitor/Capacitor → Sources/CapacitorObjC}/CAPPluginCall.m +0 -0
  71. /package/{Capacitor → Sources/CapacitorObjC/include}/Capacitor/CAPBridgedPlugin.h +0 -0
  72. /package/{Capacitor → Sources/CapacitorObjC/include}/Capacitor/CAPInstanceConfiguration.h +0 -0
  73. /package/{Capacitor → Sources/CapacitorObjC/include}/Capacitor/CAPInstanceDescriptor.h +0 -0
  74. /package/{Capacitor → Sources/CapacitorObjC/include}/Capacitor/CAPPluginMethod.h +0 -0
  75. /package/{Capacitor/Capacitor → Sources/CapacitorObjCShims}/CAPBridgedJSTypes.m +0 -0
  76. /package/{Capacitor/Capacitor → Sources/CapacitorObjCShims}/Capacitor.modulemap +0 -0
  77. /package/{Capacitor/Capacitor → Sources/CapacitorObjCShims}/UIStatusBarManager+CAPHandleTapAction.m +0 -0
  78. /package/{Capacitor/Capacitor → Sources/CapacitorObjCShims}/WKWebView+Capacitor.m +0 -0
  79. /package/{Capacitor → Sources/CapacitorObjCShims/include}/Capacitor/CAPBridgedJSTypes.h +0 -0
  80. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova}/AppDelegate.m +0 -0
  81. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova}/CDVCommandDelegateImpl.m +0 -0
  82. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova}/CDVConfigParser.m +0 -0
  83. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova}/CDVInvokedUrlCommand.m +0 -0
  84. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova}/CDVPlugin+Resources.m +0 -0
  85. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova}/CDVPlugin.m +0 -0
  86. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova}/CDVPluginManager.m +0 -0
  87. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova}/CDVPluginResult.m +0 -0
  88. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova}/CDVURLProtocol.m +0 -0
  89. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova}/CDVViewController.m +0 -0
  90. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova}/CDVWebViewProcessPoolFactory.m +0 -0
  91. /package/{CapacitorCordova/CapacitorCordova → Sources/Cordova}/CapacitorCordova.h +0 -0
  92. /package/{CapacitorCordova/CapacitorCordova → Sources/Cordova}/CapacitorCordova.modulemap +0 -0
  93. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova}/NSDictionary+CordovaPreferences.m +0 -0
  94. /package/{CapacitorCordova/CapacitorCordova → Sources/Cordova}/PrivacyInfo.xcprivacy +0 -0
  95. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova/include/Cordova}/AppDelegate.h +0 -0
  96. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova/include/Cordova}/CDV.h +0 -0
  97. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova/include/Cordova}/CDVAvailability.h +0 -0
  98. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova/include/Cordova}/CDVAvailabilityDeprecated.h +0 -0
  99. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova/include/Cordova}/CDVCommandDelegate.h +0 -0
  100. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova/include/Cordova}/CDVCommandDelegateImpl.h +0 -0
  101. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova/include/Cordova}/CDVConfigParser.h +0 -0
  102. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova/include/Cordova}/CDVInvokedUrlCommand.h +0 -0
  103. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova/include/Cordova}/CDVPlugin+Resources.h +0 -0
  104. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova/include/Cordova}/CDVPlugin.h +0 -0
  105. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova/include/Cordova}/CDVPluginManager.h +0 -0
  106. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova/include/Cordova}/CDVPluginResult.h +0 -0
  107. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova/include/Cordova}/CDVScreenOrientationDelegate.h +0 -0
  108. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova/include/Cordova}/CDVURLProtocol.h +0 -0
  109. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova/include/Cordova}/CDVViewController.h +0 -0
  110. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova/include/Cordova}/CDVWebViewProcessPoolFactory.h +0 -0
  111. /package/{CapacitorCordova/CapacitorCordova/Classes/Public → Sources/Cordova/include/Cordova}/NSDictionary+CordovaPreferences.h +0 -0
@@ -95,8 +95,6 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
95
95
  public static let capacitorSite = "https://capacitorjs.com/"
96
96
  public static let fileStartIdentifier = "/_capacitor_file_"
97
97
  public static let httpInterceptorStartIdentifier = "/_capacitor_http_interceptor_"
98
- @available(*, deprecated, message: "`httpsInterceptorStartIdentifier` is no longer required. All proxied requests are handled via `httpInterceptorStartIdentifier` instead")
99
- public static let httpsInterceptorStartIdentifier = "/_capacitor_https_interceptor_"
100
98
  public static let httpInterceptorUrlParam = "u"
101
99
  public static let defaultScheme = "capacitor"
102
100
 
@@ -125,47 +123,6 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
125
123
  // Array of block based observers
126
124
  var observers: [NSObjectProtocol] = []
127
125
 
128
- // MARK: - CAPBridgeProtocol: Deprecated
129
-
130
- public func getWebView() -> WKWebView? {
131
- return webView
132
- }
133
-
134
- public func isSimulator() -> Bool {
135
- return isSimEnvironment
136
- }
137
-
138
- public func isDevMode() -> Bool {
139
- return isDevEnvironment
140
- }
141
-
142
- public func getStatusBarVisible() -> Bool {
143
- return statusBarVisible
144
- }
145
-
146
- @nonobjc public func setStatusBarVisible(_ visible: Bool) {
147
- statusBarVisible = visible
148
- }
149
-
150
- public func getStatusBarStyle() -> UIStatusBarStyle {
151
- return statusBarStyle
152
- }
153
- @nonobjc public func setStatusBarStyle(_ style: UIStatusBarStyle) {
154
- statusBarStyle = style
155
- }
156
-
157
- public func getUserInterfaceStyle() -> UIUserInterfaceStyle {
158
- return userInterfaceStyle
159
- }
160
-
161
- public func getLocalUrl() -> String {
162
- return config.localURL.absoluteString
163
- }
164
-
165
- @nonobjc public func setStatusBarAnimation(_ animation: UIStatusBarAnimation) {
166
- statusBarAnimation = animation
167
- }
168
-
169
126
  public func setServerBasePath(_ path: String) {
170
127
  let url = URL(fileURLWithPath: path, isDirectory: true)
171
128
  guard FileManager.default.fileExists(atPath: url.path) else { return }
@@ -198,11 +155,6 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
198
155
 
199
156
  // MARK: - Initialization
200
157
 
201
- @available(*, deprecated, renamed: "init", message: "Use different init")
202
- public convenience init(with configuration: InstanceConfiguration, delegate bridgeDelegate: CAPBridgeDelegate, cordovaConfiguration: Any, assetHandler: WebViewAssetHandler, delegationHandler: WebViewDelegationHandler, autoRegisterPlugins: Bool = true) {
203
- self.init(with: configuration, delegate: bridgeDelegate, assetHandler: assetHandler, delegationHandler: delegationHandler, autoRegisterPlugins: autoRegisterPlugins)
204
- }
205
-
206
158
  public init(with configuration: InstanceConfiguration, delegate bridgeDelegate: CAPBridgeDelegate, assetHandler: WebViewAssetHandler, delegationHandler: WebViewDelegationHandler, autoRegisterPlugins: Bool = true) {
207
159
 
208
160
  self.bridgeDelegate = bridgeDelegate
@@ -215,6 +167,7 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
215
167
  super.init()
216
168
 
217
169
  self.webViewDelegationHandler.bridge = self
170
+ self.webViewAssetHandler.setConfiguration(configuration)
218
171
 
219
172
  exportCoreJS(localUrl: configuration.localURL.absoluteString)
220
173
  registerPlugins()
@@ -261,26 +214,50 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
261
214
  if !cordovaIsPresent {
262
215
  observers.append(
263
216
  NotificationCenter.default.addObserver(
264
- forName: UIApplication.willEnterForegroundNotification,
217
+ forName: UIScene.willEnterForegroundNotification,
265
218
  object: nil,
266
219
  queue: .main
267
- ) { [weak self] _ in
268
- self?.triggerDocumentJSEvent(eventName: "resume")
220
+ ) { [weak self] notification in
221
+ self?.triggerSceneLifecycleJSEvent("resume", for: notification)
269
222
  }
270
223
  )
271
224
 
272
225
  observers.append(
273
226
  NotificationCenter.default.addObserver(
274
- forName: UIApplication.didEnterBackgroundNotification,
227
+ forName: UIScene.didEnterBackgroundNotification,
275
228
  object: nil,
276
229
  queue: .main
277
- ) { [weak self] _ in
278
- self?.triggerDocumentJSEvent(eventName: "pause")
230
+ ) { [weak self] notification in
231
+ self?.triggerSceneLifecycleJSEvent("pause", for: notification)
279
232
  }
280
233
  )
281
234
  }
282
235
  }
283
236
 
237
+ /**
238
+ Forward a scene lifecycle transition to the page as a document event, but only once
239
+ the page exists to receive it.
240
+
241
+ On a cold start `UIScene.willEnterForegroundNotification` is posted while the initial
242
+ load is still in flight, before `window.Capacitor` has been defined. Evaluating
243
+ `triggerEvent` at that point throws inside the web view and surfaces as a
244
+ "JS Eval error" in the log. The same happens when the web content process was
245
+ terminated and the page is being reloaded. In both cases the page is about to load
246
+ from scratch, so there is nothing for it to resume or pause; the event is dropped
247
+ rather than deferred, because a "resume" delivered right after a fresh load would
248
+ make the page react to a transition it never went through.
249
+ */
250
+ private func triggerSceneLifecycleJSEvent(_ eventName: String, for notification: Notification) {
251
+ guard let scene = notification.object as? UIWindowScene,
252
+ scene === viewController?.view.window?.windowScene else {
253
+ return
254
+ }
255
+ guard case .subsequentLoad = webViewDelegationHandler.webViewLoadingState, webView?.isLoading == false else {
256
+ return
257
+ }
258
+ triggerDocumentJSEvent(eventName: eventName)
259
+ }
260
+
284
261
  /**
285
262
  Reset the state of the bridge between navigations to avoid
286
263
  sending data back to the page from a previous page.
@@ -403,16 +380,6 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
403
380
  _ = storedCalls.withLock { $0.removeValue(forKey: withID) }
404
381
  }
405
382
 
406
- // MARK: - Deprecated Versions
407
-
408
- @objc public func getSavedCall(_ callbackId: String) -> CAPPluginCall? {
409
- return savedCall(withID: callbackId)
410
- }
411
-
412
- @objc public func releaseCall(callbackId: String) {
413
- releaseCall(withID: callbackId)
414
- }
415
-
416
383
  // MARK: - Internal
417
384
 
418
385
  func getDispatchQueue() -> DispatchQueue {
@@ -420,7 +387,7 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
420
387
  }
421
388
 
422
389
  func reload() {
423
- self.getWebView()?.reload()
390
+ self.webView?.reload()
424
391
  }
425
392
 
426
393
  func docLink(_ url: String) -> String {
@@ -491,7 +458,7 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
491
458
  if let result = result {
492
459
  self?.toJs(result: JSResult(call: call, callResult: result), save: pluginCall?.keepAlive ?? false)
493
460
  } else {
494
- self?.toJs(result: JSResult(call: call, result: .dictionary([:])), save: pluginCall?.keepAlive ?? false)
461
+ self?.toJs(result: JSResult(call: call, data: [:]), save: pluginCall?.keepAlive ?? false)
495
462
  }
496
463
  }, error: {(error: CAPPluginCallError?) in
497
464
  if let error = error {
@@ -501,7 +468,7 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
501
468
  errorMessage: "",
502
469
  errorDescription: "",
503
470
  errorCode: nil,
504
- result: .dictionary([:])))
471
+ data: [:]))
505
472
  }
506
473
  })
507
474
 
@@ -589,7 +556,7 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
589
556
  """
590
557
 
591
558
  DispatchQueue.main.async {
592
- self.getWebView()?.evaluateJavaScript(wrappedJs, completionHandler: { (_, error) in
559
+ self.webView?.evaluateJavaScript(wrappedJs, completionHandler: { (_, error) in
593
560
  if let error = error {
594
561
  CAPLog.print("⚡️ JS Eval error", error.localizedDescription)
595
562
  }
@@ -605,7 +572,7 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
605
572
  // swiftlint:disable:next identifier_name
606
573
  @objc public func eval(js: String) {
607
574
  DispatchQueue.main.async {
608
- self.getWebView()?.evaluateJavaScript(js, completionHandler: { (_, error) in
575
+ self.webView?.evaluateJavaScript(js, completionHandler: { (_, error) in
609
576
  if let error = error {
610
577
  CAPLog.print("⚡️ JS Eval error", error.localizedDescription)
611
578
  }
@@ -639,7 +606,7 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
639
606
 
640
607
  public func logToJs(_ message: String, _ level: String = "log") {
641
608
  DispatchQueue.main.async {
642
- self.getWebView()?.evaluateJavaScript("window.Capacitor.logJs('\(message)', '\(level)')") { (result, error) in
609
+ self.webView?.evaluateJavaScript("window.Capacitor.logJs('\(message)', '\(level)')") { (result, error) in
643
610
  if error != nil, let result = result {
644
611
  CAPLog.print(result)
645
612
  }
@@ -695,12 +662,4 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
695
662
  alert.addAction(UIAlertAction(title: buttonTitle, style: UIAlertAction.Style.default, handler: nil))
696
663
  self.viewController?.present(alert, animated: true, completion: nil)
697
664
  }
698
-
699
- @objc open func presentVC(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
700
- self.viewController?.present(viewControllerToPresent, animated: flag, completion: completion)
701
- }
702
-
703
- @objc open func dismissVC(animated flag: Bool, completion: (() -> Void)? = nil) {
704
- self.viewController?.dismiss(animated: flag, completion: completion)
705
- }
706
665
  }
@@ -0,0 +1,11 @@
1
+ // The Objective-C base classes (CAPPlugin, CAPPluginCall, CAPPluginMethod, CAPBridgedPlugin,
2
+ // CAPInstanceDescriptor, CAPInstanceConfiguration) live in the CapacitorObjC target so that they
3
+ // compile before the Swift module that subclasses and extends them. Re-export them so the rest of
4
+ // this module — and downstream `import Capacitor` consumers — keep seeing these symbols without an
5
+ // explicit `import CapacitorObjC`.
6
+ //
7
+ // Under CocoaPods all of these sources are compiled into a single Capacitor module, so there is no
8
+ // CapacitorObjC module to import and the re-export is unnecessary.
9
+ #if SWIFT_PACKAGE
10
+ @_exported import CapacitorObjC
11
+ #endif
@@ -1,16 +1,5 @@
1
1
  import Foundation
2
2
 
3
- public class JSDate {
4
- @available(*, deprecated, message: "No longer needed. Dates will be mapped to strings during serialization.")
5
- static func toString(_ date: Date) -> String {
6
- let formatter = ISO8601DateFormatter()
7
- return formatter.string(from: date)
8
- }
9
- }
10
-
11
- @available(*, deprecated, renamed: "PluginCallResultData")
12
- public typealias JSResultBody = [String: Any]
13
-
14
3
  /**
15
4
  * A call originating from JavaScript land
16
5
  */
@@ -55,17 +44,17 @@ private enum SerializationResult: String {
55
44
 
56
45
  internal struct JSResult: JSResultProtocol {
57
46
  let call: JSCall
58
- let result: PluginCallResult?
47
+ let data: PluginCallResultData?
59
48
 
60
49
  func jsonPayload() -> String {
61
- guard let result = result else {
50
+ guard let data = data else {
62
51
  return SerializationResult.undefined.rawValue
63
52
  }
64
53
  do {
65
- if let payload = try result.jsonRepresentation() {
54
+ if let payload = try JSResultSerialization.jsonRepresentation(of: data) {
66
55
  return payload
67
56
  }
68
- } catch PluginCallResult.SerializationError.invalidObject {
57
+ } catch JSResultSerialization.SerializationError.invalidObject {
69
58
  CAPLog.print("[Capacitor Plugin Error] - \(call.pluginId) - \(call.method) - Unable to serialize plugin response as JSON." +
70
59
  "Ensure that all data passed to success callback from module method is JSON serializable!")
71
60
  } catch {
@@ -78,7 +67,7 @@ internal struct JSResult: JSResultProtocol {
78
67
  internal extension JSResult {
79
68
  init(call: JSCall, callResult: CAPPluginCallResult) {
80
69
  self.call = call
81
- self.result = callResult.resultData
70
+ self.data = callResult.data
82
71
  }
83
72
  }
84
73
 
@@ -87,7 +76,7 @@ internal struct JSResultError: JSResultProtocol {
87
76
  let errorMessage: String
88
77
  let errorDescription: String
89
78
  let errorCode: String?
90
- let result: PluginCallResult
79
+ let data: PluginCallResultData
91
80
 
92
81
  func jsonPayload() -> String {
93
82
  var errorDictionary: [String: Any] = [
@@ -97,11 +86,11 @@ internal struct JSResultError: JSResultProtocol {
97
86
  errorDictionary["code"] = self.errorCode
98
87
 
99
88
  do {
100
- if let payload = try result.jsonRepresentation(includingFields: errorDictionary) {
89
+ if let payload = try JSResultSerialization.jsonRepresentation(of: data, includingFields: errorDictionary) {
101
90
  CAPLog.print("ERROR MESSAGE: ", payload.prefix(512))
102
91
  return payload
103
92
  }
104
- } catch PluginCallResult.SerializationError.invalidObject {
93
+ } catch JSResultSerialization.SerializationError.invalidObject {
105
94
  CAPLog.print("[Capacitor Plugin Error] - \(call.pluginId) - \(call.method) - Unable to serialize plugin response as JSON." +
106
95
  "Ensure that all data passed to success callback from module method is JSON serializable!")
107
96
  } catch {
@@ -117,6 +106,6 @@ internal extension JSResultError {
117
106
  errorMessage = callError.message
118
107
  errorDescription = callError.error?.localizedDescription ?? ""
119
108
  errorCode = callError.code
120
- result = callError.resultData ?? .dictionary([:])
109
+ data = callError.data ?? [:]
121
110
  }
122
111
  }
@@ -22,8 +22,12 @@ internal class JSExport {
22
22
  }
23
23
 
24
24
  static func exportBridgeJS(userContentController: WKUserContentController) throws {
25
- let capBundle = Bundle(for: Self.self)
26
- guard let jsUrl = capBundle.url(forResource: "native-bridge", withExtension: "js") else {
25
+ #if SWIFT_PACKAGE
26
+ let jsUrl = Bundle.module.url(forResource: "native-bridge", withExtension: "js", subdirectory: "assets")
27
+ #else
28
+ let jsUrl = Bundle(for: Self.self).url(forResource: "native-bridge", withExtension: "js")
29
+ #endif
30
+ guard let jsUrl else {
27
31
  CAPLog.print("ERROR: Required native-bridge.js file in Capacitor not found. Bridge will not function!")
28
32
  throw CapacitorBridgeError.errorExportingCoreJS
29
33
  }
@@ -0,0 +1,56 @@
1
+ import Foundation
2
+
3
+ public typealias PluginCallResultData = [String: Any]
4
+
5
+ /// Serializes a plugin call's result dictionary to the JSON string sent back across the bridge,
6
+ /// converting `Date` values to ISO8601 strings (recursively through nested dictionaries/arrays).
7
+ ///
8
+ /// Carries the serialization logic that used to live on the `PluginCallResult` enum, which was
9
+ /// replaced by the Objective-C `CAPPluginCallResult`/`CAPPluginCallError` carriers. Those store
10
+ /// their payloads as plain dictionaries, so the logic no longer has an enum to hang off.
11
+ enum JSResultSerialization {
12
+ enum SerializationError: Error {
13
+ case invalidObject
14
+ }
15
+
16
+ private static let formatter = ISO8601DateFormatter()
17
+
18
+ static func jsonRepresentation(of dictionary: PluginCallResultData, includingFields: PluginCallResultData? = nil) throws -> String? {
19
+ var dictionary = dictionary
20
+ if let fields = includingFields {
21
+ dictionary.merge(fields) { (current, _) in current }
22
+ }
23
+ let prepared = prepare(dictionary: dictionary)
24
+ guard JSONSerialization.isValidJSONObject(prepared) else {
25
+ throw SerializationError.invalidObject
26
+ }
27
+ let data = try JSONSerialization.data(withJSONObject: prepared, options: [])
28
+ return String(data: data, encoding: .utf8)
29
+ }
30
+
31
+ private static func prepare(dictionary: PluginCallResultData) -> PluginCallResultData {
32
+ return dictionary.mapValues { (value) -> Any in
33
+ if let date = value as? Date {
34
+ return formatter.string(from: date)
35
+ } else if let aDictionary = value as? PluginCallResultData {
36
+ return prepare(dictionary: aDictionary)
37
+ } else if let anArray = value as? [Any] {
38
+ return prepare(array: anArray)
39
+ }
40
+ return value
41
+ }
42
+ }
43
+
44
+ private static func prepare(array: [Any]) -> [Any] {
45
+ return array.map { (value) -> Any in
46
+ if let date = value as? Date {
47
+ return formatter.string(from: date)
48
+ } else if let aDictionary = value as? PluginCallResultData {
49
+ return prepare(dictionary: aDictionary)
50
+ } else if let anArray = value as? [Any] {
51
+ return prepare(array: anArray)
52
+ }
53
+ return value
54
+ }
55
+ }
56
+ }
@@ -1,11 +1,20 @@
1
1
  import Foundation
2
2
 
3
3
  @objc(CAPNotificationRouter) public class NotificationRouter: NSObject, UNUserNotificationCenterDelegate {
4
+ // UNUserNotificationCenter.current() raises when the process has no application bundle, which
5
+ // is the case in a host-less unit test runner and some extension contexts. There is no
6
+ // notification center to register with there, so treat it as unavailable rather than trapping.
7
+ private static var isNotificationCenterAvailable: Bool {
8
+ return ["app", "appex"].contains(Bundle.main.bundleURL.pathExtension)
9
+ }
10
+
4
11
  var handleApplicationNotifications: Bool {
5
12
  get {
13
+ guard Self.isNotificationCenterAvailable else { return false }
6
14
  return UNUserNotificationCenter.current().delegate === self
7
15
  }
8
16
  set {
17
+ guard Self.isNotificationCenterAvailable else { return }
9
18
  let center = UNUserNotificationCenter.current()
10
19
 
11
20
  if newValue {
@@ -0,0 +1,17 @@
1
+ import Foundation
2
+
3
+ public enum PluginCallResult {
4
+ case dictionary(PluginCallResultData)
5
+ }
6
+
7
+ public extension CAPPluginCallResult {
8
+ var resultData: PluginCallResult? {
9
+ return data.map { .dictionary($0) }
10
+ }
11
+ }
12
+
13
+ public extension CAPPluginCallError {
14
+ var resultData: PluginCallResult? {
15
+ return data.map { .dictionary($0) }
16
+ }
17
+ }
@@ -12,8 +12,8 @@ open class CapacitorUrlRequest: NSObject, URLSessionTaskDelegate {
12
12
  request = URLRequest(url: url)
13
13
  request.httpMethod = method
14
14
  headers = [:]
15
- if let lang = Locale.autoupdatingCurrent.languageCode {
16
- if let country = Locale.autoupdatingCurrent.regionCode {
15
+ if let lang = Locale.autoupdatingCurrent.language.languageCode?.identifier {
16
+ if let country = Locale.autoupdatingCurrent.region?.identifier {
17
17
  headers["Accept-Language"] = "\(lang)-\(country),\(lang);q=0.5"
18
18
  } else {
19
19
  headers["Accept-Language"] = "\(lang);q=0.5"
@@ -195,15 +195,6 @@ open class CapacitorUrlRequest: NSObject, URLSessionTaskDelegate {
195
195
  }
196
196
  }
197
197
 
198
- @available(*, deprecated, message: "Use newer function with passed headers of type [String: Any]")
199
- public func setRequestHeaders(_ headers: [String: String]) {
200
- headers.keys.forEach { (key: String) in
201
- let value = headers[key]
202
- request.addValue(value!, forHTTPHeaderField: key)
203
- self.headers[key] = value
204
- }
205
- }
206
-
207
198
  public func setRequestHeaders(_ headers: [String: Any]) {
208
199
  headers.keys.forEach { (key: String) in
209
200
  let value = headers[key]
@@ -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 UIApplication.shared.applicationState == .active {
116
+ if webView.window?.windowScene?.activationState == .foregroundActive {
111
117
  UIApplication.shared.open(navURL, options: [:], completionHandler: nil)
112
118
  }
113
119
  decisionHandler(.cancel)
@@ -367,12 +367,6 @@ var nativeBridge = (function (exports) {
367
367
  }
368
368
  };
369
369
  const platform = getPlatformId(win);
370
- if (platform == 'android' && typeof win.CapacitorSystemBarsAndroidInterface !== 'undefined') {
371
- // add DOM ready listener for System Bars
372
- document.addEventListener('DOMContentLoaded', function () {
373
- win.CapacitorSystemBarsAndroidInterface.onDOMReady();
374
- });
375
- }
376
370
  if (platform == 'android' || platform == 'ios') {
377
371
  // patch document.cookie on Android/iOS
378
372
  win.CapacitorCookiesDescriptor =
@@ -1,4 +1,9 @@
1
1
  import Capacitor
2
+ // Under CocoaPods this file is compiled into the Cordova module itself, so importing it would be a
3
+ // self-import. Under SPM the Swift and Objective-C halves are separate targets.
4
+ #if SWIFT_PACKAGE
5
+ import Cordova
6
+ #endif
2
7
 
3
8
  @objc(CordovaPlugin)
4
9
  public class CordovaPlugin: CAPPlugin, CAPBridgedPlugin {
@@ -1,5 +1,13 @@
1
1
  #import "CAPInstanceConfiguration.h"
2
- #import <Capacitor/Capacitor-Swift.h>
2
+ #import "CAPInstanceDescriptor.h"
3
+
4
+ // Implemented in Swift (CAPInstanceDescriptor.swift), which can't be imported here without a
5
+ // circular dependency. Declared locally rather than in the header so Swift doesn't see a
6
+ // redeclaration.
7
+ @interface CAPInstanceDescriptor (SwiftVended)
8
+ @property (nonatomic, readonly) BOOL cordovaDeployDisabled;
9
+ - (void)normalize;
10
+ @end
3
11
 
4
12
  @interface CAPInstanceConfiguration (Internal)
5
13
  - (instancetype)initWithConfiguration:(CAPInstanceConfiguration*)configuration andLocation:(NSURL*)location;
@@ -1,5 +1,4 @@
1
1
  #import "CAPInstanceDescriptor.h"
2
- #import <Capacitor/Capacitor-Swift.h>
3
2
 
4
3
  // Swift extensions marked as @objc and internal are available to the Obj-C runtime but are not available at compile time.
5
4
  // so we need this declaration to avoid compiler complaints
@@ -0,0 +1,100 @@
1
+ #import "CAPPlugin.h"
2
+ #import "CAPPluginCall.h"
3
+ #import <Foundation/Foundation.h>
4
+
5
+ // Implemented in Swift (CAPPlugin+Bridge.swift), which can't be imported here without a circular
6
+ // dependency. Declared locally rather than in the header so Swift doesn't see a redeclaration.
7
+ @interface CAPPlugin (SwiftVended)
8
+ - (void)notifyListeners:(NSString* _Nonnull)eventName data:(NSDictionary<NSString *, id>* _Nullable)data;
9
+ @end
10
+
11
+ @implementation CAPPlugin
12
+
13
+ - (instancetype)init {
14
+ if ((self = [super init])) {
15
+ _pluginId = @"";
16
+ _pluginName = @"";
17
+ _eventListeners = [[NSMutableDictionary alloc] init];
18
+ _retainedEventArguments = [[NSMutableDictionary alloc] init];
19
+ _shouldStringifyDatesInCalls = YES;
20
+ }
21
+ return self;
22
+ }
23
+
24
+ -(NSString *) getId {
25
+ return self.pluginName;
26
+ }
27
+
28
+ -(void)load {}
29
+
30
+ - (void)addEventListener:(NSString *)eventName listener:(CAPPluginCall *)listener {
31
+ NSMutableArray *listenersForEvent = [self.eventListeners objectForKey:eventName];
32
+ if(listenersForEvent == nil || [listenersForEvent count] == 0) {
33
+ listenersForEvent = [[NSMutableArray alloc] initWithObjects:listener, nil];
34
+ [self.eventListeners setValue:listenersForEvent forKey:eventName];
35
+
36
+ [self sendRetainedArgumentsForEvent:eventName];
37
+ } else {
38
+ [listenersForEvent addObject:listener];
39
+ }
40
+ }
41
+
42
+ - (void)sendRetainedArgumentsForEvent:(NSString *)eventName {
43
+ // copy retained args and null source to prevent potential race conditions
44
+ NSMutableArray *retained = [self.retainedEventArguments objectForKey:eventName];
45
+ if (retained == nil) {
46
+ return;
47
+ }
48
+
49
+ [self.retainedEventArguments removeObjectForKey:eventName];
50
+
51
+ for(id data in retained) {
52
+ [self notifyListeners:eventName data:data];
53
+ }
54
+ }
55
+
56
+ - (void)removeEventListener:(NSString *)eventName listener:(CAPPluginCall *)listener {
57
+ NSMutableArray *listenersForEvent = [self.eventListeners objectForKey:eventName];
58
+ if(!listenersForEvent) { return; }
59
+ NSUInteger listenerIndex = [listenersForEvent indexOfObject:listener];
60
+ if(listenerIndex == NSNotFound) {
61
+ return;
62
+ }
63
+ [listenersForEvent removeObjectAtIndex:listenerIndex];
64
+ }
65
+
66
+ - (void)addListener:(CAPPluginCall *)call {
67
+ NSString *eventName = [call.options objectForKey:@"eventName"];
68
+ [call setKeepAlive:TRUE];
69
+ [self addEventListener:eventName listener:call];
70
+ }
71
+
72
+ - (NSArray<CAPPluginCall *>*)getListeners:(NSString *)eventName {
73
+ NSArray<CAPPluginCall *>* listeners = [self.eventListeners objectForKey:eventName];
74
+ return listeners;
75
+ }
76
+
77
+ - (BOOL)hasListeners:(NSString *)eventName {
78
+ NSArray<CAPPluginCall *>* listeners = [self.eventListeners objectForKey:eventName];
79
+
80
+ if (listeners == nil) {
81
+ return false;
82
+ }
83
+ return [listeners count] > 0;
84
+ }
85
+
86
+ -(BOOL)supportsPopover {
87
+ return YES;
88
+ }
89
+
90
+ - (NSNumber*)shouldOverrideLoad:(WKNavigationAction*)navigationAction {
91
+ return nil;
92
+ }
93
+
94
+ - (BOOL)handleWKWebViewURLAuthenticationChallenge:(NSURLAuthenticationChallenge* _Nonnull)challenge completionHandler:(void (^_Nonnull)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
95
+ return NO;
96
+ }
97
+
98
+
99
+ @end
100
+