capacitor-freerasp 2.4.1 → 2.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/android/build.gradle +1 -1
  3. package/android/src/main/java/com/aheaditec/freerasp/FreeraspPlugin.kt +61 -46
  4. package/android/src/main/java/com/aheaditec/freerasp/PluginThreatHandler.kt +25 -27
  5. package/android/src/main/java/com/aheaditec/freerasp/dispatchers/ExecutionStateDispatcher.kt +35 -16
  6. package/android/src/main/java/com/aheaditec/freerasp/dispatchers/ThreatDispatcher.kt +42 -24
  7. package/android/src/main/java/com/aheaditec/freerasp/utils/RandomGenerator.kt +1 -2
  8. package/dist/esm/api/listeners/raspExecutionState.js +23 -11
  9. package/dist/esm/api/listeners/raspExecutionState.js.map +1 -1
  10. package/dist/esm/api/listeners/threat.js +25 -12
  11. package/dist/esm/api/listeners/threat.js.map +1 -1
  12. package/dist/esm/api/methods/capacitor.js +7 -1
  13. package/dist/esm/api/methods/capacitor.js.map +1 -1
  14. package/dist/esm/channels/threat.js +2 -5
  15. package/dist/esm/channels/threat.js.map +1 -1
  16. package/dist/esm/models/threat.js +1 -0
  17. package/dist/esm/models/threat.js.map +1 -1
  18. package/dist/esm/types/types.d.ts +6 -1
  19. package/dist/esm/types/types.js.map +1 -1
  20. package/dist/plugin.cjs.js +58 -28
  21. package/dist/plugin.cjs.js.map +1 -1
  22. package/dist/plugin.js +58 -28
  23. package/dist/plugin.js.map +1 -1
  24. package/ios/Plugin/FreeraspPlugin.m +1 -0
  25. package/ios/Plugin/FreeraspPlugin.swift +28 -8
  26. package/ios/Plugin/TalsecRuntime.xcframework/Info.plist +5 -5
  27. package/ios/Plugin/TalsecRuntime.xcframework/_CodeSignature/CodeDirectory +0 -0
  28. package/ios/Plugin/TalsecRuntime.xcframework/_CodeSignature/CodeResources +95 -62
  29. package/ios/Plugin/TalsecRuntime.xcframework/_CodeSignature/CodeSignature +0 -0
  30. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/CurlWrapper.h +1 -1
  31. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/TalsecRuntime-Swift.h +1 -1
  32. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/curl.h +7 -7
  33. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/multi.h +4 -4
  34. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/options.h +1 -1
  35. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/urlapi.h +1 -1
  36. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Info.plist +0 -0
  37. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios.abi.json +360 -103
  38. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios.private.swiftinterface +2 -0
  39. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  40. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios.swiftinterface +2 -0
  41. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/PrivacyInfo.xcprivacy +8 -0
  42. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/TalsecRuntime +0 -0
  43. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/_CodeSignature/CodeResources +377 -0
  44. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/CurlWrapper.h +1 -1
  45. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/TalsecRuntime-Swift.h +2 -2
  46. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/curl.h +7 -7
  47. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/multi.h +4 -4
  48. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/options.h +1 -1
  49. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/urlapi.h +1 -1
  50. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Info.plist +0 -0
  51. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios-simulator.abi.json +367 -110
  52. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +2 -0
  53. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  54. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios-simulator.swiftinterface +2 -0
  55. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/x86_64-apple-ios-simulator.abi.json +367 -110
  56. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +2 -0
  57. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  58. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +2 -0
  59. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/PrivacyInfo.xcprivacy +8 -0
  60. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/TalsecRuntime +0 -0
  61. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/_CodeSignature/CodeResources +42 -53
  62. package/ios/Plugin/models/SecurityThreat.swift +2 -0
  63. package/ios/Plugin/utils/EventIdentifiers.swift +2 -2
  64. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,75 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.5.1] - 2026-03-24
9
+
10
+ - Android SDK version: 18.0.4
11
+ - iOS SDK version: 6.14.4
12
+
13
+ ### Capacitor
14
+
15
+ #### Fixed
16
+
17
+ - Fixed case where event dispatchers on Android were not initialized before calling onResume at the app launch
18
+
19
+ ### iOS
20
+
21
+ #### Fixed
22
+
23
+ - Fixed new jailbreak checks false positives on iOS 14 and 13.
24
+ - Fixed false positives with jailbreak on iOS 15 and 16.
25
+ - Fixed issue with app crashing on screenshot/screen recording.
26
+ - Fixed retrigger jailbreak issue on iOS 15 and 16.
27
+
28
+ ## [2.5.0] - 2026-03-03
29
+
30
+ - Android SDK version: 18.0.4
31
+ - iOS SDK version: 6.14.1
32
+
33
+ ### Capacitor
34
+
35
+ #### Changed
36
+
37
+ - Refactor the Android plugin to separate the logic for managing listener states
38
+
39
+ ### Android
40
+
41
+ #### Added
42
+
43
+ - Added support for `KernelSU` to the existing root detection capabilities
44
+ - Added support for `HMA` to the existing root detection capabilities
45
+ - Added new malware detection capabilities
46
+ - Added `onAutomationDetected()` callback to `ThreatDetected` interface
47
+ - We are introducing a new capability, detecting whether the device is being automated using tools like Appium
48
+ - Added value restrictions to `externalId`
49
+ - Method `storeExternalId()` now returns `ExternalIdResult`, which indicates `Success` or `Error` when `externalId` violates restrictions
50
+
51
+ #### Fixed
52
+
53
+ - Fixed exception handling for the KeyStore `getEntry` operation
54
+ - Fixed issue in `ScreenProtector` concerning the `onScreenRecordingDetected` invocations
55
+ - Merged internal shared libraries into a single one, reducing the final APK size
56
+ - Fixed bug related to key storing in keystore type detection (hw-backed keystore check)
57
+ - Fixed manifest queries merge
58
+
59
+ #### Changed
60
+
61
+ - Removed unused library `tmlib`
62
+ - Refactoring of signature verification code
63
+ - Updated compile and target API to 36
64
+ - Improved root detection capabilities
65
+ - Detection of wireless ADB added to ADB detections
66
+
67
+ ### iOS
68
+
69
+ #### Added
70
+
71
+ - Added time spoofing detection, detecting an inaccurate device clock. It is a new threat `timeSpoofing`.
72
+
73
+ #### Changed
74
+
75
+ - Improved jailbreak detection methods.
76
+
8
77
  ## [2.4.1] - 2026-02-13
9
78
 
10
79
  - Android SDK version: 18.0.2
@@ -76,5 +76,5 @@ dependencies {
76
76
  androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
77
77
  androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
78
78
 
79
- implementation 'com.aheaditec.talsec.security:TalsecSecurity-Community-Capacitor:18.0.2'
79
+ implementation 'com.aheaditec.talsec.security:TalsecSecurity-Community-Capacitor:18.0.4'
80
80
  }
@@ -5,6 +5,8 @@ import android.os.Build
5
5
  import android.os.Handler
6
6
  import android.os.HandlerThread
7
7
  import android.os.Looper
8
+ import com.aheaditec.freerasp.dispatchers.ExecutionStateDispatcher
9
+ import com.aheaditec.freerasp.dispatchers.ThreatDispatcher
8
10
  import com.aheaditec.freerasp.utils.Utils
9
11
  import com.aheaditec.freerasp.utils.getArraySafe
10
12
  import com.aheaditec.freerasp.utils.getNestedArraySafe
@@ -29,8 +31,6 @@ typealias CapacitorCallback = (String, JSObject) -> Unit
29
31
  @CapacitorPlugin(name = "Freerasp")
30
32
  class FreeraspPlugin : Plugin() {
31
33
 
32
- private var registered = true
33
-
34
34
  override fun load() {
35
35
  initializeEventKeys()
36
36
  super.load()
@@ -38,6 +38,11 @@ class FreeraspPlugin : Plugin() {
38
38
 
39
39
  @PluginMethod
40
40
  fun talsecStart(call: PluginCall) {
41
+ if (talsecStarted) {
42
+ call.resolve(JSObject().put("started", true))
43
+ return
44
+ }
45
+
41
46
  val config = call.getObject("config")
42
47
  if (config == null) {
43
48
  call.reject("Missing config parameter in freeRASP Native Plugin")
@@ -45,14 +50,7 @@ class FreeraspPlugin : Plugin() {
45
50
  }
46
51
  try {
47
52
  val talsecConfig = buildTalsecConfigThrowing(config)
48
-
49
- val pluginCallback: CapacitorCallback = { eventName, data ->
50
- notifyListeners(eventName, data, true)
51
- }
52
-
53
- PluginThreatHandler.threatDispatcher.listener = PluginListener(context, pluginCallback)
54
- PluginThreatHandler.executionStateDispatcher.listener = PluginListener(context, pluginCallback)
55
- PluginThreatHandler.registerListener(context)
53
+ PluginThreatHandler.registerSDKListener(context)
56
54
 
57
55
  bridge.activity.runOnUiThread {
58
56
  Talsec.start(context, talsecConfig)
@@ -75,35 +73,52 @@ class FreeraspPlugin : Plugin() {
75
73
  }
76
74
  }
77
75
 
78
- override fun handleOnStart() {
79
- super.handleOnStart()
80
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
81
- ScreenProtector.register(activity)
76
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
77
+ override fun addListener(call: PluginCall) {
78
+ val eventName = call.getString("eventName")
79
+ val pluginCallback: CapacitorCallback = { eventName, data ->
80
+ notifyListeners(eventName, data, true)
81
+ }
82
+ if (eventName == ThreatEvent.CHANNEL_NAME) {
83
+ ThreatDispatcher.registerListener(PluginListener(context, pluginCallback))
84
+ }
85
+ if (eventName == RaspExecutionStateEvent.CHANNEL_NAME) {
86
+ ExecutionStateDispatcher.registerListener(PluginListener(context, pluginCallback))
87
+ }
88
+ super.addListener(call)
89
+ }
90
+
91
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
92
+ fun removeListenerForEvent(call: PluginCall) {
93
+ val eventName = call.getString("eventName")
94
+ if (eventName == ThreatEvent.CHANNEL_NAME) {
95
+ ThreatDispatcher.unregisterListener()
96
+ }
97
+ if (eventName == RaspExecutionStateEvent.CHANNEL_NAME) {
98
+ ExecutionStateDispatcher.unregisterListener()
82
99
  }
83
100
  }
84
101
 
85
102
  override fun handleOnPause() {
86
103
  super.handleOnPause()
104
+ ThreatDispatcher.onPause()
105
+ ExecutionStateDispatcher.onPause()
106
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
107
+ ScreenProtector.unregister(activity)
108
+ }
87
109
  if (activity.isFinishing) {
88
- PluginThreatHandler.unregisterListener(context)
89
- registered = false
90
- PluginThreatHandler.threatDispatcher.listener = null
91
- PluginThreatHandler.executionStateDispatcher.listener = null
110
+ ThreatDispatcher.unregisterListener()
111
+ ExecutionStateDispatcher.unregisterListener()
112
+ PluginThreatHandler.unregisterSDKListener(context)
92
113
  }
93
114
  }
94
115
 
95
116
  override fun handleOnResume() {
96
117
  super.handleOnResume()
97
- if (!registered) {
98
- registered = true
99
- PluginThreatHandler.registerListener(context)
100
- }
101
- }
102
-
103
- override fun handleOnStop() {
104
- super.handleOnStop()
118
+ ThreatDispatcher.onResume()
119
+ ExecutionStateDispatcher.onResume()
105
120
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
106
- ScreenProtector.unregister(activity)
121
+ ScreenProtector.register(activity)
107
122
  }
108
123
  }
109
124
 
@@ -317,8 +332,25 @@ class FreeraspPlugin : Plugin() {
317
332
  private val mainHandler = Handler(Looper.getMainLooper())
318
333
 
319
334
  internal var talsecStarted = false
335
+ }
320
336
 
321
- internal fun notifyEvent(
337
+ internal class PluginListener(
338
+ private val context: Context,
339
+ private val pluginCallback: CapacitorCallback
340
+ ) : PluginThreatListener, PluginExecutionStateListener {
341
+ override fun threatDetected(threatEventType: ThreatEvent) {
342
+ notifyEvent(threatEventType, pluginCallback)
343
+ }
344
+
345
+ override fun malwareDetected(suspiciousApps: MutableList<SuspiciousAppInfo>) {
346
+ notifyMalware(suspiciousApps, context, pluginCallback)
347
+ }
348
+
349
+ override fun raspExecutionStateChanged(event: RaspExecutionStateEvent) {
350
+ notifyEvent(event, pluginCallback)
351
+ }
352
+
353
+ private fun notifyEvent(
322
354
  event: BaseRaspEvent,
323
355
  notifyListenersCallback: CapacitorCallback
324
356
  ) {
@@ -326,7 +358,7 @@ class FreeraspPlugin : Plugin() {
326
358
  notifyListenersCallback(event.channelName, params)
327
359
  }
328
360
 
329
- internal fun notifyMalware(
361
+ private fun notifyMalware(
330
362
  suspiciousApps: MutableList<SuspiciousAppInfo>,
331
363
  context: Context,
332
364
  notifyListenersCallback: CapacitorCallback
@@ -345,21 +377,4 @@ class FreeraspPlugin : Plugin() {
345
377
  }
346
378
  }
347
379
  }
348
-
349
- internal class PluginListener(
350
- private val context: Context,
351
- private val pluginCallback: CapacitorCallback
352
- ) : PluginThreatListener, PluginExecutionStateListener {
353
- override fun threatDetected(threatEventType: ThreatEvent) {
354
- notifyEvent(threatEventType, pluginCallback)
355
- }
356
-
357
- override fun malwareDetected(suspiciousApps: MutableList<SuspiciousAppInfo>) {
358
- notifyMalware(suspiciousApps, context, pluginCallback)
359
- }
360
-
361
- override fun raspExecutionStateChanged(event: RaspExecutionStateEvent) {
362
- notifyEvent(event, pluginCallback)
363
- }
364
- }
365
380
  }
@@ -10,112 +10,110 @@ import com.aheaditec.freerasp.events.ThreatEvent
10
10
 
11
11
  internal object PluginThreatHandler {
12
12
 
13
- internal val threatDispatcher = ThreatDispatcher()
14
- internal val executionStateDispatcher = ExecutionStateDispatcher()
15
13
 
16
14
  private val threatDetected = object : ThreatListener.ThreatDetected() {
17
15
 
18
16
  override fun onRootDetected() {
19
- threatDispatcher.dispatchThreat(ThreatEvent.PrivilegedAccess)
17
+ ThreatDispatcher.dispatchThreat(ThreatEvent.PrivilegedAccess)
20
18
  }
21
19
 
22
20
  override fun onDebuggerDetected() {
23
- threatDispatcher.dispatchThreat(ThreatEvent.Debug)
21
+ ThreatDispatcher.dispatchThreat(ThreatEvent.Debug)
24
22
  }
25
23
 
26
24
  override fun onEmulatorDetected() {
27
- threatDispatcher.dispatchThreat(ThreatEvent.Simulator)
25
+ ThreatDispatcher.dispatchThreat(ThreatEvent.Simulator)
28
26
  }
29
27
 
30
28
  override fun onTamperDetected() {
31
- threatDispatcher.dispatchThreat(ThreatEvent.AppIntegrity)
29
+ ThreatDispatcher.dispatchThreat(ThreatEvent.AppIntegrity)
32
30
  }
33
31
 
34
32
  override fun onUntrustedInstallationSourceDetected() {
35
- threatDispatcher.dispatchThreat(ThreatEvent.UnofficialStore)
33
+ ThreatDispatcher.dispatchThreat(ThreatEvent.UnofficialStore)
36
34
  }
37
35
 
38
36
  override fun onHookDetected() {
39
- threatDispatcher.dispatchThreat(ThreatEvent.Hooks)
37
+ ThreatDispatcher.dispatchThreat(ThreatEvent.Hooks)
40
38
  }
41
39
 
42
40
  override fun onDeviceBindingDetected() {
43
- threatDispatcher.dispatchThreat(ThreatEvent.DeviceBinding)
41
+ ThreatDispatcher.dispatchThreat(ThreatEvent.DeviceBinding)
44
42
  }
45
43
 
46
44
  override fun onObfuscationIssuesDetected() {
47
- threatDispatcher.dispatchThreat(ThreatEvent.ObfuscationIssues)
45
+ ThreatDispatcher.dispatchThreat(ThreatEvent.ObfuscationIssues)
48
46
  }
49
47
 
50
48
  override fun onMalwareDetected(suspiciousAppInfos: MutableList<SuspiciousAppInfo>) {
51
- threatDispatcher.dispatchMalware(suspiciousAppInfos ?: mutableListOf())
49
+ ThreatDispatcher.dispatchMalware(suspiciousAppInfos ?: mutableListOf())
52
50
  }
53
51
 
54
52
  override fun onScreenshotDetected() {
55
- threatDispatcher.dispatchThreat(ThreatEvent.Screenshot)
53
+ ThreatDispatcher.dispatchThreat(ThreatEvent.Screenshot)
56
54
  }
57
55
 
58
56
  override fun onScreenRecordingDetected() {
59
- threatDispatcher.dispatchThreat(ThreatEvent.ScreenRecording)
57
+ ThreatDispatcher.dispatchThreat(ThreatEvent.ScreenRecording)
60
58
  }
61
59
 
62
60
  override fun onMultiInstanceDetected() {
63
- threatDispatcher.dispatchThreat(ThreatEvent.MultiInstance)
61
+ ThreatDispatcher.dispatchThreat(ThreatEvent.MultiInstance)
64
62
  }
65
63
 
66
64
  override fun onUnsecureWifiDetected() {
67
- threatDispatcher.dispatchThreat(ThreatEvent.UnsecureWifi)
65
+ ThreatDispatcher.dispatchThreat(ThreatEvent.UnsecureWifi)
68
66
  }
69
67
 
70
68
  override fun onTimeSpoofingDetected() {
71
- threatDispatcher.dispatchThreat(ThreatEvent.TimeSpoofing)
69
+ ThreatDispatcher.dispatchThreat(ThreatEvent.TimeSpoofing)
72
70
  }
73
71
 
74
72
  override fun onLocationSpoofingDetected() {
75
- threatDispatcher.dispatchThreat(ThreatEvent.LocationSpoofing)
73
+ ThreatDispatcher.dispatchThreat(ThreatEvent.LocationSpoofing)
76
74
  }
77
75
 
78
76
  override fun onAutomationDetected() {
79
- threatDispatcher.dispatchThreat(ThreatEvent.Automation)
77
+ ThreatDispatcher.dispatchThreat(ThreatEvent.Automation)
80
78
  }
81
79
  }
82
80
 
83
81
  private val deviceState = object : ThreatListener.DeviceState() {
84
82
 
85
83
  override fun onUnlockedDeviceDetected() {
86
- threatDispatcher.dispatchThreat(ThreatEvent.Passcode)
84
+ ThreatDispatcher.dispatchThreat(ThreatEvent.Passcode)
87
85
  }
88
86
 
89
87
  override fun onHardwareBackedKeystoreNotAvailableDetected() {
90
- threatDispatcher.dispatchThreat(ThreatEvent.SecureHardwareNotAvailable)
88
+ ThreatDispatcher.dispatchThreat(ThreatEvent.SecureHardwareNotAvailable)
91
89
  }
92
90
 
93
91
  override fun onDeveloperModeDetected() {
94
- threatDispatcher.dispatchThreat(ThreatEvent.DevMode)
92
+ ThreatDispatcher.dispatchThreat(ThreatEvent.DevMode)
95
93
  }
96
94
 
97
95
  override fun onADBEnabledDetected() {
98
- threatDispatcher.dispatchThreat(ThreatEvent.ADBEnabled)
96
+ ThreatDispatcher.dispatchThreat(ThreatEvent.ADBEnabled)
99
97
  }
100
98
 
101
99
  override fun onSystemVPNDetected() {
102
- threatDispatcher.dispatchThreat(ThreatEvent.SystemVPN)
100
+ ThreatDispatcher.dispatchThreat(ThreatEvent.SystemVPN)
103
101
  }
104
102
  }
105
103
 
106
104
  private val raspExecutionState = object : ThreatListener.RaspExecutionState() {
107
105
  override fun onAllChecksFinished() {
108
- executionStateDispatcher.dispatch(RaspExecutionStateEvent.AllChecksFinished)
106
+ ExecutionStateDispatcher.dispatch(RaspExecutionStateEvent.AllChecksFinished)
109
107
  }
110
108
  }
111
109
 
112
110
  private val internalListener = ThreatListener(threatDetected, deviceState, raspExecutionState)
113
111
 
114
- internal fun registerListener(context: Context) {
112
+ internal fun registerSDKListener(context: Context) {
115
113
  internalListener.registerListener(context)
116
114
  }
117
115
 
118
- internal fun unregisterListener(context: Context) {
116
+ internal fun unregisterSDKListener(context: Context) {
119
117
  internalListener.unregisterListener(context)
120
118
  }
121
- }
119
+ }
@@ -3,36 +3,55 @@ package com.aheaditec.freerasp.dispatchers
3
3
  import com.aheaditec.freerasp.events.RaspExecutionStateEvent
4
4
  import com.aheaditec.freerasp.interfaces.PluginExecutionStateListener
5
5
 
6
- internal class ExecutionStateDispatcher {
6
+ internal object ExecutionStateDispatcher {
7
+ private lateinit var listener: PluginExecutionStateListener
7
8
  private val cache = mutableSetOf<RaspExecutionStateEvent>()
8
9
 
9
- var listener: PluginExecutionStateListener? = null
10
- set(value) {
11
- field = value
12
- if (value != null) {
13
- flushCache(value)
14
- }
10
+ private var isAppInForeground = false
11
+ private var isListenerRegistered = false
12
+
13
+ fun registerListener(newListener: PluginExecutionStateListener) {
14
+ listener = newListener
15
+ isListenerRegistered = true
16
+ isAppInForeground = true
17
+ flushCache()
18
+ }
19
+
20
+ fun unregisterListener() {
21
+ isListenerRegistered = false
22
+ isAppInForeground = false
23
+ }
24
+
25
+ fun onResume() {
26
+ isAppInForeground = true
27
+ if (isListenerRegistered) {
28
+ flushCache()
15
29
  }
30
+ }
31
+
32
+ fun onPause() {
33
+ isAppInForeground = false
34
+ }
16
35
 
17
36
  fun dispatch(event: RaspExecutionStateEvent) {
18
- val checkedListener = synchronized(cache) {
19
- val currentListener = listener
20
- if (currentListener != null) {
21
- currentListener
22
- } else {
37
+ if (isAppInForeground && isListenerRegistered) {
38
+ listener.raspExecutionStateChanged(event)
39
+ } else {
40
+ synchronized(cache) {
23
41
  cache.add(event)
24
- null
25
42
  }
26
43
  }
27
- checkedListener?.raspExecutionStateChanged(event)
28
44
  }
29
45
 
30
- private fun flushCache(registeredListener: PluginExecutionStateListener) {
46
+ private fun flushCache() {
47
+ if (!isListenerRegistered || !isAppInForeground) {
48
+ return
49
+ }
31
50
  val events = synchronized(cache) {
32
51
  val snapshot = cache.toSet()
33
52
  cache.clear()
34
53
  snapshot
35
54
  }
36
- events.forEach { registeredListener.raspExecutionStateChanged(it) }
55
+ events.forEach { listener.raspExecutionStateChanged(it) }
37
56
  }
38
57
  }
@@ -4,51 +4,69 @@ import com.aheaditec.talsec_security.security.api.SuspiciousAppInfo
4
4
  import com.aheaditec.freerasp.events.ThreatEvent
5
5
  import com.aheaditec.freerasp.interfaces.PluginThreatListener
6
6
 
7
- internal class ThreatDispatcher {
7
+ internal object ThreatDispatcher {
8
+ private lateinit var listener: PluginThreatListener
8
9
  private val threatCache = mutableSetOf<ThreatEvent>()
9
10
  private val malwareCache = mutableSetOf<SuspiciousAppInfo>()
10
11
 
11
- var listener: PluginThreatListener? = null
12
- set(value) {
13
- field = value
14
- if (value != null) {
15
- flushCache(value)
16
- }
12
+ private var isAppInForeground = false
13
+ private var isListenerRegistered = false
14
+
15
+ fun registerListener(newListener: PluginThreatListener) {
16
+ listener = newListener
17
+ isListenerRegistered = true
18
+ isAppInForeground = true
19
+ flushCache()
20
+ }
21
+
22
+ fun unregisterListener() {
23
+ isListenerRegistered = false
24
+ isAppInForeground = false
25
+ }
26
+
27
+ fun onResume() {
28
+ isAppInForeground = true
29
+ if (isListenerRegistered) {
30
+ flushCache()
17
31
  }
32
+ }
33
+
34
+ fun onPause() {
35
+ isAppInForeground = false
36
+ }
18
37
 
19
38
  fun dispatchThreat(event: ThreatEvent) {
20
- val checkedListener = synchronized(threatCache) {
21
- val currentListener = listener
22
- if (currentListener != null) {
23
- currentListener
24
- } else {
39
+ if (isAppInForeground && isListenerRegistered) {
40
+ listener.threatDetected(event)
41
+ } else {
42
+ synchronized(threatCache) {
25
43
  threatCache.add(event)
26
- null
27
44
  }
28
45
  }
29
- checkedListener?.threatDetected(event)
30
46
  }
31
47
 
32
48
  fun dispatchMalware(apps: MutableList<SuspiciousAppInfo>) {
33
- val checkedListener = synchronized(malwareCache) {
34
- val currentListener = listener
35
- if (currentListener != null) {
36
- currentListener
37
- } else {
49
+ if (isAppInForeground && isListenerRegistered) {
50
+ listener.malwareDetected(apps)
51
+ }
52
+ else {
53
+ synchronized(malwareCache) {
38
54
  malwareCache.addAll(apps)
39
- null
40
55
  }
41
56
  }
42
- checkedListener?.malwareDetected(apps)
43
57
  }
44
58
 
45
- private fun flushCache(registeredListener: PluginThreatListener) {
59
+ private fun flushCache() {
60
+ if (!isListenerRegistered || !isAppInForeground) {
61
+ return
62
+ }
63
+
46
64
  val threats = synchronized(threatCache) {
47
65
  val snapshot = threatCache.toSet()
48
66
  threatCache.clear()
49
67
  snapshot
50
68
  }
51
- threats.forEach { registeredListener.threatDetected(it) }
69
+ threats.forEach { listener.threatDetected(it) }
52
70
 
53
71
  val malware = synchronized(malwareCache) {
54
72
  val snapshot = malwareCache.toMutableList()
@@ -56,7 +74,7 @@ internal class ThreatDispatcher {
56
74
  snapshot
57
75
  }
58
76
  if (malware.isNotEmpty()) {
59
- registeredListener.malwareDetected(malware)
77
+ listener.malwareDetected(malware)
60
78
  }
61
79
  }
62
80
  }
@@ -20,5 +20,4 @@ internal object RandomGenerator {
20
20
 
21
21
  return nextNumber
22
22
  }
23
-
24
- }
23
+ }
@@ -3,24 +3,34 @@ import { RaspExecutionState } from '../../models/raspExecutionState';
3
3
  import { onInvalidCallback } from '../methods/native';
4
4
  import { Talsec } from '../nativeModules';
5
5
  let eventsListener = null;
6
+ let executionStateChannel = null;
7
+ let executionStateKey = null;
6
8
  let isInitializing = false;
9
+ let isMappingPrepared = false;
7
10
  export const registerRaspExecutionStateListener = async (config) => {
8
11
  if (isInitializing) {
9
12
  return;
10
13
  }
11
14
  isInitializing = true;
12
- if (eventsListener) {
13
- await eventsListener.remove();
14
- eventsListener = null;
15
+ await removeRaspExecutionStateListener();
16
+ if (!executionStateChannel || !executionStateKey) {
17
+ [executionStateChannel, executionStateKey] = await getRaspExecutionStateChannelData();
15
18
  }
16
- const [channel, key] = await getRaspExecutionStateChannelData();
17
- await prepareRaspExecutionStateMapping();
18
- eventsListener = await Talsec.addListener(channel, async (event) => {
19
+ if (!isMappingPrepared) {
20
+ await prepareRaspExecutionStateMapping();
21
+ isMappingPrepared = true;
22
+ }
23
+ if (!executionStateChannel) {
24
+ onInvalidCallback();
25
+ return;
26
+ }
27
+ eventsListener = await Talsec.addListener(executionStateChannel, async (event) => {
19
28
  var _a;
20
- if (event[key] == undefined) {
29
+ if (!executionStateKey) {
21
30
  onInvalidCallback();
31
+ return;
22
32
  }
23
- switch (event[key]) {
33
+ switch (event[executionStateKey]) {
24
34
  case RaspExecutionState.AllChecksFinished.value:
25
35
  (_a = config.allChecksFinished) === null || _a === void 0 ? void 0 : _a.call(config);
26
36
  break;
@@ -32,9 +42,11 @@ export const registerRaspExecutionStateListener = async (config) => {
32
42
  isInitializing = false;
33
43
  };
34
44
  export const removeRaspExecutionStateListener = async () => {
35
- if (eventsListener) {
36
- await eventsListener.remove();
37
- eventsListener = null;
45
+ if (!eventsListener || !executionStateChannel) {
46
+ return;
38
47
  }
48
+ await eventsListener.remove();
49
+ eventsListener = null;
50
+ await Talsec.removeListenerForEvent({ eventName: executionStateChannel });
39
51
  };
40
52
  //# sourceMappingURL=raspExecutionState.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"raspExecutionState.js","sourceRoot":"","sources":["../../../../src/api/listeners/raspExecutionState.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gCAAgC,EAAE,gCAAgC,EAAE,MAAM,mCAAmC,CAAC;AACvH,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAErE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,IAAI,cAAc,GAAgC,IAAI,CAAC;AACvD,IAAI,cAAc,GAAG,KAAK,CAAC;AAE3B,MAAM,CAAC,MAAM,kCAAkC,GAAG,KAAK,EAAE,MAAsC,EAAiB,EAAE;IAChH,IAAI,cAAc,EAAE,CAAC;QACnB,OAAO;IACT,CAAC;IACD,cAAc,GAAG,IAAI,CAAC;IAEtB,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,cAAc,CAAC,MAAM,EAAE,CAAC;QAC9B,cAAc,GAAG,IAAI,CAAC;IACxB,CAAC;IAED,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,MAAM,gCAAgC,EAAE,CAAC;IAChE,MAAM,gCAAgC,EAAE,CAAC;IAEzC,cAAc,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,KAAU,EAAE,EAAE;;QACtE,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,SAAS,EAAE,CAAC;YAC5B,iBAAiB,EAAE,CAAC;QACtB,CAAC;QACD,QAAQ,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YACnB,KAAK,kBAAkB,CAAC,iBAAiB,CAAC,KAAK;gBAC7C,MAAA,MAAM,CAAC,iBAAiB,sDAAI,CAAC;gBAC7B,MAAM;YACR;gBACE,iBAAiB,EAAE,CAAC;gBACpB,MAAM;QACV,CAAC;IACH,CAAC,CAAC,CAAC;IACH,cAAc,GAAG,KAAK,CAAC;AACzB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gCAAgC,GAAG,KAAK,IAAmB,EAAE;IACxE,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,cAAc,CAAC,MAAM,EAAE,CAAC;QAC9B,cAAc,GAAG,IAAI,CAAC;IACxB,CAAC;AACH,CAAC,CAAC","sourcesContent":["import type { PluginListenerHandle } from '@capacitor/core';\n\nimport { getRaspExecutionStateChannelData, prepareRaspExecutionStateMapping } from '../../channels/raspExecutionState';\nimport { RaspExecutionState } from '../../models/raspExecutionState';\nimport type { RaspExecutionStateEventActions } from '../../types/types';\nimport { onInvalidCallback } from '../methods/native';\nimport { Talsec } from '../nativeModules';\n\nlet eventsListener: PluginListenerHandle | null = null;\nlet isInitializing = false;\n\nexport const registerRaspExecutionStateListener = async (config: RaspExecutionStateEventActions): Promise<void> => {\n if (isInitializing) {\n return;\n }\n isInitializing = true;\n\n if (eventsListener) {\n await eventsListener.remove();\n eventsListener = null;\n }\n\n const [channel, key] = await getRaspExecutionStateChannelData();\n await prepareRaspExecutionStateMapping();\n\n eventsListener = await Talsec.addListener(channel, async (event: any) => {\n if (event[key] == undefined) {\n onInvalidCallback();\n }\n switch (event[key]) {\n case RaspExecutionState.AllChecksFinished.value:\n config.allChecksFinished?.();\n break;\n default:\n onInvalidCallback();\n break;\n }\n });\n isInitializing = false;\n};\n\nexport const removeRaspExecutionStateListener = async (): Promise<void> => {\n if (eventsListener) {\n await eventsListener.remove();\n eventsListener = null;\n }\n};\n"]}
1
+ {"version":3,"file":"raspExecutionState.js","sourceRoot":"","sources":["../../../../src/api/listeners/raspExecutionState.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gCAAgC,EAAE,gCAAgC,EAAE,MAAM,mCAAmC,CAAC;AACvH,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAErE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,IAAI,cAAc,GAAgC,IAAI,CAAC;AACvD,IAAI,qBAAqB,GAAkB,IAAI,CAAC;AAChD,IAAI,iBAAiB,GAAkB,IAAI,CAAC;AAE5C,IAAI,cAAc,GAAG,KAAK,CAAC;AAC3B,IAAI,iBAAiB,GAAG,KAAK,CAAC;AAE9B,MAAM,CAAC,MAAM,kCAAkC,GAAG,KAAK,EAAE,MAAsC,EAAiB,EAAE;IAChH,IAAI,cAAc,EAAE,CAAC;QACnB,OAAO;IACT,CAAC;IACD,cAAc,GAAG,IAAI,CAAC;IAEtB,MAAM,gCAAgC,EAAE,CAAC;IAEzC,IAAI,CAAC,qBAAqB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACjD,CAAC,qBAAqB,EAAE,iBAAiB,CAAC,GAAG,MAAM,gCAAgC,EAAE,CAAC;IACxF,CAAC;IAED,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,MAAM,gCAAgC,EAAE,CAAC;QACzC,iBAAiB,GAAG,IAAI,CAAC;IAC3B,CAAC;IAED,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC3B,iBAAiB,EAAE,CAAC;QACpB,OAAO;IACT,CAAC;IAED,cAAc,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,qBAAqB,EAAE,KAAK,EAAE,KAAU,EAAE,EAAE;;QACpF,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,iBAAiB,EAAE,CAAC;YACpB,OAAO;QACT,CAAC;QAED,QAAQ,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACjC,KAAK,kBAAkB,CAAC,iBAAiB,CAAC,KAAK;gBAC7C,MAAA,MAAM,CAAC,iBAAiB,sDAAI,CAAC;gBAC7B,MAAM;YACR;gBACE,iBAAiB,EAAE,CAAC;gBACpB,MAAM;QACV,CAAC;IACH,CAAC,CAAC,CAAC;IACH,cAAc,GAAG,KAAK,CAAC;AACzB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gCAAgC,GAAG,KAAK,IAAmB,EAAE;IACxE,IAAI,CAAC,cAAc,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC9C,OAAO;IACT,CAAC;IACD,MAAM,cAAc,CAAC,MAAM,EAAE,CAAC;IAC9B,cAAc,GAAG,IAAI,CAAC;IACtB,MAAM,MAAM,CAAC,sBAAsB,CAAC,EAAE,SAAS,EAAE,qBAAqB,EAAE,CAAC,CAAC;AAC5E,CAAC,CAAC","sourcesContent":["import type { PluginListenerHandle } from '@capacitor/core';\n\nimport { getRaspExecutionStateChannelData, prepareRaspExecutionStateMapping } from '../../channels/raspExecutionState';\nimport { RaspExecutionState } from '../../models/raspExecutionState';\nimport type { RaspExecutionStateEventActions } from '../../types/types';\nimport { onInvalidCallback } from '../methods/native';\nimport { Talsec } from '../nativeModules';\n\nlet eventsListener: PluginListenerHandle | null = null;\nlet executionStateChannel: string | null = null;\nlet executionStateKey: string | null = null;\n\nlet isInitializing = false;\nlet isMappingPrepared = false;\n\nexport const registerRaspExecutionStateListener = async (config: RaspExecutionStateEventActions): Promise<void> => {\n if (isInitializing) {\n return;\n }\n isInitializing = true;\n\n await removeRaspExecutionStateListener();\n\n if (!executionStateChannel || !executionStateKey) {\n [executionStateChannel, executionStateKey] = await getRaspExecutionStateChannelData();\n }\n\n if (!isMappingPrepared) {\n await prepareRaspExecutionStateMapping();\n isMappingPrepared = true;\n }\n\n if (!executionStateChannel) {\n onInvalidCallback();\n return;\n }\n\n eventsListener = await Talsec.addListener(executionStateChannel, async (event: any) => {\n if (!executionStateKey) {\n onInvalidCallback();\n return;\n }\n\n switch (event[executionStateKey]) {\n case RaspExecutionState.AllChecksFinished.value:\n config.allChecksFinished?.();\n break;\n default:\n onInvalidCallback();\n break;\n }\n });\n isInitializing = false;\n};\n\nexport const removeRaspExecutionStateListener = async (): Promise<void> => {\n if (!eventsListener || !executionStateChannel) {\n return;\n }\n await eventsListener.remove();\n eventsListener = null;\n await Talsec.removeListenerForEvent({ eventName: executionStateChannel });\n};\n"]}