@capacitor/ios 4.2.1-nightly-20220921T150520.0 → 4.3.0

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/CHANGELOG.md CHANGED
@@ -3,6 +3,22 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [4.3.0](https://github.com/ionic-team/capacitor/compare/4.2.0...4.3.0) (2022-09-21)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **core:** Exception object was not set on Cap ([#5917](https://github.com/ionic-team/capacitor/issues/5917)) ([9ca27a4](https://github.com/ionic-team/capacitor/commit/9ca27a4f8441b368f8bf9d97dda57b1a55ac0e4e))
12
+
13
+
14
+ ### Features
15
+
16
+ * Capacitor Cookies & Capacitor Http core plugins ([d4047cf](https://github.com/ionic-team/capacitor/commit/d4047cfa947676777f400389a8d65defae140b45))
17
+
18
+
19
+
20
+
21
+
6
22
  # [4.2.0](https://github.com/ionic-team/capacitor/compare/4.1.0...4.2.0) (2022-09-08)
7
23
 
8
24
  **Note:** Version bump only for package @capacitor/ios
@@ -0,0 +1,66 @@
1
+ import Foundation
2
+
3
+ public class CapacitorCookieManager {
4
+ var config: InstanceConfiguration?
5
+
6
+ init(_ capConfig: InstanceConfiguration?) {
7
+ self.config = capConfig
8
+ }
9
+
10
+ public func getServerUrl() -> URL? {
11
+ return self.config?.serverURL
12
+ }
13
+
14
+ public func getServerUrl(_ call: CAPPluginCall) -> URL? {
15
+ guard let urlString = call.getString("url") else {
16
+ return getServerUrl()
17
+ }
18
+
19
+ guard let url = URL(string: urlString) else {
20
+ return getServerUrl()
21
+ }
22
+
23
+ return url
24
+ }
25
+
26
+ public func encode(_ value: String) -> String {
27
+ return value.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)!
28
+ }
29
+
30
+ public func decode(_ value: String) -> String {
31
+ return value.removingPercentEncoding!
32
+ }
33
+
34
+ public func setCookie(_ url: URL, _ key: String, _ value: String) {
35
+ let jar = HTTPCookieStorage.shared
36
+ let field = ["Set-Cookie": "\(key)=\(value)"]
37
+ let cookies = HTTPCookie.cookies(withResponseHeaderFields: field, for: url)
38
+ jar.setCookies(cookies, for: url, mainDocumentURL: url)
39
+ }
40
+
41
+ public func getCookies() -> String {
42
+ let jar = HTTPCookieStorage.shared
43
+ guard let url = self.getServerUrl() else { return "" }
44
+ guard let cookies = jar.cookies(for: url) else { return "" }
45
+ return cookies.map({"\($0.name)=\($0.value)"}).joined(separator: ";")
46
+ }
47
+
48
+ public func deleteCookie(_ url: URL, _ key: String) {
49
+ let jar = HTTPCookieStorage.shared
50
+ let cookie = jar.cookies(for: url)?.first(where: { (cookie) -> Bool in
51
+ return cookie.name == key
52
+ })
53
+
54
+ if cookie != nil { jar.deleteCookie(cookie!) }
55
+ }
56
+
57
+ public func clearCookies(_ url: URL) {
58
+ let jar = HTTPCookieStorage.shared
59
+ jar.cookies(for: url)?.forEach({ (cookie) in jar.deleteCookie(cookie) })
60
+ }
61
+
62
+ public func clearAllCookies() {
63
+ let jar = HTTPCookieStorage.shared
64
+ jar.cookies?.forEach({ (cookie) in jar.deleteCookie(cookie) })
65
+ }
66
+ }
@@ -0,0 +1,52 @@
1
+ import Foundation
2
+
3
+ @objc(CAPCookiesPlugin)
4
+ public class CAPCookiesPlugin: CAPPlugin {
5
+ var cookieManager: CapacitorCookieManager?
6
+
7
+ @objc override public func load() {
8
+ cookieManager = CapacitorCookieManager(bridge?.config)
9
+ }
10
+
11
+ @objc func setCookie(_ call: CAPPluginCall) {
12
+ guard let key = call.getString("key") else { return call.reject("Must provide key") }
13
+ guard let value = call.getString("value") else { return call.reject("Must provide value") }
14
+
15
+ let url = cookieManager!.getServerUrl(call)
16
+ if url != nil {
17
+ cookieManager!.setCookie(url!, key, cookieManager!.encode(value))
18
+ call.resolve()
19
+ }
20
+ }
21
+
22
+ @objc func deleteCookie(_ call: CAPPluginCall) {
23
+ guard let key = call.getString("key") else { return call.reject("Must provide key") }
24
+ let url = cookieManager!.getServerUrl(call)
25
+ if url != nil {
26
+ let jar = HTTPCookieStorage.shared
27
+
28
+ let cookie = jar.cookies(for: url!)?.first(where: { (cookie) -> Bool in
29
+ return cookie.name == key
30
+ })
31
+
32
+ if cookie != nil {
33
+ jar.deleteCookie(cookie!)
34
+ }
35
+
36
+ call.resolve()
37
+ }
38
+ }
39
+
40
+ @objc func clearCookies(_ call: CAPPluginCall) {
41
+ let url = cookieManager!.getServerUrl(call)
42
+ if url != nil {
43
+ cookieManager!.clearCookies(url!)
44
+ call.resolve()
45
+ }
46
+ }
47
+
48
+ @objc func clearAllCookies(_ call: CAPPluginCall) {
49
+ cookieManager!.clearAllCookies()
50
+ call.resolve()
51
+ }
52
+ }
@@ -0,0 +1,40 @@
1
+ import Foundation
2
+
3
+ @objc(CAPHttpPlugin)
4
+ public class CAPHttpPlugin: CAPPlugin {
5
+ @objc func http(_ call: CAPPluginCall, _ httpMethod: String?) {
6
+ // Protect against bad values from JS before calling request
7
+ guard let url = call.getString("url") else { return call.reject("Must provide a URL"); }
8
+ guard var _ = URL(string: url) else { return call.reject("Invalid URL"); }
9
+
10
+ do {
11
+ try HttpRequestHandler.request(call, httpMethod)
12
+ } catch let error {
13
+ call.reject(error.localizedDescription)
14
+ }
15
+ }
16
+
17
+ @objc func request(_ call: CAPPluginCall) {
18
+ http(call, nil)
19
+ }
20
+
21
+ @objc func get(_ call: CAPPluginCall) {
22
+ http(call, "GET")
23
+ }
24
+
25
+ @objc func post(_ call: CAPPluginCall) {
26
+ http(call, "POST")
27
+ }
28
+
29
+ @objc func put(_ call: CAPPluginCall) {
30
+ http(call, "PUT")
31
+ }
32
+
33
+ @objc func patch(_ call: CAPPluginCall) {
34
+ http(call, "PATCH")
35
+ }
36
+
37
+ @objc func del(_ call: CAPPluginCall) {
38
+ http(call, "DELETE")
39
+ }
40
+ }
@@ -0,0 +1,150 @@
1
+ import Foundation
2
+
3
+ public class CapacitorUrlRequest: NSObject, URLSessionTaskDelegate {
4
+ private var request: URLRequest
5
+ private var headers: [String: String]
6
+
7
+ enum CapacitorUrlRequestError: Error {
8
+ case serializationError(String?)
9
+ }
10
+
11
+ init(_ url: URL, method: String) {
12
+ request = URLRequest(url: url)
13
+ request.httpMethod = method
14
+ headers = [:]
15
+ if let lang = Locale.autoupdatingCurrent.languageCode {
16
+ if let country = Locale.autoupdatingCurrent.regionCode {
17
+ headers["Accept-Language"] = "\(lang)-\(country),\(lang);q=0.5"
18
+ } else {
19
+ headers["Accept-Language"] = "\(lang);q=0.5"
20
+ }
21
+ request.addValue(headers["Accept-Language"]!, forHTTPHeaderField: "Accept-Language")
22
+ }
23
+ }
24
+
25
+ private func getRequestDataAsJson(_ data: JSValue) throws -> Data? {
26
+ // We need to check if the JSON is valid before attempting to serialize, as JSONSerialization.data will not throw an exception that can be caught, and will cause the application to crash if it fails.
27
+ if JSONSerialization.isValidJSONObject(data) {
28
+ return try JSONSerialization.data(withJSONObject: data)
29
+ } else {
30
+ throw CapacitorUrlRequest.CapacitorUrlRequestError.serializationError("[ data ] argument for request of content-type [ application/json ] must be serializable to JSON")
31
+ }
32
+ }
33
+
34
+ private func getRequestDataAsFormUrlEncoded(_ data: JSValue) throws -> Data? {
35
+ guard var components = URLComponents(url: request.url!, resolvingAgainstBaseURL: false) else { return nil }
36
+ components.queryItems = []
37
+
38
+ guard let obj = data as? JSObject else {
39
+ // Throw, other data types explicitly not supported
40
+ throw CapacitorUrlRequestError.serializationError("[ data ] argument for request with content-type [ multipart/form-data ] may only be a plain javascript object")
41
+ }
42
+
43
+ obj.keys.forEach { (key: String) in
44
+ components.queryItems?.append(URLQueryItem(name: key, value: "\(obj[key] ?? "")"))
45
+ }
46
+
47
+ if components.query != nil {
48
+ return Data(components.query!.utf8)
49
+ }
50
+
51
+ return nil
52
+ }
53
+
54
+ private func getRequestDataAsMultipartFormData(_ data: JSValue) throws -> Data {
55
+ guard let obj = data as? JSObject else {
56
+ // Throw, other data types explicitly not supported.
57
+ throw CapacitorUrlRequestError.serializationError("[ data ] argument for request with content-type [ application/x-www-form-urlencoded ] may only be a plain javascript object")
58
+ }
59
+
60
+ let strings: [String: String] = obj.compactMapValues { any in
61
+ any as? String
62
+ }
63
+
64
+ var data = Data()
65
+ let boundary = UUID().uuidString
66
+ let contentType = "multipart/form-data; boundary=\(boundary)"
67
+ request.setValue(contentType, forHTTPHeaderField: "Content-Type")
68
+ headers["Content-Type"] = contentType
69
+
70
+ strings.forEach { key, value in
71
+ data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
72
+ data.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: .utf8)!)
73
+ data.append(value.data(using: .utf8)!)
74
+ }
75
+ data.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)
76
+
77
+ return data
78
+ }
79
+
80
+ private func getRequestDataAsString(_ data: JSValue) throws -> Data {
81
+ guard let stringData = data as? String else {
82
+ throw CapacitorUrlRequestError.serializationError("[ data ] argument could not be parsed as string")
83
+ }
84
+ return Data(stringData.utf8)
85
+ }
86
+
87
+ func getRequestHeader(_ index: String) -> Any? {
88
+ var normalized = [:] as [String: Any]
89
+ self.headers.keys.forEach { (key: String) in
90
+ normalized[key.lowercased()] = self.headers[key]
91
+ }
92
+
93
+ return normalized[index.lowercased()]
94
+ }
95
+
96
+ func getRequestData(_ body: JSValue, _ contentType: String) throws -> Data? {
97
+ // If data can be parsed directly as a string, return that without processing.
98
+ if let strVal = try? getRequestDataAsString(body) {
99
+ return strVal
100
+ } else if contentType.contains("application/json") {
101
+ return try getRequestDataAsJson(body)
102
+ } else if contentType.contains("application/x-www-form-urlencoded") {
103
+ return try getRequestDataAsFormUrlEncoded(body)
104
+ } else if contentType.contains("multipart/form-data") {
105
+ return try getRequestDataAsMultipartFormData(body)
106
+ } else {
107
+ throw CapacitorUrlRequestError.serializationError("[ data ] argument could not be parsed for content type [ \(contentType) ]")
108
+ }
109
+ }
110
+
111
+ public func setRequestHeaders(_ headers: [String: String]) {
112
+ headers.keys.forEach { (key: String) in
113
+ let value = headers[key]
114
+ request.addValue(value!, forHTTPHeaderField: key)
115
+ self.headers[key] = value
116
+ }
117
+ }
118
+
119
+ public func setRequestBody(_ body: JSValue) throws {
120
+ let contentType = self.getRequestHeader("Content-Type") as? String
121
+
122
+ if contentType != nil {
123
+ request.httpBody = try getRequestData(body, contentType!)
124
+ }
125
+ }
126
+
127
+ public func setContentType(_ data: String?) {
128
+ request.setValue(data, forHTTPHeaderField: "Content-Type")
129
+ }
130
+
131
+ public func setTimeout(_ timeout: TimeInterval) {
132
+ request.timeoutInterval = timeout
133
+ }
134
+
135
+ public func getUrlRequest() -> URLRequest {
136
+ return request
137
+ }
138
+
139
+ public func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) {
140
+ completionHandler(nil)
141
+ }
142
+
143
+ public func getUrlSession(_ call: CAPPluginCall) -> URLSession {
144
+ let disableRedirects = call.getBool("disableRedirects") ?? false
145
+ if !disableRedirects {
146
+ return URLSession.shared
147
+ }
148
+ return URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: nil)
149
+ }
150
+ }
@@ -2,6 +2,22 @@
2
2
 
3
3
  #import "CAPBridgedPlugin.h"
4
4
 
5
+ CAP_PLUGIN(CAPCookiesPlugin, "CapacitorCookies",
6
+ CAP_PLUGIN_METHOD(setCookie, CAPPluginReturnPromise);
7
+ CAP_PLUGIN_METHOD(deleteCookie, CAPPluginReturnPromise);
8
+ CAP_PLUGIN_METHOD(clearCookies, CAPPluginReturnPromise);
9
+ CAP_PLUGIN_METHOD(clearAllCookies, CAPPluginReturnPromise);
10
+ )
11
+
12
+ CAP_PLUGIN(CAPHttpPlugin, "CapacitorHttp",
13
+ CAP_PLUGIN_METHOD(request, CAPPluginReturnPromise);
14
+ CAP_PLUGIN_METHOD(get, CAPPluginReturnPromise);
15
+ CAP_PLUGIN_METHOD(post, CAPPluginReturnPromise);
16
+ CAP_PLUGIN_METHOD(put, CAPPluginReturnPromise);
17
+ CAP_PLUGIN_METHOD(patch, CAPPluginReturnPromise);
18
+ CAP_PLUGIN_METHOD(delete, CAPPluginReturnPromise);
19
+ )
20
+
5
21
  CAP_PLUGIN(CAPConsolePlugin, "Console",
6
22
  CAP_PLUGIN_METHOD(log, CAPPluginReturnNone);
7
23
  )
@@ -0,0 +1,174 @@
1
+ import Foundation
2
+
3
+ /// See https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType
4
+ private enum ResponseType: String {
5
+ case arrayBuffer = "arraybuffer"
6
+ case blob = "blob"
7
+ case document = "document"
8
+ case json = "json"
9
+ case text = "text"
10
+
11
+ static let `default`: ResponseType = .text
12
+
13
+ init(string: String?) {
14
+ guard let string = string else {
15
+ self = .default
16
+ return
17
+ }
18
+
19
+ guard let responseType = ResponseType(rawValue: string.lowercased()) else {
20
+ self = .default
21
+ return
22
+ }
23
+
24
+ self = responseType
25
+ }
26
+ }
27
+
28
+ /// Helper that safely parses JSON Data. Otherwise returns an error (without throwing)
29
+ /// - Parameters:
30
+ /// - data: The JSON Data to parse
31
+ /// - Returns: The parsed value or an error
32
+ func tryParseJson(_ data: Data) -> Any {
33
+ do {
34
+ return try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
35
+ } catch {
36
+ return error.localizedDescription
37
+ }
38
+ }
39
+
40
+ class HttpRequestHandler {
41
+ private class CapacitorHttpRequestBuilder {
42
+ private var url: URL?
43
+ private var method: String?
44
+ private var params: [String: String]?
45
+ private var request: CapacitorUrlRequest?
46
+
47
+ /// Set the URL of the HttpRequest
48
+ /// - Throws: an error of URLError if the urlString cannot be parsed
49
+ /// - Parameters:
50
+ /// - urlString: The URL value to parse
51
+ /// - Returns: self to continue chaining functions
52
+ public func setUrl(_ urlString: String) throws -> CapacitorHttpRequestBuilder {
53
+ guard let url = URL(string: urlString) else {
54
+ throw URLError(.badURL)
55
+ }
56
+ self.url = url
57
+ return self
58
+ }
59
+
60
+ public func setMethod(_ method: String) -> CapacitorHttpRequestBuilder {
61
+ self.method = method
62
+ return self
63
+ }
64
+
65
+ public func setUrlParams(_ params: [String: Any]) -> CapacitorHttpRequestBuilder {
66
+ if params.count != 0 {
67
+ // swiftlint:disable force_cast
68
+ var cmps = URLComponents(url: url!, resolvingAgainstBaseURL: true)
69
+ if cmps?.queryItems == nil {
70
+ cmps?.queryItems = []
71
+ }
72
+
73
+ var urlSafeParams: [URLQueryItem] = []
74
+ for (key, value) in params {
75
+ if let arr = value as? [String] {
76
+ arr.forEach { str in
77
+ urlSafeParams.append(URLQueryItem(name: key, value: str))
78
+ }
79
+ } else {
80
+ urlSafeParams.append(URLQueryItem(name: key, value: (value as! String)))
81
+ }
82
+ }
83
+
84
+ cmps!.queryItems?.append(contentsOf: urlSafeParams)
85
+ url = cmps!.url!
86
+ }
87
+ return self
88
+ }
89
+
90
+ public func openConnection() -> CapacitorHttpRequestBuilder {
91
+ request = CapacitorUrlRequest(url!, method: method!)
92
+ return self
93
+ }
94
+
95
+ public func build() -> CapacitorUrlRequest {
96
+ return request!
97
+ }
98
+ }
99
+
100
+ private static func buildResponse(_ data: Data?, _ response: HTTPURLResponse, responseType: ResponseType = .default) -> [String: Any] {
101
+ var output = [:] as [String: Any]
102
+
103
+ output["status"] = response.statusCode
104
+ output["headers"] = response.allHeaderFields
105
+ output["url"] = response.url?.absoluteString
106
+
107
+ guard let data = data else {
108
+ output["data"] = ""
109
+ return output
110
+ }
111
+
112
+ let contentType = (response.allHeaderFields["Content-Type"] as? String ?? "application/default").lowercased()
113
+
114
+ if contentType.contains("application/json") || responseType == .json {
115
+ output["data"] = tryParseJson(data)
116
+ } else if responseType == .arrayBuffer || responseType == .blob {
117
+ output["data"] = data.base64EncodedString()
118
+ } else if responseType == .document || responseType == .text || responseType == .default {
119
+ output["data"] = String(data: data, encoding: .utf8)
120
+ }
121
+
122
+ return output
123
+ }
124
+
125
+ public static func request(_ call: CAPPluginCall, _ httpMethod: String?) throws {
126
+ guard let urlString = call.getString("url") else { throw URLError(.badURL) }
127
+ let method = httpMethod ?? call.getString("method", "GET")
128
+
129
+ // swiftlint:disable force_cast
130
+ let headers = (call.getObject("headers") ?? [:]) as! [String: String]
131
+ let params = (call.getObject("params") ?? [:]) as [String: Any]
132
+ let responseType = call.getString("responseType") ?? "text"
133
+ let connectTimeout = call.getDouble("connectTimeout")
134
+ let readTimeout = call.getDouble("readTimeout")
135
+
136
+ let request = try CapacitorHttpRequestBuilder()
137
+ .setUrl(urlString)
138
+ .setMethod(method)
139
+ .setUrlParams(params)
140
+ .openConnection()
141
+ .build()
142
+
143
+ request.setRequestHeaders(headers)
144
+
145
+ // Timeouts in iOS are in seconds. So read the value in millis and divide by 1000
146
+ let timeout = (connectTimeout ?? readTimeout ?? 600000.0) / 1000.0
147
+ request.setTimeout(timeout)
148
+
149
+ if let data = call.options["data"] as? JSValue {
150
+ do {
151
+ try request.setRequestBody(data)
152
+ } catch {
153
+ // Explicitly reject if the http request body was not set successfully,
154
+ // so as to not send a known malformed request, and to provide the developer with additional context.
155
+ call.reject("Error", "REQUEST", error, [:])
156
+ return
157
+ }
158
+ }
159
+
160
+ let urlRequest = request.getUrlRequest()
161
+ let urlSession = request.getUrlSession(call)
162
+ let task = urlSession.dataTask(with: urlRequest) { (data, response, error) in
163
+ urlSession.invalidateAndCancel()
164
+ if error != nil {
165
+ return
166
+ }
167
+
168
+ let type = ResponseType(rawValue: responseType) ?? .default
169
+ call.resolve(self.buildResponse(data, response as! HTTPURLResponse, responseType: type))
170
+ }
171
+
172
+ task.resume()
173
+ }
174
+ }
@@ -243,6 +243,34 @@ internal class WebViewDelegationHandler: NSObject, WKNavigationDelegate, WKUIDel
243
243
  }
244
244
 
245
245
  public func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
246
+
247
+ // Check if this is synchronous cookie or http call
248
+ do {
249
+ if let dataFromString = prompt.data(using: .utf8, allowLossyConversion: false) {
250
+ if let payload = try JSONSerialization.jsonObject(with: dataFromString, options: .fragmentsAllowed) as? [String: AnyObject] {
251
+ let type = payload["type"] as? String
252
+
253
+ if type == "CapacitorCookies" {
254
+ completionHandler(CapacitorCookieManager(bridge!.config).getCookies())
255
+ // Don't present prompt
256
+ return
257
+ } else if type == "CapacitorCookies.isEnabled" {
258
+ let pluginConfig = bridge!.config.getPluginConfig("CapacitorCookies")
259
+ completionHandler(String(pluginConfig.getBoolean("enabled", false)))
260
+ // Don't present prompt
261
+ return
262
+ } else if type == "CapacitorHttp" {
263
+ let pluginConfig = bridge!.config.getPluginConfig("CapacitorHttp")
264
+ completionHandler(String(pluginConfig.getBoolean("enabled", false)))
265
+ // Don't present prompt
266
+ return
267
+ }
268
+ }
269
+ }
270
+ } catch {
271
+ // Continue with regular prompt
272
+ }
273
+
246
274
  guard let viewController = bridge?.viewController else {
247
275
  return
248
276
  }
@@ -2,7 +2,7 @@
2
2
  /*! Capacitor: https://capacitorjs.com/ - MIT License */
3
3
  /* Generated File. Do not edit. */
4
4
 
5
- var nativeBridge = (function (exports) {
5
+ const nativeBridge = (function (exports) {
6
6
  'use strict';
7
7
 
8
8
  var ExceptionCode;
@@ -268,6 +268,274 @@ var nativeBridge = (function (exports) {
268
268
  }
269
269
  return String(msg);
270
270
  };
271
+ /**
272
+ * Safely web decode a string value (inspired by js-cookie)
273
+ * @param str The string value to decode
274
+ */
275
+ const decode = (str) => str.replace(/(%[\dA-F]{2})+/gi, decodeURIComponent);
276
+ const platform = getPlatformId(win);
277
+ if (platform == 'android' || platform == 'ios') {
278
+ // patch document.cookie on Android/iOS
279
+ win.CapacitorCookiesDescriptor =
280
+ Object.getOwnPropertyDescriptor(Document.prototype, 'cookie') ||
281
+ Object.getOwnPropertyDescriptor(HTMLDocument.prototype, 'cookie');
282
+ let doPatchCookies = false;
283
+ // check if capacitor cookies is disabled before patching
284
+ if (platform === 'ios') {
285
+ // Use prompt to synchronously get capacitor cookies config.
286
+ // https://stackoverflow.com/questions/29249132/wkwebview-complex-communication-between-javascript-native-code/49474323#49474323
287
+ const payload = {
288
+ type: 'CapacitorCookies.isEnabled',
289
+ };
290
+ const isCookiesEnabled = prompt(JSON.stringify(payload));
291
+ if (isCookiesEnabled === 'true') {
292
+ doPatchCookies = true;
293
+ }
294
+ }
295
+ else if (typeof win.CapacitorCookiesAndroidInterface !== 'undefined') {
296
+ const isCookiesEnabled = win.CapacitorCookiesAndroidInterface.isEnabled();
297
+ if (isCookiesEnabled === true) {
298
+ doPatchCookies = true;
299
+ }
300
+ }
301
+ if (doPatchCookies) {
302
+ Object.defineProperty(document, 'cookie', {
303
+ get: function () {
304
+ if (platform === 'ios') {
305
+ // Use prompt to synchronously get cookies.
306
+ // https://stackoverflow.com/questions/29249132/wkwebview-complex-communication-between-javascript-native-code/49474323#49474323
307
+ const payload = {
308
+ type: 'CapacitorCookies',
309
+ };
310
+ const res = prompt(JSON.stringify(payload));
311
+ return res;
312
+ }
313
+ else if (typeof win.CapacitorCookiesAndroidInterface !== 'undefined') {
314
+ return win.CapacitorCookiesAndroidInterface.getCookies();
315
+ }
316
+ },
317
+ set: function (val) {
318
+ const cookiePairs = val.split(';');
319
+ for (const cookiePair of cookiePairs) {
320
+ const cookieKey = cookiePair.split('=')[0];
321
+ const cookieValue = cookiePair.split('=')[1];
322
+ if (null == cookieValue) {
323
+ continue;
324
+ }
325
+ cap.toNative('CapacitorCookies', 'setCookie', {
326
+ key: cookieKey,
327
+ value: decode(cookieValue),
328
+ });
329
+ }
330
+ },
331
+ });
332
+ }
333
+ // patch fetch / XHR on Android/iOS
334
+ // store original fetch & XHR functions
335
+ win.CapacitorWebFetch = window.fetch;
336
+ win.CapacitorWebXMLHttpRequest = {
337
+ abort: window.XMLHttpRequest.prototype.abort,
338
+ open: window.XMLHttpRequest.prototype.open,
339
+ send: window.XMLHttpRequest.prototype.send,
340
+ setRequestHeader: window.XMLHttpRequest.prototype.setRequestHeader,
341
+ };
342
+ let doPatchHttp = false;
343
+ // check if capacitor http is disabled before patching
344
+ if (platform === 'ios') {
345
+ // Use prompt to synchronously get capacitor http config.
346
+ // https://stackoverflow.com/questions/29249132/wkwebview-complex-communication-between-javascript-native-code/49474323#49474323
347
+ const payload = {
348
+ type: 'CapacitorHttp',
349
+ };
350
+ const isHttpEnabled = prompt(JSON.stringify(payload));
351
+ if (isHttpEnabled === 'true') {
352
+ doPatchHttp = true;
353
+ }
354
+ }
355
+ else if (typeof win.CapacitorHttpAndroidInterface !== 'undefined') {
356
+ const isHttpEnabled = win.CapacitorHttpAndroidInterface.isEnabled();
357
+ if (isHttpEnabled === true) {
358
+ doPatchHttp = true;
359
+ }
360
+ }
361
+ if (doPatchHttp) {
362
+ // fetch patch
363
+ window.fetch = async (resource, options) => {
364
+ if (resource.toString().startsWith('data:') ||
365
+ resource.toString().startsWith('blob:')) {
366
+ return win.CapacitorWebFetch(resource, options);
367
+ }
368
+ try {
369
+ // intercept request & pass to the bridge
370
+ const nativeResponse = await cap.nativePromise('CapacitorHttp', 'request', {
371
+ url: resource,
372
+ method: (options === null || options === void 0 ? void 0 : options.method) ? options.method : undefined,
373
+ data: (options === null || options === void 0 ? void 0 : options.body) ? options.body : undefined,
374
+ headers: (options === null || options === void 0 ? void 0 : options.headers) ? options.headers : undefined,
375
+ });
376
+ const data = typeof nativeResponse.data === 'string'
377
+ ? nativeResponse.data
378
+ : JSON.stringify(nativeResponse.data);
379
+ // intercept & parse response before returning
380
+ const response = new Response(data, {
381
+ headers: nativeResponse.headers,
382
+ status: nativeResponse.status,
383
+ });
384
+ return response;
385
+ }
386
+ catch (error) {
387
+ return Promise.reject(error);
388
+ }
389
+ };
390
+ // XHR event listeners
391
+ const addEventListeners = function () {
392
+ this.addEventListener('abort', function () {
393
+ if (typeof this.onabort === 'function')
394
+ this.onabort();
395
+ });
396
+ this.addEventListener('error', function () {
397
+ if (typeof this.onerror === 'function')
398
+ this.onerror();
399
+ });
400
+ this.addEventListener('load', function () {
401
+ if (typeof this.onload === 'function')
402
+ this.onload();
403
+ });
404
+ this.addEventListener('loadend', function () {
405
+ if (typeof this.onloadend === 'function')
406
+ this.onloadend();
407
+ });
408
+ this.addEventListener('loadstart', function () {
409
+ if (typeof this.onloadstart === 'function')
410
+ this.onloadstart();
411
+ });
412
+ this.addEventListener('readystatechange', function () {
413
+ if (typeof this.onreadystatechange === 'function')
414
+ this.onreadystatechange();
415
+ });
416
+ this.addEventListener('timeout', function () {
417
+ if (typeof this.ontimeout === 'function')
418
+ this.ontimeout();
419
+ });
420
+ };
421
+ // XHR patch abort
422
+ window.XMLHttpRequest.prototype.abort = function () {
423
+ this.readyState = 0;
424
+ this.dispatchEvent(new Event('abort'));
425
+ this.dispatchEvent(new Event('loadend'));
426
+ };
427
+ // XHR patch open
428
+ window.XMLHttpRequest.prototype.open = function (method, url) {
429
+ Object.defineProperties(this, {
430
+ _headers: {
431
+ value: {},
432
+ writable: true,
433
+ },
434
+ readyState: {
435
+ get: function () {
436
+ var _a;
437
+ return (_a = this._readyState) !== null && _a !== void 0 ? _a : 0;
438
+ },
439
+ set: function (val) {
440
+ this._readyState = val;
441
+ this.dispatchEvent(new Event('readystatechange'));
442
+ },
443
+ },
444
+ response: {
445
+ value: '',
446
+ writable: true,
447
+ },
448
+ responseText: {
449
+ value: '',
450
+ writable: true,
451
+ },
452
+ responseURL: {
453
+ value: '',
454
+ writable: true,
455
+ },
456
+ status: {
457
+ value: 0,
458
+ writable: true,
459
+ },
460
+ });
461
+ addEventListeners.call(this);
462
+ this._method = method;
463
+ this._url = url;
464
+ this.readyState = 1;
465
+ };
466
+ // XHR patch set request header
467
+ window.XMLHttpRequest.prototype.setRequestHeader = function (header, value) {
468
+ this._headers[header] = value;
469
+ };
470
+ // XHR patch send
471
+ window.XMLHttpRequest.prototype.send = function (body) {
472
+ try {
473
+ this.readyState = 2;
474
+ // intercept request & pass to the bridge
475
+ cap
476
+ .nativePromise('CapacitorHttp', 'request', {
477
+ url: this._url,
478
+ method: this._method,
479
+ data: body !== null ? body : undefined,
480
+ headers: this._headers,
481
+ })
482
+ .then((nativeResponse) => {
483
+ // intercept & parse response before returning
484
+ if (this.readyState == 2) {
485
+ this.dispatchEvent(new Event('loadstart'));
486
+ this._headers = nativeResponse.headers;
487
+ this.status = nativeResponse.status;
488
+ this.response = nativeResponse.data;
489
+ this.responseText =
490
+ typeof nativeResponse.data === 'string'
491
+ ? nativeResponse.data
492
+ : JSON.stringify(nativeResponse.data);
493
+ this.responseURL = nativeResponse.url;
494
+ this.readyState = 4;
495
+ this.dispatchEvent(new Event('load'));
496
+ this.dispatchEvent(new Event('loadend'));
497
+ }
498
+ })
499
+ .catch((error) => {
500
+ this.dispatchEvent(new Event('loadstart'));
501
+ this.status = error.status;
502
+ this._headers = error.headers;
503
+ this.response = error.data;
504
+ this.responseText = JSON.stringify(error.data);
505
+ this.responseURL = error.url;
506
+ this.readyState = 4;
507
+ this.dispatchEvent(new Event('error'));
508
+ this.dispatchEvent(new Event('loadend'));
509
+ });
510
+ }
511
+ catch (error) {
512
+ this.dispatchEvent(new Event('loadstart'));
513
+ this.status = 500;
514
+ this._headers = {};
515
+ this.response = error;
516
+ this.responseText = error.toString();
517
+ this.responseURL = this._url;
518
+ this.readyState = 4;
519
+ this.dispatchEvent(new Event('error'));
520
+ this.dispatchEvent(new Event('loadend'));
521
+ }
522
+ };
523
+ // XHR patch getAllResponseHeaders
524
+ window.XMLHttpRequest.prototype.getAllResponseHeaders = function () {
525
+ let returnString = '';
526
+ for (const key in this._headers) {
527
+ if (key != 'Set-Cookie') {
528
+ returnString += key + ': ' + this._headers[key] + '\r\n';
529
+ }
530
+ }
531
+ return returnString;
532
+ };
533
+ // XHR patch getResponseHeader
534
+ window.XMLHttpRequest.prototype.getResponseHeader = function (name) {
535
+ return this._headers[name];
536
+ };
537
+ }
538
+ }
271
539
  // patch window.console on iOS and store original console fns
272
540
  const isIos = getPlatformId(win) === 'ios';
273
541
  if (win.console && isIos) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capacitor/ios",
3
- "version": "4.2.1-nightly-20220921T150520.0",
3
+ "version": "4.3.0",
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)",
@@ -30,5 +30,5 @@
30
30
  "publishConfig": {
31
31
  "access": "public"
32
32
  },
33
- "gitHead": "4706f8325864d6c32bc0ad7ff9c07848bcf32ccd"
33
+ "gitHead": "3d4433b505252d263784ec0fafc72a9b7cd8591e"
34
34
  }