app links setting

This commit is contained in:
Fabian Freund
2026-01-24 07:38:57 +01:00
parent aeb8a8d5af
commit be0575664d
18 changed files with 1194 additions and 830 deletions
@@ -19,7 +19,9 @@ import android.widget.FrameLayout
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.CallSuper
import androidx.core.content.edit
import androidx.fragment.app.Fragment
import androidx.preference.PreferenceManager
import eu.weblibre.flutter_mozilla_components.addons.WebExtensionActionPopupActivity
import eu.weblibre.flutter_mozilla_components.addons.WebExtensionPromptFeature
import eu.weblibre.flutter_mozilla_components.databinding.FragmentBrowserBinding
@@ -297,8 +299,13 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
sessionId = sessionId,
fragmentManager = parentFragmentManager,
loadUrlUseCase = components.useCases.sessionUseCases.loadUrl,
launchInApp = { true },
shouldPrompt = { true },
launchInApp = { GlobalComponents.shouldOpenLinksInApp() },
shouldPrompt = { GlobalComponents.shouldPromptOpenLinksInApp() },
alwaysOpenCheckboxAction = {
GlobalComponents.engineSettingsApi?.setAppLinksMode(
eu.weblibre.flutter_mozilla_components.pigeons.AppLinksMode.ALWAYS
)
},
failedToLaunchAction = { fallbackUrl ->
fallbackUrl?.let {
val appLinksUseCases = components.useCases.appLinksUseCases
@@ -17,6 +17,7 @@ import eu.weblibre.flutter_mozilla_components.pigeons.GeckoTabContentEvents
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoViewportEvents
import eu.weblibre.flutter_mozilla_components.pigeons.ReaderViewController
import eu.weblibre.flutter_mozilla_components.api.GeckoViewportApiImpl
import eu.weblibre.flutter_mozilla_components.api.GeckoEngineSettingsApiImpl
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
@@ -53,6 +54,25 @@ object GlobalComponents {
// Viewport API for applying pending settings when engineView becomes available
var viewportApi: GeckoViewportApiImpl? = null
// Engine settings API for managing engine-specific settings
var engineSettingsApi: GeckoEngineSettingsApiImpl? = null
fun shouldOpenLinksInApp(): Boolean {
return when (engineSettingsApi!!.getAppLinksMode()) {
eu.weblibre.flutter_mozilla_components.pigeons.AppLinksMode.ALWAYS -> true
eu.weblibre.flutter_mozilla_components.pigeons.AppLinksMode.ASK -> true
eu.weblibre.flutter_mozilla_components.pigeons.AppLinksMode.NEVER -> false
}
}
fun shouldPromptOpenLinksInApp(): Boolean {
return when (engineSettingsApi!!.getAppLinksMode()) {
eu.weblibre.flutter_mozilla_components.pigeons.AppLinksMode.ALWAYS -> false
eu.weblibre.flutter_mozilla_components.pigeons.AppLinksMode.ASK -> true
eu.weblibre.flutter_mozilla_components.pigeons.AppLinksMode.NEVER -> false
}
}
@DelicateCoroutinesApi
private fun restoreBrowserState(newComponents: Components) =
GlobalScope.launch(Dispatchers.Main) {
@@ -231,10 +231,12 @@ class GeckoBrowserApiImpl : GeckoBrowserApi {
addonCollection
)
val engineSettingsApiImpl = GeckoEngineSettingsApiImpl()
GeckoEngineSettingsApi.setUp(
_flutterPluginBinding.binaryMessenger,
GeckoEngineSettingsApiImpl()
engineSettingsApiImpl
)
GlobalComponents.engineSettingsApi = engineSettingsApiImpl
GeckoAddonsApi.setUp(
_flutterPluginBinding.binaryMessenger,
GeckoAddonsApiImpl(profileApplicationContext)
@@ -6,7 +6,11 @@
package eu.weblibre.flutter_mozilla_components.api
import androidx.core.content.edit
import androidx.preference.PreferenceManager
import eu.weblibre.flutter_mozilla_components.GlobalComponents
import eu.weblibre.flutter_mozilla_components.R
import eu.weblibre.flutter_mozilla_components.pigeons.AppLinksMode
import eu.weblibre.flutter_mozilla_components.pigeons.ColorScheme
import eu.weblibre.flutter_mozilla_components.pigeons.CookieBannerHandlingMode
import eu.weblibre.flutter_mozilla_components.pigeons.CustomCookiePolicy
@@ -317,4 +321,33 @@ class GeckoEngineSettingsApiImpl : GeckoEngineSettingsApi {
override fun setPullToRefreshEnabled(enabled: Boolean) {
GlobalComponents.pullToRefreshEnabled = enabled
}
override fun setAppLinksMode(mode: AppLinksMode) {
val context = components.profileApplicationContext
val prefKey = context.getString(R.string.pref_key_open_links_in_apps)
val modeValue = when (mode) {
AppLinksMode.ALWAYS -> context.getString(R.string.pref_key_open_links_in_apps_always)
AppLinksMode.ASK -> context.getString(R.string.pref_key_open_links_in_apps_ask)
AppLinksMode.NEVER -> context.getString(R.string.pref_key_open_links_in_apps_never)
}
PreferenceManager.getDefaultSharedPreferences(context).edit {
putString(prefKey, modeValue)
}
}
override fun getAppLinksMode(): AppLinksMode {
val context = components.profileApplicationContext
val prefKey = context.getString(R.string.pref_key_open_links_in_apps)
val defaultValue = context.getString(R.string.pref_key_open_links_in_apps_ask)
val modeValue = PreferenceManager.getDefaultSharedPreferences(context)
.getString(prefKey, defaultValue) ?: defaultValue
return when (modeValue) {
context.getString(R.string.pref_key_open_links_in_apps_always) -> AppLinksMode.ALWAYS
context.getString(R.string.pref_key_open_links_in_apps_ask) -> AppLinksMode.ASK
context.getString(R.string.pref_key_open_links_in_apps_never) -> AppLinksMode.NEVER
else -> AppLinksMode.ASK
}
}
}
@@ -6,6 +6,7 @@ package eu.weblibre.flutter_mozilla_components.components
import android.content.Context
import androidx.preference.PreferenceManager
import eu.weblibre.flutter_mozilla_components.GlobalComponents
import eu.weblibre.flutter_mozilla_components.R
import eu.weblibre.flutter_mozilla_components.ext.getPreferenceKey
import mozilla.components.browser.state.store.BrowserStore
@@ -25,7 +26,7 @@ class Services(
val appLinksInterceptor by lazy {
AppLinksInterceptor(
context = context,
launchInApp = { true },
launchInApp = { GlobalComponents.shouldOpenLinksInApp() },
store = store,
)
}
@@ -322,6 +322,22 @@ enum class CookieBannerHandlingMode(val raw: Int) {
}
}
/** App links behavior mode - controls how external app links are handled */
enum class AppLinksMode(val raw: Int) {
/** Always open links in their native apps without prompting */
ALWAYS(0),
/** Prompt user before opening in app (with "Always open" checkbox) */
ASK(1),
/** Never open links in external apps, always use browser */
NEVER(2);
companion object {
fun ofRaw(raw: Int): AppLinksMode? {
return values().firstOrNull { it.raw == raw }
}
}
}
enum class WebContentIsolationStrategy(val raw: Int) {
ISOLATE_NOTHING(0),
ISOLATE_EVERYTHING(1),
@@ -3036,345 +3052,350 @@ private open class GeckoPigeonCodec : StandardMessageCodec() {
}
144.toByte() -> {
return (readValue(buffer) as Long?)?.let {
WebContentIsolationStrategy.ofRaw(it.toInt())
AppLinksMode.ofRaw(it.toInt())
}
}
145.toByte() -> {
return (readValue(buffer) as Long?)?.let {
CustomCookiePolicy.ofRaw(it.toInt())
WebContentIsolationStrategy.ofRaw(it.toInt())
}
}
146.toByte() -> {
return (readValue(buffer) as Long?)?.let {
TrackingScope.ofRaw(it.toInt())
CustomCookiePolicy.ofRaw(it.toInt())
}
}
147.toByte() -> {
return (readValue(buffer) as Long?)?.let {
DohSettingsMode.ofRaw(it.toInt())
TrackingScope.ofRaw(it.toInt())
}
}
148.toByte() -> {
return (readValue(buffer) as Long?)?.let {
DownloadStatus.ofRaw(it.toInt())
DohSettingsMode.ofRaw(it.toInt())
}
}
149.toByte() -> {
return (readValue(buffer) as Long?)?.let {
LogLevel.ofRaw(it.toInt())
DownloadStatus.ofRaw(it.toInt())
}
}
150.toByte() -> {
return (readValue(buffer) as Long?)?.let {
MlProgressType.ofRaw(it.toInt())
LogLevel.ofRaw(it.toInt())
}
}
151.toByte() -> {
return (readValue(buffer) as Long?)?.let {
MlProgressStatus.ofRaw(it.toInt())
MlProgressType.ofRaw(it.toInt())
}
}
152.toByte() -> {
return (readValue(buffer) as Long?)?.let {
ClearDataType.ofRaw(it.toInt())
MlProgressStatus.ofRaw(it.toInt())
}
}
153.toByte() -> {
return (readValue(buffer) as Long?)?.let {
GeckoFetchMethod.ofRaw(it.toInt())
ClearDataType.ofRaw(it.toInt())
}
}
154.toByte() -> {
return (readValue(buffer) as Long?)?.let {
GeckoFetchRedircet.ofRaw(it.toInt())
GeckoFetchMethod.ofRaw(it.toInt())
}
}
155.toByte() -> {
return (readValue(buffer) as Long?)?.let {
GeckoFetchCookiePolicy.ofRaw(it.toInt())
GeckoFetchRedircet.ofRaw(it.toInt())
}
}
156.toByte() -> {
return (readValue(buffer) as Long?)?.let {
BookmarkNodeType.ofRaw(it.toInt())
GeckoFetchCookiePolicy.ofRaw(it.toInt())
}
}
157.toByte() -> {
return (readValue(buffer) as Long?)?.let {
SitePermissionStatus.ofRaw(it.toInt())
BookmarkNodeType.ofRaw(it.toInt())
}
}
158.toByte() -> {
return (readValue(buffer) as Long?)?.let {
AutoplayStatus.ofRaw(it.toInt())
SitePermissionStatus.ofRaw(it.toInt())
}
}
159.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
TranslationOptions.fromList(it)
return (readValue(buffer) as Long?)?.let {
AutoplayStatus.ofRaw(it.toInt())
}
}
160.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
ReaderState.fromList(it)
TranslationOptions.fromList(it)
}
}
161.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
AddTabParams.fromList(it)
ReaderState.fromList(it)
}
}
162.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
LastMediaAccessState.fromList(it)
AddTabParams.fromList(it)
}
}
163.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
HistoryMetadataKey.fromList(it)
LastMediaAccessState.fromList(it)
}
}
164.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
PackageCategoryValue.fromList(it)
HistoryMetadataKey.fromList(it)
}
}
165.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
ExternalPackage.fromList(it)
PackageCategoryValue.fromList(it)
}
}
166.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
LoadUrlFlagsValue.fromList(it)
ExternalPackage.fromList(it)
}
}
167.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
SourceValue.fromList(it)
LoadUrlFlagsValue.fromList(it)
}
}
168.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
TabState.fromList(it)
SourceValue.fromList(it)
}
}
169.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
RecoverableTab.fromList(it)
TabState.fromList(it)
}
}
170.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
RecoverableBrowserState.fromList(it)
RecoverableTab.fromList(it)
}
}
171.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
IconRequest.fromList(it)
RecoverableBrowserState.fromList(it)
}
}
172.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
ResourceSize.fromList(it)
IconRequest.fromList(it)
}
}
173.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
Resource.fromList(it)
ResourceSize.fromList(it)
}
}
174.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
IconResult.fromList(it)
Resource.fromList(it)
}
}
175.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
CookiePartitionKey.fromList(it)
IconResult.fromList(it)
}
}
176.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
Cookie.fromList(it)
CookiePartitionKey.fromList(it)
}
}
177.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
VisitInfo.fromList(it)
Cookie.fromList(it)
}
}
178.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
HistoryItem.fromList(it)
VisitInfo.fromList(it)
}
}
179.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
HistoryState.fromList(it)
HistoryItem.fromList(it)
}
}
180.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
ReaderableState.fromList(it)
HistoryState.fromList(it)
}
}
181.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
SecurityInfoState.fromList(it)
ReaderableState.fromList(it)
}
}
182.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
TabContentState.fromList(it)
SecurityInfoState.fromList(it)
}
}
183.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
FindResultState.fromList(it)
TabContentState.fromList(it)
}
}
184.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
CustomSelectionAction.fromList(it)
FindResultState.fromList(it)
}
}
185.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
WebExtensionData.fromList(it)
CustomSelectionAction.fromList(it)
}
}
186.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
GeckoSuggestion.fromList(it)
WebExtensionData.fromList(it)
}
}
187.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
TabContent.fromList(it)
GeckoSuggestion.fromList(it)
}
}
188.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
ContentBlocking.fromList(it)
TabContent.fromList(it)
}
}
189.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
DohSettings.fromList(it)
ContentBlocking.fromList(it)
}
}
190.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
GeckoEngineSettings.fromList(it)
DohSettings.fromList(it)
}
}
191.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
AutocompleteResult.fromList(it)
GeckoEngineSettings.fromList(it)
}
}
192.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
UnknownHitResult.fromList(it)
AutocompleteResult.fromList(it)
}
}
193.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
ImageHitResult.fromList(it)
UnknownHitResult.fromList(it)
}
}
194.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
VideoHitResult.fromList(it)
ImageHitResult.fromList(it)
}
}
195.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
AudioHitResult.fromList(it)
VideoHitResult.fromList(it)
}
}
196.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
ImageSrcHitResult.fromList(it)
AudioHitResult.fromList(it)
}
}
197.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
PhoneHitResult.fromList(it)
ImageSrcHitResult.fromList(it)
}
}
198.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
EmailHitResult.fromList(it)
PhoneHitResult.fromList(it)
}
}
199.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
GeoHitResult.fromList(it)
EmailHitResult.fromList(it)
}
}
200.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
DownloadState.fromList(it)
GeoHitResult.fromList(it)
}
}
201.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
ShareInternetResourceState.fromList(it)
DownloadState.fromList(it)
}
}
202.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
AddonCollection.fromList(it)
ShareInternetResourceState.fromList(it)
}
}
203.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
GeckoPref.fromList(it)
AddonCollection.fromList(it)
}
}
204.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
MlProgressData.fromList(it)
GeckoPref.fromList(it)
}
}
205.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
ContainerSiteAssignment.fromList(it)
MlProgressData.fromList(it)
}
}
206.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
GeckoHeader.fromList(it)
ContainerSiteAssignment.fromList(it)
}
}
207.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
GeckoFetchRequest.fromList(it)
GeckoHeader.fromList(it)
}
}
208.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
GeckoFetchResponse.fromList(it)
GeckoFetchRequest.fromList(it)
}
}
209.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
BookmarkNode.fromList(it)
GeckoFetchResponse.fromList(it)
}
}
210.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
BookmarkInfo.fromList(it)
BookmarkNode.fromList(it)
}
}
211.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
SitePermissions.fromList(it)
BookmarkInfo.fromList(it)
}
}
212.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
SitePermissions.fromList(it)
}
}
213.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
TrackingProtectionException.fromList(it)
}
@@ -3444,282 +3465,286 @@ private open class GeckoPigeonCodec : StandardMessageCodec() {
stream.write(143)
writeValue(stream, value.raw.toLong())
}
is WebContentIsolationStrategy -> {
is AppLinksMode -> {
stream.write(144)
writeValue(stream, value.raw.toLong())
}
is CustomCookiePolicy -> {
is WebContentIsolationStrategy -> {
stream.write(145)
writeValue(stream, value.raw.toLong())
}
is TrackingScope -> {
is CustomCookiePolicy -> {
stream.write(146)
writeValue(stream, value.raw.toLong())
}
is DohSettingsMode -> {
is TrackingScope -> {
stream.write(147)
writeValue(stream, value.raw.toLong())
}
is DownloadStatus -> {
is DohSettingsMode -> {
stream.write(148)
writeValue(stream, value.raw.toLong())
}
is LogLevel -> {
is DownloadStatus -> {
stream.write(149)
writeValue(stream, value.raw.toLong())
}
is MlProgressType -> {
is LogLevel -> {
stream.write(150)
writeValue(stream, value.raw.toLong())
}
is MlProgressStatus -> {
is MlProgressType -> {
stream.write(151)
writeValue(stream, value.raw.toLong())
}
is ClearDataType -> {
is MlProgressStatus -> {
stream.write(152)
writeValue(stream, value.raw.toLong())
}
is GeckoFetchMethod -> {
is ClearDataType -> {
stream.write(153)
writeValue(stream, value.raw.toLong())
}
is GeckoFetchRedircet -> {
is GeckoFetchMethod -> {
stream.write(154)
writeValue(stream, value.raw.toLong())
}
is GeckoFetchCookiePolicy -> {
is GeckoFetchRedircet -> {
stream.write(155)
writeValue(stream, value.raw.toLong())
}
is BookmarkNodeType -> {
is GeckoFetchCookiePolicy -> {
stream.write(156)
writeValue(stream, value.raw.toLong())
}
is SitePermissionStatus -> {
is BookmarkNodeType -> {
stream.write(157)
writeValue(stream, value.raw.toLong())
}
is AutoplayStatus -> {
is SitePermissionStatus -> {
stream.write(158)
writeValue(stream, value.raw.toLong())
}
is TranslationOptions -> {
is AutoplayStatus -> {
stream.write(159)
writeValue(stream, value.toList())
writeValue(stream, value.raw.toLong())
}
is ReaderState -> {
is TranslationOptions -> {
stream.write(160)
writeValue(stream, value.toList())
}
is AddTabParams -> {
is ReaderState -> {
stream.write(161)
writeValue(stream, value.toList())
}
is LastMediaAccessState -> {
is AddTabParams -> {
stream.write(162)
writeValue(stream, value.toList())
}
is HistoryMetadataKey -> {
is LastMediaAccessState -> {
stream.write(163)
writeValue(stream, value.toList())
}
is PackageCategoryValue -> {
is HistoryMetadataKey -> {
stream.write(164)
writeValue(stream, value.toList())
}
is ExternalPackage -> {
is PackageCategoryValue -> {
stream.write(165)
writeValue(stream, value.toList())
}
is LoadUrlFlagsValue -> {
is ExternalPackage -> {
stream.write(166)
writeValue(stream, value.toList())
}
is SourceValue -> {
is LoadUrlFlagsValue -> {
stream.write(167)
writeValue(stream, value.toList())
}
is TabState -> {
is SourceValue -> {
stream.write(168)
writeValue(stream, value.toList())
}
is RecoverableTab -> {
is TabState -> {
stream.write(169)
writeValue(stream, value.toList())
}
is RecoverableBrowserState -> {
is RecoverableTab -> {
stream.write(170)
writeValue(stream, value.toList())
}
is IconRequest -> {
is RecoverableBrowserState -> {
stream.write(171)
writeValue(stream, value.toList())
}
is ResourceSize -> {
is IconRequest -> {
stream.write(172)
writeValue(stream, value.toList())
}
is Resource -> {
is ResourceSize -> {
stream.write(173)
writeValue(stream, value.toList())
}
is IconResult -> {
is Resource -> {
stream.write(174)
writeValue(stream, value.toList())
}
is CookiePartitionKey -> {
is IconResult -> {
stream.write(175)
writeValue(stream, value.toList())
}
is Cookie -> {
is CookiePartitionKey -> {
stream.write(176)
writeValue(stream, value.toList())
}
is VisitInfo -> {
is Cookie -> {
stream.write(177)
writeValue(stream, value.toList())
}
is HistoryItem -> {
is VisitInfo -> {
stream.write(178)
writeValue(stream, value.toList())
}
is HistoryState -> {
is HistoryItem -> {
stream.write(179)
writeValue(stream, value.toList())
}
is ReaderableState -> {
is HistoryState -> {
stream.write(180)
writeValue(stream, value.toList())
}
is SecurityInfoState -> {
is ReaderableState -> {
stream.write(181)
writeValue(stream, value.toList())
}
is TabContentState -> {
is SecurityInfoState -> {
stream.write(182)
writeValue(stream, value.toList())
}
is FindResultState -> {
is TabContentState -> {
stream.write(183)
writeValue(stream, value.toList())
}
is CustomSelectionAction -> {
is FindResultState -> {
stream.write(184)
writeValue(stream, value.toList())
}
is WebExtensionData -> {
is CustomSelectionAction -> {
stream.write(185)
writeValue(stream, value.toList())
}
is GeckoSuggestion -> {
is WebExtensionData -> {
stream.write(186)
writeValue(stream, value.toList())
}
is TabContent -> {
is GeckoSuggestion -> {
stream.write(187)
writeValue(stream, value.toList())
}
is ContentBlocking -> {
is TabContent -> {
stream.write(188)
writeValue(stream, value.toList())
}
is DohSettings -> {
is ContentBlocking -> {
stream.write(189)
writeValue(stream, value.toList())
}
is GeckoEngineSettings -> {
is DohSettings -> {
stream.write(190)
writeValue(stream, value.toList())
}
is AutocompleteResult -> {
is GeckoEngineSettings -> {
stream.write(191)
writeValue(stream, value.toList())
}
is UnknownHitResult -> {
is AutocompleteResult -> {
stream.write(192)
writeValue(stream, value.toList())
}
is ImageHitResult -> {
is UnknownHitResult -> {
stream.write(193)
writeValue(stream, value.toList())
}
is VideoHitResult -> {
is ImageHitResult -> {
stream.write(194)
writeValue(stream, value.toList())
}
is AudioHitResult -> {
is VideoHitResult -> {
stream.write(195)
writeValue(stream, value.toList())
}
is ImageSrcHitResult -> {
is AudioHitResult -> {
stream.write(196)
writeValue(stream, value.toList())
}
is PhoneHitResult -> {
is ImageSrcHitResult -> {
stream.write(197)
writeValue(stream, value.toList())
}
is EmailHitResult -> {
is PhoneHitResult -> {
stream.write(198)
writeValue(stream, value.toList())
}
is GeoHitResult -> {
is EmailHitResult -> {
stream.write(199)
writeValue(stream, value.toList())
}
is DownloadState -> {
is GeoHitResult -> {
stream.write(200)
writeValue(stream, value.toList())
}
is ShareInternetResourceState -> {
is DownloadState -> {
stream.write(201)
writeValue(stream, value.toList())
}
is AddonCollection -> {
is ShareInternetResourceState -> {
stream.write(202)
writeValue(stream, value.toList())
}
is GeckoPref -> {
is AddonCollection -> {
stream.write(203)
writeValue(stream, value.toList())
}
is MlProgressData -> {
is GeckoPref -> {
stream.write(204)
writeValue(stream, value.toList())
}
is ContainerSiteAssignment -> {
is MlProgressData -> {
stream.write(205)
writeValue(stream, value.toList())
}
is GeckoHeader -> {
is ContainerSiteAssignment -> {
stream.write(206)
writeValue(stream, value.toList())
}
is GeckoFetchRequest -> {
is GeckoHeader -> {
stream.write(207)
writeValue(stream, value.toList())
}
is GeckoFetchResponse -> {
is GeckoFetchRequest -> {
stream.write(208)
writeValue(stream, value.toList())
}
is BookmarkNode -> {
is GeckoFetchResponse -> {
stream.write(209)
writeValue(stream, value.toList())
}
is BookmarkInfo -> {
is BookmarkNode -> {
stream.write(210)
writeValue(stream, value.toList())
}
is SitePermissions -> {
is BookmarkInfo -> {
stream.write(211)
writeValue(stream, value.toList())
}
is TrackingProtectionException -> {
is SitePermissions -> {
stream.write(212)
writeValue(stream, value.toList())
}
is TrackingProtectionException -> {
stream.write(213)
writeValue(stream, value.toList())
}
else -> super.writeValue(stream, value)
}
}
@@ -3819,6 +3844,12 @@ interface GeckoEngineSettingsApi {
fun setDefaultSettings(settings: GeckoEngineSettings)
fun updateRuntimeSettings(settings: GeckoEngineSettings)
fun setPullToRefreshEnabled(enabled: Boolean)
/**
* Sets the app links mode preference (stored in SharedPreferences).
* Controls how external app links are handled in the browser.
*/
fun setAppLinksMode(mode: AppLinksMode)
fun getAppLinksMode(): AppLinksMode
companion object {
/** The codec used by GeckoEngineSettingsApi. */
@@ -3883,6 +3914,39 @@ interface GeckoEngineSettingsApi {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.setAppLinksMode$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val modeArg = args[0] as AppLinksMode
val wrapped: List<Any?> = try {
api.setAppLinksMode(modeArg)
listOf(null)
} catch (exception: Throwable) {
GeckoPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.getAppLinksMode$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { _, reply ->
val wrapped: List<Any?> = try {
listOf(api.getAppLinksMode())
} catch (exception: Throwable) {
GeckoPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
}
}
}
@@ -28,4 +28,10 @@
<string name="pref_key_override_amo_collection" translatable="false">pref_key_override_amo_collection</string>
<string name="pref_key_override_amo_user" translatable="false">pref_key_override_amo_user</string>
<string name="pref_key_compose_ui" translatable="false">pref_key_compose_ui</string>
<!-- App Links Settings -->
<string name="pref_key_open_links_in_apps" translatable="false">pref_key_open_links_in_apps</string>
<string name="pref_key_open_links_in_apps_always" translatable="false">pref_key_open_links_in_apps_always</string>
<string name="pref_key_open_links_in_apps_ask" translatable="false">pref_key_open_links_in_apps_ask</string>
<string name="pref_key_open_links_in_apps_never" translatable="false">pref_key_open_links_in_apps_never</string>
</resources>