Skip to content

Commit 005f255

Browse files
authored
fix(session-replay): Extend masking and focus masking on sensitive information (#6292)
1 parent 25bf0e7 commit 005f255

File tree

9 files changed

+550
-1123
lines changed

9 files changed

+550
-1123
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@
3535
- Fix rendering method for fast view rendering (#6360)
3636
- Fix issue where the thread that generated an event could be missing when more than 100 threads are running (#6377)
3737
- 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)
38+
- Session Replay masking improvements (#6292)
39+
- Fix SwiftUI.List background decoration view causing incorrect clipping of screen content
40+
- Fix sublayer rendering order by properly sorting by zPosition with insertion order as tie-breaker
41+
- Fix UISwitch internal images being incorrectly redacted
42+
- Fix UITextField placeholder text (UITextFieldLabel) not being detected for redaction
43+
- Use string-based class comparison to avoid triggering Objective-C +initialize on background threads
44+
- Add layer class filtering for views used in multiple contexts (e.g., SwiftUI._UIGraphicsView)
45+
- Improve transform calculations for views with custom anchor points
46+
- Fix axis-aligned transform detection for optimized opaque view clipping
3847

3948
### Improvements
4049

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)