From 5549b7ecbe8cac1983a34368d6f0373603c44940 Mon Sep 17 00:00:00 2001 From: Mert Buran Date: Thu, 8 Apr 2021 16:48:41 +0200 Subject: [PATCH] RUMM-1234 URLSessionDelegateProviding introduced --- .../DDURLSessionDelegate.swift | 18 ++++++++++++- .../URLSessionSwizzler.swift | 8 +++--- .../DDURLSessionDelegate+objc.swift | 25 ++++++++++++++++++- ...DURLSessionDelegateAsSuperclassTests.swift | 12 +++++++++ 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/Sources/Datadog/URLSessionAutoInstrumentation/DDURLSessionDelegate.swift b/Sources/Datadog/URLSessionAutoInstrumentation/DDURLSessionDelegate.swift index 4e55c82b2c..16a6c9221d 100644 --- a/Sources/Datadog/URLSessionAutoInstrumentation/DDURLSessionDelegate.swift +++ b/Sources/Datadog/URLSessionAutoInstrumentation/DDURLSessionDelegate.swift @@ -6,12 +6,28 @@ import Foundation +/// In case that you are not able to use `DDURLSessionDelegate` or its subclasses in your `URLSession` instance, +/// you can use `DDURLSessionDelegateProviding` protocol. +/// Implement this protocol in your `URLSessionDelegate` class and forward required API calls to `DDURLSessionDelegate`. +@objc +public protocol URLSessionDelegateProviding: URLSessionDelegate { + /// Datadog delegate object. + /// The class implementing `DDURLSessionDelegateProviding` must ensure that following method calls are forwarded to `ddURLSessionDelegate`: + // - `func urlSession(_:task:didFinishCollecting:)` + // - `func urlSession(_:task: didCompleteWithError:)` + var ddURLSessionDelegate: DDURLSessionDelegate { get } +} + /// The `URLSession` delegate object which enables network requests instrumentation. **It must be /// used together with** `Datadog.Configuration.trackURLSession(firstPartyHosts:)`. /// /// All requests made with the `URLSession` instrumented with this delegate will be intercepted by the SDK. @objc -open class DDURLSessionDelegate: NSObject, URLSessionTaskDelegate { +open class DDURLSessionDelegate: NSObject, URLSessionTaskDelegate, URLSessionDelegateProviding { + public var ddURLSessionDelegate: DDURLSessionDelegate { + return self + } + var interceptor: URLSessionInterceptorType? let firstPartyURLsFilter: FirstPartyURLsFilter? diff --git a/Sources/Datadog/URLSessionAutoInstrumentation/URLSessionSwizzler.swift b/Sources/Datadog/URLSessionAutoInstrumentation/URLSessionSwizzler.swift index 9ffd959622..dba9df9059 100644 --- a/Sources/Datadog/URLSessionAutoInstrumentation/URLSessionSwizzler.swift +++ b/Sources/Datadog/URLSessionAutoInstrumentation/URLSessionSwizzler.swift @@ -70,7 +70,7 @@ internal class URLSessionSwizzler { typealias Signature = @convention(block) (URLSession, URLRequest, CompletionHandler?) -> URLSessionDataTask swizzle(method) { previousImplementation -> Signature in return { session, urlRequest, completionHandler -> URLSessionDataTask in - guard let interceptor = (session.delegate as? DDURLSessionDelegate)?.interceptor else { + guard let interceptor = (session.delegate as? URLSessionDelegateProviding)?.ddURLSessionDelegate.interceptor else { return previousImplementation(session, Self.selector, urlRequest, completionHandler) } let task: URLSessionDataTask @@ -129,7 +129,7 @@ internal class URLSessionSwizzler { typealias Signature = @convention(block) (URLSession, URL, CompletionHandler?) -> URLSessionDataTask swizzle(method) { previousImplementation -> Signature in return { session, url, completionHandler -> URLSessionDataTask in - guard let interceptor = (session.delegate as? DDURLSessionDelegate)?.interceptor else { + guard let interceptor = (session.delegate as? URLSessionDelegateProviding)?.ddURLSessionDelegate.interceptor else { return previousImplementation(session, Self.selector, url, completionHandler) } let task: URLSessionDataTask @@ -183,7 +183,7 @@ internal class URLSessionSwizzler { typealias Signature = @convention(block) (URLSession, URLRequest) -> URLSessionDataTask swizzle(method) { previousImplementation -> Signature in return { session, urlRequest -> URLSessionDataTask in - guard let interceptor = (session.delegate as? DDURLSessionDelegate)?.interceptor else { + guard let interceptor = (session.delegate as? URLSessionDelegateProviding)?.ddURLSessionDelegate.interceptor else { return previousImplementation(session, Self.selector, urlRequest) } let newRequest = interceptor.modify(request: urlRequest, session: session) @@ -227,7 +227,7 @@ internal class URLSessionSwizzler { typealias Signature = @convention(block) (URLSession, URL) -> URLSessionDataTask swizzle(method) { previousImplementation -> Signature in return { session, url -> URLSessionDataTask in - guard let interceptor = (session.delegate as? DDURLSessionDelegate)?.interceptor else { + guard let interceptor = (session.delegate as? URLSessionDelegateProviding)?.ddURLSessionDelegate.interceptor else { return previousImplementation(session, Self.selector, url) } let task = previousImplementation(session, Self.selector, url) diff --git a/Sources/DatadogObjc/DDURLSessionDelegate+objc.swift b/Sources/DatadogObjc/DDURLSessionDelegate+objc.swift index 11bbcde866..82dbd60231 100644 --- a/Sources/DatadogObjc/DDURLSessionDelegate+objc.swift +++ b/Sources/DatadogObjc/DDURLSessionDelegate+objc.swift @@ -8,4 +8,27 @@ import Foundation import Datadog @objc -public class DDNSURLSessionDelegate: DDURLSessionDelegate {} +open class DDNSURLSessionDelegate: NSObject, URLSessionTaskDelegate, URLSessionDelegateProviding { + let swiftDelegate: DDURLSessionDelegate + public var ddURLSessionDelegate: DDURLSessionDelegate { + return swiftDelegate + } + + @objc + override public init() { + swiftDelegate = DDURLSessionDelegate() + } + + @objc + public init(additionalFirstPartyHosts: Set) { + swiftDelegate = DDURLSessionDelegate(additionalFirstPartyHosts: additionalFirstPartyHosts) + } + + open func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { + swiftDelegate.urlSession(session, task: task, didCompleteWithError: error) + } + + open func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) { + swiftDelegate.urlSession(session, task: task, didFinishCollecting: metrics) + } +} diff --git a/Tests/DatadogTests/Datadog/URLSessionAutoInstrumentation/DDURLSessionDelegateAsSuperclassTests.swift b/Tests/DatadogTests/Datadog/URLSessionAutoInstrumentation/DDURLSessionDelegateAsSuperclassTests.swift index 2115cd2bd2..e77ffdd1eb 100644 --- a/Tests/DatadogTests/Datadog/URLSessionAutoInstrumentation/DDURLSessionDelegateAsSuperclassTests.swift +++ b/Tests/DatadogTests/Datadog/URLSessionAutoInstrumentation/DDURLSessionDelegateAsSuperclassTests.swift @@ -6,6 +6,18 @@ import XCTest import Datadog +import DatadogObjc + +@objc +public class SubDDNSURLSessionDelegate: DDNSURLSessionDelegate { + override public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { + super.urlSession(session, task: task, didCompleteWithError: error) + } + + override public func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) { + super.urlSession(session, task: task, didFinishCollecting: metrics) + } +} internal final class SubDDURLSessionDelegate: DDURLSessionDelegate { let property: String