Skip to content

Commit 3472355

Browse files
authored
Merge pull request #153 from talsec/make-malware-async
release: freeRASP 6.10.0
2 parents 8ec8d80 + 2f88c01 commit 3472355

File tree

7 files changed

+125
-9
lines changed

7 files changed

+125
-9
lines changed

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [6.10.0] - 2024-12-17
9+
10+
- iOS SDK version: 6.6.3
11+
- Android SDK version: 13.0.0
12+
13+
### Flutter
14+
15+
#### Changed
16+
17+
- App icons for detected malware are not fetched automatically anymore, which reduces computation required to retrieve malware data. From now on, app icons have to be retrieved using the `getAppIcon` method
18+
19+
### Android
20+
21+
#### Changed
22+
23+
- Malware data is now parsed on background thread to improve responsiveness
24+
825
## [6.9.0] - 2024-11-19
926
- Android SDK version: 13.0.0
1027
- iOS SDK version: 6.6.3

android/src/main/kotlin/com/aheaditec/freerasp/Extensions.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ private fun PackageInfo.toPigeon(context: Context): FlutterPackageInfo {
4949
context.packageManager.getApplicationLabel(it) as String
5050
},
5151
version = getVersionString(),
52-
appIcon = Utils.parseIconBase64(context, packageName),
5352
installationSource = Utils.getInstallerPackageName(context, packageName),
5453
)
5554
}

android/src/main/kotlin/com/aheaditec/freerasp/handlers/MethodCallHandler.kt

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
package com.aheaditec.freerasp.handlers
22

33
import android.content.Context
4+
import android.os.Handler
5+
import android.os.HandlerThread
6+
import android.os.Looper
7+
import androidx.lifecycle.Lifecycle
8+
import androidx.lifecycle.LifecycleEventObserver
9+
import androidx.lifecycle.LifecycleOwner
410
import com.aheaditec.freerasp.runResultCatching
511
import com.aheaditec.freerasp.Utils
612
import com.aheaditec.freerasp.generated.TalsecPigeonApi
@@ -16,10 +22,13 @@ import io.flutter.plugin.common.MethodChannel.MethodCallHandler
1622
/**
1723
* A method handler that creates and manages an [MethodChannel] for freeRASP methods.
1824
*/
19-
internal class MethodCallHandler : MethodCallHandler {
25+
internal class MethodCallHandler : MethodCallHandler, LifecycleEventObserver {
2026
private var context: Context? = null
2127
private var methodChannel: MethodChannel? = null
2228
private var pigeonApi: TalsecPigeonApi? = null
29+
private val backgroundHandlerThread = HandlerThread("BackgroundThread").apply { start() }
30+
private val backgroundHandler = Handler(backgroundHandlerThread.looper)
31+
private val mainHandler = Handler(Looper.getMainLooper())
2332

2433
companion object {
2534
private const val CHANNEL_NAME: String = "talsec.app/freerasp/methods"
@@ -82,6 +91,20 @@ internal class MethodCallHandler : MethodCallHandler {
8291
TalsecThreatHandler.detachMethodSink()
8392
}
8493

94+
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
95+
when (event) {
96+
Lifecycle.Event.ON_DESTROY -> {
97+
context?.let {
98+
backgroundHandlerThread.quitSafely()
99+
}
100+
}
101+
102+
else -> {
103+
// Nothing to do
104+
}
105+
}
106+
}
107+
85108
/**
86109
* Handles method calls received through the [MethodChannel].
87110
*
@@ -92,6 +115,7 @@ internal class MethodCallHandler : MethodCallHandler {
92115
when (call.method) {
93116
"start" -> start(call, result)
94117
"addToWhitelist" -> addToWhitelist(call, result)
118+
"getAppIcon" -> getAppIcon(call, result)
95119
else -> result.notImplemented()
96120
}
97121
}
@@ -124,4 +148,25 @@ internal class MethodCallHandler : MethodCallHandler {
124148
result.success(null)
125149
}
126150
}
151+
152+
/**
153+
* Retrieves app icon for the given package name.
154+
*
155+
* @param call The method call containing the package name.
156+
* @param result The result handler of the method call.
157+
*/
158+
private fun getAppIcon(call: MethodCall, result: MethodChannel.Result) {
159+
runResultCatching(result) {
160+
val packageName = call.argument<String>("packageName")
161+
?: throw NullPointerException("Package name cannot be null.")
162+
163+
backgroundHandler.post {
164+
context?.let {
165+
val appIcon = Utils.parseIconBase64(it, packageName)
166+
mainHandler.post { result.success(appIcon) }
167+
}
168+
}
169+
170+
}
171+
}
127172
}

example/lib/widgets/malware_bottom_sheet.dart

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,25 @@ class MalwareListTile extends StatelessWidget {
6060

6161
@override
6262
Widget build(BuildContext context) {
63-
return ListTile(
64-
title: Text(malware.packageInfo.packageName),
65-
subtitle: Text('Reason: ${malware.reason}'),
66-
leading: malware.packageInfo.appIcon == null
67-
? const Icon(Icons.warning, color: Colors.red)
68-
: Image.memory(base64.decode(malware.packageInfo.appIcon!)),
63+
return FutureBuilder<String?>(
64+
future: Talsec.instance.getAppIcon(malware.packageInfo.packageName),
65+
builder: (context, snapshot) {
66+
Widget appIcon;
67+
if (snapshot.data != null) {
68+
appIcon = Image.memory(base64.decode(snapshot.data!));
69+
} else {
70+
appIcon = const Icon(
71+
Icons.error,
72+
color: Colors.red,
73+
);
74+
}
75+
76+
return ListTile(
77+
title: Text(malware.packageInfo.packageName),
78+
subtitle: Text('Reason: ${malware.reason}'),
79+
leading: appIcon,
80+
);
81+
},
6982
);
7083
}
7184
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import 'package:freerasp/freerasp.dart';
2+
3+
/// An exception that is thrown when there is a failure in malware data parsing.
4+
///
5+
/// This exception extends the [TalsecException] class and includes an error
6+
/// code of 'malware-failure'. It can include an optional [message] and
7+
/// [stackTrace] parameter.
8+
class MalwareFailureException extends TalsecException {
9+
/// Constructs an instance of [MalwareFailureException].
10+
const MalwareFailureException({super.message, super.stackTrace})
11+
: super(code: 'malware-failure');
12+
}

lib/src/talsec.dart

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'dart:io';
55
import 'package:flutter/foundation.dart';
66
import 'package:flutter/services.dart';
77
import 'package:freerasp/freerasp.dart';
8+
import 'package:freerasp/src/errors/malware_failure_exception.dart';
89
import 'package:freerasp/src/generated/talsec_pigeon_api.g.dart';
910

1011
/// A class which maintains all security related operations.
@@ -215,4 +216,33 @@ class Talsec {
215216
// ignore: only_throw_errors
216217
throw error;
217218
}
219+
220+
/// Retrieves the app icon for the given [packageName] as base64 string.
221+
///
222+
/// Throws a [TalsecException] with error message description if
223+
/// the app with given package name couldn't be obtained.
224+
Future<String> getAppIcon(String packageName) async {
225+
if (!Platform.isAndroid) {
226+
throw UnimplementedError(
227+
'Platform is not supported: $defaultTargetPlatform}',
228+
);
229+
}
230+
231+
try {
232+
return await _getAppIcon(packageName);
233+
} on PlatformException catch (e) {
234+
throw TalsecException.fromPlatformException(e);
235+
}
236+
}
237+
238+
Future<String> _getAppIcon(String packageName) async {
239+
final args = {'packageName': packageName};
240+
final result = await methodChannel.invokeMethod<String>('getAppIcon', args);
241+
242+
if (result is! String) {
243+
throw const MalwareFailureException(message: 'Malware App icon is null.');
244+
}
245+
246+
return result;
247+
}
218248
}

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: freerasp
22
description: Flutter library for improving app security and threat monitoring on Android and iOS mobile devices. Learn more about provided features on the freeRASP's homepage first.
3-
version: 6.9.0
3+
version: 6.10.0
44
homepage: https://www.talsec.app/freerasp-in-app-protection-security-talsec
55
repository: https://github.com/talsec/Free-RASP-Flutter
66

0 commit comments

Comments
 (0)