Skip to content

Commit

Permalink
[v9]: Enable privacy masking for screenshots by default (#2728)
Browse files Browse the repository at this point in the history
  • Loading branch information
denrase authored Feb 18, 2025
1 parent 75e3eba commit 7c468df
Show file tree
Hide file tree
Showing 6 changed files with 13 additions and 69 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
- Responses are now only attached if size is below ~0.15mb
- Responses are attached to the `Hint` object, which can be read in `beforeSend`/`beforeSendTransaction` callbacks via `hint.response`.
- For now, only the `dio` integration is supported.

- Enable privacy masking for screenshots by default ([#2728](https://github.com/getsentry/sentry-dart/pull/2728))

### Enhancements

- Replay: improve Android native interop performance by using JNI ([#2670](https://github.com/getsentry/sentry-dart/pull/2670))
Expand Down
12 changes: 5 additions & 7 deletions flutter/lib/src/native/sentry_native_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,11 @@ class SentryNativeChannel
'sessionSampleRate': options.experimental.replay.sessionSampleRate,
'onErrorSampleRate': options.experimental.replay.onErrorSampleRate,
'tags': <String, dynamic>{
'maskAllText': options.experimental.privacyForReplay.maskAllText,
'maskAllImages': options.experimental.privacyForReplay.maskAllImages,
'maskAssetImages':
options.experimental.privacyForReplay.maskAssetImages,
if (options.experimental.privacyForReplay.userMaskingRules.isNotEmpty)
'maskingRules': options
.experimental.privacyForReplay.userMaskingRules
'maskAllText': options.experimental.privacy.maskAllText,
'maskAllImages': options.experimental.privacy.maskAllImages,
'maskAssetImages': options.experimental.privacy.maskAssetImages,
if (options.experimental.privacy.userMaskingRules.isNotEmpty)
'maskingRules': options.experimental.privacy.userMaskingRules
.map((rule) => '${rule.name}: ${rule.description}')
.toList(growable: false),
},
Expand Down
2 changes: 1 addition & 1 deletion flutter/lib/src/replay/replay_recorder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ var _instanceCounter = 0;
class ReplayScreenshotRecorder extends ScreenshotRecorder {
ReplayScreenshotRecorder(super.config, super.options)
: super(
privacyOptions: options.experimental.privacyForReplay,
privacyOptions: options.experimental.privacy,
logName: 'ReplayRecorder #${++_instanceCounter}');

@override
Expand Down
10 changes: 3 additions & 7 deletions flutter/lib/src/screenshot/recorder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,17 @@ class ScreenshotRecorder {
bool _warningLogged = false;
late final SentryMaskingConfig? _maskingConfig;

// TODO: remove in the next major release, see recorder_test.dart.
@visibleForTesting
bool get hasWidgetFilter => _maskingConfig != null;

ScreenshotRecorder(
this.config,
this.options, {
SentryPrivacyOptions? privacyOptions,
this.logName = 'ScreenshotRecorder',
}) {
privacyOptions ??= options.experimental.privacyForScreenshots;
privacyOptions ??= options.experimental.privacy;

final maskingConfig =
privacyOptions?.buildMaskingConfig(_log, options.platformChecker);
_maskingConfig = (maskingConfig?.length ?? 0) > 0 ? maskingConfig : null;
privacyOptions.buildMaskingConfig(_log, options.platformChecker);
_maskingConfig = maskingConfig.length > 0 ? maskingConfig : null;
}

void _log(SentryLevel level, String message,
Expand Down
29 changes: 2 additions & 27 deletions flutter/lib/src/sentry_flutter_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -381,33 +381,8 @@ class _SentryFlutterExperimentalOptions {
final replay = SentryReplayOptions();

/// Privacy configuration for masking sensitive data in screenshots and Session Replay.
/// Screen content masking is:
/// - enabled by default for SessionReplay
/// - disabled by default for screenshots captured with events.
/// In order to mask screenshots captured with events, access or change
/// this property in your application: `options.experimental.privacy`.
/// Doing so will indicate that you want to configure privacy settings and
/// will enable screenshot masking alongside the default replay masking.
/// Note: this will change in a future SDK major release to enable screenshot
/// masking by default for all captures.
SentryPrivacyOptions get privacy {
// If the user explicitly sets the privacy setting, we use that.
// Otherwise, we use the default settings, which is no masking for screenshots
// and full masking for session replay.
// This property must only by accessed by user code otherwise it defeats the purpose.
_privacy ??= SentryPrivacyOptions();
return _privacy!;
}

/// TODO: remove when default masking value are synced with SS & SR in the next major release
SentryPrivacyOptions? _privacy;

@meta.internal
SentryPrivacyOptions? get privacyForScreenshots => _privacy;

@meta.internal
SentryPrivacyOptions get privacyForReplay =>
_privacy ?? SentryPrivacyOptions();
/// Screen content masking is enabled by default.
final privacy = SentryPrivacyOptions();
}

/// A callback which can be used to suppress capturing of screenshots.
Expand Down
26 changes: 0 additions & 26 deletions flutter/test/screenshot/recorder_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import 'dart:ui';
import 'package:flutter/widgets.dart' as widgets;
import 'package:flutter_test/flutter_test.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:sentry_flutter/src/replay/replay_recorder.dart';
import 'package:sentry_flutter/src/screenshot/recorder.dart';
import 'package:sentry_flutter/src/screenshot/recorder_config.dart';
import 'package:sentry_flutter/src/screenshot/screenshot.dart';
Expand Down Expand Up @@ -114,31 +113,6 @@ void main() async {
expect(await fixture.capture(), isNull);
});

// TODO: remove in the next major release, see _SentryFlutterExperimentalOptions.
group('Widget filter is used based on config or application', () {
test('Uses widget filter by default for Replay', () {
final sut = ReplayScreenshotRecorder(
ScreenshotRecorderConfig(),
defaultTestOptions(),
);
expect(sut.hasWidgetFilter, isTrue);
});

test('Does not use widget filter by default for Screenshots', () {
final sut =
ScreenshotRecorder(ScreenshotRecorderConfig(), defaultTestOptions());
expect(sut.hasWidgetFilter, isFalse);
});

test(
'Uses widget filter for Screenshots when privacy configured explicitly',
() {
final sut = ScreenshotRecorder(ScreenshotRecorderConfig(),
defaultTestOptions()..experimental.privacy.maskAllText = false);
expect(sut.hasWidgetFilter, isTrue);
});
});

group('$Screenshot', () {
test('listEquals()', () {
expect(
Expand Down

0 comments on commit 7c468df

Please sign in to comment.