diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index 51f90cc6149..4d96fd69de8 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -992,7 +992,6 @@ D8C66A372A77B1F70015696A /* SentryPropagationContext.m in Sources */ = {isa = PBXBuildFile; fileRef = D8C66A352A77B1F70015696A /* SentryPropagationContext.m */; }; D8C67E9B28000E24007E326E /* SentryUIApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = D8C67E9928000E23007E326E /* SentryUIApplication.h */; }; D8C67E9C28000E24007E326E /* SentryScreenshot.h in Headers */ = {isa = PBXBuildFile; fileRef = D8C67E9A28000E23007E326E /* SentryScreenshot.h */; }; - D8CA12952C203E71005894F4 /* SentrySessionListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8CA12942C203E71005894F4 /* SentrySessionListener.swift */; }; D8CAC02E2BA0663E00E38F34 /* SentryReplayOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8CAC02A2BA0663E00E38F34 /* SentryReplayOptions.swift */; }; D8CAC02F2BA0663E00E38F34 /* SentryVideoInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8CAC02B2BA0663E00E38F34 /* SentryVideoInfo.swift */; }; D8CB74152947246600A5F964 /* SentryEnvelopeAttachmentHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = D8CB74142947246600A5F964 /* SentryEnvelopeAttachmentHeader.h */; }; @@ -2245,7 +2244,6 @@ D8C66A352A77B1F70015696A /* SentryPropagationContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryPropagationContext.m; sourceTree = ""; }; D8C67E9928000E23007E326E /* SentryUIApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryUIApplication.h; path = include/SentryUIApplication.h; sourceTree = ""; }; D8C67E9A28000E23007E326E /* SentryScreenshot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryScreenshot.h; path = include/SentryScreenshot.h; sourceTree = ""; }; - D8CA12942C203E71005894F4 /* SentrySessionListener.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySessionListener.swift; sourceTree = ""; }; D8CAC02A2BA0663E00E38F34 /* SentryReplayOptions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SentryReplayOptions.swift; sourceTree = ""; }; D8CAC02B2BA0663E00E38F34 /* SentryVideoInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SentryVideoInfo.swift; sourceTree = ""; }; D8CB74142947246600A5F964 /* SentryEnvelopeAttachmentHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryEnvelopeAttachmentHeader.h; path = include/SentryEnvelopeAttachmentHeader.h; sourceTree = ""; }; @@ -4472,7 +4470,6 @@ isa = PBXGroup; children = ( 620078752D38F1110022CB67 /* Codable */, - D8CA12942C203E71005894F4 /* SentrySessionListener.swift */, ); path = Protocol; sourceTree = ""; @@ -5329,7 +5326,6 @@ 63FE716920DA4C1100CDBAE8 /* SentryCrashStackCursor.c in Sources */, 7BA61CCA247D128B00C130A8 /* SentryThreadInspector.m in Sources */, 623FD9042D3FA92700803EDA /* NSNumberDecodableWrapper.swift in Sources */, - D8CA12952C203E71005894F4 /* SentrySessionListener.swift in Sources */, 63FE718D20DA4C1100CDBAE8 /* SentryCrashReportStore.c in Sources */, 7BA0C0482805600A003E0326 /* SentryTransportAdapter.m in Sources */, 63FE712920DA4C1000CDBAE8 /* SentryCrashCPU_arm.c in Sources */, diff --git a/SentryTestUtils/TestDisplayLinkWrapper.swift b/SentryTestUtils/TestDisplayLinkWrapper.swift index 08e2d756d08..a2a9fb98d1f 100644 --- a/SentryTestUtils/TestDisplayLinkWrapper.swift +++ b/SentryTestUtils/TestDisplayLinkWrapper.swift @@ -1,4 +1,5 @@ import Foundation +@_spi(Private) import Sentry #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) @@ -17,7 +18,7 @@ public enum FrameRate: UInt64 { } } -public class TestDisplayLinkWrapper: SentryDisplayLinkWrapper { +@_spi(Private) public class TestDisplayLinkWrapper: SentryDisplayLinkWrapper, SentryReplayDisplayLinkWrapper { public var target: AnyObject! public var selector: Selector! public var currentFrameRate: FrameRate = .low diff --git a/Sources/Sentry/SentryDependencyContainer.m b/Sources/Sentry/SentryDependencyContainer.m index 2c2974b8b87..61eae998a74 100644 --- a/Sources/Sentry/SentryDependencyContainer.m +++ b/Sources/Sentry/SentryDependencyContainer.m @@ -81,6 +81,9 @@ #define SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK \ SENTRY_DISABLE_THREAD_SANITIZER("Double-checked locks produce false alarms.") +@interface SentryFileManager () +@end + @interface SentryDependencyContainer () @property (nonatomic, strong) id anrTracker; diff --git a/Sources/Sentry/SentrySessionReplayIntegration.m b/Sources/Sentry/SentrySessionReplayIntegration.m index 6b64a108e23..ed65b821188 100644 --- a/Sources/Sentry/SentrySessionReplayIntegration.m +++ b/Sources/Sentry/SentrySessionReplayIntegration.m @@ -32,6 +32,10 @@ static NSString *SENTRY_CURRENT_REPLAY = @"replay.current"; static NSString *SENTRY_LAST_REPLAY = @"replay.last"; +@interface SentryDisplayLinkWrapper (Replay) + +@end + /** * We need to use this from the swizzled block * and using an instance property would hold reference diff --git a/Sources/Sentry/include/SentryHub+Private.h b/Sources/Sentry/include/SentryHub+Private.h index c5cc952ed38..e25c7a14ff5 100644 --- a/Sources/Sentry/include/SentryHub+Private.h +++ b/Sources/Sentry/include/SentryHub+Private.h @@ -13,10 +13,16 @@ @class SentryReplayEvent; @class SentryReplayRecording; @protocol SentryIntegrationProtocol; -@protocol SentrySessionListener; NS_ASSUME_NONNULL_BEGIN +@protocol SentrySessionListener + +- (void)sentrySessionEnded:(SentrySession *)session; +- (void)sentrySessionStarted:(SentrySession *)session; + +@end + @interface SentryHub () @property (nullable, nonatomic, strong) SentrySession *session; diff --git a/Sources/Swift/Core/Integrations/FramesTracking/SentryFramesDelayResult.swift b/Sources/Swift/Core/Integrations/FramesTracking/SentryFramesDelayResult.swift index b128131d82a..8a859582fb0 100644 --- a/Sources/Swift/Core/Integrations/FramesTracking/SentryFramesDelayResult.swift +++ b/Sources/Swift/Core/Integrations/FramesTracking/SentryFramesDelayResult.swift @@ -6,7 +6,7 @@ import Foundation public let delayDuration: CFTimeInterval public let framesContributingToDelayCount: UInt - init(delayDuration: CFTimeInterval, framesContributingToDelayCount: UInt) { + public init(delayDuration: CFTimeInterval, framesContributingToDelayCount: UInt) { self.delayDuration = delayDuration self.framesContributingToDelayCount = framesContributingToDelayCount } diff --git a/Sources/Swift/Core/Tools/ViewCapture/SentryViewPhotographer.swift b/Sources/Swift/Core/Tools/ViewCapture/SentryViewPhotographer.swift index 3fd0314847a..2abc75698e2 100644 --- a/Sources/Swift/Core/Tools/ViewCapture/SentryViewPhotographer.swift +++ b/Sources/Swift/Core/Tools/ViewCapture/SentryViewPhotographer.swift @@ -60,22 +60,22 @@ import UIKit } @objc(addIgnoreClasses:) - func addIgnoreClasses(classes: [AnyClass]) { + public func addIgnoreClasses(classes: [AnyClass]) { redactBuilder.addIgnoreClasses(classes) } @objc(addRedactClasses:) - func addRedactClasses(classes: [AnyClass]) { + public func addRedactClasses(classes: [AnyClass]) { redactBuilder.addRedactClasses(classes) } @objc(setIgnoreContainerClass:) - func setIgnoreContainerClass(_ containerClass: AnyClass) { + public func setIgnoreContainerClass(_ containerClass: AnyClass) { redactBuilder.setIgnoreContainerClass(containerClass) } @objc(setRedactContainerClass:) - func setRedactContainerClass(_ containerClass: AnyClass) { + public func setRedactContainerClass(_ containerClass: AnyClass) { redactBuilder.setRedactContainerClass(containerClass) } diff --git a/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebBreadcrumbEvent.swift b/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebBreadcrumbEvent.swift index 6cbb755ddae..6979f4304e0 100644 --- a/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebBreadcrumbEvent.swift +++ b/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebBreadcrumbEvent.swift @@ -1,7 +1,7 @@ import Foundation @_spi(Private) public final class SentryRRWebBreadcrumbEvent: SentryRRWebCustomEvent { - init(timestamp: Date, category: String, message: String? = nil, level: SentryLevel = .none, data: [String: Any]? = nil) { + public init(timestamp: Date, category: String, message: String? = nil, level: SentryLevel = .none, data: [String: Any]? = nil) { var payload: [String: Any] = ["type": "default", "category": category, "level": level.description, "timestamp": timestamp.timeIntervalSince1970 ] diff --git a/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebSpanEvent.swift b/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebSpanEvent.swift index e2514bfc3c8..73cbfcb3f6c 100644 --- a/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebSpanEvent.swift +++ b/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebSpanEvent.swift @@ -2,7 +2,7 @@ import Foundation @objc @_spi(Private) public class SentryRRWebSpanEvent: SentryRRWebCustomEvent { - init(timestamp: Date, endTimestamp: Date, operation: String, description: String, data: [String: Any]) { + public init(timestamp: Date, endTimestamp: Date, operation: String, description: String, data: [String: Any]) { super.init(timestamp: timestamp, tag: "performanceSpan", payload: [ "op": operation, diff --git a/Sources/Swift/Integrations/SessionReplay/SentryOnDemandReplay.swift b/Sources/Swift/Integrations/SessionReplay/SentryOnDemandReplay.swift index b84e00de0d9..011ba23dc37 100644 --- a/Sources/Swift/Integrations/SessionReplay/SentryOnDemandReplay.swift +++ b/Sources/Swift/Integrations/SessionReplay/SentryOnDemandReplay.swift @@ -74,7 +74,7 @@ import UIKit } } - @objc func addFrameAsync(timestamp: Date, maskedViewImage: UIImage, forScreen screen: String?) { + @objc public func addFrameAsync(timestamp: Date, maskedViewImage: UIImage, forScreen screen: String?) { SentrySDKLog.debug("[Session Replay] Adding frame async for screen: \(screen ?? "nil")") // Dispatch the frame addition to a background queue to avoid blocking the main queue. // This must be on the processing queue to avoid deadlocks. @@ -125,7 +125,7 @@ import UIKit return UIGraphicsGetImageFromCurrentImageContext() } - func releaseFramesUntil(_ date: Date) { + public func releaseFramesUntil(_ date: Date) { processingQueue.dispatchAsync { SentrySDKLog.debug("[Session Replay] Releasing frames until date: \(date)") while let first = self._frames.first, first.time < date { @@ -146,7 +146,7 @@ import UIKit return _frames.first?.time } - func createVideoInBackgroundWith(beginning: Date, end: Date, completion: @escaping ([SentryVideoInfo]) -> Void) { + public func createVideoInBackgroundWith(beginning: Date, end: Date, completion: @escaping ([SentryVideoInfo]) -> Void) { // Note: In Swift it is best practice to use `Result` instead of `(Value?, Error?)` // Due to interoperability with Objective-C and @objc, we can not use Result for the completion callback. SentrySDKLog.debug("[Session Replay] Creating video in background with beginning: \(beginning), end: \(end)") diff --git a/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift b/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift index c21c234a7fc..f404fe02874 100644 --- a/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift +++ b/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift @@ -265,7 +265,7 @@ public class SentryReplayOptions: NSObject, SentryRedactOptions { * * - Note: See ``SentryReplayOptions.DefaultValues.maximumDuration`` for the default value. */ - var maximumDuration: TimeInterval + @_spi(Private) public var maximumDuration: TimeInterval /** * Used by hybrid SDKs to be able to configure SDK info for Session Replay diff --git a/Sources/Swift/Integrations/SessionReplay/SentryReplayVideoMaker.swift b/Sources/Swift/Integrations/SessionReplay/SentryReplayVideoMaker.swift index bc8c4d8cc2c..0224d4c98fc 100644 --- a/Sources/Swift/Integrations/SessionReplay/SentryReplayVideoMaker.swift +++ b/Sources/Swift/Integrations/SessionReplay/SentryReplayVideoMaker.swift @@ -3,7 +3,7 @@ import Foundation import UIKit @objc -protocol SentryReplayVideoMaker: NSObjectProtocol { +@_spi(Private) public protocol SentryReplayVideoMaker: NSObjectProtocol { func addFrameAsync(timestamp: Date, maskedViewImage: UIImage, forScreen: String?) func releaseFramesUntil(_ date: Date) func createVideoInBackgroundWith(beginning: Date, end: Date, completion: @escaping ([SentryVideoInfo]) -> Void) diff --git a/Sources/Swift/Integrations/SessionReplay/SentrySessionReplay.swift b/Sources/Swift/Integrations/SessionReplay/SentrySessionReplay.swift index 0953226d77f..10279ac9f07 100644 --- a/Sources/Swift/Integrations/SessionReplay/SentrySessionReplay.swift +++ b/Sources/Swift/Integrations/SessionReplay/SentrySessionReplay.swift @@ -3,6 +3,13 @@ import Foundation @_implementationOnly import _SentryPrivate import UIKit +@objc +@_spi(Private) public protocol SentryReplayDisplayLinkWrapper { + func isRunning() -> Bool + func invalidate() + func link(withTarget: Any, selector: Selector) +} + // swiftlint:disable type_body_length @objcMembers @_spi(Private) public class SentrySessionReplay: NSObject { @@ -23,7 +30,7 @@ import UIKit private let replayOptions: SentryReplayOptions private let replayMaker: SentryReplayVideoMaker - private let displayLink: SentryDisplayLinkWrapper + private let displayLink: SentryReplayDisplayLinkWrapper private let dateProvider: SentryCurrentDateProvider private let touchTracker: SentryTouchTracker? private let lock = NSLock() @@ -36,7 +43,7 @@ import UIKit public var screenshotProvider: SentryViewScreenshotProvider public var breadcrumbConverter: SentryReplayBreadcrumbConverter - init( + public init( replayOptions: SentryReplayOptions, replayFolderPath: URL, screenshotProvider: SentryViewScreenshotProvider, @@ -45,7 +52,7 @@ import UIKit touchTracker: SentryTouchTracker?, dateProvider: SentryCurrentDateProvider, delegate: SentrySessionReplayDelegate, - displayLinkWrapper: SentryDisplayLinkWrapper + displayLinkWrapper: SentryReplayDisplayLinkWrapper ) { self.replayOptions = replayOptions self.dateProvider = dateProvider diff --git a/Sources/Swift/Integrations/WatchdogTerminations/Processors/SentryWatchdogTerminationContextProcessor.swift b/Sources/Swift/Integrations/WatchdogTerminations/Processors/SentryWatchdogTerminationContextProcessor.swift index a42f0158618..d649cb835ee 100644 --- a/Sources/Swift/Integrations/WatchdogTerminations/Processors/SentryWatchdogTerminationContextProcessor.swift +++ b/Sources/Swift/Integrations/WatchdogTerminations/Processors/SentryWatchdogTerminationContextProcessor.swift @@ -7,7 +7,7 @@ import Foundation private let dispatchQueueWrapper: SentryDispatchQueueWrapper private let scopeContextStore: SentryScopeContextPersistentStore - init( + public init( withDispatchQueueWrapper dispatchQueueWrapper: SentryDispatchQueueWrapper, scopeContextStore: SentryScopeContextPersistentStore ) { diff --git a/Sources/Swift/Persistence/SentryScopeContextPersistentStore.swift b/Sources/Swift/Persistence/SentryScopeContextPersistentStore.swift index 3002427cc85..7007ab7bca1 100644 --- a/Sources/Swift/Persistence/SentryScopeContextPersistentStore.swift +++ b/Sources/Swift/Persistence/SentryScopeContextPersistentStore.swift @@ -1,10 +1,19 @@ @_implementationOnly import _SentryPrivate +@_spi(Private) @objc public protocol SentryFileManagerProtocol { + func moveState(_ stateFilePath: String, toPreviousState previousStateFilePath: String) + func readData(fromPath path: String) throws -> Data + @objc(writeData:toPath:) + @discardableResult func write(_ data: Data, toPath path: String) -> Bool + func removeFile(atPath path: String) + func getSentryPathAsURL() -> URL +} + @objcMembers @_spi(Private) public class SentryScopeContextPersistentStore: NSObject { - private let fileManager: SentryFileManager + private let fileManager: SentryFileManagerProtocol - init(fileManager: SentryFileManager) { + public init(fileManager: SentryFileManagerProtocol) { self.fileManager = fileManager } diff --git a/Sources/Swift/Protocol/SentrySessionListener.swift b/Sources/Swift/Protocol/SentrySessionListener.swift deleted file mode 100644 index 06e320efa33..00000000000 --- a/Sources/Swift/Protocol/SentrySessionListener.swift +++ /dev/null @@ -1,8 +0,0 @@ -@_implementationOnly import _SentryPrivate -import Foundation - -@objc -protocol SentrySessionListener: NSObjectProtocol { - func sentrySessionEnded(_ session: SentrySession) - func sentrySessionStarted(_ session: SentrySession) -} diff --git a/Tests/SentryProfilerTests/SentryAppLaunchProfilingTests.swift b/Tests/SentryProfilerTests/SentryAppLaunchProfilingTests.swift index 09047634a20..f4c4d213acf 100644 --- a/Tests/SentryProfilerTests/SentryAppLaunchProfilingTests.swift +++ b/Tests/SentryProfilerTests/SentryAppLaunchProfilingTests.swift @@ -1,4 +1,4 @@ -import SentryTestUtils +@_spi(Private) import SentryTestUtils import XCTest #if os(iOS) || os(macOS) || targetEnvironment(macCatalyst) diff --git a/Tests/SentryTests/Integrations/WatchdogTerminations/SentryWatchdogTerminationTrackerTests.swift b/Tests/SentryTests/Integrations/WatchdogTerminations/SentryWatchdogTerminationTrackerTests.swift index 9917b87f11f..c4b3ed390dd 100644 --- a/Tests/SentryTests/Integrations/WatchdogTerminations/SentryWatchdogTerminationTrackerTests.swift +++ b/Tests/SentryTests/Integrations/WatchdogTerminations/SentryWatchdogTerminationTrackerTests.swift @@ -2,6 +2,12 @@ @_spi(Private) import SentryTestUtils import XCTest +#if compiler(>=6.0) +@_spi(Private) extension SentryFileManager: @retroactive SentryFileManagerProtocol { } +#else +@_spi(Private) extension SentryFileManager: SentryFileManagerProtocol { } +#endif + #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) class SentryWatchdogTerminationTrackerTests: NotificationCenterTestCase {