Skip to content

Commit 69ec1e8

Browse files
buenaflordenrase
andauthored
Only enable load debug image integration for obfuscated apps (#2907)
* Update * Update * add initial impl * Update * Update mocks * Formatting * Update searching for debug id * Update * Update * Revert main * Improve readability * Return unmodifiable * Update CHANGELOG * Update web_load_debug_images_integration.dart * Update * Improve * Update naming * Add additional test * Update test * Update debug id impl * Update * Update * rename processors to match integration names * update condition, update naming of processors * add cl entry * Update runtime_checker.dart * Rename * Fix analyze * Fix log * dont add on web * fix cl * Fix test * update * Fix test * Formatting * Update * Update --------- Co-authored-by: Denis Andrasec <[email protected]>
1 parent 5002a1f commit 69ec1e8

8 files changed

+106
-17
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ void initState() {
5353
- [changelog](https://github.com/getsentry/sentry-native/blob/master/CHANGELOG.md#090)
5454
- [diff](https://github.com/getsentry/sentry-native/compare/0.8.4...0.9.0)
5555

56+
### Enhancements
57+
58+
- Only enable load debug image integration for obfuscated apps ([#2907](https://github.com/getsentry/sentry-dart/pull/2907))
59+
5660
## 9.0.0
5761

5862
Version 9.0.0 marks a major release of the Sentry Dart/Flutter SDKs containing breaking changes.

dart/lib/src/load_dart_debug_images_integration.dart

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,23 @@ import 'protocol/sentry_stack_trace.dart';
1414
import 'sentry_options.dart';
1515

1616
class LoadDartDebugImagesIntegration extends Integration<SentryOptions> {
17-
static const integrationName = 'LoadDartDebugImagesIntegration';
17+
static const integrationName = 'LoadDartDebugImages';
1818

1919
@override
2020
void call(Hub hub, SentryOptions options) {
21-
if (options.enableDartSymbolication) {
22-
options.addEventProcessor(LoadImageIntegrationEventProcessor(options));
21+
if (options.enableDartSymbolication &&
22+
options.runtimeChecker.isAppObfuscated() &&
23+
!options.platform.isWeb) {
24+
options.addEventProcessor(
25+
LoadDartDebugImagesIntegrationEventProcessor(options));
2326
options.sdk.addIntegration(integrationName);
2427
}
2528
}
2629
}
2730

2831
@internal
29-
class LoadImageIntegrationEventProcessor implements EventProcessor {
30-
LoadImageIntegrationEventProcessor(this._options);
32+
class LoadDartDebugImagesIntegrationEventProcessor implements EventProcessor {
33+
LoadDartDebugImagesIntegrationEventProcessor(this._options);
3134

3235
final SentryOptions _options;
3336

dart/lib/src/runtime_checker.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@ class RuntimeChecker {
2222
return const bool.fromEnvironment('dart.vm.profile', defaultValue: false);
2323
}
2424

25+
/// Check if the Dart code is obfuscated.
26+
bool isAppObfuscated() {
27+
// In non-obfuscated builds, this will return "RuntimeChecker"
28+
// In obfuscated builds, this will return something like "a" or other short identifier
29+
// Note: Flutter Web production builds will always be minified / "obfuscated".
30+
final typeName = runtimeType.toString();
31+
return !typeName.contains('RuntimeChecker');
32+
}
33+
2534
final bool isRootZone;
2635

2736
String get compileMode {

dart/test/load_dart_debug_images_integration_test.dart

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'package:sentry/src/platform/mock_platform.dart';
99
import 'package:sentry/src/sentry_stack_trace_factory.dart';
1010
import 'package:test/test.dart';
1111

12+
import 'mocks/mock_runtime_checker.dart';
1213
import 'test_utils.dart';
1314

1415
void main() {
@@ -26,6 +27,7 @@ void main() {
2627
setUp(() {
2728
fixture = Fixture();
2829
fixture.options.platform = platform;
30+
fixture.callIntegration();
2931
});
3032

3133
test('adds itself to sdk.integrations', () {
@@ -40,7 +42,7 @@ void main() {
4042
expect(fixture.options.eventProcessors.length, 1);
4143
expect(
4244
fixture.options.eventProcessors.first.runtimeType.toString(),
43-
'LoadImageIntegrationEventProcessor',
45+
'LoadDartDebugImagesIntegrationEventProcessor',
4446
);
4547
});
4648

@@ -191,8 +193,39 @@ isolate_dso_base: 10000000
191193
});
192194
}
193195

196+
test('does not add itself to sdk.integrations if app is not obfuscated', () {
197+
final fixture = Fixture()
198+
..options.runtimeChecker = MockRuntimeChecker(isObfuscated: false);
199+
fixture.callIntegration();
200+
expect(
201+
fixture.options.sdk.integrations
202+
.contains(LoadDartDebugImagesIntegration.integrationName),
203+
false,
204+
);
205+
});
206+
207+
test('does not add event processor to options if app is not obfuscated', () {
208+
final fixture = Fixture()
209+
..options.runtimeChecker = MockRuntimeChecker(isObfuscated: false);
210+
fixture.callIntegration();
211+
expect(fixture.options.eventProcessors.length, 0);
212+
});
213+
214+
test('does not add itself to sdk.integrations if platform is web', () {
215+
final fixture = Fixture()
216+
..options.runtimeChecker = MockRuntimeChecker(isObfuscated: true)
217+
..options.platform = MockPlatform(isWeb: true);
218+
fixture.callIntegration();
219+
expect(
220+
fixture.options.sdk.integrations
221+
.contains(LoadDartDebugImagesIntegration.integrationName),
222+
false,
223+
);
224+
});
225+
194226
test('debug image is null on unsupported platforms', () async {
195227
final fixture = Fixture()..options.platform = MockPlatform.linux();
228+
fixture.callIntegration();
196229
final event = fixture.newEvent(stackTrace: fixture.parse('''
197230
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
198231
build_id: 'b680cb890f9e3c12a24b172d050dec73'
@@ -205,10 +238,11 @@ isolate_dso_base: 40000000
205238
}
206239

207240
class Fixture {
208-
final options = defaultTestOptions();
241+
final options = defaultTestOptions()
242+
..runtimeChecker = MockRuntimeChecker(isObfuscated: true);
209243
late final factory = SentryStackTraceFactory(options);
210244

211-
Fixture() {
245+
void callIntegration() {
212246
final integration = LoadDartDebugImagesIntegration();
213247
integration.call(Hub(options), options);
214248
}

dart/test/mocks/mock_runtime_checker.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ class MockRuntimeChecker extends RuntimeChecker with NoSuchMethodProvider {
77
this.isDebug = false,
88
this.isProfile = false,
99
this.isRelease = false,
10+
this.isObfuscated = false,
1011
bool isRootZone = true,
1112
}) : super(isRootZone: isRootZone);
1213

1314
final bool isDebug;
1415
final bool isProfile;
1516
final bool isRelease;
17+
final bool isObfuscated;
1618

1719
@override
1820
bool isDebugMode() => isDebug;
@@ -22,4 +24,7 @@ class MockRuntimeChecker extends RuntimeChecker with NoSuchMethodProvider {
2224

2325
@override
2426
bool isReleaseMode() => isRelease;
27+
28+
@override
29+
bool isAppObfuscated() => isObfuscated;
2530
}

flutter/lib/src/integrations/native_load_debug_images_integration.dart

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,25 @@ class LoadNativeDebugImagesIntegration
2222

2323
@override
2424
void call(Hub hub, SentryFlutterOptions options) {
25-
options.addEventProcessor(
26-
_LoadImageListIntegrationEventProcessor(options, _native),
27-
);
28-
options.sdk.addIntegration(integrationName);
25+
// ignore: invalid_use_of_internal_member
26+
if (options.runtimeChecker.isAppObfuscated()) {
27+
options.addEventProcessor(
28+
_LoadNativeDebugImagesIntegrationEventProcessor(options, _native),
29+
);
30+
options.sdk.addIntegration(integrationName);
31+
}
2932
}
3033
}
3134

32-
class _LoadImageListIntegrationEventProcessor implements EventProcessor {
33-
_LoadImageListIntegrationEventProcessor(this._options, this._native);
35+
class _LoadNativeDebugImagesIntegrationEventProcessor
36+
implements EventProcessor {
37+
_LoadNativeDebugImagesIntegrationEventProcessor(this._options, this._native);
3438

3539
final SentryFlutterOptions _options;
3640
final SentryNativeBinding _native;
3741

38-
late final _dartProcessor = LoadImageIntegrationEventProcessor(_options);
42+
late final _dartProcessor =
43+
LoadDartDebugImagesIntegrationEventProcessor(_options);
3944

4045
@override
4146
Future<SentryEvent?> apply(SentryEvent event, Hint hint) async {

flutter/test/integrations/load_native_debug_images_integration_test.dart

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:mockito/mockito.dart';
66
import 'package:sentry_flutter/sentry_flutter.dart';
77
import 'package:sentry_flutter/src/integrations/native_load_debug_images_integration.dart';
88

9+
import '../mocks.dart';
910
import 'fixture.dart';
1011

1112
void main() {
@@ -26,6 +27,7 @@ void main() {
2627

2728
setUp(() async {
2829
fixture = IntegrationTestFixture(LoadNativeDebugImagesIntegration.new);
30+
fixture.options.runtimeChecker = MockRuntimeChecker(isObfuscated: true);
2931
when(fixture.binding.loadDebugImages(any))
3032
.thenAnswer((_) async => imageList.toList());
3133
await fixture.registerIntegration();
@@ -73,8 +75,8 @@ void main() {
7375

7476
test('Event processor adds image list to the event', () async {
7577
final ep = fixture.options.eventProcessors.first;
76-
expect(
77-
ep.runtimeType.toString(), "_LoadImageListIntegrationEventProcessor");
78+
expect(ep.runtimeType.toString(),
79+
"_LoadNativeDebugImagesIntegrationEventProcessor");
7880
SentryEvent? event = _getEvent();
7981
event = await ep.apply(event, Hint());
8082

@@ -104,6 +106,28 @@ void main() {
104106
verifyNever(fixture.binding.loadDebugImages(any));
105107
});
106108
});
109+
110+
test('does not add itself to sdk.integrations if app is not obfuscated',
111+
() async {
112+
final fixture =
113+
IntegrationTestFixture(LoadNativeDebugImagesIntegration.new);
114+
fixture.options.runtimeChecker = MockRuntimeChecker();
115+
await fixture.registerIntegration();
116+
expect(
117+
fixture.options.sdk.integrations
118+
.contains(LoadNativeDebugImagesIntegration.integrationName),
119+
false,
120+
);
121+
});
122+
123+
test('does not add event processor to options if app is not obfuscated',
124+
() async {
125+
final fixture =
126+
IntegrationTestFixture(LoadNativeDebugImagesIntegration.new);
127+
fixture.options.runtimeChecker = MockRuntimeChecker();
128+
await fixture.registerIntegration();
129+
expect(fixture.options.eventProcessors.length, 0);
130+
});
107131
}
108132

109133
SentryEvent _getEvent() {

flutter/test/mocks.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,12 @@ void main() {}
7979
class MockRuntimeChecker with NoSuchMethodProvider implements RuntimeChecker {
8080
MockRuntimeChecker({
8181
this.buildMode = MockRuntimeCheckerBuildMode.debug,
82+
this.isObfuscated = false,
8283
this.isRoot = true,
8384
});
8485

8586
final MockRuntimeCheckerBuildMode buildMode;
87+
final bool isObfuscated;
8688
final bool isRoot;
8789

8890
@override
@@ -94,6 +96,9 @@ class MockRuntimeChecker with NoSuchMethodProvider implements RuntimeChecker {
9496
@override
9597
bool isReleaseMode() => buildMode == MockRuntimeCheckerBuildMode.release;
9698

99+
@override
100+
bool isAppObfuscated() => isObfuscated;
101+
97102
@override
98103
bool get isRootZone => isRoot;
99104
}

0 commit comments

Comments
 (0)