Skip to content

Commit 5db8538

Browse files
authored
Make malware async (#25)
* fix(Android): move malware processing to background thread * fix(ts): move malware processing to background thread * feat(example): move malware processing to background thread * docs: update changelog * chore(release): freeRASP 1.8.0 * chore: bug fix
1 parent 86b27cd commit 5db8538

File tree

14 files changed

+151
-30
lines changed

14 files changed

+151
-30
lines changed

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,24 @@ 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+
## [1.8.0] - 2024-12-06
9+
10+
- iOS SDK version: 6.6.3
11+
- Android SDK version: 13.0.0
12+
13+
### Capacitor
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+
- Parsing of malware data is now async
19+
20+
### Android
21+
22+
#### Changed
23+
24+
- Malware data is now parsed on background thread to improve responsiveness
25+
826
## [1.7.0] - 2024-11-19
927

1028
### Capacitor

android/src/main/java/com/aheaditec/freerasp/FreeraspPlugin.kt

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package com.aheaditec.freerasp
22

3+
import android.os.Handler
4+
import android.os.HandlerThread
5+
import android.os.Looper
6+
import com.aheaditec.freerasp.utils.Utils
37
import com.aheaditec.freerasp.utils.getArraySafe
48
import com.aheaditec.freerasp.utils.getNestedArraySafe
59
import com.aheaditec.freerasp.utils.toEncodedJSArray
@@ -37,7 +41,11 @@ class FreeraspPlugin : Plugin() {
3741
}
3842
call.resolve(JSObject().put("started", true))
3943
} catch (e: Exception) {
40-
call.reject("Error during Talsec Native plugin initialization - ${e.message}", "TalsecInitializationError", e)
44+
call.reject(
45+
"Error during Talsec Native plugin initialization - ${e.message}",
46+
"TalsecInitializationError",
47+
e
48+
)
4149
}
4250
}
4351

@@ -57,6 +65,11 @@ class FreeraspPlugin : Plugin() {
5765
}
5866
}
5967

68+
override fun handleOnDestroy() {
69+
super.handleOnDestroy()
70+
backgroundHandlerThread.quitSafely()
71+
}
72+
6073
/**
6174
* Method to get the random identifiers of callbacks
6275
*/
@@ -107,13 +120,44 @@ class FreeraspPlugin : Plugin() {
107120
call.resolve(JSObject().put("result", true))
108121
}
109122

123+
/**
124+
* Method retrieves app icon for the given parameter
125+
* @param packageName package name of the app we want to retrieve icon for
126+
* @return PNG with app icon encoded as a base64 string
127+
*/
128+
@PluginMethod
129+
fun getAppIcon(call: PluginCall) {
130+
val packageName = call.getString("packageName")
131+
if (packageName.isNullOrEmpty()) {
132+
call.reject(
133+
"Package name argument is missing or empty in the call",
134+
"MissingArgumentError"
135+
)
136+
return
137+
}
138+
// Perform the app icon encoding on a background thread
139+
backgroundHandler.post {
140+
val encodedData = Utils.getAppIconAsBase64String(context, packageName)
141+
mainHandler.post { call.resolve(JSObject().put("result", encodedData)) }
142+
}
143+
}
144+
110145
internal fun notifyListeners(threat: Threat) {
111146
notifyListeners(THREAT_CHANNEL_NAME, JSObject().put(THREAT_CHANNEL_KEY, threat.value), true)
112147
}
113148

114149
internal fun notifyMalware(suspiciousApps: MutableList<SuspiciousAppInfo>) {
115-
notifyListeners(THREAT_CHANNEL_NAME, JSObject().put(THREAT_CHANNEL_KEY, Threat.Malware.value).put(
116-
MALWARE_CHANNEL_KEY, suspiciousApps.toEncodedJSArray(context)), true)
150+
// Perform the malware encoding on a background thread
151+
backgroundHandler.post {
152+
153+
val encodedSuspiciousApps = suspiciousApps.toEncodedJSArray(context)
154+
mainHandler.post {
155+
val params = JSObject()
156+
.put(THREAT_CHANNEL_KEY, Threat.Malware.value)
157+
.put(MALWARE_CHANNEL_KEY, encodedSuspiciousApps)
158+
notifyListeners(THREAT_CHANNEL_NAME, params, true)
159+
}
160+
}
117161
}
118162

119163
private fun buildTalsecConfigThrowing(configJson: JSObject): TalsecConfig {
@@ -140,7 +184,10 @@ class FreeraspPlugin : Plugin() {
140184
.toString() // name of the channel over which threat callbacks are sent
141185
private val THREAT_CHANNEL_KEY = (10000..999999999).random()
142186
.toString() // key of the argument map under which threats are expected
143-
val MALWARE_CHANNEL_KEY = (10000..999999999).random()
187+
private val MALWARE_CHANNEL_KEY = (10000..999999999).random()
144188
.toString() // key of the argument map under which malware data is expected
189+
private val backgroundHandlerThread = HandlerThread("BackgroundThread").apply { start() }
190+
private val backgroundHandler = Handler(backgroundHandlerThread.looper)
191+
private val mainHandler = Handler(Looper.getMainLooper())
145192
}
146193
}

android/src/main/java/com/aheaditec/freerasp/utils/Extensions.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ internal fun PackageInfo.toCapPackageInfo(context: Context): CapPackageInfo {
6868
packageName = this.packageName,
6969
appName = Utils.getAppName(context, this.applicationInfo),
7070
version = this.versionName,
71-
appIcon = Utils.getAppIconAsBase64String(context, this.packageName),
71+
appIcon = null, // this requires heavier computations, so appIcon has to be retrieved separately
7272
installerStore = Utils.getInstallationSource(context, this.packageName)
7373
)
7474
}

android/src/main/java/com/aheaditec/freerasp/utils/Utils.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,10 @@ internal object Utils {
7474
context.packageManager.getInstallerPackageName(packageName)
7575
}
7676
} catch (e: Exception) {
77-
Log.e("Talsec", "Could not retrieve app installation source for ${packageName}: ${e.message}")
77+
Log.e(
78+
"Talsec",
79+
"Could not retrieve app installation source for ${packageName}: ${e.message}"
80+
)
7881
null
7982
}
8083
}

dist/esm/definitions.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ export interface FreeraspPlugin {
1717
}): Promise<{
1818
result: boolean;
1919
}>;
20+
getAppIcon(options: {
21+
packageName: string;
22+
}): Promise<{
23+
result: string;
24+
}>;
2025
}
2126
export type FreeraspConfig = {
2227
androidConfig?: AndroidConfig;

dist/esm/definitions.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/esm/index.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ declare const setThreatListeners: <T extends NativeEventEmitterActions>(callback
44
declare const removeThreatListeners: () => void;
55
declare const startFreeRASP: <T extends NativeEventEmitterActions>(config: FreeraspConfig, reactions: T & Record<Exclude<keyof T, keyof NativeEventEmitterActions>, []>) => Promise<boolean>;
66
declare const addToWhitelist: (packageName: string) => Promise<boolean>;
7+
declare const getAppIcon: (packageName: string) => Promise<string>;
78
export * from './definitions';
8-
export { Freerasp, startFreeRASP, setThreatListeners, removeThreatListeners, addToWhitelist, };
9+
export { Freerasp, startFreeRASP, setThreatListeners, removeThreatListeners, addToWhitelist, getAppIcon, };

dist/esm/index.js

Lines changed: 20 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)