iosWebViewFix/ios/Classes/MyURLProtocol.swift

150 lines
5.5 KiB
Swift
Raw Normal View History

//
// MyURLProtocol.swift
// Pods
//
// Created by Lorenzo on 12/10/18.
//
import Foundation
import WebKit
func currentTimeInMilliSeconds() -> Int {
let currentDate = Date()
let since1970 = currentDate.timeIntervalSince1970
return Int(since1970 * 1000)
}
class MyURLProtocol: URLProtocol {
// struct Constants {
// static let RequestHandledKey = "URLProtocolRequestHandled"
// }
var wkWebViewUuid: String?
var session: URLSession?
var sessionTask: URLSessionDataTask?
var response: URLResponse?
var data: Data?
static var wkWebViewDelegateMap: [String: MyURLProtocolDelegate] = [:]
var loadingTime: Int = 0
override init(request: URLRequest, cachedResponse: CachedURLResponse?, client: URLProtocolClient?) {
super.init(request: request, cachedResponse: cachedResponse, client: client)
self.wkWebViewUuid = MyURLProtocol.getUuid(request)
if session == nil && self.wkWebViewUuid != nil {
session = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
}
}
override class func canInit(with request: URLRequest) -> Bool {
if getUuid(request) == nil {
return false
}
// if MyURLProtocol.property(forKey: Constants.RequestHandledKey, in: request) != nil {
// return false
// }
return true
}
override class func canonicalRequest(for request: URLRequest) -> URLRequest {
return request
}
override func startLoading() {
let newRequest = ((request as NSURLRequest).mutableCopy() as? NSMutableURLRequest)!
loadingTime = currentTimeInMilliSeconds()
//MyURLProtocol.setProperty(true, forKey: Constants.RequestHandledKey, in: newRequest)
sessionTask = session?.dataTask(with: newRequest as URLRequest)
sessionTask?.resume()
}
override func stopLoading() {
if let uuid = self.wkWebViewUuid {
if MyURLProtocol.wkWebViewDelegateMap[uuid] != nil && self.response != nil {
loadingTime = currentTimeInMilliSeconds() - loadingTime
if self.data == nil {
self.data = Data()
}
MyURLProtocol.wkWebViewDelegateMap[uuid]!.didReceiveResponse(self.response!, fromRequest: request, withData: self.data!, loadingTime: loadingTime)
}
}
sessionTask?.cancel()
}
class func getUuid(_ request: URLRequest?) -> String? {
let userAgent: String? = request?.allHTTPHeaderFields?["User-Agent"]
var uuid: String? = nil
if userAgent != nil {
if userAgent!.contains("WKWebView/") {
let userAgentSplitted = userAgent!.split(separator: " ")
uuid = String(userAgentSplitted[userAgentSplitted.count-1]).replacingOccurrences(of: "WKWebView/", with: "")
}
}
return uuid
}
}
extension MyURLProtocol: URLSessionDataDelegate {
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
if self.data == nil {
self.data = data
}
else {
self.data!.append(data)
}
client?.urlProtocol(self, didLoad: data)
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
let policy = URLCache.StoragePolicy(rawValue: request.cachePolicy.rawValue) ?? .notAllowed
self.response = response
client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: policy)
completionHandler(.allow)
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if let error = error {
client?.urlProtocol(self, didFailWithError: error)
} else {
client?.urlProtocolDidFinishLoading(self)
}
}
func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) {
client?.urlProtocol(self, wasRedirectedTo: request, redirectResponse: response)
completionHandler(request)
}
func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {
guard let error = error else { return }
client?.urlProtocol(self, didFailWithError: error)
}
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
let protectionSpace = challenge.protectionSpace
let sender = challenge.sender
if protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
if let serverTrust = protectionSpace.serverTrust {
let credential = URLCredential(trust: serverTrust)
sender?.use(credential, for: challenge)
completionHandler(.useCredential, credential)
return
}
}
}
func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
client?.urlProtocolDidFinishLoading(self)
}
}
protocol MyURLProtocolDelegate {
func didReceiveResponse(_ response: URLResponse, fromRequest request: URLRequest?, withData data: Data, loadingTime time: Int)
}