@capgo/inappbrowser 0.0.1

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 (43) hide show
  1. package/CapgoInappbrowser.podspec +17 -0
  2. package/README.md +118 -0
  3. package/android/build.gradle +58 -0
  4. package/android/src/main/AndroidManifest.xml +3 -0
  5. package/android/src/main/java/ee/forgr/capacitor_inappbrowser/InAppBrowserPlugin.java +160 -0
  6. package/android/src/main/java/ee/forgr/capacitor_inappbrowser/Options.java +88 -0
  7. package/android/src/main/java/ee/forgr/capacitor_inappbrowser/WebViewCallbacks.java +7 -0
  8. package/android/src/main/java/ee/forgr/capacitor_inappbrowser/WebViewDialog.java +218 -0
  9. package/android/src/main/res/.gitkeep +0 -0
  10. package/android/src/main/res/drawable/arrow_back_disabled.xml +9 -0
  11. package/android/src/main/res/drawable/arrow_back_enabled.xml +9 -0
  12. package/android/src/main/res/drawable/arrow_forward_disabled.xml +9 -0
  13. package/android/src/main/res/drawable/arrow_forward_enabled.xml +9 -0
  14. package/android/src/main/res/drawable/ic_clear_24px.xml +9 -0
  15. package/android/src/main/res/layout/activity_browser.xml +22 -0
  16. package/android/src/main/res/layout/bridge_layout_main.xml +15 -0
  17. package/android/src/main/res/layout/content_browser.xml +16 -0
  18. package/android/src/main/res/layout/tool_bar.xml +50 -0
  19. package/android/src/main/res/values/colors.xml +5 -0
  20. package/android/src/main/res/values/dimens.xml +3 -0
  21. package/android/src/main/res/values/strings.xml +9 -0
  22. package/android/src/main/res/values/styles.xml +12 -0
  23. package/dist/docs.json +234 -0
  24. package/dist/esm/definitions.d.ts +34 -0
  25. package/dist/esm/definitions.js +8 -0
  26. package/dist/esm/definitions.js.map +1 -0
  27. package/dist/esm/index.d.ts +4 -0
  28. package/dist/esm/index.js +7 -0
  29. package/dist/esm/index.js.map +1 -0
  30. package/dist/esm/web.d.ts +7 -0
  31. package/dist/esm/web.js +16 -0
  32. package/dist/esm/web.js.map +1 -0
  33. package/dist/plugin.cjs.js +40 -0
  34. package/dist/plugin.cjs.js.map +1 -0
  35. package/dist/plugin.js +43 -0
  36. package/dist/plugin.js.map +1 -0
  37. package/ios/Plugin/Enums.swift +64 -0
  38. package/ios/Plugin/InAppBrowserPlugin.h +10 -0
  39. package/ios/Plugin/InAppBrowserPlugin.m +14 -0
  40. package/ios/Plugin/InAppBrowserPlugin.swift +191 -0
  41. package/ios/Plugin/Info.plist +24 -0
  42. package/ios/Plugin/WKWebViewController.swift +782 -0
  43. package/package.json +78 -0
@@ -0,0 +1,782 @@
1
+ //
2
+ // WKWebViewController.swift
3
+ // Sample
4
+ //
5
+ // Created by Meniny on 2018-01-20.
6
+ // Copyright © 2018年 Meniny. All rights reserved.
7
+ //
8
+
9
+ import UIKit
10
+ import WebKit
11
+
12
+ fileprivate let estimatedProgressKeyPath = "estimatedProgress"
13
+ fileprivate let titleKeyPath = "title"
14
+ fileprivate let cookieKey = "Cookie"
15
+
16
+ fileprivate struct UrlsHandledByApp {
17
+ public static var hosts = ["itunes.apple.com"]
18
+ public static var schemes = ["tel", "mailto", "sms"]
19
+ public static var blank = true
20
+ }
21
+
22
+ @objc public protocol WKWebViewControllerDelegate {
23
+ @objc optional func webViewController(_ controller: WKWebViewController, canDismiss url: URL) -> Bool
24
+
25
+ @objc optional func webViewController(_ controller: WKWebViewController, didStart url: URL)
26
+ @objc optional func webViewController(_ controller: WKWebViewController, didFinish url: URL)
27
+ @objc optional func webViewController(_ controller: WKWebViewController, didFail url: URL, withError error: Error)
28
+ @objc optional func webViewController(_ controller: WKWebViewController, decidePolicy url: URL, navigationType: NavigationType) -> Bool
29
+ }
30
+
31
+ open class WKWebViewController: UIViewController {
32
+
33
+ public init() {
34
+ super.init(nibName: nil, bundle: nil)
35
+ }
36
+
37
+ public required init?(coder aDecoder: NSCoder) {
38
+ super.init(coder: aDecoder)
39
+ }
40
+
41
+ public init(source: WKWebSource?) {
42
+ super.init(nibName: nil, bundle: nil)
43
+ self.source = source
44
+ self.initWebview()
45
+ }
46
+
47
+ public init(url: URL) {
48
+ super.init(nibName: nil, bundle: nil)
49
+ self.source = .remote(url)
50
+ self.initWebview()
51
+ }
52
+
53
+ public init(url: URL, headers: [String: String]) {
54
+ super.init(nibName: nil, bundle: nil)
55
+ self.source = .remote(url)
56
+ self.setHeaders(headers: headers)
57
+ self.initWebview()
58
+ }
59
+
60
+ open var hasDynamicTitle = false
61
+ open var source: WKWebSource?
62
+ /// use `source` instead
63
+ open internal(set) var url: URL?
64
+ open var tintColor: UIColor?
65
+ open var allowsFileURL = true
66
+ open var delegate: WKWebViewControllerDelegate?
67
+ open var bypassedSSLHosts: [String]?
68
+ open var cookies: [HTTPCookie]?
69
+ open var headers: [String: String]?
70
+ open var capBrowserPlugin: CapBrowser?
71
+ var shareDisclaimer: [String: Any]?
72
+ var shareSubject: String?
73
+ var didpageInit = false
74
+ var viewHeightLandscape: CGFloat?
75
+ var viewHeightPortrait: CGFloat?
76
+ var currentViewHeight: CGFloat?
77
+
78
+ func setHeaders(headers: [String: String]) {
79
+ self.headers = headers
80
+ let userAgent = self.headers?["User-Agent"]
81
+ self.headers?.removeValue(forKey: "User-Agent")
82
+ if userAgent != nil {
83
+ self.customUserAgent = userAgent
84
+ }
85
+ }
86
+
87
+ internal var customUserAgent: String? {
88
+ didSet {
89
+ guard let agent = userAgent else {
90
+ return
91
+ }
92
+ webView?.customUserAgent = agent
93
+ }
94
+ }
95
+
96
+ open var userAgent: String? {
97
+ didSet {
98
+ guard let originalUserAgent = originalUserAgent, let userAgent = userAgent else {
99
+ return
100
+ }
101
+ webView?.customUserAgent = [originalUserAgent, userAgent].joined(separator: " ")
102
+ }
103
+ }
104
+
105
+ open var pureUserAgent: String? {
106
+ didSet {
107
+ guard let agent = pureUserAgent else {
108
+ return
109
+ }
110
+ webView?.customUserAgent = agent
111
+ }
112
+ }
113
+
114
+ open var websiteTitleInNavigationBar = true
115
+ open var doneBarButtonItemPosition: NavigationBarPosition = .right
116
+ open var leftNavigaionBarItemTypes: [BarButtonItemType] = []
117
+ open var rightNavigaionBarItemTypes: [BarButtonItemType] = []
118
+ open var toolbarItemTypes: [BarButtonItemType] = [.back, .forward, .reload, .activity]
119
+
120
+ open var backBarButtonItemImage: UIImage?
121
+ open var forwardBarButtonItemImage: UIImage?
122
+ open var reloadBarButtonItemImage: UIImage?
123
+ open var stopBarButtonItemImage: UIImage?
124
+ open var activityBarButtonItemImage: UIImage?
125
+
126
+ fileprivate var webView: WKWebView?
127
+ fileprivate var progressView: UIProgressView?
128
+
129
+ fileprivate var previousNavigationBarState: (tintColor: UIColor, hidden: Bool) = (.black, false)
130
+ fileprivate var previousToolbarState: (tintColor: UIColor, hidden: Bool) = (.black, false)
131
+
132
+ fileprivate var originalUserAgent: String?
133
+
134
+ lazy fileprivate var backBarButtonItem: UIBarButtonItem = {
135
+ let bundle = Bundle(for: WKWebViewController.self)
136
+ return UIBarButtonItem(image: backBarButtonItemImage ?? UIImage(named: "Back", in: bundle, compatibleWith: nil), style: .plain, target: self, action: #selector(backDidClick(sender:)))
137
+ }()
138
+
139
+ lazy fileprivate var forwardBarButtonItem: UIBarButtonItem = {
140
+ let bundle = Bundle(for: WKWebViewController.self)
141
+ return UIBarButtonItem(image: forwardBarButtonItemImage ?? UIImage(named: "Forward", in: bundle, compatibleWith: nil), style: .plain, target: self, action: #selector(forwardDidClick(sender:)))
142
+ }()
143
+
144
+ lazy fileprivate var reloadBarButtonItem: UIBarButtonItem = {
145
+ if let image = reloadBarButtonItemImage {
146
+ return UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(reloadDidClick(sender:)))
147
+ } else {
148
+ return UIBarButtonItem(barButtonSystemItem: .refresh, target: self, action: #selector(reloadDidClick(sender:)))
149
+ }
150
+ }()
151
+
152
+ lazy fileprivate var stopBarButtonItem: UIBarButtonItem = {
153
+ if let image = stopBarButtonItemImage {
154
+ return UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(stopDidClick(sender:)))
155
+ } else {
156
+ return UIBarButtonItem(barButtonSystemItem: .stop, target: self, action: #selector(stopDidClick(sender:)))
157
+ }
158
+ }()
159
+
160
+ lazy fileprivate var activityBarButtonItem: UIBarButtonItem = {
161
+ if let image = activityBarButtonItemImage {
162
+ return UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(activityDidClick(sender:)))
163
+ } else {
164
+ return UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(activityDidClick(sender:)))
165
+ }
166
+ }()
167
+
168
+ lazy fileprivate var doneBarButtonItem: UIBarButtonItem = {
169
+ return UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneDidClick(sender:)))
170
+ }()
171
+
172
+ lazy fileprivate var flexibleSpaceBarButtonItem: UIBarButtonItem = {
173
+ return UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
174
+ }()
175
+
176
+ deinit {
177
+ webView?.removeObserver(self, forKeyPath: estimatedProgressKeyPath)
178
+ if websiteTitleInNavigationBar {
179
+ webView?.removeObserver(self, forKeyPath: titleKeyPath)
180
+ }
181
+ webView?.removeObserver(self, forKeyPath: #keyPath(WKWebView.url))
182
+ }
183
+
184
+ override open func viewDidLoad(){
185
+ super.viewDidLoad()
186
+ if self.webView == nil {
187
+ self.initWebview()
188
+ }
189
+ }
190
+
191
+ open func initWebview() {
192
+
193
+ self.view.backgroundColor = UIColor.white
194
+
195
+ self.extendedLayoutIncludesOpaqueBars = true
196
+ self.edgesForExtendedLayout = [.bottom]
197
+
198
+ let webConfiguration = WKWebViewConfiguration()
199
+ let webView = WKWebView(frame: .zero, configuration: webConfiguration)
200
+
201
+ webView.uiDelegate = self
202
+ webView.navigationDelegate = self
203
+
204
+ webView.allowsBackForwardNavigationGestures = true
205
+ webView.isMultipleTouchEnabled = true
206
+
207
+ webView.addObserver(self, forKeyPath: estimatedProgressKeyPath, options: .new, context: nil)
208
+ if websiteTitleInNavigationBar {
209
+ webView.addObserver(self, forKeyPath: titleKeyPath, options: .new, context: nil)
210
+ }
211
+ webView.addObserver(self, forKeyPath: #keyPath(WKWebView.url) , options: .new, context: nil)
212
+ // NotificationCenter.default.addObserver(self, selector: #selector(restateViewHeight), name: UIDevice.orientationDidChangeNotification, object: nil)
213
+
214
+ self.view = webView
215
+ self.webView = webView
216
+
217
+ self.webView?.customUserAgent = self.customUserAgent ?? self.userAgent ?? self.originalUserAgent
218
+
219
+ self.navigationItem.title = self.navigationItem.title ?? self.source?.absoluteString
220
+
221
+ if let navigation = self.navigationController {
222
+ self.previousNavigationBarState = (navigation.navigationBar.tintColor, navigation.navigationBar.isHidden)
223
+ self.previousToolbarState = (navigation.toolbar.tintColor, navigation.toolbar.isHidden)
224
+ }
225
+
226
+ // self.restateViewHeight()
227
+
228
+ if let s = self.source {
229
+ self.load(source: s)
230
+ } else {
231
+ print("[\(type(of: self))][Error] Invalid url")
232
+ }
233
+ }
234
+
235
+ open func setupViewElements() {
236
+ self.setUpProgressView()
237
+ self.setUpConstraints()
238
+ self.addBarButtonItems()
239
+ }
240
+
241
+ @objc func restateViewHeight() {
242
+ var bottomPadding = CGFloat(0.0)
243
+ var topPadding = CGFloat(0.0)
244
+ if #available(iOS 11.0, *) {
245
+ let window = UIApplication.shared.keyWindow
246
+ bottomPadding = (window?.safeAreaInsets.bottom)!
247
+ topPadding = (window?.safeAreaInsets.top)!
248
+ }
249
+ if UIDevice.current.orientation.isPortrait {
250
+ self.navigationController?.toolbar.isHidden = false
251
+ if self.viewHeightPortrait == nil {
252
+ self.viewHeightPortrait = self.view.safeAreaLayoutGuide.layoutFrame.size.height
253
+ if toolbarItemTypes.count == 0 {
254
+ self.viewHeightPortrait! = self.viewHeightPortrait! + bottomPadding
255
+ }
256
+ if self.navigationController?.navigationBar.isHidden == true {
257
+ self.viewHeightPortrait = self.viewHeightPortrait! + topPadding
258
+ }
259
+ }
260
+ self.currentViewHeight = self.viewHeightPortrait
261
+ } else if UIDevice.current.orientation.isLandscape {
262
+ self.navigationController?.toolbar.isHidden = false
263
+ if self.viewHeightLandscape == nil {
264
+ self.viewHeightLandscape = self.view.safeAreaLayoutGuide.layoutFrame.size.height
265
+ if toolbarItemTypes.count == 0 {
266
+ self.viewHeightLandscape! = self.viewHeightLandscape! + bottomPadding
267
+ }
268
+ if self.navigationController?.navigationBar.isHidden == true {
269
+ self.viewHeightLandscape = self.viewHeightLandscape! + topPadding
270
+ }
271
+ }
272
+ self.currentViewHeight = self.viewHeightLandscape
273
+ }
274
+ }
275
+
276
+ open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
277
+ // self.view.frame.size.height = self.currentViewHeight!
278
+ }
279
+
280
+ open override func viewWillLayoutSubviews() {
281
+ restateViewHeight()
282
+ if self.currentViewHeight != nil {
283
+ self.view.frame.size.height = self.currentViewHeight!
284
+ }
285
+ }
286
+
287
+ override open func viewWillAppear(_ animated: Bool) {
288
+ super.viewWillAppear(animated)
289
+ self.setupViewElements()
290
+ setUpState()
291
+ }
292
+
293
+ override open func viewWillDisappear(_ animated: Bool) {
294
+ super.viewWillDisappear(animated)
295
+ rollbackState()
296
+ }
297
+
298
+ override open func didReceiveMemoryWarning() {
299
+ super.didReceiveMemoryWarning()
300
+ // Dispose of any resources that can be recreated.
301
+ }
302
+
303
+ override open func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
304
+ switch keyPath {
305
+ case estimatedProgressKeyPath?:
306
+ guard let estimatedProgress = self.webView?.estimatedProgress else {
307
+ return
308
+ }
309
+ self.progressView?.alpha = 1
310
+ self.progressView?.setProgress(Float(estimatedProgress), animated: true)
311
+
312
+ if estimatedProgress >= 1.0 {
313
+ UIView.animate(withDuration: 0.3, delay: 0.3, options: .curveEaseOut, animations: {
314
+ self.progressView?.alpha = 0
315
+ }, completion: {
316
+ finished in
317
+ self.progressView?.setProgress(0, animated: false)
318
+ })
319
+ }
320
+ case titleKeyPath?:
321
+ if self.hasDynamicTitle {
322
+ self.navigationItem.title = webView?.url?.host
323
+ }
324
+ case "URL":
325
+ self.capBrowserPlugin?.notifyListeners("urlChangeEvent", data: ["url" : webView?.url?.absoluteString])
326
+ default:
327
+ super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
328
+ }
329
+ }
330
+ }
331
+
332
+ // MARK: - Public Methods
333
+ public extension WKWebViewController {
334
+
335
+ func load(source s: WKWebSource) {
336
+ switch s {
337
+ case .remote(let url):
338
+ self.load(remote: url)
339
+ case .file(let url, access: let access):
340
+ self.load(file: url, access: access)
341
+ case .string(let str, base: let base):
342
+ self.load(string: str, base: base)
343
+ }
344
+ }
345
+
346
+ func load(remote: URL) {
347
+ webView?.load(createRequest(url: remote))
348
+ }
349
+
350
+ func load(file: URL, access: URL) {
351
+ webView?.loadFileURL(file, allowingReadAccessTo: access)
352
+ }
353
+
354
+ func load(string: String, base: URL? = nil) {
355
+ webView?.loadHTMLString(string, baseURL: base)
356
+ }
357
+
358
+ func goBackToFirstPage() {
359
+ if let firstPageItem = webView?.backForwardList.backList.first {
360
+ webView?.go(to: firstPageItem)
361
+ }
362
+ }
363
+ }
364
+
365
+ // MARK: - Fileprivate Methods
366
+ fileprivate extension WKWebViewController {
367
+ var availableCookies: [HTTPCookie]? {
368
+ return cookies?.filter {
369
+ cookie in
370
+ var result = true
371
+ let url = self.source?.remoteURL
372
+ if let host = url?.host, !cookie.domain.hasSuffix(host) {
373
+ result = false
374
+ }
375
+ if cookie.isSecure && url?.scheme != "https" {
376
+ result = false
377
+ }
378
+
379
+ return result
380
+ }
381
+ }
382
+ func createRequest(url: URL) -> URLRequest {
383
+ var request = URLRequest(url: url)
384
+
385
+ // Set up headers
386
+ if let headers = headers {
387
+ for (field, value) in headers {
388
+ request.addValue(value, forHTTPHeaderField: field)
389
+ }
390
+ }
391
+
392
+ // Set up Cookies
393
+ if let cookies = availableCookies, let value = HTTPCookie.requestHeaderFields(with: cookies)[cookieKey] {
394
+ request.addValue(value, forHTTPHeaderField: cookieKey)
395
+ }
396
+
397
+ return request
398
+ }
399
+
400
+ func setUpProgressView() {
401
+ let progressView = UIProgressView(progressViewStyle: .default)
402
+ progressView.trackTintColor = UIColor(white: 1, alpha: 0)
403
+ self.progressView = progressView
404
+ // updateProgressViewFrame()
405
+ }
406
+
407
+ func setUpConstraints() {
408
+ if !(self.navigationController?.navigationBar.isHidden)! {
409
+ self.progressView?.frame.origin.y = CGFloat((self.navigationController?.navigationBar.frame.height)!)
410
+ self.navigationController?.navigationBar.addSubview(self.progressView!)
411
+ webView?.addObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: .new, context: nil)
412
+ }
413
+ }
414
+
415
+ func addBarButtonItems() {
416
+ func barButtonItem(_ type: BarButtonItemType) -> UIBarButtonItem? {
417
+ switch type {
418
+ case .back:
419
+ return backBarButtonItem
420
+ case .forward:
421
+ return forwardBarButtonItem
422
+ case .reload:
423
+ return reloadBarButtonItem
424
+ case .stop:
425
+ return stopBarButtonItem
426
+ case .activity:
427
+ return activityBarButtonItem
428
+ case .done:
429
+ return doneBarButtonItem
430
+ case .flexibleSpace:
431
+ return flexibleSpaceBarButtonItem
432
+ case .custom(let icon, let title, let action):
433
+ let item: BlockBarButtonItem
434
+ if let icon = icon {
435
+ item = BlockBarButtonItem(image: icon, style: .plain, target: self, action: #selector(customDidClick(sender:)))
436
+ } else {
437
+ item = BlockBarButtonItem(title: title, style: .plain, target: self, action: #selector(customDidClick(sender:)))
438
+ }
439
+ item.block = action
440
+ return item
441
+ }
442
+ }
443
+
444
+ // if presentingViewController != nil {
445
+ switch doneBarButtonItemPosition {
446
+ case .left:
447
+ if !leftNavigaionBarItemTypes.contains(where: { type in
448
+ switch type {
449
+ case .done:
450
+ return true
451
+ default:
452
+ return false
453
+ }
454
+ }) {
455
+ leftNavigaionBarItemTypes.insert(.done, at: 0)
456
+ }
457
+ case .right:
458
+ if !rightNavigaionBarItemTypes.contains(where: { type in
459
+ switch type {
460
+ case .done:
461
+ return true
462
+ default:
463
+ return false
464
+ }
465
+ }) {
466
+ rightNavigaionBarItemTypes.insert(.done, at: 0)
467
+ }
468
+ case .none:
469
+ break
470
+ }
471
+ // }
472
+
473
+ navigationItem.leftBarButtonItems = leftNavigaionBarItemTypes.map {
474
+ barButtonItemType in
475
+ if let barButtonItem = barButtonItem(barButtonItemType) {
476
+ return barButtonItem
477
+ }
478
+ return UIBarButtonItem()
479
+ }
480
+
481
+ navigationItem.rightBarButtonItems = rightNavigaionBarItemTypes.map {
482
+ barButtonItemType in
483
+ if let barButtonItem = barButtonItem(barButtonItemType) {
484
+ return barButtonItem
485
+ }
486
+ return UIBarButtonItem()
487
+ }
488
+
489
+ if toolbarItemTypes.count > 0 {
490
+ for index in 0..<toolbarItemTypes.count - 1 {
491
+ toolbarItemTypes.insert(.flexibleSpace, at: 2 * index + 1)
492
+ }
493
+ }
494
+
495
+ setToolbarItems(toolbarItemTypes.map {
496
+ barButtonItemType -> UIBarButtonItem in
497
+ if let barButtonItem = barButtonItem(barButtonItemType) {
498
+ return barButtonItem
499
+ }
500
+ return UIBarButtonItem()
501
+ }, animated: true)
502
+ }
503
+
504
+ func updateBarButtonItems() {
505
+ backBarButtonItem.isEnabled = webView?.canGoBack ?? false
506
+ forwardBarButtonItem.isEnabled = webView?.canGoForward ?? false
507
+
508
+ let updateReloadBarButtonItem: (UIBarButtonItem, Bool) -> UIBarButtonItem = {
509
+ [unowned self] barButtonItem, isLoading in
510
+ switch barButtonItem {
511
+ case self.reloadBarButtonItem:
512
+ fallthrough
513
+ case self.stopBarButtonItem:
514
+ return isLoading ? self.stopBarButtonItem : self.reloadBarButtonItem
515
+ default:
516
+ break
517
+ }
518
+ return barButtonItem
519
+ }
520
+
521
+ let isLoading = webView?.isLoading ?? false
522
+ toolbarItems = toolbarItems?.map {
523
+ barButtonItem -> UIBarButtonItem in
524
+ return updateReloadBarButtonItem(barButtonItem, isLoading)
525
+ }
526
+
527
+ navigationItem.leftBarButtonItems = navigationItem.leftBarButtonItems?.map {
528
+ barButtonItem -> UIBarButtonItem in
529
+ return updateReloadBarButtonItem(barButtonItem, isLoading)
530
+ }
531
+
532
+ navigationItem.rightBarButtonItems = navigationItem.rightBarButtonItems?.map {
533
+ barButtonItem -> UIBarButtonItem in
534
+ return updateReloadBarButtonItem(barButtonItem, isLoading)
535
+ }
536
+ }
537
+
538
+ func setUpState() {
539
+ navigationController?.setNavigationBarHidden(false, animated: true)
540
+ navigationController?.setToolbarHidden(toolbarItemTypes.count == 0, animated: true)
541
+
542
+ if let tintColor = tintColor {
543
+ progressView?.progressTintColor = tintColor
544
+ navigationController?.navigationBar.tintColor = tintColor
545
+ navigationController?.toolbar.tintColor = tintColor
546
+ }
547
+ }
548
+
549
+ func rollbackState() {
550
+ progressView?.progress = 0
551
+
552
+ navigationController?.navigationBar.tintColor = previousNavigationBarState.tintColor
553
+ navigationController?.toolbar.tintColor = previousToolbarState.tintColor
554
+
555
+ navigationController?.setToolbarHidden(previousToolbarState.hidden, animated: true)
556
+ navigationController?.setNavigationBarHidden(previousNavigationBarState.hidden, animated: true)
557
+ }
558
+
559
+ func checkRequestCookies(_ request: URLRequest, cookies: [HTTPCookie]) -> Bool {
560
+ if cookies.count <= 0 {
561
+ return true
562
+ }
563
+ guard let headerFields = request.allHTTPHeaderFields, let cookieString = headerFields[cookieKey] else {
564
+ return false
565
+ }
566
+
567
+ let requestCookies = cookieString.components(separatedBy: ";").map {
568
+ $0.trimmingCharacters(in: .whitespacesAndNewlines).split(separator: "=", maxSplits: 1).map(String.init)
569
+ }
570
+
571
+ var valid = false
572
+ for cookie in cookies {
573
+ valid = requestCookies.filter {
574
+ $0[0] == cookie.name && $0[1] == cookie.value
575
+ }.count > 0
576
+ if !valid {
577
+ break
578
+ }
579
+ }
580
+ return valid
581
+ }
582
+
583
+ func openURLWithApp(_ url: URL) -> Bool {
584
+ let application = UIApplication.shared
585
+ if application.canOpenURL(url) {
586
+ return application.openURL(url)
587
+ }
588
+
589
+ return false
590
+ }
591
+
592
+ func handleURLWithApp(_ url: URL, targetFrame: WKFrameInfo?) -> Bool {
593
+ let hosts = UrlsHandledByApp.hosts
594
+ let schemes = UrlsHandledByApp.schemes
595
+ let blank = UrlsHandledByApp.blank
596
+
597
+ var tryToOpenURLWithApp = false
598
+ if let host = url.host, hosts.contains(host) {
599
+ tryToOpenURLWithApp = true
600
+ }
601
+ if let scheme = url.scheme, schemes.contains(scheme) {
602
+ tryToOpenURLWithApp = true
603
+ }
604
+ if blank && targetFrame == nil {
605
+ tryToOpenURLWithApp = true
606
+ }
607
+
608
+ return tryToOpenURLWithApp ? openURLWithApp(url) : false
609
+ }
610
+
611
+ @objc func backDidClick(sender: AnyObject) {
612
+ webView?.goBack()
613
+ }
614
+
615
+ @objc func forwardDidClick(sender: AnyObject) {
616
+ webView?.goForward()
617
+ }
618
+
619
+ @objc func reloadDidClick(sender: AnyObject) {
620
+ webView?.stopLoading()
621
+ if webView?.url != nil {
622
+ webView?.reload()
623
+ } else if let s = self.source {
624
+ self.load(source: s)
625
+ }
626
+ }
627
+
628
+ @objc func stopDidClick(sender: AnyObject) {
629
+ webView?.stopLoading()
630
+ }
631
+
632
+ @objc func activityDidClick(sender: AnyObject) {
633
+ guard let s = self.source else {
634
+ return
635
+ }
636
+
637
+ let items: [Any]
638
+ switch s {
639
+ case .remote(let u):
640
+ items = [u]
641
+ case .file(let u, access: _):
642
+ items = [u]
643
+ case .string(let str, base: _):
644
+ items = [str]
645
+ }
646
+ showDisclaimer(items: items, sender: sender)
647
+ }
648
+
649
+ func showDisclaimer(items: [Any], sender: AnyObject) {
650
+ let showDisclaimer: Bool = self.shareDisclaimer != nil
651
+ if(showDisclaimer) {
652
+ let alert = UIAlertController(
653
+ title: self.shareDisclaimer?["title"] as? String ?? "Title",
654
+ message: self.shareDisclaimer?["message"] as? String ?? "Message",
655
+ preferredStyle: UIAlertController.Style.alert)
656
+ alert.addAction(UIAlertAction(title: self.shareDisclaimer?["confirmBtn"] as? String ?? "Confirm", style: UIAlertAction.Style.default, handler: { action in
657
+ self.shareDisclaimer = nil
658
+ self.capBrowserPlugin?.notifyListeners("confirmBtnClicked", data: nil)
659
+ let activityViewController = UIActivityViewController(activityItems: items, applicationActivities: nil)
660
+ activityViewController.setValue(self.shareSubject ?? self.title, forKey: "subject")
661
+ activityViewController.popoverPresentationController?.barButtonItem = (sender as! UIBarButtonItem)
662
+ self.present(activityViewController, animated: true, completion: nil)
663
+ }))
664
+ alert.addAction(UIAlertAction(title: self.shareDisclaimer?["cancelBtn"] as? String ?? "Cancel", style: UIAlertAction.Style.default, handler: nil))
665
+ self.present(alert, animated: true, completion: nil)
666
+ } else {
667
+ let activityViewController = UIActivityViewController(activityItems: items, applicationActivities: nil)
668
+ activityViewController.setValue(self.shareSubject ?? self.title, forKey: "subject")
669
+ activityViewController.popoverPresentationController?.barButtonItem = (sender as! UIBarButtonItem)
670
+ self.present(activityViewController, animated: true, completion: nil)
671
+ }
672
+ }
673
+
674
+ @objc func doneDidClick(sender: AnyObject) {
675
+ var canDismiss = true
676
+ if let url = self.source?.url {
677
+ canDismiss = delegate?.webViewController?(self, canDismiss: url) ?? true
678
+ }
679
+ if canDismiss {
680
+ // UIDevice.current.setValue(Int(UIInterfaceOrientation.portrait.rawValue), forKey: "orientation")
681
+ dismiss(animated: true, completion: nil)
682
+ }
683
+ }
684
+
685
+ @objc func customDidClick(sender: BlockBarButtonItem) {
686
+ sender.block?(self)
687
+ }
688
+
689
+ func canRotate() -> Void {}
690
+ }
691
+
692
+ // MARK: - WKUIDelegate
693
+ extension WKWebViewController: WKUIDelegate {
694
+
695
+ }
696
+
697
+ // MARK: - WKNavigationDelegate
698
+ extension WKWebViewController: WKNavigationDelegate {
699
+ public func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
700
+ updateBarButtonItems()
701
+ self.progressView?.progress = 0
702
+ if let u = webView.url {
703
+ self.url = u
704
+ delegate?.webViewController?(self, didStart: u)
705
+ }
706
+ }
707
+ public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
708
+ if !didpageInit && self.capBrowserPlugin?.isPresentAfterPageLoad == true {
709
+ self.capBrowserPlugin?.presentView()
710
+ }
711
+ didpageInit = true
712
+ updateBarButtonItems()
713
+ self.progressView?.progress = 0
714
+ if let url = webView.url {
715
+ self.url = url
716
+ delegate?.webViewController?(self, didFinish: url)
717
+ }
718
+ }
719
+
720
+ public func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
721
+ updateBarButtonItems()
722
+ self.progressView?.progress = 0
723
+ if let url = webView.url {
724
+ self.url = url
725
+ delegate?.webViewController?(self, didFail: url, withError: error)
726
+ }
727
+ }
728
+
729
+ public func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
730
+ updateBarButtonItems()
731
+ self.progressView?.progress = 0
732
+ if let url = webView.url {
733
+ self.url = url
734
+ delegate?.webViewController?(self, didFail: url, withError: error)
735
+ }
736
+ }
737
+
738
+ public func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
739
+ if let bypassedSSLHosts = bypassedSSLHosts, bypassedSSLHosts.contains(challenge.protectionSpace.host) {
740
+ let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
741
+ completionHandler(.useCredential, credential)
742
+ } else {
743
+ completionHandler(.performDefaultHandling, nil)
744
+ }
745
+ }
746
+
747
+ public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
748
+ var actionPolicy: WKNavigationActionPolicy = .allow
749
+ defer {
750
+ decisionHandler(actionPolicy)
751
+ }
752
+ guard let u = navigationAction.request.url else {
753
+ print("Cannot handle empty URLs")
754
+ return
755
+ }
756
+
757
+ if !self.allowsFileURL && u.isFileURL {
758
+ print("Cannot handle file URLs")
759
+ return
760
+ }
761
+
762
+ if handleURLWithApp(u, targetFrame: navigationAction.targetFrame) {
763
+ actionPolicy = .cancel
764
+ return
765
+ }
766
+
767
+ if u.host == self.source?.url?.host, let cookies = availableCookies, !checkRequestCookies(navigationAction.request, cookies: cookies) {
768
+ self.load(remote: u)
769
+ actionPolicy = .cancel
770
+ return
771
+ }
772
+
773
+ if let navigationType = NavigationType(rawValue: navigationAction.navigationType.rawValue), let result = delegate?.webViewController?(self, decidePolicy: u, navigationType: navigationType) {
774
+ actionPolicy = result ? .allow : .cancel
775
+ }
776
+ }
777
+ }
778
+
779
+ class BlockBarButtonItem: UIBarButtonItem {
780
+
781
+ var block: ((WKWebViewController) -> Void)?
782
+ }