diff --git a/sdk-webview/src/main/java/com/xuqm/sdk/webview/XWebViewView.kt b/sdk-webview/src/main/java/com/xuqm/sdk/webview/XWebViewView.kt index ac98b89..d22be73 100644 --- a/sdk-webview/src/main/java/com/xuqm/sdk/webview/XWebViewView.kt +++ b/sdk-webview/src/main/java/com/xuqm/sdk/webview/XWebViewView.kt @@ -360,6 +360,7 @@ fun XWebViewView( // camera capture val pendingFileCallback = remember { mutableStateOf>?>(null) } val pendingCameraUri = remember { mutableStateOf(null) } + val pendingAcceptMimes = remember { mutableStateOf?>(null) } val takePictureLauncher = rememberLauncherForActivityResult( ActivityResultContracts.TakePicture() @@ -374,7 +375,28 @@ fun XWebViewView( val pickContentLauncher = rememberLauncherForActivityResult(GetContentWithMimeTypes()) { uri -> val cb = pendingFileCallback.value pendingFileCallback.value = null - cb?.onReceiveValue(if (uri != null) arrayOf(uri) else null) + if (uri == null) { + cb?.onReceiveValue(null) + return@rememberLauncherForActivityResult + } + // Validate that the selected file's actual MIME type is within the accepted list. + // Some devices show extra file types in the picker (e.g. .doc when only .docx was + // requested). Passing an unsupported type to the WebView renderer can cause a native + // crash. We accept the file only when its MIME type matches, or fall back to passing + // it through when we can't determine the type (to avoid blocking legitimate uploads). + val acceptedMimes = pendingAcceptMimes.value + val actualMime = uri.let { context.contentResolver.getType(it) } + val allowed = acceptedMimes.isNullOrEmpty() || + acceptedMimes.any { accepted -> + accepted == "*/*" || + (actualMime != null && (actualMime == accepted || actualMime.startsWith(accepted.substringBefore("*")))) + } + if (!allowed) { + android.util.Log.w("XWV", "Rejected file: actualMime=$actualMime not in accepted=$acceptedMimes") + cb?.onReceiveValue(null) + } else { + cb?.onReceiveValue(arrayOf(uri)) + } } val shouldLaunchCamera = remember { mutableStateOf(false) } @@ -605,6 +627,7 @@ fun XWebViewView( pendingFileCallback.value = filePathCallback val acceptMimes = resolvePickerMimeTypes(fileChooserParams.acceptTypes) + pendingAcceptMimes.value = acceptMimes val isCameraCapture = fileChooserParams.isCaptureEnabled && fileChooserParams.acceptTypes.any { it.contains("image") } val isImageOnly = acceptMimes.all { it.startsWith("image/") || it == "image/*" }