@@ -11,28 +11,77 @@ public class SwiftFlutterSystemProxyPlugin: NSObject, FlutterPlugin {
1111 public func handle( _ call: FlutterMethodCall , result: @escaping FlutterResult ) {
1212 switch call. method {
1313 case " getDeviceProxy " :
14- let systemProxySettings = CFNetworkCopySystemProxySettings ( ) ? . takeUnretainedValue ( ) ?? [ : ] as CFDictionary
15- result ( systemProxySettings as NSDictionary )
16- break
17- case " executePAC " :
18- let systemProxySettings = CFNetworkCopySystemProxySettings ( ) ? . takeUnretainedValue ( ) ?? [ : ] as CFDictionary
19- let proxyDict = systemProxySettings as NSDictionary
20- if ( proxyDict. value ( forKey: " ProxyAutoConfigEnable " ) as! Bool ) {
21- let args = call. arguments as! NSDictionary
22- let url = args. value ( forKey: " url " ) as! String
23- let host = args. value ( forKey: " host " ) as! String
24- let js = args. value ( forKey: " js " ) as! String
25- let jsEngine : JSContext = JSContext ( )
26- jsEngine. evaluateScript ( js)
27- let fn = " FindProxyForURL( \" " + url + " \" , \" " + host+ " \" ) "
28- let proxy = jsEngine. evaluateScript ( fn)
29- result ( proxy? . toString ( ) )
30- } else {
31- result ( " DIRECT " )
32- }
14+ let args = call. arguments as! NSDictionary
15+ let url = args. value ( forKey: " url " ) as! String
16+ var dict : [ String : Any ] = [ : ]
17+ findProxyFromEnvironment ( url: url, callback: { host, port in
18+ dict [ " host " ] = host
19+ dict [ " port " ] = port
20+ result ( dict)
21+ } )
3322 break
3423 default :
3524 result ( FlutterMethodNotImplemented)
3625 }
3726 }
27+
28+ func findProxyFromEnvironment( url: String , callback: @escaping ( _ host: String ? , _ port: Int ? ) -> Void ) {
29+ let proxConfigDict = CFNetworkCopySystemProxySettings ( ) ? . takeUnretainedValue ( ) as NSDictionary ?
30+ if ( proxConfigDict != nil ) {
31+ if ( proxConfigDict![ " ProxyAutoConfigEnable " ] as? Int == 1 ) {
32+ let pacUrl = proxConfigDict![ " ProxyAutoConfigURLString " ] as? String
33+ let pacContent = proxConfigDict![ " ProxyAutoConfigJavaScript " ] as? String
34+ if ( pacContent != nil ) {
35+ self . handlePacContent ( pacContent: pacContent! as String , url: url, callback: callback)
36+ }
37+ downloadPac ( pacUrl: pacUrl!, callback: { pacContent, error in
38+
39+ if ( error != nil ) {
40+ callback ( nil , nil )
41+ } else {
42+ self . handlePacContent ( pacContent: pacContent!, url: url, callback: callback)
43+ }
44+ } )
45+ } else if ( proxConfigDict![ " HTTPEnable " ] as? Int == 1 ) {
46+ callback ( ( proxConfigDict![ " HTTPProxy " ] as? String ) , ( proxConfigDict![ " HTTPPort " ] as? Int ) )
47+ } else if ( proxConfigDict![ " HTTPSEnable " ] as? Int == 1 ) {
48+ callback ( ( proxConfigDict![ " HTTPSProxy " ] as? String ) , ( proxConfigDict![ " HTTPSPort " ] as? Int ) )
49+ } else {
50+ callback ( nil , nil )
51+ }
52+ }
53+ }
54+
55+ func handlePacContent( pacContent: String , url: String , callback: ( _ host: String ? , _ port: Int ? ) -> Void ) {
56+ let proxies = CFNetworkCopyProxiesForAutoConfigurationScript ( pacContent as CFString , CFURLCreateWithString ( kCFAllocatorDefault, url as CFString , nil ) , nil ) !. takeUnretainedValue ( ) as? [ [ CFString : Any ] ] ?? [ ] ;
57+ if ( proxies. count > 0 ) {
58+ let proxy = proxies. first { $0 [ kCFProxyTypeKey] as! CFString == kCFProxyTypeHTTP || $0 [ kCFProxyTypeKey] as! CFString == kCFProxyTypeHTTPS}
59+ if ( proxy != nil ) {
60+ let host = proxy ? [ kCFProxyHostNameKey] ?? nil
61+ let port = proxy ? [ kCFProxyPortNumberKey] ?? nil
62+ callback ( host as? String , port as? Int )
63+ } else {
64+ callback ( nil , nil )
65+ }
66+ } else {
67+ callback ( nil , nil )
68+ }
69+ }
70+
71+
72+ func downloadPac( pacUrl: String , callback: @escaping ( _ pacContent: String ? , _ error: Error ? ) -> Void ) {
73+ var pacContent : String = " "
74+ let config = URLSessionConfiguration . default
75+ config. connectionProxyDictionary = [ AnyHashable: Any] ( )
76+ let session = URLSession . init ( configuration: config, delegate: nil , delegateQueue: OperationQueue . current)
77+ session. dataTask ( with: URL ( string: pacUrl) !, completionHandler: { data, response, error in
78+ if ( error != nil ) {
79+ callback ( nil , error)
80+ }
81+ pacContent = String ( bytes: data!, encoding: String . Encoding. utf8) !
82+ callback ( pacContent, nil )
83+ } ) . resume ( )
84+
85+ }
86+
3887}
0 commit comments