SwiftFlutterPlugin.swift 31 KB
Newer Older
pichillilorenzo's avatar
pichillilorenzo committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 Licensed to the Apache Software Foundation (ASF) under one
 or more contributor license agreements.  See the NOTICE file
 distributed with this work for additional information
 regarding copyright ownership.  The ASF licenses this file
 to you under the Apache License, Version 2.0 (the
 "License"); you may not use this file except in compliance
 with the License.  You may obtain a copy of the License at
 http://www.apache.org/licenses/LICENSE-2.0
 Unless required by applicable law or agreed to in writing,
 software distributed under the License is distributed on an
 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 */

import Flutter
import UIKit
import WebKit
import Foundation
import AVFoundation
23
import SafariServices
pichillilorenzo's avatar
pichillilorenzo committed
24

25 26
let WEBVIEW_STORYBOARD = "WebView"
let WEBVIEW_STORYBOARD_CONTROLLER_ID = "viewController"
pichillilorenzo's avatar
pichillilorenzo committed
27

28 29 30 31 32 33 34 35
extension Dictionary where Key: ExpressibleByStringLiteral {
    public mutating func lowercaseKeys() {
        for key in self.keys {
            self[String(describing: key).lowercased() as! Key] = self.removeValue(forKey: key)
        }
    }
}

pichillilorenzo's avatar
pichillilorenzo committed
36
public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
pichillilorenzo's avatar
pichillilorenzo committed
37 38
    
    static var registrar: FlutterPluginRegistrar?
39
    static var channel: FlutterMethodChannel?
pichillilorenzo's avatar
pichillilorenzo committed
40
    
41
    static let webViewProcessPool: WKProcessPool = WKProcessPool()
42 43
    var webViewControllers: [String: InAppBrowserWebViewController?] = [:]
    var safariViewControllers: [String: Any?] = [:]
pichillilorenzo's avatar
pichillilorenzo committed
44 45 46 47 48
    
    var tmpWindow: UIWindow?
    private var previousStatusBarStyle = -1
    
    public init(with registrar: FlutterPluginRegistrar) {
49
        SwiftFlutterPlugin.channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_inappbrowser", binaryMessenger: registrar.messenger())
pichillilorenzo's avatar
pichillilorenzo committed
50 51 52
    }
    
    public static func register(with registrar: FlutterPluginRegistrar) {
pichillilorenzo's avatar
pichillilorenzo committed
53 54
        
        SwiftFlutterPlugin.registrar = registrar
55
        
pichillilorenzo's avatar
pichillilorenzo committed
56 57 58
        let channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_inappbrowser", binaryMessenger: registrar.messenger())
        let instance = SwiftFlutterPlugin(with: registrar)
        registrar.addMethodCallDelegate(instance, channel: channel)
59
        
60 61
        registrar.register(FlutterWebViewFactory(registrar: registrar) as FlutterPlatformViewFactory, withId: "com.pichillilorenzo/flutter_inappwebview")
        
62 63 64 65 66
        if #available(iOS 11.0, *) {
            MyCookieManager(registrar: registrar)
        } else {
            // Fallback on earlier versions
        }
pichillilorenzo's avatar
pichillilorenzo committed
67 68 69 70
    }
    
    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
        let arguments = call.arguments as? NSDictionary
pichillilorenzo's avatar
pichillilorenzo committed
71
        let uuid: String = arguments!["uuid"] as! String
pichillilorenzo's avatar
pichillilorenzo committed
72

pichillilorenzo's avatar
pichillilorenzo committed
73
        switch call.method {
74 75 76
            case "open":
                self.open(uuid: uuid, arguments: arguments!, result: result)
                break
pichillilorenzo's avatar
pichillilorenzo committed
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
            case "getUrl":
                if let webViewController = self.webViewControllers[uuid] {
                    result(webViewController!.webView.url?.absoluteString)
                }
                else {
                    result(nil)
                }
                break
            case "getTitle":
                if let webViewController = self.webViewControllers[uuid] {
                    result(webViewController!.webView.title)
                }
                else {
                    result(nil)
                }
                break
            case "getProgress":
                if let webViewController = self.webViewControllers[uuid] {
                    let progress = Int(webViewController!.webView.estimatedProgress * 100)
                    result(progress)
                }
                else {
                    result(nil)
                }
                break
102 103 104
            case "loadUrl":
                self.loadUrl(uuid: uuid, arguments: arguments!, result: result)
                break
pichillilorenzo's avatar
pichillilorenzo committed
105 106 107 108 109 110
            case "loadData":
                self.loadData(uuid: uuid, arguments: arguments!, result: result)
                break
            case "postUrl":
                self.postUrl(uuid: uuid, arguments: arguments!, result: result)
                break
pichillilorenzo's avatar
pichillilorenzo committed
111 112 113
            case "loadFile":
                self.loadFile(uuid: uuid, arguments: arguments!, result: result)
                break
114 115 116 117 118 119 120 121 122 123 124 125 126 127
            case "close":
                self.close(uuid: uuid)
                result(true)
                break
            case "show":
                self.show(uuid: uuid)
                result(true)
                break
            case "hide":
                self.hide(uuid: uuid)
                result(true)
                break
            case "reload":
                if let webViewController = self.webViewControllers[uuid] {
pichillilorenzo's avatar
pichillilorenzo committed
128
                    webViewController!.reload()
129 130 131 132 133
                }
                result(true)
                break
            case "goBack":
                if let webViewController = self.webViewControllers[uuid] {
pichillilorenzo's avatar
pichillilorenzo committed
134
                    webViewController!.goBack()
135 136 137 138 139
                }
                result(true)
                break
            case "canGoBack":
                if let webViewController = self.webViewControllers[uuid] {
pichillilorenzo's avatar
pichillilorenzo committed
140
                    result(webViewController!.canGoBack())
141 142 143 144 145 146 147
                }
                else {
                    result(false)
                }
                break
            case "goForward":
                if let webViewController = self.webViewControllers[uuid] {
pichillilorenzo's avatar
pichillilorenzo committed
148
                    webViewController!.goForward()
149 150 151 152 153
                }
                result(true)
                break
            case "canGoForward":
                if let webViewController = self.webViewControllers[uuid] {
pichillilorenzo's avatar
pichillilorenzo committed
154
                    result(webViewController!.canGoForward())
155 156 157 158 159
                }
                else {
                    result(false)
                }
                break
160 161 162
            case "goBackOrForward":
                if let webViewController = self.webViewControllers[uuid] {
                    let steps = arguments!["steps"] as! Int
pichillilorenzo's avatar
pichillilorenzo committed
163
                    webViewController!.goBackOrForward(steps: steps)
164 165 166 167 168 169
                }
                result(true)
                break
            case "canGoBackOrForward":
                if let webViewController = self.webViewControllers[uuid] {
                    let steps = arguments!["steps"] as! Int
pichillilorenzo's avatar
pichillilorenzo committed
170
                    result(webViewController!.canGoBackOrForward(steps: steps))
171 172 173 174 175
                }
                else {
                    result(false)
                }
                break
176 177
            case "isLoading":
                if let webViewController = self.webViewControllers[uuid] {
pichillilorenzo's avatar
pichillilorenzo committed
178
                    result(webViewController!.webView.isLoading == true)
179 180 181 182 183 184 185
                }
                else {
                    result(false)
                }
                break
            case "stopLoading":
                if let webViewController = self.webViewControllers[uuid] {
pichillilorenzo's avatar
pichillilorenzo committed
186
                    webViewController!.webView.stopLoading()
187 188 189 190 191
                }
                result(true)
                break
            case "isHidden":
                if let webViewController = self.webViewControllers[uuid] {
pichillilorenzo's avatar
pichillilorenzo committed
192
                    result(webViewController!.isHidden == true)
193 194 195 196 197 198 199 200 201
                }
                else {
                    result(false)
                }
                break
            case "injectScriptCode":
                self.injectScriptCode(uuid: uuid, arguments: arguments!, result: result)
                break
            case "injectScriptFile":
202
                self.injectScriptFile(uuid: uuid, arguments: arguments!)
203 204 205
                result(true)
                break
            case "injectStyleCode":
206
                self.injectStyleCode(uuid: uuid, arguments: arguments!)
207 208 209
                result(true)
                break
            case "injectStyleFile":
210
                self.injectStyleFile(uuid: uuid, arguments: arguments!)
211 212
                result(true)
                break
pichillilorenzo's avatar
pichillilorenzo committed
213 214
            case "takeScreenshot":
                if let webViewController = self.webViewControllers[uuid] {
215
                    webViewController!.webView.takeScreenshot(completionHandler: { (screenshot) -> Void in
pichillilorenzo's avatar
pichillilorenzo committed
216 217 218 219 220 221 222 223
                        result(screenshot)
                    })
                }
                else {
                    result(nil)
                }
                break
            case "setOptions":
224
                let optionsType = arguments!["optionsType"] as! String
pichillilorenzo's avatar
pichillilorenzo committed
225 226
                switch (optionsType){
                    case "InAppBrowserOptions":
227 228 229 230 231
                        let inAppBrowserOptions = InAppBrowserOptions()
                        let inAppBrowserOptionsMap = arguments!["options"] as! [String: Any]
                        inAppBrowserOptions.parse(options: inAppBrowserOptionsMap)
                        self.setOptions(uuid: uuid, options: inAppBrowserOptions, optionsMap: inAppBrowserOptionsMap)
                        break
pichillilorenzo's avatar
pichillilorenzo committed
232 233 234 235 236 237 238 239
                    default:
                        result(FlutterError(code: "InAppBrowserFlutterPlugin", message: "Options " + optionsType + " not available.", details: nil))
                }
                result(true)
                break
            case "getOptions":
                result(self.getOptions(uuid: uuid))
                break
240
            case "getCopyBackForwardList":
241 242
                result(self.getCopyBackForwardList(uuid: uuid))
                break
243 244 245
            default:
                result(FlutterMethodNotImplemented)
                break
pichillilorenzo's avatar
pichillilorenzo committed
246 247 248
        }
    }
    
249 250 251 252 253 254
    func close(uuid: String) {
        if let webViewController = self.webViewControllers[uuid] {
            // Things are cleaned up in browserExit.
            webViewController?.close()
        }
        else {
pichillilorenzo's avatar
pichillilorenzo committed
255 256 257 258 259 260 261 262 263 264 265
            print("IAB.close() called but it was already closed.")
        }
    }
    
    func isSystemUrl(_ url: URL) -> Bool {
        if (url.host == "itunes.apple.com") {
            return true
        }
        return false
    }
    
266
    public func open(uuid: String, arguments: NSDictionary, result: @escaping FlutterResult) {
pichillilorenzo's avatar
pichillilorenzo committed
267
        let isData: Bool = (arguments["isData"] as? Bool)!
268
        
pichillilorenzo's avatar
pichillilorenzo committed
269 270
        if !isData {
            let url: String = (arguments["url"] as? String)!
pichillilorenzo's avatar
pichillilorenzo committed
271

pichillilorenzo's avatar
pichillilorenzo committed
272 273 274 275
            let headers = (arguments["headers"] as? [String: String])!
            var absoluteUrl = URL(string: url)?.absoluteURL

            let useChromeSafariBrowser = (arguments["useChromeSafariBrowser"] as? Bool)!
pichillilorenzo's avatar
pichillilorenzo committed
276
            
pichillilorenzo's avatar
pichillilorenzo committed
277 278 279 280 281 282
            if useChromeSafariBrowser {
                let uuidFallback = (arguments["uuidFallback"] as? String)!
                let safariOptions = (arguments["options"] as? [String: Any])!
                
                let optionsFallback = (arguments["optionsFallback"] as? [String: Any])!
                
283
                open(uuid: uuid, uuidFallback: uuidFallback, inAppBrowser: absoluteUrl!, headers: headers, withOptions: safariOptions, useChromeSafariBrowser: true, withOptionsFallback: optionsFallback, result: result)
pichillilorenzo's avatar
pichillilorenzo committed
284 285
            }
            else {
pichillilorenzo's avatar
pichillilorenzo committed
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
                let options = (arguments["options"] as? [String: Any])!
                
                let isLocalFile = (arguments["isLocalFile"] as? Bool)!
                var openWithSystemBrowser = (arguments["openWithSystemBrowser"] as? Bool)!
                
                if isLocalFile {
                    let key = SwiftFlutterPlugin.registrar!.lookupKey(forAsset: url)
                    let assetURL = Bundle.main.url(forResource: key, withExtension: nil)
                    if assetURL == nil {
                        result(FlutterError(code: "InAppBrowserFlutterPlugin", message: url + " asset file cannot be found!", details: nil))
                        return
                    }
                    absoluteUrl = assetURL!
                }

                if isSystemUrl(absoluteUrl!) {
                    openWithSystemBrowser = true
                }
                
                if (openWithSystemBrowser) {
                    open(inSystem: absoluteUrl!, result: result)
                }
                else {
                    open(uuid: uuid, uuidFallback: nil, inAppBrowser: absoluteUrl!, headers: headers, withOptions: options, useChromeSafariBrowser: false, withOptionsFallback: nil, result: result)
                }
pichillilorenzo's avatar
pichillilorenzo committed
311 312
            }
        }
pichillilorenzo's avatar
pichillilorenzo committed
313 314 315 316 317 318 319 320 321
        else {
            let options = (arguments["options"] as? [String: Any])!
            let data = (arguments["data"] as? String)!
            let mimeType = (arguments["mimeType"] as? String)!
            let encoding = (arguments["encoding"] as? String)!
            let baseUrl = (arguments["baseUrl"] as? String)!
            open(uuid: uuid, options: options, data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl)
            result(true)
        }
pichillilorenzo's avatar
pichillilorenzo committed
322 323
    }
    
pichillilorenzo's avatar
pichillilorenzo committed
324
    func open(uuid: String, uuidFallback: String?, inAppBrowser url: URL, headers: [String: String], withOptions options: [String: Any], useChromeSafariBrowser: Bool, withOptionsFallback optionsFallback: [String: Any]?, result: @escaping FlutterResult) {
325
        
326
        var uuid = uuid
pichillilorenzo's avatar
pichillilorenzo committed
327
        
328 329
        if self.webViewControllers[uuid] != nil {
            close(uuid: uuid)
330
        }
331
        
332
        let safariViewController = self.safariViewControllers[uuid]
333 334 335
        if safariViewController != nil {
            if #available(iOS 9.0, *) {
                (safariViewController! as! SafariViewController).close()
336
                self.safariViewControllers[uuid] = nil
337 338 339 340 341 342
            } else {
                // Fallback on earlier versions
            }
        }
        
        if self.previousStatusBarStyle == -1 {
343 344 345 346 347 348 349 350
            self.previousStatusBarStyle = UIApplication.shared.statusBarStyle.rawValue
        }
        
        if !(self.tmpWindow != nil) {
            let frame: CGRect = UIScreen.main.bounds
            self.tmpWindow = UIWindow(frame: frame)
        }
        
351 352 353 354 355 356 357
        let tmpController = UIViewController()
        let baseWindowLevel = UIApplication.shared.keyWindow?.windowLevel
        self.tmpWindow?.rootViewController = tmpController
        self.tmpWindow?.windowLevel = UIWindowLevel(baseWindowLevel! + 1)
        self.tmpWindow?.makeKeyAndVisible()
        
        let browserOptions: InAppBrowserOptions
pichillilorenzo's avatar
pichillilorenzo committed
358
        let webViewOptions: InAppWebViewOptions
359 360 361
        
        if useChromeSafariBrowser == true {
            if #available(iOS 9.0, *) {
pichillilorenzo's avatar
pichillilorenzo committed
362 363
                let safariOptions = SafariBrowserOptions()
                safariOptions.parse(options: options)
364 365 366 367 368 369 370 371 372 373 374 375 376 377
                
                let safari: SafariViewController
                
                if #available(iOS 11.0, *) {
                    let config = SFSafariViewController.Configuration()
                    config.entersReaderIfAvailable = safariOptions.entersReaderIfAvailable
                    config.barCollapsingEnabled = safariOptions.barCollapsingEnabled
                    
                    safari = SafariViewController(url: url, configuration: config)
                } else {
                    // Fallback on earlier versions
                    safari = SafariViewController(url: url)
                }
                
378
                safari.uuid = uuid
379 380 381 382 383
                safari.delegate = safari
                safari.statusDelegate = self
                safari.tmpWindow = tmpWindow
                safari.safariOptions = safariOptions
                
384
                self.safariViewControllers[uuid] = safari
385
                
386 387
                tmpController.present(self.safariViewControllers[uuid]! as! SFSafariViewController, animated: true)
                onChromeSafariBrowserOpened(uuid: uuid)
pichillilorenzo's avatar
pichillilorenzo committed
388
                result(true)
389 390 391 392
                
                return
            }
            else {
393 394
                if uuidFallback == nil {
                    print("No WebView fallback declared.")
pichillilorenzo's avatar
pichillilorenzo committed
395 396
                    result(true)
                    
397 398 399
                    return
                }
                uuid = uuidFallback!
pichillilorenzo's avatar
pichillilorenzo committed
400 401 402 403 404
                browserOptions = InAppBrowserOptions()
                browserOptions.parse(options: optionsFallback!)
                
                webViewOptions = InAppWebViewOptions()
                webViewOptions.parse(options: optionsFallback!)
405 406 407
            }
        }
        else {
pichillilorenzo's avatar
pichillilorenzo committed
408 409 410 411 412
            browserOptions = InAppBrowserOptions()
            browserOptions.parse(options: options)
            
            webViewOptions = InAppWebViewOptions()
            webViewOptions.parse(options: options)
pichillilorenzo's avatar
pichillilorenzo committed
413 414
        }
        
415
        let storyboard = UIStoryboard(name: WEBVIEW_STORYBOARD, bundle: Bundle(for: InAppBrowserFlutterPlugin.self))
416
        let vc = storyboard.instantiateViewController(withIdentifier: WEBVIEW_STORYBOARD_CONTROLLER_ID)
417 418 419 420
        self.webViewControllers[uuid] = vc as? InAppBrowserWebViewController
        let webViewController: InAppBrowserWebViewController = self.webViewControllers[uuid] as! InAppBrowserWebViewController
        webViewController.uuid = uuid
        webViewController.browserOptions = browserOptions
pichillilorenzo's avatar
pichillilorenzo committed
421
        webViewController.webViewOptions = webViewOptions
422 423
        webViewController.isHidden = browserOptions.hidden
        webViewController.tmpWindow = tmpWindow
424
        webViewController.initURL = url
425 426
        webViewController.initHeaders = headers
        webViewController.navigationDelegate = self
427
        
428
        if browserOptions.hidden {
429 430
            webViewController.view.isHidden = true
            tmpController.present(webViewController, animated: false, completion: {() -> Void in
431 432 433
//                if self.previousStatusBarStyle != -1 {
//                    UIApplication.shared.statusBarStyle = UIStatusBarStyle(rawValue: self.previousStatusBarStyle)!
//                }
434
            })
435 436 437
//            if self.previousStatusBarStyle != -1 {
//                UIApplication.shared.statusBarStyle = UIStatusBarStyle(rawValue: self.previousStatusBarStyle)!
//            }
438
            webViewController.presentingViewController?.dismiss(animated: false, completion: {() -> Void in
439 440 441
                self.tmpWindow?.windowLevel = 0.0
                UIApplication.shared.delegate?.window??.makeKeyAndVisible()
            })
pichillilorenzo's avatar
pichillilorenzo committed
442
        }
443
        else {
444
            tmpController.present(webViewController, animated: true, completion: nil)
pichillilorenzo's avatar
pichillilorenzo committed
445
        }
pichillilorenzo's avatar
pichillilorenzo committed
446 447
        
        result(true)
pichillilorenzo's avatar
pichillilorenzo committed
448 449
    }
    
pichillilorenzo's avatar
pichillilorenzo committed
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
    func open(uuid: String, options: [String: Any], data: String, mimeType: String, encoding: String, baseUrl: String) {
        
        var uuid = uuid
        
        if self.webViewControllers[uuid] != nil {
            close(uuid: uuid)
        }
        
        if self.previousStatusBarStyle == -1 {
            self.previousStatusBarStyle = UIApplication.shared.statusBarStyle.rawValue
        }
        
        if !(self.tmpWindow != nil) {
            let frame: CGRect = UIScreen.main.bounds
            self.tmpWindow = UIWindow(frame: frame)
        }
        
        let tmpController = UIViewController()
        let baseWindowLevel = UIApplication.shared.keyWindow?.windowLevel
        self.tmpWindow?.rootViewController = tmpController
        self.tmpWindow?.windowLevel = UIWindowLevel(baseWindowLevel! + 1)
        self.tmpWindow?.makeKeyAndVisible()
        
        let browserOptions: InAppBrowserOptions
        let webViewOptions: InAppWebViewOptions
        
        browserOptions = InAppBrowserOptions()
        browserOptions.parse(options: options)
        
        webViewOptions = InAppWebViewOptions()
        webViewOptions.parse(options: options)
        
        let storyboard = UIStoryboard(name: WEBVIEW_STORYBOARD, bundle: Bundle(for: InAppBrowserFlutterPlugin.self))
        let vc = storyboard.instantiateViewController(withIdentifier: WEBVIEW_STORYBOARD_CONTROLLER_ID)
        self.webViewControllers[uuid] = vc as? InAppBrowserWebViewController
        let webViewController: InAppBrowserWebViewController = self.webViewControllers[uuid] as! InAppBrowserWebViewController
        webViewController.uuid = uuid
        webViewController.browserOptions = browserOptions
        webViewController.webViewOptions = webViewOptions
        webViewController.isHidden = browserOptions.hidden
        webViewController.tmpWindow = tmpWindow
        webViewController.initData = data
        webViewController.initMimeType = mimeType
        webViewController.initEncoding = encoding
        webViewController.initBaseUrl = baseUrl
        webViewController.navigationDelegate = self
        
        if browserOptions.hidden {
            webViewController.view.isHidden = true
            tmpController.present(webViewController, animated: false, completion: {() -> Void in
500
                webViewController.webView.loadData(data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl)
pichillilorenzo's avatar
pichillilorenzo committed
501 502 503 504 505 506 507 508
            })
            webViewController.presentingViewController?.dismiss(animated: false, completion: {() -> Void in
                self.tmpWindow?.windowLevel = 0.0
                UIApplication.shared.delegate?.window??.makeKeyAndVisible()
            })
        }
        else {
            tmpController.present(webViewController, animated: true, completion: {() -> Void in
509
                webViewController.webView.loadData(data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl)
pichillilorenzo's avatar
pichillilorenzo committed
510 511 512 513 514
            })
        }
        
    }
    
515 516 517
    func open(inSystem url: URL, result: @escaping FlutterResult) {
        if !UIApplication.shared.canOpenURL(url) {
            result(FlutterError(code: "InAppBrowserFlutterPlugin", message: url.absoluteString + " cannot be opened!", details: nil))
pichillilorenzo's avatar
pichillilorenzo committed
518
            return
pichillilorenzo's avatar
pichillilorenzo committed
519
        }
pichillilorenzo's avatar
pichillilorenzo committed
520
        else {
521 522 523 524
            if #available(iOS 10.0, *) {
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
            } else {
                UIApplication.shared.openURL(url)
pichillilorenzo's avatar
pichillilorenzo committed
525
            }
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
        }
        result(true)
    }
    
    public func show(uuid: String) {
        if let webViewController = self.webViewControllers[uuid] {
            if webViewController != nil {
                webViewController?.isHidden = false
                webViewController?.view.isHidden = false
                
                // Run later to avoid the "took a long time" log message.
                DispatchQueue.main.async(execute: {() -> Void in
                    if webViewController != nil {
                        let baseWindowLevel = UIApplication.shared.keyWindow?.windowLevel
                        self.tmpWindow?.windowLevel = UIWindowLevel(baseWindowLevel! + 1)
                        self.tmpWindow?.makeKeyAndVisible()
                        UIApplication.shared.delegate?.window??.makeKeyAndVisible()
                        self.tmpWindow?.rootViewController?.present(webViewController!, animated: true, completion: nil)
                    }
                })
            }
            else {
                print("Tried to hide IAB after it was closed.")
pichillilorenzo's avatar
pichillilorenzo committed
549
            }
550
        }
pichillilorenzo's avatar
pichillilorenzo committed
551
    }
552

553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
    public func hide(uuid: String) {
        if let webViewController = self.webViewControllers[uuid] {
            if webViewController != nil {
                webViewController?.isHidden = true
                
                // Run later to avoid the "took a long time" log message.
                DispatchQueue.main.async(execute: {() -> Void in
                    if webViewController != nil {
                        webViewController?.presentingViewController?.dismiss(animated: true, completion: {() -> Void in
                            self.tmpWindow?.windowLevel = 0.0
                            UIApplication.shared.delegate?.window??.makeKeyAndVisible()
                            if self.previousStatusBarStyle != -1 {
                                UIApplication.shared.statusBarStyle = UIStatusBarStyle(rawValue: self.previousStatusBarStyle)!
                            }
                        })
568
                    }
pichillilorenzo's avatar
pichillilorenzo committed
569 570
                })
            }
571 572 573 574
            else {
                print("Tried to hide IAB after it was closed.")
            }
        }
pichillilorenzo's avatar
pichillilorenzo committed
575 576
    }
    
577 578 579 580 581 582 583 584 585 586 587 588
    public func loadUrl(uuid: String, arguments: NSDictionary, result: @escaping FlutterResult) {
        if let webViewController = self.webViewControllers[uuid] {
            if let url = arguments["url"] as? String {
                let headers = (arguments["headers"] as? [String: String])!
                let absoluteUrl = URL(string: url)!.absoluteURL
                webViewController!.loadUrl(url: absoluteUrl, headers: headers)
            }
            else {
                result(FlutterError(code: "InAppBrowserFlutterPlugin", message: "url is empty", details: nil))
                return
            }
            result(true)
589
        }
pichillilorenzo's avatar
pichillilorenzo committed
590
        else {
591
            result(FlutterError(code: "InAppBrowserFlutterPlugin", message: "webView is null", details: nil))
pichillilorenzo's avatar
pichillilorenzo committed
592 593 594
        }
    }
    
595
    public func loadData(uuid: String, arguments: NSDictionary, result: @escaping FlutterResult) {
596
        if let webViewController = self.webViewControllers[uuid] {
597 598 599 600 601 602 603 604 605
            let data = (arguments["data"] as? String)!
            let mimeType = (arguments["mimeType"] as? String)!
            let encoding = (arguments["encoding"] as? String)!
            let baseUrl = (arguments["baseUrl"] as? String)!
            webViewController!.webView.loadData(data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl)
            result(true)
        }
        else {
            result(FlutterError(code: "InAppBrowserFlutterPlugin", message: "webView is null", details: nil))
pichillilorenzo's avatar
pichillilorenzo committed
606 607 608
        }
    }
    
609
    public func postUrl(uuid: String, arguments: NSDictionary, result: @escaping FlutterResult) {
pichillilorenzo's avatar
pichillilorenzo committed
610
        if let webViewController = self.webViewControllers[uuid] {
611 612 613 614 615 616 617 618 619 620 621 622 623 624
            if let url = arguments["url"] as? String {
                let postData = (arguments["postData"] as? FlutterStandardTypedData)!
                let absoluteUrl = URL(string: url)!.absoluteURL
                webViewController!.webView.postUrl(url: absoluteUrl, postData: postData.data, completionHandler: { () -> Void in
                    result(true)
                })
            }
            else {
                result(FlutterError(code: "InAppBrowserFlutterPlugin", message: "url is empty", details: nil))
                return
            }
        }
        else {
            result(FlutterError(code: "InAppBrowserFlutterPlugin", message: "webView is null", details: nil))
pichillilorenzo's avatar
pichillilorenzo committed
625 626 627
        }
    }
    
628
    public func loadFile(uuid: String, arguments: NSDictionary, result: @escaping FlutterResult) {
629
        if let webViewController = self.webViewControllers[uuid] {
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
            if let url = arguments["url"] as? String {
                let headers = (arguments["headers"] as? [String: String])!
                do {
                    try webViewController!.webView.loadFile(url: url, headers: headers)
                }
                catch let error as NSError {
                    dump(error)
                    result(FlutterError(code: "InAppBrowserFlutterPlugin", message: error.localizedDescription, details: nil))
                    return
                }
            }
            else {
                result(FlutterError(code: "InAppBrowserFlutterPlugin", message: "url is empty", details: nil))
                return
            }
            result(true)
        }
        else {
            result(FlutterError(code: "InAppBrowserFlutterPlugin", message: "webView is null", details: nil))
649
        }
pichillilorenzo's avatar
pichillilorenzo committed
650 651
    }
    
652
    public func injectScriptCode(uuid: String, arguments: NSDictionary, result: @escaping FlutterResult) {
653
        if let webViewController = self.webViewControllers[uuid] {
654 655 656 657
            webViewController!.webView.injectScriptCode(source: arguments["source"] as! String, result: result)
        }
        else {
            result(FlutterError(code: "InAppBrowserFlutterPlugin", message: "webView is null", details: nil))
658
        }
pichillilorenzo's avatar
pichillilorenzo committed
659 660
    }
    
661
    public func injectScriptFile(uuid: String, arguments: NSDictionary) {
662
        if let webViewController = self.webViewControllers[uuid] {
663
            webViewController!.webView.injectScriptFile(urlFile: arguments["urlFile"] as! String)
664
        }
665 666
    }
    
667
    public func injectStyleCode(uuid: String, arguments: NSDictionary) {
pichillilorenzo's avatar
pichillilorenzo committed
668
        if let webViewController = self.webViewControllers[uuid] {
669
            webViewController!.webView.injectStyleCode(source: arguments["source"] as! String)
pichillilorenzo's avatar
pichillilorenzo committed
670 671 672
        }
    }
    
673 674 675
    public func injectStyleFile(uuid: String, arguments: NSDictionary) {
        if let webViewController = self.webViewControllers[uuid] {
            webViewController!.webView.injectStyleFile(urlFile: arguments["urlFile"] as! String)
676 677 678
        }
    }
    
679
    func onBrowserCreated(uuid: String, webView: WKWebView) {
pichillilorenzo's avatar
pichillilorenzo committed
680
        if let webViewController = self.webViewControllers[uuid] {
681
            SwiftFlutterPlugin.channel!.invokeMethod("onBrowserCreated", arguments: ["uuid": uuid])
pichillilorenzo's avatar
pichillilorenzo committed
682 683 684
        }
    }
    
685
    func onExit(uuid: String) {
686
        SwiftFlutterPlugin.channel!.invokeMethod("onExit", arguments: ["uuid": uuid])
687 688
    }
    
689
    func onChromeSafariBrowserOpened(uuid: String) {
690
        if self.safariViewControllers[uuid] != nil {
691
            SwiftFlutterPlugin.channel!.invokeMethod("onChromeSafariBrowserOpened", arguments: ["uuid": uuid])
692
        }
693 694
    }
    
695
    func onChromeSafariBrowserLoaded(uuid: String) {
696
        if self.safariViewControllers[uuid] != nil {
697
            SwiftFlutterPlugin.channel!.invokeMethod("onChromeSafariBrowserLoaded", arguments: ["uuid": uuid])
698
        }
699 700
    }
    
701
    func onChromeSafariBrowserClosed(uuid: String) {
702
        SwiftFlutterPlugin.channel!.invokeMethod("onChromeSafariBrowserClosed", arguments: ["uuid": uuid])
703 704
    }
    
705 706 707 708 709 710 711 712
    func safariExit(uuid: String) {
        if let safariViewController = self.safariViewControllers[uuid] {
            if #available(iOS 9.0, *) {
                (safariViewController as! SafariViewController).statusDelegate = nil
                (safariViewController as! SafariViewController).delegate = nil
            }
            self.safariViewControllers[uuid] = nil
            onChromeSafariBrowserClosed(uuid: uuid)
713 714 715
        }
    }
    
716 717 718 719 720 721 722 723 724 725 726 727 728
    func browserExit(uuid: String) {
        if let webViewController = self.webViewControllers[uuid] {
            // Set navigationDelegate to nil to ensure no callbacks are received from it.
            webViewController?.navigationDelegate = nil
            // Don't recycle the ViewController since it may be consuming a lot of memory.
            // Also - this is required for the PDF/User-Agent bug work-around.
            self.webViewControllers[uuid] = nil
            
            if previousStatusBarStyle != -1 {
                UIApplication.shared.statusBarStyle = UIStatusBarStyle(rawValue: previousStatusBarStyle)!
            }
            
            onExit(uuid: uuid)
729
        }
pichillilorenzo's avatar
pichillilorenzo committed
730 731
    }
    
pichillilorenzo's avatar
pichillilorenzo committed
732 733 734 735 736 737 738 739 740 741 742 743 744
    func setOptions(uuid: String, options: InAppBrowserOptions, optionsMap: [String: Any]) {
        if let webViewController = self.webViewControllers[uuid] {
            webViewController!.setOptions(newOptions: options, newOptionsMap: optionsMap)
        }
    }
    
    func getOptions(uuid: String) -> [String: Any]? {
        if let webViewController = self.webViewControllers[uuid] {
            return webViewController!.getOptions()
        }
        return nil
    }
    
745 746
    func getCopyBackForwardList(uuid: String) -> [String: Any]? {
        if let webViewController = self.webViewControllers[uuid] {
747
            return webViewController!.webView.getCopyBackForwardList()
748 749 750 751
        }
        return nil
    }
    
pichillilorenzo's avatar
pichillilorenzo committed
752
}