@capgo/inappbrowser 7.0.0 → 7.1.6
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/CapgoInappbrowser.podspec +1 -1
- package/README.md +448 -54
- package/android/build.gradle +15 -13
- package/android/src/main/AndroidManifest.xml +2 -1
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/InAppBrowserPlugin.java +530 -35
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/Options.java +251 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/WebViewCallbacks.java +4 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/WebViewDialog.java +904 -20
- package/android/src/main/res/drawable/ic_refresh.xml +9 -0
- package/android/src/main/res/layout/tool_bar.xml +25 -3
- package/android/src/main/res/values/strings.xml +2 -0
- package/dist/docs.json +1365 -67
- package/dist/esm/definitions.d.ts +218 -9
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +10 -2
- package/dist/esm/web.js +26 -2
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +26 -2
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +26 -2
- package/dist/plugin.js.map +1 -1
- package/ios/Plugin/InAppBrowserPlugin.m +5 -1
- package/ios/Plugin/InAppBrowserPlugin.swift +247 -12
- package/ios/Plugin/WKWebViewController.swift +303 -55
- package/package.json +26 -27
|
@@ -19,6 +19,11 @@ private struct UrlsHandledByApp {
|
|
|
19
19
|
static var blank = true
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
public struct WKWebViewCredentials {
|
|
23
|
+
var username: String
|
|
24
|
+
var password: String
|
|
25
|
+
}
|
|
26
|
+
|
|
22
27
|
@objc public protocol WKWebViewControllerDelegate {
|
|
23
28
|
@objc optional func webViewController(_ controller: WKWebViewController, canDismiss url: URL) -> Bool
|
|
24
29
|
|
|
@@ -28,7 +33,17 @@ private struct UrlsHandledByApp {
|
|
|
28
33
|
@objc optional func webViewController(_ controller: WKWebViewController, decidePolicy url: URL, navigationType: NavigationType) -> Bool
|
|
29
34
|
}
|
|
30
35
|
|
|
31
|
-
|
|
36
|
+
extension Dictionary {
|
|
37
|
+
func mapKeys<T>(_ transform: (Key) throws -> T) rethrows -> [T: Value] {
|
|
38
|
+
var dictionary = [T: Value]()
|
|
39
|
+
for (key, value) in self {
|
|
40
|
+
dictionary[try transform(key)] = value
|
|
41
|
+
}
|
|
42
|
+
return dictionary
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
open class WKWebViewController: UIViewController, WKScriptMessageHandler {
|
|
32
47
|
|
|
33
48
|
public init() {
|
|
34
49
|
super.init(nibName: nil, bundle: nil)
|
|
@@ -38,23 +53,27 @@ open class WKWebViewController: UIViewController {
|
|
|
38
53
|
super.init(coder: aDecoder)
|
|
39
54
|
}
|
|
40
55
|
|
|
41
|
-
public init(source: WKWebSource?) {
|
|
56
|
+
public init(source: WKWebSource?, credentials: WKWebViewCredentials? = nil) {
|
|
42
57
|
super.init(nibName: nil, bundle: nil)
|
|
43
58
|
self.source = source
|
|
59
|
+
self.credentials = credentials
|
|
44
60
|
self.initWebview()
|
|
45
61
|
}
|
|
46
62
|
|
|
47
|
-
public init(url: URL) {
|
|
63
|
+
public init(url: URL, credentials: WKWebViewCredentials? = nil) {
|
|
48
64
|
super.init(nibName: nil, bundle: nil)
|
|
49
65
|
self.source = .remote(url)
|
|
66
|
+
self.credentials = credentials
|
|
50
67
|
self.initWebview()
|
|
51
68
|
}
|
|
52
69
|
|
|
53
|
-
public init(url: URL, headers: [String: String]) {
|
|
70
|
+
public init(url: URL, headers: [String: String], isInspectable: Bool, credentials: WKWebViewCredentials? = nil, preventDeeplink: Bool) {
|
|
54
71
|
super.init(nibName: nil, bundle: nil)
|
|
55
72
|
self.source = .remote(url)
|
|
73
|
+
self.credentials = credentials
|
|
56
74
|
self.setHeaders(headers: headers)
|
|
57
|
-
self.
|
|
75
|
+
self.setPreventDeeplink(preventDeeplink: preventDeeplink)
|
|
76
|
+
self.initWebview(isInspectable: isInspectable)
|
|
58
77
|
}
|
|
59
78
|
|
|
60
79
|
open var hasDynamicTitle = false
|
|
@@ -74,16 +93,34 @@ open class WKWebViewController: UIViewController {
|
|
|
74
93
|
var viewHeightLandscape: CGFloat?
|
|
75
94
|
var viewHeightPortrait: CGFloat?
|
|
76
95
|
var currentViewHeight: CGFloat?
|
|
96
|
+
open var closeModal = false
|
|
97
|
+
open var closeModalTitle = ""
|
|
98
|
+
open var closeModalDescription = ""
|
|
99
|
+
open var closeModalOk = ""
|
|
100
|
+
open var closeModalCancel = ""
|
|
101
|
+
open var ignoreUntrustedSSLError = false
|
|
102
|
+
var viewWasPresented = false
|
|
103
|
+
var preventDeeplink: Bool = false
|
|
104
|
+
|
|
105
|
+
internal var preShowSemaphore: DispatchSemaphore?
|
|
106
|
+
internal var preShowError: String?
|
|
77
107
|
|
|
78
108
|
func setHeaders(headers: [String: String]) {
|
|
79
109
|
self.headers = headers
|
|
80
|
-
let
|
|
110
|
+
let lowercasedHeaders = headers.mapKeys { $0.lowercased() }
|
|
111
|
+
let userAgent = lowercasedHeaders["user-agent"]
|
|
81
112
|
self.headers?.removeValue(forKey: "User-Agent")
|
|
82
|
-
|
|
113
|
+
self.headers?.removeValue(forKey: "user-agent")
|
|
114
|
+
|
|
115
|
+
if let userAgent = userAgent {
|
|
83
116
|
self.customUserAgent = userAgent
|
|
84
117
|
}
|
|
85
118
|
}
|
|
86
119
|
|
|
120
|
+
func setPreventDeeplink(preventDeeplink: Bool) {
|
|
121
|
+
self.preventDeeplink = preventDeeplink
|
|
122
|
+
}
|
|
123
|
+
|
|
87
124
|
internal var customUserAgent: String? {
|
|
88
125
|
didSet {
|
|
89
126
|
guard let agent = userAgent else {
|
|
@@ -113,7 +150,8 @@ open class WKWebViewController: UIViewController {
|
|
|
113
150
|
|
|
114
151
|
open var websiteTitleInNavigationBar = true
|
|
115
152
|
open var doneBarButtonItemPosition: NavigationBarPosition = .right
|
|
116
|
-
open var
|
|
153
|
+
open var preShowScript: String?
|
|
154
|
+
open var leftNavigationBarItemTypes: [BarButtonItemType] = []
|
|
117
155
|
open var rightNavigaionBarItemTypes: [BarButtonItemType] = []
|
|
118
156
|
open var toolbarItemTypes: [BarButtonItemType] = [.back, .forward, .reload, .activity]
|
|
119
157
|
|
|
@@ -123,6 +161,8 @@ open class WKWebViewController: UIViewController {
|
|
|
123
161
|
open var stopBarButtonItemImage: UIImage?
|
|
124
162
|
open var activityBarButtonItemImage: UIImage?
|
|
125
163
|
|
|
164
|
+
open var buttonNearDoneIcon: UIImage?
|
|
165
|
+
|
|
126
166
|
fileprivate var webView: WKWebView?
|
|
127
167
|
fileprivate var progressView: UIProgressView?
|
|
128
168
|
|
|
@@ -173,6 +213,8 @@ open class WKWebViewController: UIViewController {
|
|
|
173
213
|
return UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
|
|
174
214
|
}()
|
|
175
215
|
|
|
216
|
+
fileprivate var credentials: WKWebViewCredentials?
|
|
217
|
+
|
|
176
218
|
deinit {
|
|
177
219
|
webView?.removeObserver(self, forKeyPath: estimatedProgressKeyPath)
|
|
178
220
|
if websiteTitleInNavigationBar {
|
|
@@ -188,7 +230,66 @@ open class WKWebViewController: UIViewController {
|
|
|
188
230
|
}
|
|
189
231
|
}
|
|
190
232
|
|
|
191
|
-
open func
|
|
233
|
+
open func setCredentials(credentials: WKWebViewCredentials?) {
|
|
234
|
+
self.credentials = credentials
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Method to send a message from Swift to JavaScript
|
|
238
|
+
open func postMessageToJS(message: [String: Any]) {
|
|
239
|
+
if let jsonData = try? JSONSerialization.data(withJSONObject: message, options: []),
|
|
240
|
+
let jsonString = String(data: jsonData, encoding: .utf8) {
|
|
241
|
+
let script = "window.dispatchEvent(new CustomEvent('messageFromNative', { detail: \(jsonString) }));"
|
|
242
|
+
DispatchQueue.main.async {
|
|
243
|
+
self.webView?.evaluateJavaScript(script, completionHandler: nil)
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Method to receive messages from JavaScript
|
|
249
|
+
public func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
|
|
250
|
+
if message.name == "messageHandler" {
|
|
251
|
+
if let messageBody = message.body as? [String: Any] {
|
|
252
|
+
print("Received message from JavaScript:", messageBody)
|
|
253
|
+
self.capBrowserPlugin?.notifyListeners("messageFromWebview", data: messageBody)
|
|
254
|
+
} else {
|
|
255
|
+
print("Received non-dictionary message from JavaScript:", message.body)
|
|
256
|
+
self.capBrowserPlugin?.notifyListeners("messageFromWebview", data: ["rawMessage": String(describing: message.body)])
|
|
257
|
+
}
|
|
258
|
+
} else if message.name == "preShowScriptSuccess" {
|
|
259
|
+
guard let semaphore = preShowSemaphore else {
|
|
260
|
+
print("[InAppBrowser - preShowScriptSuccess]: Semaphore not found")
|
|
261
|
+
return
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
semaphore.signal()
|
|
265
|
+
} else if message.name == "preShowScriptError" {
|
|
266
|
+
guard let semaphore = preShowSemaphore else {
|
|
267
|
+
print("[InAppBrowser - preShowScriptError]: Semaphore not found")
|
|
268
|
+
return
|
|
269
|
+
}
|
|
270
|
+
print("[InAppBrowser - preShowScriptError]: Error!!!!")
|
|
271
|
+
semaphore.signal()
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
func injectJavaScriptInterface() {
|
|
276
|
+
let script = """
|
|
277
|
+
if (!window.mobileApp) {
|
|
278
|
+
window.mobileApp = {
|
|
279
|
+
postMessage: function(message) {
|
|
280
|
+
if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.messageHandler) {
|
|
281
|
+
window.webkit.messageHandlers.messageHandler.postMessage(message);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
"""
|
|
287
|
+
DispatchQueue.main.async {
|
|
288
|
+
self.webView?.evaluateJavaScript(script, completionHandler: nil)
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
open func initWebview(isInspectable: Bool = true) {
|
|
192
293
|
|
|
193
294
|
self.view.backgroundColor = UIColor.white
|
|
194
295
|
|
|
@@ -196,8 +297,18 @@ open class WKWebViewController: UIViewController {
|
|
|
196
297
|
self.edgesForExtendedLayout = [.bottom]
|
|
197
298
|
|
|
198
299
|
let webConfiguration = WKWebViewConfiguration()
|
|
300
|
+
let userContentController = WKUserContentController()
|
|
301
|
+
userContentController.add(self, name: "messageHandler")
|
|
302
|
+
userContentController.add(self, name: "preShowScriptError")
|
|
303
|
+
userContentController.add(self, name: "preShowScriptSuccess")
|
|
304
|
+
webConfiguration.userContentController = userContentController
|
|
199
305
|
let webView = WKWebView(frame: .zero, configuration: webConfiguration)
|
|
200
306
|
|
|
307
|
+
if webView.responds(to: Selector(("setInspectable:"))) {
|
|
308
|
+
// Fix: https://stackoverflow.com/questions/76216183/how-to-debug-wkwebview-in-ios-16-4-1-using-xcode-14-2/76603043#76603043
|
|
309
|
+
webView.perform(Selector(("setInspectable:")), with: isInspectable)
|
|
310
|
+
}
|
|
311
|
+
|
|
201
312
|
webView.uiDelegate = self
|
|
202
313
|
webView.navigationDelegate = self
|
|
203
314
|
|
|
@@ -223,8 +334,6 @@ open class WKWebViewController: UIViewController {
|
|
|
223
334
|
self.previousToolbarState = (navigation.toolbar.tintColor, navigation.toolbar.isHidden)
|
|
224
335
|
}
|
|
225
336
|
|
|
226
|
-
// self.restateViewHeight()
|
|
227
|
-
|
|
228
337
|
if let s = self.source {
|
|
229
338
|
self.load(source: s)
|
|
230
339
|
} else {
|
|
@@ -242,19 +351,19 @@ open class WKWebViewController: UIViewController {
|
|
|
242
351
|
var bottomPadding = CGFloat(0.0)
|
|
243
352
|
var topPadding = CGFloat(0.0)
|
|
244
353
|
if #available(iOS 11.0, *) {
|
|
245
|
-
let window = UIApplication.shared.
|
|
246
|
-
bottomPadding =
|
|
247
|
-
topPadding =
|
|
354
|
+
let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow })
|
|
355
|
+
bottomPadding = window?.safeAreaInsets.bottom ?? 0.0
|
|
356
|
+
topPadding = window?.safeAreaInsets.top ?? 0.0
|
|
248
357
|
}
|
|
249
358
|
if UIDevice.current.orientation.isPortrait {
|
|
250
359
|
self.navigationController?.toolbar.isHidden = false
|
|
251
360
|
if self.viewHeightPortrait == nil {
|
|
252
361
|
self.viewHeightPortrait = self.view.safeAreaLayoutGuide.layoutFrame.size.height
|
|
253
362
|
if toolbarItemTypes.count == 0 {
|
|
254
|
-
self.viewHeightPortrait!
|
|
363
|
+
self.viewHeightPortrait! += bottomPadding
|
|
255
364
|
}
|
|
256
365
|
if self.navigationController?.navigationBar.isHidden == true {
|
|
257
|
-
self.viewHeightPortrait
|
|
366
|
+
self.viewHeightPortrait! += topPadding
|
|
258
367
|
}
|
|
259
368
|
}
|
|
260
369
|
self.currentViewHeight = self.viewHeightPortrait
|
|
@@ -263,10 +372,10 @@ open class WKWebViewController: UIViewController {
|
|
|
263
372
|
if self.viewHeightLandscape == nil {
|
|
264
373
|
self.viewHeightLandscape = self.view.safeAreaLayoutGuide.layoutFrame.size.height
|
|
265
374
|
if toolbarItemTypes.count == 0 {
|
|
266
|
-
self.viewHeightLandscape!
|
|
375
|
+
self.viewHeightLandscape! += bottomPadding
|
|
267
376
|
}
|
|
268
377
|
if self.navigationController?.navigationBar.isHidden == true {
|
|
269
|
-
self.viewHeightLandscape
|
|
378
|
+
self.viewHeightLandscape! += topPadding
|
|
270
379
|
}
|
|
271
380
|
}
|
|
272
381
|
self.currentViewHeight = self.viewHeightLandscape
|
|
@@ -286,8 +395,11 @@ open class WKWebViewController: UIViewController {
|
|
|
286
395
|
|
|
287
396
|
override open func viewWillAppear(_ animated: Bool) {
|
|
288
397
|
super.viewWillAppear(animated)
|
|
289
|
-
self.
|
|
290
|
-
|
|
398
|
+
if !self.viewWasPresented {
|
|
399
|
+
self.setupViewElements()
|
|
400
|
+
setUpState()
|
|
401
|
+
self.viewWasPresented = true
|
|
402
|
+
}
|
|
291
403
|
}
|
|
292
404
|
|
|
293
405
|
override open func viewWillDisappear(_ animated: Bool) {
|
|
@@ -295,34 +407,33 @@ open class WKWebViewController: UIViewController {
|
|
|
295
407
|
rollbackState()
|
|
296
408
|
}
|
|
297
409
|
|
|
298
|
-
override open func didReceiveMemoryWarning() {
|
|
299
|
-
super.didReceiveMemoryWarning()
|
|
300
|
-
// Dispose of any resources that can be recreated.
|
|
301
|
-
}
|
|
302
|
-
|
|
303
410
|
override open func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
|
|
304
411
|
switch keyPath {
|
|
305
412
|
case estimatedProgressKeyPath?:
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
413
|
+
DispatchQueue.main.async {
|
|
414
|
+
guard let estimatedProgress = self.webView?.estimatedProgress else {
|
|
415
|
+
return
|
|
416
|
+
}
|
|
417
|
+
self.progressView?.alpha = 1
|
|
418
|
+
self.progressView?.setProgress(Float(estimatedProgress), animated: true)
|
|
419
|
+
|
|
420
|
+
if estimatedProgress >= 1.0 {
|
|
421
|
+
UIView.animate(withDuration: 0.3, delay: 0.3, options: .curveEaseOut, animations: {
|
|
422
|
+
self.progressView?.alpha = 0
|
|
423
|
+
}, completion: {
|
|
424
|
+
_ in
|
|
425
|
+
self.progressView?.setProgress(0, animated: false)
|
|
426
|
+
})
|
|
427
|
+
}
|
|
319
428
|
}
|
|
320
429
|
case titleKeyPath?:
|
|
321
430
|
if self.hasDynamicTitle {
|
|
322
431
|
self.navigationItem.title = webView?.url?.host
|
|
323
432
|
}
|
|
324
433
|
case "URL":
|
|
434
|
+
|
|
325
435
|
self.capBrowserPlugin?.notifyListeners("urlChangeEvent", data: ["url": webView?.url?.absoluteString ?? ""])
|
|
436
|
+
self.injectJavaScriptInterface()
|
|
326
437
|
default:
|
|
327
438
|
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
|
|
328
439
|
}
|
|
@@ -344,7 +455,9 @@ public extension WKWebViewController {
|
|
|
344
455
|
}
|
|
345
456
|
|
|
346
457
|
func load(remote: URL) {
|
|
347
|
-
|
|
458
|
+
DispatchQueue.main.async {
|
|
459
|
+
self.webView?.load(self.createRequest(url: remote))
|
|
460
|
+
}
|
|
348
461
|
}
|
|
349
462
|
|
|
350
463
|
func load(file: URL, access: URL) {
|
|
@@ -360,6 +473,15 @@ public extension WKWebViewController {
|
|
|
360
473
|
webView?.go(to: firstPageItem)
|
|
361
474
|
}
|
|
362
475
|
}
|
|
476
|
+
func reload() {
|
|
477
|
+
webView?.reload()
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
func executeScript(script: String, completion: ((Any?, Error?) -> Void)? = nil) {
|
|
481
|
+
DispatchQueue.main.async { [weak self] in
|
|
482
|
+
self?.webView?.evaluateJavaScript(script, completionHandler: completion)
|
|
483
|
+
}
|
|
484
|
+
}
|
|
363
485
|
}
|
|
364
486
|
|
|
365
487
|
// MARK: - Fileprivate Methods
|
|
@@ -444,7 +566,7 @@ fileprivate extension WKWebViewController {
|
|
|
444
566
|
// if presentingViewController != nil {
|
|
445
567
|
switch doneBarButtonItemPosition {
|
|
446
568
|
case .left:
|
|
447
|
-
if !
|
|
569
|
+
if !leftNavigationBarItemTypes.contains(where: { type in
|
|
448
570
|
switch type {
|
|
449
571
|
case .done:
|
|
450
572
|
return true
|
|
@@ -452,7 +574,7 @@ fileprivate extension WKWebViewController {
|
|
|
452
574
|
return false
|
|
453
575
|
}
|
|
454
576
|
}) {
|
|
455
|
-
|
|
577
|
+
leftNavigationBarItemTypes.insert(.done, at: 0)
|
|
456
578
|
}
|
|
457
579
|
case .right:
|
|
458
580
|
if !rightNavigaionBarItemTypes.contains(where: { type in
|
|
@@ -470,7 +592,7 @@ fileprivate extension WKWebViewController {
|
|
|
470
592
|
}
|
|
471
593
|
// }
|
|
472
594
|
|
|
473
|
-
navigationItem.leftBarButtonItems =
|
|
595
|
+
navigationItem.leftBarButtonItems = leftNavigationBarItemTypes.map {
|
|
474
596
|
barButtonItemType in
|
|
475
597
|
if let barButtonItem = barButtonItem(barButtonItemType) {
|
|
476
598
|
return barButtonItem
|
|
@@ -478,13 +600,17 @@ fileprivate extension WKWebViewController {
|
|
|
478
600
|
return UIBarButtonItem()
|
|
479
601
|
}
|
|
480
602
|
|
|
481
|
-
|
|
603
|
+
var rightBarButtons = rightNavigaionBarItemTypes.map {
|
|
482
604
|
barButtonItemType in
|
|
483
605
|
if let barButtonItem = barButtonItem(barButtonItemType) {
|
|
484
606
|
return barButtonItem
|
|
485
607
|
}
|
|
486
608
|
return UIBarButtonItem()
|
|
487
609
|
}
|
|
610
|
+
if rightBarButtons.count == 1 && buttonNearDoneIcon != nil && rightBarButtons[0] == doneBarButtonItem {
|
|
611
|
+
rightBarButtons.append(UIBarButtonItem(image: buttonNearDoneIcon, style: .plain, target: self, action: #selector(buttonNearDoneDidClick)))
|
|
612
|
+
}
|
|
613
|
+
navigationItem.rightBarButtonItems = rightBarButtons
|
|
488
614
|
|
|
489
615
|
if toolbarItemTypes.count > 0 {
|
|
490
616
|
for index in 0..<toolbarItemTypes.count - 1 {
|
|
@@ -492,13 +618,14 @@ fileprivate extension WKWebViewController {
|
|
|
492
618
|
}
|
|
493
619
|
}
|
|
494
620
|
|
|
495
|
-
|
|
621
|
+
let gen = toolbarItemTypes.map {
|
|
496
622
|
barButtonItemType -> UIBarButtonItem in
|
|
497
623
|
if let barButtonItem = barButtonItem(barButtonItemType) {
|
|
498
624
|
return barButtonItem
|
|
499
625
|
}
|
|
500
626
|
return UIBarButtonItem()
|
|
501
|
-
}
|
|
627
|
+
}
|
|
628
|
+
setToolbarItems(gen, animated: true)
|
|
502
629
|
}
|
|
503
630
|
|
|
504
631
|
func updateBarButtonItems() {
|
|
@@ -617,6 +744,10 @@ fileprivate extension WKWebViewController {
|
|
|
617
744
|
webView?.goForward()
|
|
618
745
|
}
|
|
619
746
|
|
|
747
|
+
@objc func buttonNearDoneDidClick(sender: AnyObject) {
|
|
748
|
+
self.capBrowserPlugin?.notifyListeners("buttonNearDoneClick", data: [:])
|
|
749
|
+
}
|
|
750
|
+
|
|
620
751
|
@objc func reloadDidClick(sender: AnyObject) {
|
|
621
752
|
webView?.stopLoading()
|
|
622
753
|
if webView?.url != nil {
|
|
@@ -666,13 +797,14 @@ fileprivate extension WKWebViewController {
|
|
|
666
797
|
self.present(alert, animated: true, completion: nil)
|
|
667
798
|
} else {
|
|
668
799
|
let activityViewController = UIActivityViewController(activityItems: items, applicationActivities: nil)
|
|
800
|
+
#imageLiteral(resourceName: "simulator_screenshot_B8B44B8D-EB30-425C-9BF4-1F37697A8459.png")
|
|
669
801
|
activityViewController.setValue(self.shareSubject ?? self.title, forKey: "subject")
|
|
670
802
|
activityViewController.popoverPresentationController?.barButtonItem = (sender as! UIBarButtonItem)
|
|
671
803
|
self.present(activityViewController, animated: true, completion: nil)
|
|
672
804
|
}
|
|
673
805
|
}
|
|
674
806
|
|
|
675
|
-
|
|
807
|
+
func closeView () {
|
|
676
808
|
var canDismiss = true
|
|
677
809
|
if let url = self.source?.url {
|
|
678
810
|
canDismiss = delegate?.webViewController?(self, canDismiss: url) ?? true
|
|
@@ -684,6 +816,21 @@ fileprivate extension WKWebViewController {
|
|
|
684
816
|
}
|
|
685
817
|
}
|
|
686
818
|
|
|
819
|
+
@objc func doneDidClick(sender: AnyObject) {
|
|
820
|
+
// check if closeModal is true, if true display alert before close
|
|
821
|
+
if self.closeModal {
|
|
822
|
+
let alert = UIAlertController(title: self.closeModalTitle, message: self.closeModalDescription, preferredStyle: UIAlertController.Style.alert)
|
|
823
|
+
alert.addAction(UIAlertAction(title: self.closeModalOk, style: UIAlertAction.Style.default, handler: { _ in
|
|
824
|
+
self.closeView()
|
|
825
|
+
}))
|
|
826
|
+
alert.addAction(UIAlertAction(title: self.closeModalCancel, style: UIAlertAction.Style.default, handler: nil))
|
|
827
|
+
self.present(alert, animated: true, completion: nil)
|
|
828
|
+
} else {
|
|
829
|
+
self.closeView()
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
}
|
|
833
|
+
|
|
687
834
|
@objc func customDidClick(sender: BlockBarButtonItem) {
|
|
688
835
|
sender.block?(self)
|
|
689
836
|
}
|
|
@@ -693,11 +840,61 @@ fileprivate extension WKWebViewController {
|
|
|
693
840
|
|
|
694
841
|
// MARK: - WKUIDelegate
|
|
695
842
|
extension WKWebViewController: WKUIDelegate {
|
|
696
|
-
|
|
843
|
+
public func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
|
|
844
|
+
// Ensure UI updates are on the main thread
|
|
845
|
+
DispatchQueue.main.async {
|
|
846
|
+
let alertController = UIAlertController(title: nil, message: message, preferredStyle: .alert)
|
|
847
|
+
alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in
|
|
848
|
+
completionHandler()
|
|
849
|
+
}))
|
|
850
|
+
self.present(alertController, animated: true, completion: nil)
|
|
851
|
+
}
|
|
852
|
+
}
|
|
697
853
|
}
|
|
698
854
|
|
|
699
855
|
// MARK: - WKNavigationDelegate
|
|
700
856
|
extension WKWebViewController: WKNavigationDelegate {
|
|
857
|
+
internal func injectPreShowScript() {
|
|
858
|
+
if preShowSemaphore != nil {
|
|
859
|
+
return
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
// TODO: implement interface
|
|
863
|
+
let script = """
|
|
864
|
+
async function preShowFunction() {
|
|
865
|
+
\(self.preShowScript ?? "")
|
|
866
|
+
};
|
|
867
|
+
preShowFunction().then(
|
|
868
|
+
() => window.webkit.messageHandlers.preShowScriptSuccess.postMessage({})
|
|
869
|
+
).catch(
|
|
870
|
+
err => {
|
|
871
|
+
console.error('Preshow error', err);
|
|
872
|
+
window.webkit.messageHandlers.preShowScriptError.postMessage(JSON.stringify(err, Object.getOwnPropertyNames(err)));
|
|
873
|
+
}
|
|
874
|
+
)
|
|
875
|
+
"""
|
|
876
|
+
print("[InAppBrowser - InjectPreShowScript] PreShowScript script: \(script)")
|
|
877
|
+
|
|
878
|
+
self.preShowSemaphore = DispatchSemaphore(value: 0)
|
|
879
|
+
self.executeScript(script: script) // this will run on the main thread
|
|
880
|
+
|
|
881
|
+
defer {
|
|
882
|
+
self.preShowSemaphore = nil
|
|
883
|
+
self.preShowError = nil
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
if self.preShowSemaphore?.wait(timeout: .now() + 10) == .timedOut {
|
|
887
|
+
print("[InAppBrowser - InjectPreShowScript] PreShowScript running for over 10 seconds. The plugin will not wait any longer!")
|
|
888
|
+
return
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
// "async function preShowFunction() {\n" +
|
|
892
|
+
// self.preShowScript + "\n" +
|
|
893
|
+
// "};\n" +
|
|
894
|
+
// "preShowFunction().then(() => window.PreShowScriptInterface.success()).catch(err => { console.error('Preshow error', err); window.PreShowScriptInterface.error(JSON.stringify(err, Object.getOwnPropertyNames(err))) })";
|
|
895
|
+
|
|
896
|
+
}
|
|
897
|
+
|
|
701
898
|
public func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
|
|
702
899
|
updateBarButtonItems()
|
|
703
900
|
self.progressView?.progress = 0
|
|
@@ -708,7 +905,21 @@ extension WKWebViewController: WKNavigationDelegate {
|
|
|
708
905
|
}
|
|
709
906
|
public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
|
710
907
|
if !didpageInit && self.capBrowserPlugin?.isPresentAfterPageLoad == true {
|
|
711
|
-
|
|
908
|
+
// injectPreShowScript will block, don't execute on the main thread
|
|
909
|
+
if self.preShowScript != nil && !self.preShowScript!.isEmpty {
|
|
910
|
+
DispatchQueue.global(qos: .userInitiated).async {
|
|
911
|
+
self.injectPreShowScript()
|
|
912
|
+
DispatchQueue.main.async { [weak self] in
|
|
913
|
+
self?.capBrowserPlugin?.presentView()
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
} else {
|
|
917
|
+
self.capBrowserPlugin?.presentView()
|
|
918
|
+
}
|
|
919
|
+
} else if self.preShowScript != nil && !self.preShowScript!.isEmpty && self.capBrowserPlugin?.isPresentAfterPageLoad == true {
|
|
920
|
+
DispatchQueue.global(qos: .userInitiated).async {
|
|
921
|
+
self.injectPreShowScript()
|
|
922
|
+
}
|
|
712
923
|
}
|
|
713
924
|
didpageInit = true
|
|
714
925
|
updateBarButtonItems()
|
|
@@ -717,6 +928,8 @@ extension WKWebViewController: WKNavigationDelegate {
|
|
|
717
928
|
self.url = url
|
|
718
929
|
delegate?.webViewController?(self, didFinish: url)
|
|
719
930
|
}
|
|
931
|
+
self.injectJavaScriptInterface()
|
|
932
|
+
self.capBrowserPlugin?.notifyListeners("browserPageLoaded", data: [:])
|
|
720
933
|
}
|
|
721
934
|
|
|
722
935
|
public func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
|
|
@@ -726,6 +939,7 @@ extension WKWebViewController: WKNavigationDelegate {
|
|
|
726
939
|
self.url = url
|
|
727
940
|
delegate?.webViewController?(self, didFail: url, withError: error)
|
|
728
941
|
}
|
|
942
|
+
self.capBrowserPlugin?.notifyListeners("pageLoadError", data: [:])
|
|
729
943
|
}
|
|
730
944
|
|
|
731
945
|
public func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
|
|
@@ -735,46 +949,76 @@ extension WKWebViewController: WKNavigationDelegate {
|
|
|
735
949
|
self.url = url
|
|
736
950
|
delegate?.webViewController?(self, didFail: url, withError: error)
|
|
737
951
|
}
|
|
952
|
+
self.capBrowserPlugin?.notifyListeners("pageLoadError", data: [:])
|
|
738
953
|
}
|
|
739
954
|
|
|
740
955
|
public func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
|
|
741
|
-
if let
|
|
956
|
+
if let credentials = credentials,
|
|
957
|
+
challenge.protectionSpace.receivesCredentialSecurely,
|
|
958
|
+
let url = webView.url, challenge.protectionSpace.host == url.host, challenge.protectionSpace.protocol == url.scheme, challenge.protectionSpace.port == url.port ?? (url.scheme == "https" ? 443 : url.scheme == "http" ? 80 : nil) {
|
|
959
|
+
let urlCredential = URLCredential(user: credentials.username, password: credentials.password, persistence: .none)
|
|
960
|
+
completionHandler(.useCredential, urlCredential)
|
|
961
|
+
} else if let bypassedSSLHosts = bypassedSSLHosts, bypassedSSLHosts.contains(challenge.protectionSpace.host) {
|
|
742
962
|
let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
|
|
743
963
|
completionHandler(.useCredential, credential)
|
|
744
964
|
} else {
|
|
745
|
-
|
|
965
|
+
guard self.ignoreUntrustedSSLError else {
|
|
966
|
+
completionHandler(.performDefaultHandling, nil)
|
|
967
|
+
return
|
|
968
|
+
}
|
|
969
|
+
/* allows to open links with self-signed certificates
|
|
970
|
+
Follow Apple's guidelines https://developer.apple.com/documentation/foundation/url_loading_system/handling_an_authentication_challenge/performing_manual_server_trust_authentication
|
|
971
|
+
*/
|
|
972
|
+
guard let serverTrust = challenge.protectionSpace.serverTrust else {
|
|
973
|
+
completionHandler(.useCredential, nil)
|
|
974
|
+
return
|
|
975
|
+
}
|
|
976
|
+
let credential = URLCredential(trust: serverTrust)
|
|
977
|
+
completionHandler(.useCredential, credential)
|
|
746
978
|
}
|
|
979
|
+
self.injectJavaScriptInterface()
|
|
747
980
|
}
|
|
748
981
|
|
|
749
982
|
public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
|
|
750
983
|
var actionPolicy: WKNavigationActionPolicy = .allow
|
|
751
|
-
|
|
752
|
-
|
|
984
|
+
|
|
985
|
+
if self.preventDeeplink {
|
|
986
|
+
actionPolicy = .preventDeeplinkActionPolicy
|
|
753
987
|
}
|
|
988
|
+
|
|
754
989
|
guard let u = navigationAction.request.url else {
|
|
755
|
-
|
|
990
|
+
decisionHandler(actionPolicy)
|
|
991
|
+
return
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
// Check if the URL is an App Store URL
|
|
995
|
+
if u.absoluteString.contains("apps.apple.com") {
|
|
996
|
+
UIApplication.shared.open(u, options: [:], completionHandler: nil)
|
|
997
|
+
// Cancel the navigation in the web view
|
|
998
|
+
decisionHandler(.cancel)
|
|
756
999
|
return
|
|
757
1000
|
}
|
|
758
1001
|
|
|
759
1002
|
if !self.allowsFileURL && u.isFileURL {
|
|
760
1003
|
print("Cannot handle file URLs")
|
|
1004
|
+
decisionHandler(.cancel)
|
|
761
1005
|
return
|
|
762
1006
|
}
|
|
763
1007
|
|
|
764
1008
|
if handleURLWithApp(u, targetFrame: navigationAction.targetFrame) {
|
|
765
1009
|
actionPolicy = .cancel
|
|
766
|
-
return
|
|
767
1010
|
}
|
|
768
1011
|
|
|
769
1012
|
if u.host == self.source?.url?.host, let cookies = availableCookies, !checkRequestCookies(navigationAction.request, cookies: cookies) {
|
|
770
1013
|
self.load(remote: u)
|
|
771
1014
|
actionPolicy = .cancel
|
|
772
|
-
return
|
|
773
1015
|
}
|
|
774
1016
|
|
|
775
1017
|
if let navigationType = NavigationType(rawValue: navigationAction.navigationType.rawValue), let result = delegate?.webViewController?(self, decidePolicy: u, navigationType: navigationType) {
|
|
776
1018
|
actionPolicy = result ? .allow : .cancel
|
|
777
1019
|
}
|
|
1020
|
+
self.injectJavaScriptInterface()
|
|
1021
|
+
decisionHandler(actionPolicy)
|
|
778
1022
|
}
|
|
779
1023
|
}
|
|
780
1024
|
|
|
@@ -782,3 +1026,7 @@ class BlockBarButtonItem: UIBarButtonItem {
|
|
|
782
1026
|
|
|
783
1027
|
var block: ((WKWebViewController) -> Void)?
|
|
784
1028
|
}
|
|
1029
|
+
|
|
1030
|
+
extension WKNavigationActionPolicy {
|
|
1031
|
+
static let preventDeeplinkActionPolicy = WKNavigationActionPolicy(rawValue: WKNavigationActionPolicy.allow.rawValue + 2)!
|
|
1032
|
+
}
|