Skip to content

refactor: add share-safe file provider helpers PR 1 [WPB-26687]#5033

Open
MohamadJaara wants to merge 1 commit into
epic/forward-vs-external-sharefrom
mo/share-forward-01-share-plumbing
Open

refactor: add share-safe file provider helpers PR 1 [WPB-26687]#5033
MohamadJaara wants to merge 1 commit into
epic/forward-vs-external-sharefrom
mo/share-forward-01-share-plumbing

Conversation

@MohamadJaara

@MohamadJaara MohamadJaara commented Jul 7, 2026

Copy link
Copy Markdown
Member

https://wearezeta.atlassian.net/browse/WPB-26687

Summary

  • Adds share-safe FileProvider URI helpers backed by a dedicated shared cache directory.
  • Routes app-generated file shares through chooser intents that can exclude Wire targets.
  • Enables Android 15+ trusted share identity for Wire-origin shares.
  • Updates QR/profile, feedback, avatar, and Cells share call sites to use the shared helpers.

General Idea

This stack separates “share externally” from “forward/share inside Wire” while keeping the behavior different per Android version:

  • On Android 15+ we can rely on trusted share caller identity, so Wire can stay in the normal Android share sheet safely.
  • On older Android versions we cannot reliably know that an incoming Wire FileProvider URI came from Wire itself, so we avoid routing Wire-internal files through the public share sheet.
  • For older Android versions, internal Wire forwarding uses an explicit in-app navigation path into the import media flow.
  • External sharing uses Android chooser intents and excludes Wire where needed to prevent re-importing internal Wire files.
flowchart TD
    A["User taps Share"] --> B{"Android 15+?"}

    B -- "Yes" --> C["Use Android share sheet"]
    C --> D["Enable share identity"]
    D --> E["Wire target can be trusted"]

    B -- "No" --> F{"Target action"}
    F -- "Share externally" --> G["Open external chooser"]
    G --> H["Exclude Wire targets"]

    F -- "Share via Wire" --> I["Create shared-cache FileProvider URI"]
    I --> J["Navigate directly to ImportMediaScreen"]
    J --> K["Validate URI is from Wire shared_files root"]
    K --> L["Import as pending asset"]
Loading

Stack

This PR is part of a stacked series:

  1. mo/share-forward-01-share-plumbing
    Share-safe FileProvider helpers and chooser behavior.

  2. mo/share-forward-02-import-safety
    Incoming share validation and trusted Wire caller handling.

  3. mo/share-forward-03-asset-actions
    UI split between “Share via Wire” and “Share externally”.

  4. mo/share-forward-04-log-sharing
    Share logs as one archive, either externally or via Wire.

  5. mo/share-forward-05-stability-baselines
    Generated stability baseline updates.

@MohamadJaara MohamadJaara changed the title refactor: add share-safe file provider helpers refactor: add share-safe file provider helpers [[WPB-26687]] Jul 7, 2026
@MohamadJaara MohamadJaara changed the title refactor: add share-safe file provider helpers [[WPB-26687]] refactor: add share-safe file provider helpers [WPB-26687] Jul 7, 2026
@sonarqubecloud

sonarqubecloud Bot commented Jul 7, 2026

Copy link
Copy Markdown

@MohamadJaara MohamadJaara changed the title refactor: add share-safe file provider helpers [WPB-26687] refactor: add share-safe file provider helpers PR 1 [WPB-26687] Jul 7, 2026
Comment on lines +396 to +404
if (!excludeOwnComponents) return@apply
val ownShareComponents = packageManager.queryIntentActivitiesCompat(sendIntent)
.map { ComponentName(it.activityInfo.packageName, it.activityInfo.name) }
.filter { it.packageName == packageName }
.toTypedArray()
if (ownShareComponents.isNotEmpty()) {
putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, ownShareComponents)
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this would read a bit more naturally as:

if (excludeOwnComponents) {
    ...
}

instead of if (!excludeOwnComponents) return@apply

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

this is intentional to return early avoiding nested logic

if (excludeOwnComponents) {
    ...
        if (ownShareComponents.isNotEmpty()) {
            ...
        }
}


fun getShareableTempAvatarUri(filePath: Path): Uri {
return FileProvider.getUriForFile(context, context.getProviderAuthority(), filePath.toFile())
return context.shareableFileProviderUri(context.fileProviderSharedCacheFile(filePath.name))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you clarify this part? It looks like we're creating a new file, but I can't see where it's populated with the avatar data

@sbakhtiarov

Copy link
Copy Markdown
Contributor

I think this will break Cells code from com.wire.android.feature.cells.util.FileHelper since it is not updated. Will not be able to open Cell files in external apps.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants