Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: non-nullable privacy setting #2382

Open
wants to merge 1 commit into
base: feat/redact-screenshots-via-view-hierarchy
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ class ScreenshotEventProcessor implements EventProcessor {
var recorder = ScreenshotRecorder(
ScreenshotRecorderConfig(
quality: _options.screenshot.screenshotQuality),
_options);
_options,
isReplayRecorder: false);

Uint8List? _screenshotData;

Expand Down
20 changes: 12 additions & 8 deletions flutter/lib/src/screenshot/recorder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import 'package:flutter/rendering.dart';
import 'package:meta/meta.dart';

import '../../sentry_flutter.dart';
import 'masking_config.dart';
import 'recorder_config.dart';
import 'widget_filter.dart';

Expand All @@ -21,13 +20,18 @@ class ScreenshotRecorder {
WidgetFilter? _widgetFilter;
bool warningLogged = false;

ScreenshotRecorder(this.config, this.options) {
/// TODO: Rewrite when default redaction value are synced with SS & SR
final SentryMaskingConfig maskingConfig =
(options.experimental.privacy ?? SentryPrivacyOptions())
.buildMaskingConfig();

if (maskingConfig.length > 0) {
// TODO: remove in the next major release, see recorder_test.dart.
@visibleForTesting
bool get hasWidgetFilter => _widgetFilter != null;

// TODO: remove [isReplayRecorder] parameter in the next major release, see _SentryFlutterExperimentalOptions.
ScreenshotRecorder(this.config, this.options,
{bool isReplayRecorder = true}) {
final privacyOptions = isReplayRecorder
? options.experimental.privacyForReplay
: options.experimental.privacyForScreenshots;
final maskingConfig = privacyOptions?.buildMaskingConfig();
if (maskingConfig != null && maskingConfig.length > 0) {
_widgetFilter = WidgetFilter(maskingConfig, options.logger);
}
}
Expand Down
23 changes: 0 additions & 23 deletions flutter/lib/src/sentry_flutter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,6 @@ mixin SentryFlutter {
// ignore: invalid_use_of_internal_member
runZonedGuardedOnError: runZonedGuardedOnError,
);
// TODO: Remove when we synced SS and SR configurations and have a single default configuration
_setRedactionOptions(options);

if (_native != null) {
// ignore: invalid_use_of_internal_member
Expand Down Expand Up @@ -245,27 +243,6 @@ mixin SentryFlutter {
options.sdk = sdk;
}

/// Screen redaction was previously introduced with the SessionReplay feature.
/// Screen redaction is enabled by default for SessionReplay.
/// As we also to use this feature for Screenshot, which previously was not
/// capable of redacting the screenshot, we need to disable redaction for Screenshot by default
/// so we don`t break the existing behavior.
/// As we have only one central place to configure the redaction,
/// we need to set the redaction options to full fill the above default settings.
/// The plan is to unify this behaviour with the next major release.
static void _setRedactionOptions(SentryFlutterOptions options) {
if (options.experimental.privacy != null) {
return;
} else if (options.screenshot.attachScreenshot == true &&
!options.experimental.replay.isEnabled) {
options.experimental.privacy = SentryPrivacyOptions()
..maskAllText = false
..maskAllImages = false;
} else {
options.experimental.privacy = SentryPrivacyOptions();
}
}

/// Reports the time it took for the screen to be fully displayed.
/// This requires the [SentryFlutterOptions.enableTimeToFullDisplayTracing] option to be set to `true`.
static Future<void> reportFullyDisplayed() async {
Expand Down
25 changes: 24 additions & 1 deletion flutter/lib/src/sentry_flutter_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -395,5 +395,28 @@ class _SentryFlutterExperimentalOptions {
final replay = SentryReplayOptions();

/// Privacy configuration for masking sensitive data in the Screenshot and Session Replay.
SentryPrivacyOptions? privacy;
/// Screen redaction was previously introduced with the SessionReplay feature.
/// Screen redaction is enabled by default for SessionReplay.
/// As we also to use privacy options for Screenshot, which previously was not
/// capable of redacting, we keep the existing behaviour unless expiclitly
/// configured (i.e. [privacy] is accessed).
/// The plan is to unify this behaviour with the next major release.
SentryPrivacyOptions get privacy {
// If the user explicitly sets the privacy setting, we use that.
// Otherwise, we use the default settings, which is no redaction for screenshots
// and full redaction 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 redaction 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();
}
27 changes: 27 additions & 0 deletions flutter/test/replay/recorder_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,33 @@ void main() async {
await _Fixture.create(tester, quality: SentryScreenshotQuality.low);
expect(fixture.capture(), completion('427x854'));
});

// 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 = ScreenshotRecorder(
ScreenshotRecorderConfig(),
defaultTestOptions(),
);
expect(sut.hasWidgetFilter, isTrue);
});

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

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

class _Fixture {
Expand Down
Loading