[PM-24411] Add shareErrorReport to IntentManager (#5655)

This commit is contained in:
Patrick Honkonen
2025-08-06 16:25:40 -04:00
committed by GitHub
parent b6aa0952b1
commit 59c2261e7c
4 changed files with 42 additions and 13 deletions

View File

@@ -11,12 +11,14 @@ import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.ProvidableCompositionLocal
import androidx.compose.runtime.compositionLocalOf
import com.bitwarden.annotation.OmitFromCoverage
import com.bitwarden.core.data.manager.BuildInfoManager
import com.bitwarden.core.util.isBuildVersionAtLeast
import com.x8bit.bitwarden.data.platform.manager.util.AppResumeStateManager
import com.x8bit.bitwarden.data.platform.manager.util.AppResumeStateManagerImpl
import com.x8bit.bitwarden.ui.credentials.manager.CredentialProviderCompletionManager
import com.x8bit.bitwarden.ui.credentials.manager.CredentialProviderCompletionManagerImpl
import com.x8bit.bitwarden.ui.credentials.manager.CredentialProviderCompletionManagerUnsupportedApiImpl
import com.x8bit.bitwarden.ui.platform.manager.BitwardenBuildInfoManagerImpl
import com.x8bit.bitwarden.ui.platform.manager.biometrics.BiometricsManager
import com.x8bit.bitwarden.ui.platform.manager.biometrics.BiometricsManagerImpl
import com.x8bit.bitwarden.ui.platform.manager.exit.ExitManager
@@ -46,7 +48,12 @@ fun LocalManagerProvider(
biometricsManager: BiometricsManager = BiometricsManagerImpl(activity = activity),
clock: Clock = Clock.systemDefaultZone(),
exitManager: ExitManager = ExitManagerImpl(activity = activity),
intentManager: IntentManager = IntentManagerImpl(context = activity, clock = clock),
buildInfoManager: BuildInfoManager = BitwardenBuildInfoManagerImpl(),
intentManager: IntentManager = IntentManagerImpl(
context = activity,
clock = clock,
buildInfoManager = buildInfoManager,
),
credentialProviderCompletionManager: CredentialProviderCompletionManager =
createCredentialProviderCompletionManager(activity = activity),
keyChainManager: KeyChainManager = KeyChainManagerImpl(activity = activity),

View File

@@ -34,10 +34,12 @@ object PlatformUiManagerModule {
fun provideIntentManager(
@ApplicationContext context: Context,
clock: Clock,
buildInfoManager: BuildInfoManager,
): IntentManager =
IntentManagerImpl(
context = context,
clock = clock,
buildInfoManager = buildInfoManager,
)
@Provides

View File

@@ -78,6 +78,11 @@ interface IntentManager {
*/
fun shareText(text: String)
/**
* Launches the share sheet with an error report based on the provided [throwable].
*/
fun shareErrorReport(throwable: Throwable)
/**
* Processes the [activityResult] and attempts to get the relevant file data from it.
*/

View File

@@ -23,22 +23,17 @@ import androidx.core.content.FileProvider
import androidx.core.net.toUri
import androidx.credentials.CredentialManager
import com.bitwarden.annotation.OmitFromCoverage
import com.bitwarden.core.data.manager.BuildInfoManager
import com.bitwarden.core.data.util.toFormattedPattern
import com.bitwarden.core.util.isBuildVersionAtLeast
import com.bitwarden.ui.platform.manager.util.deviceData
import com.bitwarden.ui.platform.manager.util.fileProviderAuthority
import com.bitwarden.ui.platform.model.FileData
import com.bitwarden.ui.platform.resource.BitwardenString
import com.x8bit.bitwarden.BuildConfig
import com.x8bit.bitwarden.data.autofill.model.browser.BrowserPackage
import java.io.File
import java.time.Clock
/**
* The authority used for pulling in photos from the camera.
*
* Note: This must match the file provider authority in the manifest.
*/
private const val FILE_PROVIDER_AUTHORITY: String = "${BuildConfig.APPLICATION_ID}.fileprovider"
/**
* Temporary file name for a camera image.
*/
@@ -58,6 +53,7 @@ private const val TEMP_CAMERA_IMAGE_DIR: String = "camera_temp"
class IntentManagerImpl(
private val context: Context,
private val clock: Clock,
private val buildInfoManager: BuildInfoManager,
) : IntentManager {
override fun startActivity(intent: Intent) {
try {
@@ -155,7 +151,7 @@ class IntentManagerImpl(
override fun shareFile(title: String?, fileUri: Uri) {
val providedFile = FileProvider.getUriForFile(
context,
FILE_PROVIDER_AUTHORITY,
buildInfoManager.fileProviderAuthority,
File(fileUri.toString()),
)
val sendIntent: Intent = Intent(Intent.ACTION_SEND).apply {
@@ -174,6 +170,21 @@ class IntentManagerImpl(
startActivity(Intent.createChooser(sendIntent, null))
}
override fun shareErrorReport(throwable: Throwable) {
shareText(
StringBuilder()
.append("Stacktrace:\n")
.append("$throwable\n")
.apply { throwable.stackTrace.forEach { append("\t$it\n") } }
.append("\n")
.append("Version: ${buildInfoManager.versionData}\n")
.append("Device: ${buildInfoManager.deviceData}\n")
.apply { buildInfoManager.ciBuildInfo?.let { append("CI: $it\n") } }
.append("\n")
.toString(),
)
}
override fun getFileDataFromActivityResult(
activityResult: ActivityResult,
): FileData? {
@@ -192,7 +203,7 @@ class IntentManagerImpl(
val uriString = uri.toString()
context
.packageManager
.getPackageInfo(BuildConfig.APPLICATION_ID, PackageManager.GET_PROVIDERS)
.getPackageInfo(buildInfoManager.applicationId, PackageManager.GET_PROVIDERS)
.providers
?.any { uriString.contains(other = it.authority) } == true
}
@@ -234,7 +245,7 @@ class IntentManagerImpl(
}
val outputFileUri = FileProvider.getUriForFile(
context,
FILE_PROVIDER_AUTHORITY,
buildInfoManager.fileProviderAuthority,
file,
)
@@ -279,7 +290,11 @@ class IntentManagerImpl(
private fun getCameraFileData(): FileData {
val tmpDir = File(context.filesDir, TEMP_CAMERA_IMAGE_DIR)
val file = File(tmpDir, TEMP_CAMERA_IMAGE_NAME)
val uri = FileProvider.getUriForFile(context, FILE_PROVIDER_AUTHORITY, file)
val uri = FileProvider.getUriForFile(
context,
buildInfoManager.fileProviderAuthority,
file,
)
val fileName = "photo_${clock.instant().toFormattedPattern(pattern = "yyyyMMddHHmmss")}.jpg"
return FileData(
fileName = fileName,