From aeea838062348250596f57d7c4de096769d47fcf Mon Sep 17 00:00:00 2001 From: Marcus Hoffmann Date: Sat, 13 Aug 2022 20:23:46 +0200 Subject: [PATCH] Close #12689: Make sharing images work with Direct Share Image sharing currently only works when sharing to an app but not when using the Android Direct Share feature, where it fails with a SecurityException. "Direct Share" is what Android calls the app created shortcuts, i.e. individual chats from a messaging application. The code pretty much already does the right thing (i.e. setting the FLAG_GRANT_READ_URI_PERMISSION on the target intent as well as the Chooser action, as described in ACTION_CHOOSE Api docs[1]) but there's some platform internals that seem to go wrong here but we can work around it with this patch. https://issuetracker.google.com/issues/151386328 describes a similar Problem, especially #12 in there offers a similar workaround and an explanation: The underlying problem is that ACTION_SEND is using EXTRA_STREAM for the content URI. But the FLAG_GRANT_*_URI_PERMISSION mechanism only works with URIs in Intent.data and Intent.clipData. The framework contains some code that tries to work around this limitation. But it doesn't handle this particular case. Intent.createChooser() migrates the flags and data/clipData from the target Intent, but it does so before the framework had a chance to fix up the target Intent via Intent.migrateExtraStreamToClipData(). And indeed moving the clipData into the inner intent makes Direct Share work and preserves the image preview in the Intent. [1] file:////docs/reference/android/content/Intent.html#ACTION_CHOOSER If you need to grant URI permissions through a chooser, you must specify the permissions to be granted on the ACTION_CHOOSER Intent in addition to the EXTRA_INTENT inside. This means using setClipData(ClipData) to specify the URIs to be granted as well as FLAG_GRANT_READ_URI_PERMISSION and/or FLAG_GRANT_WRITE_URI_PERMISSION as appropriate. --- .../feature/accounts/push/FxaPushSupportFeature.kt | 13 ++++++++----- docs/changelog.md | 3 +++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/components/feature/accounts-push/src/main/java/mozilla/components/feature/accounts/push/FxaPushSupportFeature.kt b/components/feature/accounts-push/src/main/java/mozilla/components/feature/accounts/push/FxaPushSupportFeature.kt index d99752f7161..c76439775d7 100644 --- a/components/feature/accounts-push/src/main/java/mozilla/components/feature/accounts/push/FxaPushSupportFeature.kt +++ b/components/feature/accounts-push/src/main/java/mozilla/components/feature/accounts/push/FxaPushSupportFeature.kt @@ -76,17 +76,20 @@ class FxaPushSupportFeature( * Initialize the support feature to launch the appropriate observers. */ fun initialize() = coroutineScope.launch { - val autoPushObserver = AutoPushObserver(accountManager, pushFeature, pushScope.value()) + val scopeValue = pushScope.value() + + val autoPushObserver = AutoPushObserver(accountManager, pushFeature, scopeValue) val accountObserver = AccountObserver( context, pushFeature, - pushScope.value(), + scopeValue, crashReporter, owner, autoPause ) + // Registration should always be done on the Main dispatcher. coroutineScope.launch(Main) { accountManager.register(accountObserver) @@ -130,7 +133,7 @@ internal class AccountObserver( // registration could happen after onDevicesUpdate has been called, without having to tie this // into the account "auth lifecycle". // See https://github.com/mozilla-mobile/android-components/issues/8766 - GlobalScope.launch(Dispatchers.Main) { + GlobalScope.launch(Main) { account.deviceConstellation().registerDeviceObserver(constellationObserver, lifecycleOwner, autoPause) account.deviceConstellation().refreshDevices() } @@ -183,7 +186,7 @@ internal fun pushSubscribe( currentDevice.subscription?.endpoint != subscription.endpoint ) { logger.info("Updating account with new subscription info.") - CoroutineScope(Dispatchers.Main).launch { + CoroutineScope(Main).launch { account.deviceConstellation().setDevicePushSubscription(subscription.into()) } } @@ -259,7 +262,7 @@ internal class AutoPushObserver( val rawEvent = message ?: return accountManager.withConstellation { - CoroutineScope(Dispatchers.Main).launch { + CoroutineScope(Main).launch { processRawEvent(String(rawEvent)) } } diff --git a/docs/changelog.md b/docs/changelog.md index 512ead0518b..84a367f7e7d 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -21,6 +21,9 @@ permalink: /changelog/ * ⚠️ **This is a breaking change**: `FxaPushSupportFeature` now requires to be explicitly started with `initialize`. * The constructor for `FxaPushSupportFeature` has a `coroutineScope` parameter that defaults to a `CoroutineScope(Dispatchers.IO)`. +* **support-ktx** + * 🚒 Bug fixed [issue #12689](https://github.com/mozilla-mobile/android-components/issues/12689) Make `Context.shareMedia` work with Android Direct Share. + # 105.0.0 * [Commits](https://github.com/mozilla-mobile/android-components/compare/v104.0.0...v105.0.0) * [Milestone](https://github.com/mozilla-mobile/android-components/milestone/152?closed=1)