From aaecd26aa4f2d7641a838508e3fdcdb8397bf743 Mon Sep 17 00:00:00 2001 From: Denis Dobanda Date: Wed, 4 Dec 2024 09:49:29 +0100 Subject: [PATCH] feat(pigeon): switch to pigeon - Android native uses pigeon - iOS native uses pigeon Signed-off-by: Denis Dobanda --- CONTRIBUTING.md | 3 + .../FlutterSecurityToolkitPlugin.kt | 63 -------- .../ThreatCenterApi.g.kt | 116 +++++++++++++++ .../security_toolkit/ThreatCenterApi.g.kt | 116 +++++++++++++++ .../security_toolkit/ThreatCenterApiImpl.kt | 33 +++++ example/ios/Podfile.lock | 4 +- example/ios/Runner.xcodeproj/project.pbxproj | 100 ++++++------- example/ios/RunnerTests/RunnerTests.swift | 13 +- .../FlutterSecurityToolkitPlugin.swift | 24 --- ios/Classes/ThreatCenterApi.g.swift | 140 ++++++++++++++++++ ios/Classes/ThreatCenterApiImpl.swift | 25 ++++ ios/flutter_security_toolkit.podspec | 4 +- ...utter_security_toolkit_method_channel.dart | 32 ---- ...r_security_toolkit_platform_interface.dart | 39 ----- lib/src/pigeon.dart | 16 ++ lib/src/threat_center_api.g.dart | 133 +++++++++++++++++ lib/src/threat_detection_center.dart | 10 +- pubspec.yaml | 9 +- ..._security_toolkit_method_channel_test.dart | 30 ---- 19 files changed, 649 insertions(+), 261 deletions(-) delete mode 100644 android/src/main/kotlin/com/example/flutter_security_toolkit/FlutterSecurityToolkitPlugin.kt create mode 100644 android/src/main/kotlin/com/exxeta/flutter_security_toolkit/ThreatCenterApi.g.kt create mode 100644 android/src/main/kotlin/com/exxeta/security_toolkit/ThreatCenterApi.g.kt create mode 100644 android/src/main/kotlin/com/exxeta/security_toolkit/ThreatCenterApiImpl.kt delete mode 100644 ios/Classes/FlutterSecurityToolkitPlugin.swift create mode 100644 ios/Classes/ThreatCenterApi.g.swift create mode 100644 ios/Classes/ThreatCenterApiImpl.swift delete mode 100644 lib/src/flutter_security_toolkit_method_channel.dart delete mode 100644 lib/src/flutter_security_toolkit_platform_interface.dart create mode 100644 lib/src/pigeon.dart create mode 100644 lib/src/threat_center_api.g.dart delete mode 100644 test/flutter_security_toolkit_method_channel_test.dart diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ca58da3..6536646 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -63,6 +63,9 @@ and ios. Please refer to readme to participate in native development Please use the latest Flutter Version. Use the provided example project to test or bug report any existing or new features. +Use Pigeon to update interfaces between flutter and native libraries: +`dart run pigeon --input lib/src/pigeon.dart` + ## Submitting changes Before submitting your changes as a pull request, please make sure to format diff --git a/android/src/main/kotlin/com/example/flutter_security_toolkit/FlutterSecurityToolkitPlugin.kt b/android/src/main/kotlin/com/example/flutter_security_toolkit/FlutterSecurityToolkitPlugin.kt deleted file mode 100644 index 8fcbe45..0000000 --- a/android/src/main/kotlin/com/example/flutter_security_toolkit/FlutterSecurityToolkitPlugin.kt +++ /dev/null @@ -1,63 +0,0 @@ -package com.example.flutter_security_toolkit - -import android.app.Activity -import android.content.Context -import androidx.annotation.NonNull -import io.flutter.embedding.engine.plugins.FlutterPlugin -import io.flutter.embedding.engine.plugins.activity.ActivityAware -import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding -import io.flutter.plugin.common.MethodCall -import io.flutter.plugin.common.MethodChannel -import io.flutter.plugin.common.MethodChannel.MethodCallHandler -import io.flutter.plugin.common.MethodChannel.Result -import com.exxeta.securitytoolkit.ThreatDetectionCenter - -/** FlutterSecurityToolkitPlugin */ -class FlutterSecurityToolkitPlugin: FlutterPlugin, MethodCallHandler, ActivityAware { - /// The MethodChannel that will the communication between Flutter and native Android - /// - /// This local reference serves to register the plugin with the Flutter Engine and unregister it - /// when the Flutter Engine is detached from the Activity - private lateinit var channel : MethodChannel - private lateinit var context: Context - private lateinit var activity: Activity - private lateinit var threatDetectionCenter: ThreatDetectionCenter - - override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { - channel = MethodChannel(flutterPluginBinding.binaryMessenger, "flutter_security_toolkit") - channel.setMethodCallHandler(this) - context = flutterPluginBinding.applicationContext - threatDetectionCenter = ThreatDetectionCenter(flutterPluginBinding.applicationContext) - } - - override fun onMethodCall(call: MethodCall, result: Result) { - if (call.method == "areRootPrivilegesDetected") { - result.success(threatDetectionCenter.areRootPrivilegesDetected) - } else if (call.method == "areHooksDetected") { - result.success(threatDetectionCenter.areHooksDetected) - } else if (call.method == "isSimulatorDetected") { - result.success(threatDetectionCenter.isSimulatorDetected) - } else { - result.notImplemented() - } - } - - override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { - channel.setMethodCallHandler(null) - } - - // MARK: - Activity & Context management - - override fun onDetachedFromActivity() { - } - - override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) { - } - - override fun onAttachedToActivity(binding: ActivityPluginBinding) { - activity = binding.activity; - } - - override fun onDetachedFromActivityForConfigChanges() { - } -} diff --git a/android/src/main/kotlin/com/exxeta/flutter_security_toolkit/ThreatCenterApi.g.kt b/android/src/main/kotlin/com/exxeta/flutter_security_toolkit/ThreatCenterApi.g.kt new file mode 100644 index 0000000..f9fdc1c --- /dev/null +++ b/android/src/main/kotlin/com/exxeta/flutter_security_toolkit/ThreatCenterApi.g.kt @@ -0,0 +1,116 @@ +// Autogenerated from Pigeon (v22.6.4), do not edit directly. +// See also: https://pub.dev/packages/pigeon +@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") + + +import android.util.Log +import io.flutter.plugin.common.BasicMessageChannel +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.MessageCodec +import io.flutter.plugin.common.StandardMessageCodec +import java.io.ByteArrayOutputStream +import java.nio.ByteBuffer + +private fun wrapResult(result: Any?): List { + return listOf(result) +} + +private fun wrapError(exception: Throwable): List { + return if (exception is FlutterError) { + listOf( + exception.code, + exception.message, + exception.details + ) + } else { + listOf( + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) + ) + } +} + +/** + * Error class for passing custom error details to Flutter via a thrown PlatformException. + * @property code The error code. + * @property message The error message. + * @property details The error details. Must be a datatype supported by the api codec. + */ +class FlutterError ( + val code: String, + override val message: String? = null, + val details: Any? = null +) : Throwable() +private open class ThreatCenterApiPigeonCodec : StandardMessageCodec() { + override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { + return super.readValueOfType(type, buffer) + } + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + super.writeValue(stream, value) + } +} + +/** Generated interface from Pigeon that represents a handler of messages from Flutter. */ +interface ThreatCenterApi { + fun areRootPrivilegesDetected(): Boolean + fun areHooksDetected(): Boolean + fun isSimulatorDetected(): Boolean + + companion object { + /** The codec used by ThreatCenterApi. */ + val codec: MessageCodec by lazy { + ThreatCenterApiPigeonCodec() + } + /** Sets up an instance of `ThreatCenterApi` to handle messages through the `binaryMessenger`. */ + @JvmOverloads + fun setUp(binaryMessenger: BinaryMessenger, api: ThreatCenterApi?, messageChannelSuffix: String = "") { + val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.flutter_security_toolkit.ThreatCenterApi.areRootPrivilegesDetected$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { _, reply -> + val wrapped: List = try { + listOf(api.areRootPrivilegesDetected()) + } catch (exception: Throwable) { + wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.flutter_security_toolkit.ThreatCenterApi.areHooksDetected$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { _, reply -> + val wrapped: List = try { + listOf(api.areHooksDetected()) + } catch (exception: Throwable) { + wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.flutter_security_toolkit.ThreatCenterApi.isSimulatorDetected$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { _, reply -> + val wrapped: List = try { + listOf(api.isSimulatorDetected()) + } catch (exception: Throwable) { + wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } + } +} diff --git a/android/src/main/kotlin/com/exxeta/security_toolkit/ThreatCenterApi.g.kt b/android/src/main/kotlin/com/exxeta/security_toolkit/ThreatCenterApi.g.kt new file mode 100644 index 0000000..f9fdc1c --- /dev/null +++ b/android/src/main/kotlin/com/exxeta/security_toolkit/ThreatCenterApi.g.kt @@ -0,0 +1,116 @@ +// Autogenerated from Pigeon (v22.6.4), do not edit directly. +// See also: https://pub.dev/packages/pigeon +@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") + + +import android.util.Log +import io.flutter.plugin.common.BasicMessageChannel +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.MessageCodec +import io.flutter.plugin.common.StandardMessageCodec +import java.io.ByteArrayOutputStream +import java.nio.ByteBuffer + +private fun wrapResult(result: Any?): List { + return listOf(result) +} + +private fun wrapError(exception: Throwable): List { + return if (exception is FlutterError) { + listOf( + exception.code, + exception.message, + exception.details + ) + } else { + listOf( + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) + ) + } +} + +/** + * Error class for passing custom error details to Flutter via a thrown PlatformException. + * @property code The error code. + * @property message The error message. + * @property details The error details. Must be a datatype supported by the api codec. + */ +class FlutterError ( + val code: String, + override val message: String? = null, + val details: Any? = null +) : Throwable() +private open class ThreatCenterApiPigeonCodec : StandardMessageCodec() { + override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { + return super.readValueOfType(type, buffer) + } + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + super.writeValue(stream, value) + } +} + +/** Generated interface from Pigeon that represents a handler of messages from Flutter. */ +interface ThreatCenterApi { + fun areRootPrivilegesDetected(): Boolean + fun areHooksDetected(): Boolean + fun isSimulatorDetected(): Boolean + + companion object { + /** The codec used by ThreatCenterApi. */ + val codec: MessageCodec by lazy { + ThreatCenterApiPigeonCodec() + } + /** Sets up an instance of `ThreatCenterApi` to handle messages through the `binaryMessenger`. */ + @JvmOverloads + fun setUp(binaryMessenger: BinaryMessenger, api: ThreatCenterApi?, messageChannelSuffix: String = "") { + val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.flutter_security_toolkit.ThreatCenterApi.areRootPrivilegesDetected$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { _, reply -> + val wrapped: List = try { + listOf(api.areRootPrivilegesDetected()) + } catch (exception: Throwable) { + wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.flutter_security_toolkit.ThreatCenterApi.areHooksDetected$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { _, reply -> + val wrapped: List = try { + listOf(api.areHooksDetected()) + } catch (exception: Throwable) { + wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.flutter_security_toolkit.ThreatCenterApi.isSimulatorDetected$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { _, reply -> + val wrapped: List = try { + listOf(api.isSimulatorDetected()) + } catch (exception: Throwable) { + wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } + } +} diff --git a/android/src/main/kotlin/com/exxeta/security_toolkit/ThreatCenterApiImpl.kt b/android/src/main/kotlin/com/exxeta/security_toolkit/ThreatCenterApiImpl.kt new file mode 100644 index 0000000..715a535 --- /dev/null +++ b/android/src/main/kotlin/com/exxeta/security_toolkit/ThreatCenterApiImpl.kt @@ -0,0 +1,33 @@ + +package com.exxeta.security_toolkit + +import ThreatCenterApi +import com.exxeta.securitytoolkit.ThreatDetectionCenter +import io.flutter.embedding.engine.plugins.FlutterPlugin + +class ThreatCenterApiImpl : FlutterPlugin, ThreatCenterApi { + private lateinit var threatDetectionCenter: ThreatDetectionCenter + + override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { + threatDetectionCenter = ThreatDetectionCenter(binding.applicationContext) + ThreatCenterApi.setUp(binding.binaryMessenger, this) + } + + override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { + ThreatCenterApi.setUp(binding.binaryMessenger, null) + } + + // MARK: - ThreatCenterApi + + override fun areRootPrivilegesDetected(): Boolean { + return threatDetectionCenter.areRootPrivilegesDetected + } + + override fun areHooksDetected(): Boolean { + return threatDetectionCenter.areHooksDetected + } + + override fun isSimulatorDetected(): Boolean { + return threatDetectionCenter.isSimulatorDetected + } +} \ No newline at end of file diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 40c5b00..0921110 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,6 +1,6 @@ PODS: - Flutter (1.0.0) - - flutter_security_toolkit (1.0.1): + - flutter_security_toolkit (1.0.2): - Flutter - SecurityToolkit (~> 1.0) - integration_test (0.0.1): @@ -26,7 +26,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - flutter_security_toolkit: 73412e795f89286c565f7f91b76b2c4c610c953a + flutter_security_toolkit: 82972aec2bbed79dc6b22fac76aed57419e24c73 integration_test: ce0a3ffa1de96d1a89ca0ac26fca7ea18a749ef4 SecurityToolkit: 51927d4723e634bddb83a4d16e86940b344fa6a4 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 7cef621..370a567 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -10,9 +10,9 @@ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 3C0BA328391B1B34111E4BAC /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C87A4D31786ACE3542EB50DD /* Pods_Runner.framework */; }; + 553D4454345AA2A8187E7BA9 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 289ABDBD25458D1D567B1A20 /* Pods_RunnerTests.framework */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; - 80D24D3515E7726B63655F06 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1220DF8B1539FCD3D99D1A59 /* Pods_RunnerTests.framework */; }; - 845EF56157C48BC6559F3B82 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D3C8BBCF15B960431EA28B21 /* Pods_Runner.framework */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; @@ -42,29 +42,29 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 1220DF8B1539FCD3D99D1A59 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 101446E9968A930DAD11988E /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 289ABDBD25458D1D567B1A20 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3ADF8BFB18C772757FC59B21 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 66C030F384E65AE7EB6BB9FA /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 976639FAF4AFEF6FE8A166F2 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - BCC9E959282720E422C8B6F4 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - CBE9005B2CFB40FCDC0CE766 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - CC4C196C0A4950D1DBB99067 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; - D3C8BBCF15B960431EA28B21 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - E0F795F4758F1FEF75A63386 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + B63D89C8DDAE5A8E66CF0ED5 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + C87A4D31786ACE3542EB50DD /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F1B42CC07112D929FD48CD6B /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + F6FEA2297429373E05ED1C3C /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + F89842BFB2036DB1A45348B3 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -72,7 +72,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 845EF56157C48BC6559F3B82 /* Pods_Runner.framework in Frameworks */, + 3C0BA328391B1B34111E4BAC /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -80,7 +80,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 80D24D3515E7726B63655F06 /* Pods_RunnerTests.framework in Frameworks */, + 553D4454345AA2A8187E7BA9 /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -95,26 +95,26 @@ path = RunnerTests; sourceTree = ""; }; - 54AD53412B92F3CE364AB06E /* Frameworks */ = { + 5AD6654A49831B8A86A9F02C /* Pods */ = { isa = PBXGroup; children = ( - D3C8BBCF15B960431EA28B21 /* Pods_Runner.framework */, - 1220DF8B1539FCD3D99D1A59 /* Pods_RunnerTests.framework */, + F6FEA2297429373E05ED1C3C /* Pods-Runner.debug.xcconfig */, + B63D89C8DDAE5A8E66CF0ED5 /* Pods-Runner.release.xcconfig */, + 101446E9968A930DAD11988E /* Pods-Runner.profile.xcconfig */, + F1B42CC07112D929FD48CD6B /* Pods-RunnerTests.debug.xcconfig */, + 3ADF8BFB18C772757FC59B21 /* Pods-RunnerTests.release.xcconfig */, + F89842BFB2036DB1A45348B3 /* Pods-RunnerTests.profile.xcconfig */, ); - name = Frameworks; + path = Pods; sourceTree = ""; }; - 5AD6654A49831B8A86A9F02C /* Pods */ = { + 7A5AFDA92F0980C8872CC933 /* Frameworks */ = { isa = PBXGroup; children = ( - 66C030F384E65AE7EB6BB9FA /* Pods-Runner.debug.xcconfig */, - BCC9E959282720E422C8B6F4 /* Pods-Runner.release.xcconfig */, - 976639FAF4AFEF6FE8A166F2 /* Pods-Runner.profile.xcconfig */, - CBE9005B2CFB40FCDC0CE766 /* Pods-RunnerTests.debug.xcconfig */, - E0F795F4758F1FEF75A63386 /* Pods-RunnerTests.release.xcconfig */, - CC4C196C0A4950D1DBB99067 /* Pods-RunnerTests.profile.xcconfig */, + C87A4D31786ACE3542EB50DD /* Pods_Runner.framework */, + 289ABDBD25458D1D567B1A20 /* Pods_RunnerTests.framework */, ); - path = Pods; + name = Frameworks; sourceTree = ""; }; 9740EEB11CF90186004384FC /* Flutter */ = { @@ -136,7 +136,7 @@ 97C146EF1CF9000F007C117D /* Products */, 331C8082294A63A400263BE5 /* RunnerTests */, 5AD6654A49831B8A86A9F02C /* Pods */, - 54AD53412B92F3CE364AB06E /* Frameworks */, + 7A5AFDA92F0980C8872CC933 /* Frameworks */, ); sourceTree = ""; }; @@ -171,7 +171,7 @@ isa = PBXNativeTarget; buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( - EA460437C7A7D5CCFECF9ED1 /* [CP] Check Pods Manifest.lock */, + 40CF856B5D672B7B35A50490 /* [CP] Check Pods Manifest.lock */, 331C807D294A63A400263BE5 /* Sources */, 331C807F294A63A400263BE5 /* Resources */, F44BFDC660BD6F3D8C3E1883 /* Frameworks */, @@ -190,14 +190,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - 7C802916A7E84B78FFEFF688 /* [CP] Check Pods Manifest.lock */, + A0C9E5AFB3CE7886D88B1DEC /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - D7D899DE6C5FC4179B369E2B /* [CP] Embed Pods Frameworks */, + 70505776A5C0608BE71652BA /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -237,8 +237,6 @@ Base, ); mainGroup = 97C146E51CF9000F007C117D; - packageReferences = ( - ); productRefGroup = 97C146EF1CF9000F007C117D /* Products */; projectDirPath = ""; projectRoot = ""; @@ -287,7 +285,7 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; - 7C802916A7E84B78FFEFF688 /* [CP] Check Pods Manifest.lock */ = { + 40CF856B5D672B7B35A50490 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -302,46 +300,46 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 9740EEB61CF901F6004384FC /* Run Script */ = { + 70505776A5C0608BE71652BA /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); - inputPaths = ( + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - name = "Run Script"; - outputPaths = ( + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; }; - D7D899DE6C5FC4179B369E2B /* [CP] Embed Pods Frameworks */ = { + 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + inputPaths = ( ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + name = "Run Script"; + outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; - EA460437C7A7D5CCFECF9ED1 /* [CP] Check Pods Manifest.lock */ = { + A0C9E5AFB3CE7886D88B1DEC /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -356,7 +354,7 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -489,7 +487,7 @@ }; 331C8088294A63A400263BE5 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = CBE9005B2CFB40FCDC0CE766 /* Pods-RunnerTests.debug.xcconfig */; + baseConfigurationReference = F1B42CC07112D929FD48CD6B /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -507,7 +505,7 @@ }; 331C8089294A63A400263BE5 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = E0F795F4758F1FEF75A63386 /* Pods-RunnerTests.release.xcconfig */; + baseConfigurationReference = 3ADF8BFB18C772757FC59B21 /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -523,7 +521,7 @@ }; 331C808A294A63A400263BE5 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = CC4C196C0A4950D1DBB99067 /* Pods-RunnerTests.profile.xcconfig */; + baseConfigurationReference = F89842BFB2036DB1A45348B3 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; diff --git a/example/ios/RunnerTests/RunnerTests.swift b/example/ios/RunnerTests/RunnerTests.swift index ee0ff8a..2dd4ebb 100644 --- a/example/ios/RunnerTests/RunnerTests.swift +++ b/example/ios/RunnerTests/RunnerTests.swift @@ -11,16 +11,9 @@ import XCTest class RunnerTests: XCTestCase { func testGetPlatformVersion() { - let plugin = FlutterSecurityToolkitPlugin() - - let call = FlutterMethodCall(methodName: "getPlatformVersion", arguments: []) - - let resultExpectation = expectation(description: "result block must be called.") - plugin.handle(call) { result in - XCTAssertEqual(result as! String, "iOS " + UIDevice.current.systemVersion) - resultExpectation.fulfill() - } - waitForExpectations(timeout: 1) + let plugin = ThreatCenterApiImpl() + let isRoot = plugin.areRootPrivilegesDetected + XCTAssertEqual(isRoot, false) } } diff --git a/ios/Classes/FlutterSecurityToolkitPlugin.swift b/ios/Classes/FlutterSecurityToolkitPlugin.swift deleted file mode 100644 index 4985d8f..0000000 --- a/ios/Classes/FlutterSecurityToolkitPlugin.swift +++ /dev/null @@ -1,24 +0,0 @@ -import Flutter -import SecurityToolkit - -public class FlutterSecurityToolkitPlugin: NSObject, FlutterPlugin { - public static func register(with registrar: FlutterPluginRegistrar) { - let channel = FlutterMethodChannel(name: "flutter_security_toolkit", binaryMessenger: registrar.messenger()) - let instance = FlutterSecurityToolkitPlugin() - registrar.addMethodCallDelegate(instance, channel: channel) - } - - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - switch call.method - { - case "areRootPrivilegesDetected": - result(ThreatDetectionCenter.areRootPrivilegesDetected) - case "areHooksDetected": - result(ThreatDetectionCenter.areHooksDetected) - case "isSimulatorDetected": - result(ThreatDetectionCenter.isSimulatorDetected) - default: - result(FlutterMethodNotImplemented) - } - } -} diff --git a/ios/Classes/ThreatCenterApi.g.swift b/ios/Classes/ThreatCenterApi.g.swift new file mode 100644 index 0000000..02b1227 --- /dev/null +++ b/ios/Classes/ThreatCenterApi.g.swift @@ -0,0 +1,140 @@ +// Autogenerated from Pigeon (v22.6.4), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +import Foundation + +#if os(iOS) + import Flutter +#elseif os(macOS) + import FlutterMacOS +#else + #error("Unsupported platform.") +#endif + +/// Error class for passing custom error details to Dart side. +final class PigeonError: Error { + let code: String + let message: String? + let details: Any? + + init(code: String, message: String?, details: Any?) { + self.code = code + self.message = message + self.details = details + } + + var localizedDescription: String { + return + "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" + } +} + +private func wrapResult(_ result: Any?) -> [Any?] { + return [result] +} + +private func wrapError(_ error: Any) -> [Any?] { + if let pigeonError = error as? PigeonError { + return [ + pigeonError.code, + pigeonError.message, + pigeonError.details, + ] + } + if let flutterError = error as? FlutterError { + return [ + flutterError.code, + flutterError.message, + flutterError.details, + ] + } + return [ + "\(error)", + "\(type(of: error))", + "Stacktrace: \(Thread.callStackSymbols)", + ] +} + +private func isNullish(_ value: Any?) -> Bool { + return value is NSNull || value == nil +} + +private func nilOrValue(_ value: Any?) -> T? { + if value is NSNull { return nil } + return value as! T? +} + +private class ThreatCenterApiPigeonCodecReader: FlutterStandardReader { +} + +private class ThreatCenterApiPigeonCodecWriter: FlutterStandardWriter { +} + +private class ThreatCenterApiPigeonCodecReaderWriter: FlutterStandardReaderWriter { + override func reader(with data: Data) -> FlutterStandardReader { + return ThreatCenterApiPigeonCodecReader(data: data) + } + + override func writer(with data: NSMutableData) -> FlutterStandardWriter { + return ThreatCenterApiPigeonCodecWriter(data: data) + } +} + +class ThreatCenterApiPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { + static let shared = ThreatCenterApiPigeonCodec(readerWriter: ThreatCenterApiPigeonCodecReaderWriter()) +} + +/// Generated protocol from Pigeon that represents a handler of messages from Flutter. +protocol ThreatCenterApi { + func areRootPrivilegesDetected() throws -> Bool + func areHooksDetected() throws -> Bool + func isSimulatorDetected() throws -> Bool +} + +/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. +class ThreatCenterApiSetup { + static var codec: FlutterStandardMessageCodec { ThreatCenterApiPigeonCodec.shared } + /// Sets up an instance of `ThreatCenterApi` to handle messages through the `binaryMessenger`. + static func setUp(binaryMessenger: FlutterBinaryMessenger, api: ThreatCenterApi?, messageChannelSuffix: String = "") { + let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" + let areRootPrivilegesDetectedChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.flutter_security_toolkit.ThreatCenterApi.areRootPrivilegesDetected\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + areRootPrivilegesDetectedChannel.setMessageHandler { _, reply in + do { + let result = try api.areRootPrivilegesDetected() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + areRootPrivilegesDetectedChannel.setMessageHandler(nil) + } + let areHooksDetectedChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.flutter_security_toolkit.ThreatCenterApi.areHooksDetected\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + areHooksDetectedChannel.setMessageHandler { _, reply in + do { + let result = try api.areHooksDetected() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + areHooksDetectedChannel.setMessageHandler(nil) + } + let isSimulatorDetectedChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.flutter_security_toolkit.ThreatCenterApi.isSimulatorDetected\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + isSimulatorDetectedChannel.setMessageHandler { _, reply in + do { + let result = try api.isSimulatorDetected() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isSimulatorDetectedChannel.setMessageHandler(nil) + } + } +} diff --git a/ios/Classes/ThreatCenterApiImpl.swift b/ios/Classes/ThreatCenterApiImpl.swift new file mode 100644 index 0000000..16c10a9 --- /dev/null +++ b/ios/Classes/ThreatCenterApiImpl.swift @@ -0,0 +1,25 @@ +import Flutter +import SecurityToolkit + +public class ThreatCenterApiImpl: NSObject, FlutterPlugin, ThreatCenterApi { + + public static func register(with registrar: FlutterPluginRegistrar) { + let messenger : FlutterBinaryMessenger = registrar.messenger() + let api : ThreatCenterApi & NSObjectProtocol = ThreatCenterApiImpl.init() + ThreatCenterApiSetup.setUp(binaryMessenger: messenger, api: api) + } + + // MARK: - Threat Center Api + + func areRootPrivilegesDetected() throws -> Bool { + ThreatDetectionCenter.areRootPrivilegesDetected + } + + func areHooksDetected() throws -> Bool { + ThreatDetectionCenter.areHooksDetected + } + + func isSimulatorDetected() throws -> Bool { + ThreatDetectionCenter.isSimulatorDetected + } +} diff --git a/ios/flutter_security_toolkit.podspec b/ios/flutter_security_toolkit.podspec index f5e6692..7c1566e 100644 --- a/ios/flutter_security_toolkit.podspec +++ b/ios/flutter_security_toolkit.podspec @@ -4,8 +4,8 @@ # Pod::Spec.new do |s| s.name = 'flutter_security_toolkit' - s.version = '1.0.1' - s.summary = 'Internal flutter_security_toolkit' + s.version = '1.0.2' + s.summary = 'Internal security_toolkit' s.description = <<-DESC Internal flutter_security_toolkit DESC diff --git a/lib/src/flutter_security_toolkit_method_channel.dart b/lib/src/flutter_security_toolkit_method_channel.dart deleted file mode 100644 index ba97615..0000000 --- a/lib/src/flutter_security_toolkit_method_channel.dart +++ /dev/null @@ -1,32 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; - -import 'flutter_security_toolkit_platform_interface.dart'; - -/// An implementation of [FlutterSecurityToolkitPlatform] that uses method channels. -class MethodChannelFlutterSecurityToolkit - extends FlutterSecurityToolkitPlatform { - /// The method channel used to interact with the native platform. - @visibleForTesting - final methodChannel = const MethodChannel('flutter_security_toolkit'); - - @override - Future areRootPrivilegesDetected() async { - final version = - await methodChannel.invokeMethod('areRootPrivilegesDetected'); - return version; - } - - @override - Future areHooksDetected() async { - final version = await methodChannel.invokeMethod('areHooksDetected'); - return version; - } - - @override - Future isSimulatorDetected() async { - final version = - await methodChannel.invokeMethod('isSimulatorDetected'); - return version; - } -} diff --git a/lib/src/flutter_security_toolkit_platform_interface.dart b/lib/src/flutter_security_toolkit_platform_interface.dart deleted file mode 100644 index 39cfa58..0000000 --- a/lib/src/flutter_security_toolkit_platform_interface.dart +++ /dev/null @@ -1,39 +0,0 @@ -import 'package:plugin_platform_interface/plugin_platform_interface.dart'; - -import 'flutter_security_toolkit_method_channel.dart'; - -abstract class FlutterSecurityToolkitPlatform extends PlatformInterface { - /// Constructs a FlutterSecurityToolkitPlatform. - FlutterSecurityToolkitPlatform() : super(token: _token); - - static final Object _token = Object(); - - static FlutterSecurityToolkitPlatform _instance = - MethodChannelFlutterSecurityToolkit(); - - /// The default instance of [FlutterSecurityToolkitPlatform] to use. - /// - /// Defaults to [MethodChannelFlutterSecurityToolkit]. - static FlutterSecurityToolkitPlatform get instance => _instance; - - /// Platform-specific implementations should set this with their own - /// platform-specific class that extends [FlutterSecurityToolkitPlatform] when - /// they register themselves. - static set instance(FlutterSecurityToolkitPlatform instance) { - PlatformInterface.verifyToken(instance, _token); - _instance = instance; - } - - Future areRootPrivilegesDetected() { - throw UnimplementedError('isJailbroken() has not been implemented.'); - } - - Future areHooksDetected() { - throw UnimplementedError('areHooksLoaded() has not been implemented.'); - } - - Future isSimulatorDetected() { - throw UnimplementedError( - 'isRunningInSimulator() has not been implemented.'); - } -} diff --git a/lib/src/pigeon.dart b/lib/src/pigeon.dart new file mode 100644 index 0000000..82c3c30 --- /dev/null +++ b/lib/src/pigeon.dart @@ -0,0 +1,16 @@ +@ConfigurePigeon(PigeonOptions( + dartOut: 'lib/src/threat_center_api.g.dart', + dartOptions: DartOptions(), + kotlinOut: + 'android/src/main/kotlin/com/exxeta/flutter_security_toolkit/ThreatCenterApi.g.kt', + kotlinOptions: KotlinOptions(), + swiftOut: 'ios/Classes/ThreatCenterApi.g.swift', + swiftOptions: SwiftOptions(), + dartPackageName: 'flutter_security_toolkit', +)) +@HostApi() +abstract class ThreatCenterApi { + bool areRootPrivilegesDetected(); + bool areHooksDetected(); + bool isSimulatorDetected(); +} diff --git a/lib/src/threat_center_api.g.dart b/lib/src/threat_center_api.g.dart new file mode 100644 index 0000000..4c3795e --- /dev/null +++ b/lib/src/threat_center_api.g.dart @@ -0,0 +1,133 @@ +// Autogenerated from Pigeon (v22.6.4), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers + +import 'dart:async'; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; + +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; +import 'package:flutter/services.dart'; + +PlatformException _createConnectionError(String channelName) { + return PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); +} + + +class _PigeonCodec extends StandardMessageCodec { + const _PigeonCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is int) { + buffer.putUint8(4); + buffer.putInt64(value); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + default: + return super.readValueOfType(type, buffer); + } + } +} + +class ThreatCenterApi { + /// Constructor for [ThreatCenterApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + ThreatCenterApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + final BinaryMessenger? pigeonVar_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); + + final String pigeonVar_messageChannelSuffix; + + Future areRootPrivilegesDetected() async { + final String pigeonVar_channelName = 'dev.flutter.pigeon.flutter_security_toolkit.ThreatCenterApi.areRootPrivilegesDetected$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final List? pigeonVar_replyList = + await pigeonVar_channel.send(null) as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } + + Future areHooksDetected() async { + final String pigeonVar_channelName = 'dev.flutter.pigeon.flutter_security_toolkit.ThreatCenterApi.areHooksDetected$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final List? pigeonVar_replyList = + await pigeonVar_channel.send(null) as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } + + Future isSimulatorDetected() async { + final String pigeonVar_channelName = 'dev.flutter.pigeon.flutter_security_toolkit.ThreatCenterApi.isSimulatorDetected$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final List? pigeonVar_replyList = + await pigeonVar_channel.send(null) as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } +} diff --git a/lib/src/threat_detection_center.dart b/lib/src/threat_detection_center.dart index 77cf82f..c841df7 100644 --- a/lib/src/threat_detection_center.dart +++ b/lib/src/threat_detection_center.dart @@ -1,13 +1,15 @@ -import 'flutter_security_toolkit_platform_interface.dart'; +import 'package:flutter_security_toolkit/src/threat_center_api.g.dart'; /// Use this class to access the methods of detecting security threats /// Note: most methods are async class ThreatDetectionCenter { + static final _api = ThreatCenterApi(); + /// Will check for Jailbreak on iOS and for Root on Android. /// /// Returns true, if privileged access detected. static Future areRootPrivilegesDetected() { - return FlutterSecurityToolkitPlatform.instance.areRootPrivilegesDetected(); + return _api.areRootPrivilegesDetected(); } /// Will check for runtime integrity by detecting hooks / dynamic injection @@ -15,12 +17,12 @@ class ThreatDetectionCenter { /// /// Returns true, if any hooks are detected static Future areHooksDetected() { - return FlutterSecurityToolkitPlatform.instance.areHooksDetected(); + return _api.areHooksDetected(); } /// Will check for an environment and return true, if running in simulated / /// emulated environment static Future isSimulatorDetected() { - return FlutterSecurityToolkitPlatform.instance.isSimulatorDetected(); + return _api.isSimulatorDetected(); } } diff --git a/pubspec.yaml b/pubspec.yaml index 3a4e3f2..b704d91 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_security_toolkit description: "A Mobile Security Toolkit providing easy API to check device status (Root, Hooks, Simulator, etc)" -version: 1.0.1 +version: 1.0.2 homepage: https://github.com/EXXETA/Flutter-Security-Toolkit environment: @@ -16,12 +16,13 @@ dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^4.0.0 + pigeon: ^22.6.4 flutter: plugin: platforms: android: - package: com.example.flutter_security_toolkit - pluginClass: FlutterSecurityToolkitPlugin + package: com.exxeta.security_toolkit + pluginClass: ThreatCenterApiImpl ios: - pluginClass: FlutterSecurityToolkitPlugin + pluginClass: ThreatCenterApiImpl diff --git a/test/flutter_security_toolkit_method_channel_test.dart b/test/flutter_security_toolkit_method_channel_test.dart deleted file mode 100644 index 1575049..0000000 --- a/test/flutter_security_toolkit_method_channel_test.dart +++ /dev/null @@ -1,30 +0,0 @@ -import 'package:flutter/services.dart'; -import 'package:flutter_security_toolkit/src/flutter_security_toolkit_method_channel.dart'; -import 'package:flutter_test/flutter_test.dart'; - -void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - - MethodChannelFlutterSecurityToolkit platform = - MethodChannelFlutterSecurityToolkit(); - const MethodChannel channel = MethodChannel('flutter_security_toolkit'); - - setUp(() { - TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler( - channel, - (MethodCall methodCall) async { - return '42'; - }, - ); - }); - - tearDown(() { - TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler(channel, null); - }); - - test('getPlatformVersion', () async { - expect(await platform.areRootPrivilegesDetected(), false); - }); -}