Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion cxf/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ configure<LibraryExtension> {
)
}
}
flavorDimensions += listOf("mode")
productFlavors {
create("standard") {
isDefault = true
dimension = "mode"
}
create("fdroid") {
dimension = "mode"
}
}
compileOptions {
sourceCompatibility(libs.versions.jvmTarget.get())
targetCompatibility(libs.versions.jvmTarget.get())
Expand All @@ -46,6 +56,9 @@ kotlin {
}

dependencies {
fun standardImplementation(dependencyNotation: Any) {
add("standardImplementation", dependencyNotation)
}

implementation(project(":annotation"))
implementation(project(":core"))
Expand All @@ -57,13 +70,16 @@ dependencies {
implementation(libs.androidx.compose.runtime)
implementation(libs.androidx.credentials)
implementation(libs.androidx.credentials.providerevents)
implementation(libs.androidx.credentials.providerevents.play.services)
implementation(libs.google.hilt.android)
ksp(libs.google.hilt.compiler)
implementation(libs.kotlinx.coroutines.android)
implementation(libs.kotlinx.serialization)
implementation(libs.timber)

// Play Services backend for ProviderEventsManager is not FOSS, so it is excluded from the
// F-Droid flavor. The F-Droid flavor supplies no-op stubs instead.
standardImplementation(libs.androidx.credentials.providerevents.play.services)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ‘


testImplementation(platform(libs.junit.bom))
testRuntimeOnly(libs.junit.platform.launcher)
testImplementation(libs.junit.jupiter)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.bitwarden.cxf.importer

import android.content.Context
import androidx.credentials.providerevents.exception.ImportCredentialsUnknownErrorException
import com.bitwarden.annotation.OmitFromCoverage
import com.bitwarden.cxf.importer.model.ImportCredentialsSelectionResult

/**
* F-Droid implementation of [CredentialExchangeImporter]. Credential exchange relies on the
* Play Services backend, which is not available on F-Droid builds, so import is unsupported and
* always reports a failure if invoked.
*/
@OmitFromCoverage
@Suppress("UnusedParameter")
internal class CredentialExchangeImporterImpl(
activity: Context,
) : CredentialExchangeImporter {

override suspend fun importCredentials(
credentialTypes: List<String>,
): ImportCredentialsSelectionResult = ImportCredentialsSelectionResult.Failure(
error = ImportCredentialsUnknownErrorException(),
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.bitwarden.cxf.registry

import android.app.Application
import androidx.credentials.providerevents.transfer.ClearExportResponse
import androidx.credentials.providerevents.transfer.RegisterExportResponse
import com.bitwarden.annotation.OmitFromCoverage
import com.bitwarden.core.data.util.asFailure
import com.bitwarden.cxf.registry.model.RegistrationRequest

/**
* F-Droid implementation of [CredentialExchangeRegistry]. Registration relies on the Play Services
* backend, which is not available on F-Droid builds, so registration is a no-op that always fails.
*/
@OmitFromCoverage
@Suppress("UnusedParameter")
internal class CredentialExchangeRegistryImpl(
application: Application,
) : CredentialExchangeRegistry {

override suspend fun register(
registrationRequest: RegistrationRequest,
): Result<RegisterExportResponse> =
UnsupportedOperationException("Credential exchange is not supported on F-Droid builds.")
.asFailure()

override suspend fun unregister(): Result<ClearExportResponse> =
UnsupportedOperationException("Credential exchange is not supported on F-Droid builds.")
.asFailure()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.bitwarden.cxf.importer

import android.app.Activity
import com.bitwarden.cxf.importer.model.ImportCredentialsSelectionResult
import io.mockk.mockk
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test

class CredentialExchangeImporterTest {

private val importer = CredentialExchangeImporterImpl(
activity = mockk<Activity>(relaxed = true),
)

@Test
fun `importCredentials should return Failure`() = runTest {
val result = importer.importCredentials(listOf("basic-auth"))

assertTrue(result is ImportCredentialsSelectionResult.Failure)
}
}
2 changes: 1 addition & 1 deletion detekt-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ output-reports:

comments:
active: true
excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**', '**ServiceImpl.kt', '**/testFixtures/**' ]
excludes: [ '**/test/**', '**/testStandard/**', '**/testFdroid/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**', '**ServiceImpl.kt', '**/testFixtures/**' ]
AbsentOrWrongFileLicense:
active: false
licenseTemplateFile: 'license.template'
Expand Down
9 changes: 8 additions & 1 deletion fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,14 @@ platform :android do

desc "Run library module tests for specified modules"
lane :testLibraries do |options|
tasks = options[:target].split(" ").map { |mod| "#{mod}:testDebugUnitTest" }
# Modules with product flavors expose per-flavor test tasks instead of `testDebugUnitTest`.
# For those, run every flavor so both the standard and F-Droid sources are covered.
flavored_module_tasks = {
":cxf" => ["testStandardDebugUnitTest", "testFdroidDebugUnitTest"],
}
tasks = options[:target].split(" ").flat_map { |mod|
(flavored_module_tasks[mod] || ["testDebugUnitTest"]).map { |task| "#{mod}:#{task}" }
}
gradle(tasks: tasks)
end

Expand Down
Loading