Skip to content

Commit

Permalink
Merge branch 'main' into feat/twp
Browse files Browse the repository at this point in the history
  • Loading branch information
buenaflor authored Sep 6, 2023
2 parents 8144013 + 1d47eb7 commit 40f5f4b
Show file tree
Hide file tree
Showing 7 changed files with 261 additions and 23 deletions.
7 changes: 4 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@

### Fixes

- Normalize data properties of `SentryUser` and `Breadcrumb` before sending over method channel ([#1591](https://github.com/getsentry/sentry-dart/pull/1591))
- Fixing memory leak issue in SentryFlutterPlugin (Android Plugin) ([#1588](https://github.com/getsentry/sentry-dart/pull/1588))

### Dependencies

- Bump Android SDK from v6.25.2 to v6.28.0 ([#1586](https://github.com/getsentry/sentry-dart/pull/1586))
- [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#6280)
- [diff](https://github.com/getsentry/sentry-java/compare/6.25.2...6.28.0)
- Bump Cocoa SDK from v8.9.1 to v8.10.0 ([#1584](https://github.com/getsentry/sentry-dart/pull/1584), [#1606](https://github.com/getsentry/sentry-dart/pull/1606))
- [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8100)
- [diff](https://github.com/getsentry/sentry-cocoa/compare/8.9.1...8.10.0)
- Bump Cocoa SDK from v8.9.1 to v8.11.0 ([#1584](https://github.com/getsentry/sentry-dart/pull/1584), [#1606](https://github.com/getsentry/sentry-dart/pull/1606), [#1626](https://github.com/getsentry/sentry-dart/pull/1626))
- [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8110)
- [diff](https://github.com/getsentry/sentry-cocoa/compare/8.9.1...8.11.0)

## 7.9.0

Expand Down
2 changes: 1 addition & 1 deletion flutter/ios/sentry_flutter.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Sentry SDK for Flutter with support to native through sentry-cocoa.
:tag => s.version.to_s }
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Sentry/HybridSDK', '8.10.0'
s.dependency 'Sentry/HybridSDK', '8.11.0'
s.ios.dependency 'Flutter'
s.osx.dependency 'FlutterMacOS'
s.ios.deployment_target = '11.0'
Expand Down
38 changes: 38 additions & 0 deletions flutter/lib/src/method_channel_helper.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import 'package:meta/meta.dart';

/// Makes sure no invalid data is sent over method channels.
@internal
class MethodChannelHelper {
static dynamic normalize(dynamic data) {
if (data == null) {
return null;
}
if (_isPrimitive(data)) {
return data;
} else if (data is List<dynamic>) {
return _normalizeList(data);
} else if (data is Map<String, dynamic>) {
return normalizeMap(data);
} else {
return data.toString();
}
}

static Map<String, dynamic>? normalizeMap(Map<String, dynamic>? data) {
if (data == null) {
return null;
}
return data.map((key, value) => MapEntry(key, normalize(value)));
}

static List<dynamic>? _normalizeList(List<dynamic>? data) {
if (data == null) {
return null;
}
return data.map((e) => normalize(e)).toList();
}

static bool _isPrimitive(dynamic value) {
return value == null || value is String || value is num || value is bool;
}
}
32 changes: 26 additions & 6 deletions flutter/lib/src/sentry_native_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter/services.dart';
import 'package:meta/meta.dart';

import '../sentry_flutter.dart';
import 'method_channel_helper.dart';

/// Provide typed methods to access native layer.
@internal
Expand Down Expand Up @@ -47,16 +48,27 @@ class SentryNativeChannel {

Future<void> setUser(SentryUser? user) async {
try {
await _channel.invokeMethod('setUser', {'user': user?.toJson()});
final normalizedUser = user?.copyWith(
data: MethodChannelHelper.normalizeMap(user.data),
);
await _channel.invokeMethod(
'setUser',
{'user': normalizedUser?.toJson()},
);
} catch (error, stackTrace) {
_logError('setUser', error, stackTrace);
}
}

Future<void> addBreadcrumb(Breadcrumb breadcrumb) async {
try {
await _channel
.invokeMethod('addBreadcrumb', {'breadcrumb': breadcrumb.toJson()});
final normalizedBreadcrumb = breadcrumb.copyWith(
data: MethodChannelHelper.normalizeMap(breadcrumb.data),
);
await _channel.invokeMethod(
'addBreadcrumb',
{'breadcrumb': normalizedBreadcrumb.toJson()},
);
} catch (error, stackTrace) {
_logError('addBreadcrumb', error, stackTrace);
}
Expand All @@ -72,7 +84,11 @@ class SentryNativeChannel {

Future<void> setContexts(String key, dynamic value) async {
try {
await _channel.invokeMethod('setContexts', {'key': key, 'value': value});
final normalizedValue = MethodChannelHelper.normalize(value);
await _channel.invokeMethod(
'setContexts',
{'key': key, 'value': normalizedValue},
);
} catch (error, stackTrace) {
_logError('setContexts', error, stackTrace);
}
Expand All @@ -88,7 +104,11 @@ class SentryNativeChannel {

Future<void> setExtra(String key, dynamic value) async {
try {
await _channel.invokeMethod('setExtra', {'key': key, 'value': value});
final normalizedValue = MethodChannelHelper.normalize(value);
await _channel.invokeMethod(
'setExtra',
{'key': key, 'value': normalizedValue},
);
} catch (error, stackTrace) {
_logError('setExtra', error, stackTrace);
}
Expand All @@ -102,7 +122,7 @@ class SentryNativeChannel {
}
}

Future<void> setTag(String key, dynamic value) async {
Future<void> setTag(String key, String value) async {
try {
await _channel.invokeMethod('setTag', {'key': key, 'value': value});
} catch (error, stackTrace) {
Expand Down
1 change: 1 addition & 0 deletions flutter/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ dev_dependencies:
mockito: ^5.1.0
yaml: ^3.1.0 # needed for version match (code and pubspec)
flutter_lints: ^2.0.0
collection: ^1.16.0

flutter:
plugin:
Expand Down
159 changes: 159 additions & 0 deletions flutter/test/method_channel_helper_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:sentry_flutter/src/method_channel_helper.dart';
import 'package:collection/collection.dart';

void main() {
group('normalize', () {
test('primitives', () {
var expected = <String, dynamic>{
'null': null,
'int': 1,
'float': 1.1,
'bool': true,
'string': 'Foo',
};

var actual = MethodChannelHelper.normalizeMap(expected);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);

expect(MethodChannelHelper.normalize(null), null);
expect(MethodChannelHelper.normalize(1), 1);
expect(MethodChannelHelper.normalize(1.1), 1.1);
expect(MethodChannelHelper.normalize(true), true);
expect(MethodChannelHelper.normalize('Foo'), 'Foo');
});

test('object', () {
expect(MethodChannelHelper.normalize(_CustomObject()), 'CustomObject()');
});

test('object in list', () {
var input = <String, dynamic>{
'object': [_CustomObject()]
};
var expected = <String, dynamic>{
'object': ['CustomObject()']
};

var actual = MethodChannelHelper.normalize(input);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
});

test('object in map', () {
var input = <String, dynamic>{
'object': <String, dynamic>{'object': _CustomObject()}
};
var expected = <String, dynamic>{
'object': <String, dynamic>{'object': 'CustomObject()'}
};

var actual = MethodChannelHelper.normalize(input);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
});
});

group('normalizeMap', () {
test('primitives', () {
var expected = <String, dynamic>{
'null': null,
'int': 1,
'float': 1.1,
'bool': true,
'string': 'Foo',
};

var actual = MethodChannelHelper.normalizeMap(expected);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
});

test('list with primitives', () {
var expected = <String, dynamic>{
'list': [null, 1, 1.1, true, 'Foo'],
};

var actual = MethodChannelHelper.normalizeMap(expected);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
});

test('map with primitives', () {
var expected = <String, dynamic>{
'map': <String, dynamic>{
'null': null,
'int': 1,
'float': 1.1,
'bool': true,
'string': 'Foo',
},
};

var actual = MethodChannelHelper.normalizeMap(expected);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
});

test('object', () {
var input = <String, dynamic>{'object': _CustomObject()};
var expected = <String, dynamic>{'object': 'CustomObject()'};

var actual = MethodChannelHelper.normalizeMap(input);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
});

test('object in list', () {
var input = <String, dynamic>{
'object': [_CustomObject()]
};
var expected = <String, dynamic>{
'object': ['CustomObject()']
};

var actual = MethodChannelHelper.normalizeMap(input);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
});

test('object in map', () {
var input = <String, dynamic>{
'object': <String, dynamic>{'object': _CustomObject()}
};
var expected = <String, dynamic>{
'object': <String, dynamic>{'object': 'CustomObject()'}
};

var actual = MethodChannelHelper.normalizeMap(input);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
});
});
}

class _CustomObject {
@override
String toString() {
return 'CustomObject()';
}
}
Loading

0 comments on commit 40f5f4b

Please sign in to comment.