2018-10-12 01:46:33 +00:00
|
|
|
//
|
|
|
|
// MyURLProtocol.swift
|
|
|
|
// Pods
|
|
|
|
//
|
|
|
|
// Created by Lorenzo on 12/10/18.
|
|
|
|
//
|
|
|
|
|
|
|
|
import Foundation
|
2018-10-13 01:16:08 +00:00
|
|
|
import WebKit
|
|
|
|
|
|
|
|
|
|
|
|
func currentTimeInMilliSeconds() -> Int {
|
|
|
|
let currentDate = Date()
|
|
|
|
let since1970 = currentDate.timeIntervalSince1970
|
|
|
|
return Int(since1970 * 1000)
|
|
|
|
}
|
2018-10-12 01:46:33 +00:00
|
|
|
|
|
|
|
class MyURLProtocol: URLProtocol {
|
|
|
|
|
2018-10-13 01:16:08 +00:00
|
|
|
// struct Constants {
|
|
|
|
// static let RequestHandledKey = "URLProtocolRequestHandled"
|
|
|
|
// }
|
2018-10-12 01:46:33 +00:00
|
|
|
|
2018-10-13 01:16:08 +00:00
|
|
|
var wkWebViewUuid: String?
|
2018-10-12 01:46:33 +00:00
|
|
|
var session: URLSession?
|
|
|
|
var sessionTask: URLSessionDataTask?
|
2018-10-13 01:16:08 +00:00
|
|
|
var response: URLResponse?
|
|
|
|
var data: Data?
|
|
|
|
static var wkWebViewDelegateMap: [String: MyURLProtocolDelegate] = [:]
|
|
|
|
var loadingTime: Int = 0
|
2018-10-12 01:46:33 +00:00
|
|
|
|
|
|
|
override init(request: URLRequest, cachedResponse: CachedURLResponse?, client: URLProtocolClient?) {
|
|
|
|
super.init(request: request, cachedResponse: cachedResponse, client: client)
|
|
|
|
|
2018-10-13 01:16:08 +00:00
|
|
|
self.wkWebViewUuid = MyURLProtocol.getUuid(request)
|
|
|
|
|
|
|
|
if session == nil && self.wkWebViewUuid != nil {
|
2018-10-12 01:46:33 +00:00
|
|
|
session = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override class func canInit(with request: URLRequest) -> Bool {
|
2018-10-13 01:16:08 +00:00
|
|
|
|
|
|
|
if getUuid(request) == nil {
|
2018-10-12 01:46:33 +00:00
|
|
|
return false
|
|
|
|
}
|
2018-10-13 01:16:08 +00:00
|
|
|
// if MyURLProtocol.property(forKey: Constants.RequestHandledKey, in: request) != nil {
|
|
|
|
// return false
|
|
|
|
// }
|
2018-10-12 01:46:33 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
override class func canonicalRequest(for request: URLRequest) -> URLRequest {
|
|
|
|
return request
|
|
|
|
}
|
|
|
|
|
|
|
|
override func startLoading() {
|
|
|
|
let newRequest = ((request as NSURLRequest).mutableCopy() as? NSMutableURLRequest)!
|
2018-10-13 01:16:08 +00:00
|
|
|
loadingTime = currentTimeInMilliSeconds()
|
|
|
|
//MyURLProtocol.setProperty(true, forKey: Constants.RequestHandledKey, in: newRequest)
|
2018-10-12 01:46:33 +00:00
|
|
|
sessionTask = session?.dataTask(with: newRequest as URLRequest)
|
|
|
|
sessionTask?.resume()
|
|
|
|
}
|
|
|
|
|
|
|
|
override func stopLoading() {
|
2018-10-13 01:16:08 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-12 01:46:33 +00:00
|
|
|
sessionTask?.cancel()
|
|
|
|
}
|
2018-10-13 01:16:08 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
2018-10-12 01:46:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extension MyURLProtocol: URLSessionDataDelegate {
|
|
|
|
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
|
2018-10-13 01:16:08 +00:00
|
|
|
if self.data == nil {
|
|
|
|
self.data = data
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
self.data!.append(data)
|
|
|
|
}
|
2018-10-12 01:46:33 +00:00
|
|
|
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
|
2018-10-13 01:16:08 +00:00
|
|
|
self.response = response
|
2018-10-12 01:46:33 +00:00
|
|
|
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 {
|
2018-10-13 01:16:08 +00:00
|
|
|
func didReceiveResponse(_ response: URLResponse, fromRequest request: URLRequest?, withData data: Data, loadingTime time: Int)
|
2018-10-12 01:46:33 +00:00
|
|
|
}
|