From 19facaf8fd63b7b8eae3a3228e7ddbf74b6b3e13 Mon Sep 17 00:00:00 2001 From: Andrew Haisting <142518658+ahaisting-livefront@users.noreply.github.com> Date: Mon, 9 Sep 2024 15:36:34 -0500 Subject: [PATCH] BITAU-164 add no-op version of BridgeService (#3884) --- app/build.gradle.kts | 3 + .../manager/di/PlatformManagerModule.kt | 10 +++ .../processor/BridgeServiceProcessor.kt | 14 ++++ .../processor/BridgeServiceProcessorImpl.kt | 73 +++++++++++++++++++ .../data/platform/service/BridgeService.kt | 27 +++++++ .../processor/BridgeServiceProcessorTest.kt | 30 ++++++++ 6 files changed, 157 insertions(+) create mode 100644 app/src/main/java/com/x8bit/bitwarden/data/platform/processor/BridgeServiceProcessor.kt create mode 100644 app/src/main/java/com/x8bit/bitwarden/data/platform/processor/BridgeServiceProcessorImpl.kt create mode 100644 app/src/main/java/com/x8bit/bitwarden/data/platform/service/BridgeService.kt create mode 100644 app/src/test/java/com/x8bit/bitwarden/data/platform/processor/BridgeServiceProcessorTest.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 30c814da41..774c9469ee 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -135,6 +135,9 @@ dependencies { add("standardImplementation", dependencyNotation) } + // TODO: this should use a versioned aar instead of referencing the project BITAU-94 + implementation(project(":bridge")) + implementation(libs.androidx.activity.compose) implementation(libs.androidx.appcompat) implementation(libs.androidx.autofill) diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/di/PlatformManagerModule.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/di/PlatformManagerModule.kt index 5e5a3e1335..1f56c22b15 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/di/PlatformManagerModule.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/di/PlatformManagerModule.kt @@ -20,6 +20,8 @@ import com.x8bit.bitwarden.data.platform.manager.AssetManager import com.x8bit.bitwarden.data.platform.manager.AssetManagerImpl import com.x8bit.bitwarden.data.platform.manager.BiometricsEncryptionManager import com.x8bit.bitwarden.data.platform.manager.BiometricsEncryptionManagerImpl +import com.x8bit.bitwarden.data.platform.processor.BridgeServiceProcessor +import com.x8bit.bitwarden.data.platform.processor.BridgeServiceProcessorImpl import com.x8bit.bitwarden.data.platform.manager.CrashLogsManager import com.x8bit.bitwarden.data.platform.manager.CrashLogsManagerImpl import com.x8bit.bitwarden.data.platform.manager.DebugMenuFeatureFlagManagerImpl @@ -75,6 +77,14 @@ object PlatformManagerModule { fun provideAppForegroundManager(): AppForegroundManager = AppForegroundManagerImpl() + @Provides + @Singleton + fun provideBridgeServiceProcessor( + featureFlagManager: FeatureFlagManager, + ): BridgeServiceProcessor = BridgeServiceProcessorImpl( + featureFlagManager = featureFlagManager, + ) + @Provides @Singleton fun provideOrganizationEventManager( diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/processor/BridgeServiceProcessor.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/processor/BridgeServiceProcessor.kt new file mode 100644 index 0000000000..50c54c0687 --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/processor/BridgeServiceProcessor.kt @@ -0,0 +1,14 @@ +package com.x8bit.bitwarden.data.platform.processor + +import com.bitwarden.bridge.IBridgeService + +/** + * Provides access to [IBridgeService] APIs in an injectable and testable manner. + */ +interface BridgeServiceProcessor { + + /** + * Binder that implements [IBridgeService]. Null can be returned to represent a no-op binder. + */ + val binder: IBridgeService.Stub? +} diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/processor/BridgeServiceProcessorImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/processor/BridgeServiceProcessorImpl.kt new file mode 100644 index 0000000000..cb2641f33d --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/processor/BridgeServiceProcessorImpl.kt @@ -0,0 +1,73 @@ +package com.x8bit.bitwarden.data.platform.processor + +import android.content.Intent +import com.bitwarden.bridge.IBridgeService +import com.bitwarden.bridge.IBridgeServiceCallback +import com.bitwarden.bridge.model.EncryptedAddTotpLoginItemData +import com.bitwarden.bridge.model.SymmetricEncryptionKeyData +import com.bitwarden.bridge.model.SymmetricEncryptionKeyFingerprintData +import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager +import com.x8bit.bitwarden.data.platform.manager.model.FlagKey + +/** + * Default implementation of [BridgeServiceProcessor]. + */ +class BridgeServiceProcessorImpl( + private val featureFlagManager: FeatureFlagManager, +) : BridgeServiceProcessor { + + override val binder: IBridgeService.Stub? + // TODO: Check for Android API level as well: BITAU-102 + get() { + return if (featureFlagManager.getFeatureFlag(FlagKey.AuthenticatorSync)) { + defaultBinder + } else { + // If the feature flag is not enabled, return a null binder which will no-op all + // service calls. + null + } + } + + /** + * Default implementation of the bridge service binder. + */ + private val defaultBinder = object : IBridgeService.Stub() { + override fun getVersionNumber(): String { + // TODO: BITAU-104 + return "" + } + + override fun checkSymmetricEncryptionKeyFingerprint( + data: SymmetricEncryptionKeyFingerprintData?, + ): Boolean { + // TODO: BITAU-104 + return false + } + + override fun getSymmetricEncryptionKeyData(): SymmetricEncryptionKeyData? { + // TODO: BITAU-104 + return null + } + + override fun registerBridgeServiceCallback(callback: IBridgeServiceCallback?) { + // TODO: BITAU-104 + } + + override fun unregisterBridgeServiceCallback(callback: IBridgeServiceCallback?) { + // TODO: BITAU-104 + } + + override fun syncAccounts() { + // TODO: BITAU-104 + } + + override fun createAddTotpLoginItemIntent(): Intent { + // TODO: BITAU-104 + return Intent() + } + + override fun setPendingAddTotpLoginItemData(data: EncryptedAddTotpLoginItemData?) { + // TODO: BITAU-104 + } + } +} diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/service/BridgeService.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/service/BridgeService.kt new file mode 100644 index 0000000000..cac41216a0 --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/service/BridgeService.kt @@ -0,0 +1,27 @@ +package com.x8bit.bitwarden.data.platform.service + +import android.app.Service +import android.content.Intent +import com.x8bit.bitwarden.data.platform.processor.BridgeServiceProcessor +import com.bitwarden.bridge.IBridgeService +import dagger.hilt.android.AndroidEntryPoint +import javax.inject.Inject + +/** + * Service exposed via a custom permission + */ +@AndroidEntryPoint +class BridgeService : Service() { + + @Inject + lateinit var bridgeServiceProcessor: BridgeServiceProcessor + + /** + * When binding this service, logic to the [BridgeServiceProcessor], which implements + * [IBridgeService]. + * + * Note that [BridgeServiceProcessor.binder] can return a null binder, which the OS will accept + * but never connect to, effectively making a null binder a noop binder. + */ + override fun onBind(intent: Intent) = bridgeServiceProcessor.binder +} diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/processor/BridgeServiceProcessorTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/platform/processor/BridgeServiceProcessorTest.kt new file mode 100644 index 0000000000..07e22cca95 --- /dev/null +++ b/app/src/test/java/com/x8bit/bitwarden/data/platform/processor/BridgeServiceProcessorTest.kt @@ -0,0 +1,30 @@ +package com.x8bit.bitwarden.data.platform.processor + +import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager +import com.x8bit.bitwarden.data.platform.manager.model.FlagKey +import io.mockk.every +import io.mockk.mockk +import org.junit.jupiter.api.Assertions.assertNotNull +import org.junit.jupiter.api.Assertions.assertNull +import org.junit.jupiter.api.Test + +class BridgeServiceProcessorTest { + + private val featureFlagManager: FeatureFlagManager = mockk() + + private val bridgeServiceManager = BridgeServiceProcessorImpl( + featureFlagManager = featureFlagManager, + ) + + @Test + fun `when AuthenticatorSync feature flag is off, should return null binder`() { + every { featureFlagManager.getFeatureFlag(FlagKey.AuthenticatorSync) } returns false + assertNull(bridgeServiceManager.binder) + } + + @Test + fun `when AuthenticatorSync feature flag is on, should return non-null binder`() { + every { featureFlagManager.getFeatureFlag(FlagKey.AuthenticatorSync) } returns true + assertNotNull(bridgeServiceManager.binder) + } +}