Skip to content

Commit ccfa138

Browse files
committed
fix(session-replay): Extend masking and focus masking on sensitive information (#6292)
1 parent fad6b9e commit ccfa138

File tree

9 files changed

+558
-1123
lines changed

9 files changed

+558
-1123
lines changed

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,23 @@
77
- Fix crash from accessing UITouch instances from background thread in SentryTouchTracker (#6584)
88
- Disable SessionSentryReplayIntegration if the environment is unsafe [#6573]
99
- Fix crash when last replay info is missing some keys [#6577]
10+
- Fixes warnings about minimum OS version being lower than Xcode supported version (#5591)
11+
- Fix rendering method for fast view rendering (#6360)
12+
- Fix issue where the thread that generated an event could be missing when more than 100 threads are running (#6377)
13+
- Fix wrong Frame Delay when becoming active, which lead to false reported app hangs when the app moves to the foreground after being in the background (#6381)
14+
- Session Replay masking improvements (#6292)
15+
- Fix SwiftUI.List background decoration view causing incorrect clipping of screen content
16+
- Fix sublayer rendering order by properly sorting by zPosition with insertion order as tie-breaker
17+
- Fix UISwitch internal images being incorrectly redacted
18+
- Fix UITextField placeholder text (UITextFieldLabel) not being detected for redaction
19+
- Use string-based class comparison to avoid triggering Objective-C +initialize on background threads
20+
- Add layer class filtering for views used in multiple contexts (e.g., SwiftUI._UIGraphicsView)
21+
- Improve transform calculations for views with custom anchor points
22+
- Fix axis-aligned transform detection for optimized opaque view clipping
23+
24+
### Improvements
25+
26+
- Replace deprecated SCNetworkReachability with NWPathMonitor (#6019)
1027

1128
## 8.57.0
1229

Sources/Swift/Core/Tools/ViewCapture/SentryRedactRegion.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import Foundation
44
import ObjectiveC.NSObjCRuntime
55
import UIKit
66

7-
final class SentryRedactRegion {
7+
struct SentryRedactRegion: Equatable {
88
let size: CGSize
99
let transform: CGAffineTransform
1010
let type: SentryRedactRegionType

Sources/Swift/Core/Tools/ViewCapture/SentryRedactRegionType.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
public enum SentryRedactRegionType: String, Codable {
1+
public enum SentryRedactRegionType: String, Codable, Equatable {
22
/// Redacts the region.
33
case redact = "redact"
44

Sources/Swift/Core/Tools/ViewCapture/SentryUIRedactBuilder.swift

Lines changed: 395 additions & 147 deletions
Large diffs are not rendered by default.

Sources/Swift/Core/Tools/ViewCapture/SentryViewPhotographer.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,12 @@ import UIKit
3434
}
3535

3636
public func image(view: UIView, onComplete: @escaping ScreenshotCallback) {
37+
// Define a helper variable for the size, so the view is not accessed in the async block
3738
let viewSize = view.bounds.size
39+
40+
// The redact regions are expected to be thread-safe data structures
3841
let redactRegions = redactBuilder.redactRegionsFor(view: view)
42+
3943
// The render method is synchronous and must be called on the main thread.
4044
// This is because the render method accesses the view hierarchy which is managed from the main thread.
4145
let renderedScreenshot = renderer.render(view: view)

Tests/SentryTests/Integrations/SessionReplay/SentrySessionReplayIntegrationTests.swift

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -342,28 +342,32 @@ class SentrySessionReplayIntegrationTests: XCTestCase {
342342
}
343343

344344
func testMaskViewFromSDK() throws {
345-
class AnotherLabel: UILabel {
346-
}
347-
345+
// -- Arrange --
346+
class AnotherLabel: UILabel {}
347+
348348
startSDK(sessionSampleRate: 1, errorSampleRate: 1) { options in
349349
options.sessionReplay.maskedViewClasses = [AnotherLabel.self]
350350
}
351-
352-
let sut = try getSut()
353-
let redactBuilder = sut.viewPhotographer.getRedactBuilder()
354-
XCTAssertTrue(redactBuilder.containsRedactClass(AnotherLabel.self))
351+
352+
// -- Act --
353+
let redactBuilder = try getSut().viewPhotographer.getRedactBuilder()
354+
355+
// -- Assert --
356+
XCTAssertTrue(redactBuilder.containsRedactClass(viewClass: AnotherLabel.self, layerClass: CALayer.self))
355357
}
356358

357359
func testIgnoreViewFromSDK() throws {
358-
class AnotherLabel: UILabel {
359-
}
360-
360+
// -- Arrange --
361+
class AnotherLabel: UILabel {}
362+
361363
startSDK(sessionSampleRate: 1, errorSampleRate: 1) { options in
362364
options.sessionReplay.unmaskedViewClasses = [AnotherLabel.self]
363365
}
364-
365-
let sut = try getSut()
366-
let redactBuilder = sut.viewPhotographer.getRedactBuilder()
366+
367+
// -- Act --
368+
let redactBuilder = try getSut().viewPhotographer.getRedactBuilder()
369+
370+
// -- Assert --
367371
XCTAssertTrue(redactBuilder.containsIgnoreClass(AnotherLabel.self))
368372
}
369373

0 commit comments

Comments
 (0)