Skip to content

fix: preserve accept MIME types in WebView file chooser - #62

Open
OS-pedrogustavobilro wants to merge 4 commits into
mainfrom
fix/RPM-7140/mime-type-restriction
Open

fix: preserve accept MIME types in WebView file chooser#62
OS-pedrogustavobilro wants to merge 4 commits into
mainfrom
fix/RPM-7140/mime-type-restriction

Conversation

@OS-pedrogustavobilro

@OS-pedrogustavobilro OS-pedrogustavobilro commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

⚠️ 🤖 AI-assisted PR with Claude Code, with manual review and testing done by a human

Description

Fixes the Android OpenInWebView file chooser incorrectly restricting mixed file uploads to images only, plus two related bugs found during manual verification.

Root cause: OSIABWebChromeClient.launchFullChooser picked a single MIME type for the ACTION_GET_CONTENT intent via a naive acceptTypes.contains("image") / .contains("video") check on a comma-joined accept string. For an HTML input like accept="image/*,application/pdf,application/msword", this collapsed the picker down to image/*, silently dropping PDF/Word/Excel — even though Android natively supports disjoint multi-MIME selection via type = "*/*" + Intent.EXTRA_MIME_TYPES.

Changes:

  • Added OSIABFileChooserHelper (helpers/) to resolve raw accept tokens (MIME types and/or file extensions, e.g. .pdf, .docx) into concrete MIME types, and to decide the correct type / EXTRA_MIME_TYPES pair for the chooser intent.
  • OSIABWebViewActivity now keeps the accept list structured (List<String>) instead of collapsing it to a joined string, and launchFullChooser / buildPhotoVideoIntents use the resolved MIME types instead of substring matching.
  • Only a single resolved MIME type gets applied directly as type with no filtering beyond it. Any time there's more than one distinct resolved MIME type — even when they share a top-level category (e.g. application/pdf + application/msword) — the chooser now always uses */* + EXTRA_MIME_TYPES with the exact list, rather than collapsing same-category subtypes into that category's wildcard (e.g. application/*). That collapse was itself a bug: application/* is broad enough to also match zip, octet-stream, JSON, etc., which is not what a documents-only accept list requested.
  • A resolved "*/*" is now treated the same as no accept restriction at all for capture-shortcut purposes, so accept="*/*" combined with <input capture> correctly offers photo/video capture instead of silently falling back to (or failing to offer) a chooser.
  • Fixed a related crash: combining <input capture> with a documents-only accept list produced an empty capture-intent list, and launchCameraChooser indexed into it unconditionally (IndexOutOfBoundsException), which was silently swallowed and canceled the chooser with no visible feedback to the user. It now falls back to the full chooser when nothing is capturable.
  • Bumped to 2.0.3 with a CHANGELOG.md entry.

Context

Internal JIRA References:

Type of changes

  • Fix (non-breaking change which fixes an issue)
  • Feature (non-breaking change which adds functionality)
  • Refactor (cosmetic changes)
  • Breaking change (change that would cause existing functionality to not work as expected)

Tests

Manual testing

A webpage was created that reproduces the issue; to reproduce the bug / the fix:

  1. Open the app (see links below)
  2. Click the WebView button
  3. Use the existing URL that's there and click Open In WebView button.
  4. In the webpage, check U1 scenario (image + pdf + docs + excel picker) is broken before this PR, only images were able to be selected.
  5. U5 and U6 also crashed the WebView activity before this PR.
  6. ℹ️ Note no. 1: You should have different files like images or pdfs stored in your phone to be able to notice if the file picker is allowing the correct file types (you can quickly search in Google to download some if you don't have any).
  7. ℹ️ Note no. 2: Feel free to do other tests with the WebView in that app, should you wish.

Mobile apps:

Unit tests

Added OSIABFileChooserHelperTest covering:

  • MIME-token passthrough, extension-to-MIME resolution, mixed MIME+extension tokens, deduplication (including cross-form dedup between a MIME token and an extension token resolving to the same type), unresolvable/garbage/blank tokens, and empty input.
  • resolveChooserMimeConfig: empty list, single MIME type, same-category collapse (e.g. image/png + image/jpegimage/*), disjoint categories (*/* + EXTRA_MIME_TYPES), and dedup on a
    non-distinct input list.

Full existing test suite (./gradlew testDebugUnitTest) and ./gradlew assembleDebug both pass with no regressions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant