added context menu support

This commit is contained in:
Fabian Freund
2025-02-23 17:11:28 +01:00
parent a5133b0b90
commit cbfd218c7e
30 changed files with 2159 additions and 159 deletions
@@ -9,6 +9,7 @@ import eu.lensai.flutter_mozilla_components.api.GeckoBrowserApiImpl
import eu.lensai.flutter_mozilla_components.api.GeckoContainerProxyApiImpl
import eu.lensai.flutter_mozilla_components.api.GeckoCookieApiImpl
import eu.lensai.flutter_mozilla_components.api.GeckoDeleteBrowsingDataControllerImpl
import eu.lensai.flutter_mozilla_components.api.GeckoDownloadsApiImpl
import eu.lensai.flutter_mozilla_components.api.GeckoEngineSettingsApiImpl
import eu.lensai.flutter_mozilla_components.api.GeckoFindApiImpl
import eu.lensai.flutter_mozilla_components.api.GeckoIconsApiImpl
@@ -24,6 +25,7 @@ import eu.lensai.flutter_mozilla_components.pigeons.GeckoBrowserApi
import eu.lensai.flutter_mozilla_components.pigeons.GeckoContainerProxyApi
import eu.lensai.flutter_mozilla_components.pigeons.GeckoCookieApi
import eu.lensai.flutter_mozilla_components.pigeons.GeckoDeleteBrowsingDataController
import eu.lensai.flutter_mozilla_components.pigeons.GeckoDownloadsApi
import eu.lensai.flutter_mozilla_components.pigeons.GeckoEngineSettingsApi
import eu.lensai.flutter_mozilla_components.pigeons.GeckoFindApi
import eu.lensai.flutter_mozilla_components.pigeons.GeckoIconsApi
@@ -120,6 +122,7 @@ class FlutterMozillaComponentsPlugin: FlutterPlugin, ActivityAware {
selectionActionDelegate
))
GeckoDeleteBrowsingDataController.setUp(_flutterPluginBinding.binaryMessenger, GeckoDeleteBrowsingDataControllerImpl())
GeckoDownloadsApi.setUp(_flutterPluginBinding.binaryMessenger, GeckoDownloadsApiImpl())
ReaderViewEvents.setUp(
_flutterPluginBinding.binaryMessenger,
@@ -0,0 +1,91 @@
package eu.lensai.flutter_mozilla_components.api
import android.os.Environment
import eu.lensai.flutter_mozilla_components.GlobalComponents
import eu.lensai.flutter_mozilla_components.pigeons.DownloadState
import eu.lensai.flutter_mozilla_components.pigeons.GeckoDownloadsApi
import eu.lensai.flutter_mozilla_components.pigeons.ShareInternetResourceState
import mozilla.components.browser.state.action.ContentAction
import mozilla.components.browser.state.action.CopyInternetResourceAction
import mozilla.components.browser.state.action.ShareInternetResourceAction
import java.util.UUID
class GeckoDownloadsApiImpl : GeckoDownloadsApi {
private val components by lazy {
requireNotNull(GlobalComponents.components) { "Components not initialized" }
}
override fun requestDownload(tabId: String, state: DownloadState) {
components.core.store.dispatch(
ContentAction.UpdateDownloadAction(
tabId,
state.toMozillaDownloadState(),
),
)
}
override fun copyInternetResource(tabId: String, state: ShareInternetResourceState) {
components.core.store.dispatch(CopyInternetResourceAction.AddCopyAction(tabId, state.toMozillaShareInternetResourceState()))
}
override fun shareInternetResource(tabId: String, state: ShareInternetResourceState) {
components.core.store.dispatch(ShareInternetResourceAction.AddShareAction(tabId, state.toMozillaShareInternetResourceState()))
}
private fun ShareInternetResourceState.toMozillaShareInternetResourceState(): mozilla.components.browser.state.state.content.ShareInternetResourceState {
return mozilla.components.browser.state.state.content.ShareInternetResourceState(
url = url,
contentType = contentType,
private = private,
response = null, // Since Pigeon class doesn't have this field
referrerUrl = referrerUrl
)
}
fun mozilla.components.browser.state.state.content.ShareInternetResourceState.toPigeonShareInternetResourceState(): eu.lensai.flutter_mozilla_components.pigeons.ShareInternetResourceState {
return eu.lensai.flutter_mozilla_components.pigeons.ShareInternetResourceState(
url = url,
contentType = contentType,
private = private,
referrerUrl = referrerUrl
)
}
private fun DownloadState.toMozillaDownloadState(): mozilla.components.browser.state.state.content.DownloadState {
return mozilla.components.browser.state.state.content.DownloadState(
url = url,
fileName = fileName,
contentType = contentType,
contentLength = contentLength,
currentBytesCopied = currentBytesCopied ?: 0L,
status = status?.toMozillaStatus() ?: mozilla.components.browser.state.state.content.DownloadState.Status.INITIATED,
userAgent = userAgent,
destinationDirectory = destinationDirectory ?: Environment.DIRECTORY_DOWNLOADS,
directoryPath = directoryPath ?: Environment.getExternalStoragePublicDirectory(
destinationDirectory ?: Environment.DIRECTORY_DOWNLOADS
).path,
referrerUrl = referrerUrl,
skipConfirmation = skipConfirmation ?: false,
openInApp = openInApp ?: false,
id = id ?: UUID.randomUUID().toString(),
sessionId = sessionId,
private = private ?: false,
createdTime = createdTime ?: System.currentTimeMillis(),
response = null, // Cannot be mapped from Pigeon model
notificationId = notificationId?.toInt()
)
}
private fun eu.lensai.flutter_mozilla_components.pigeons.DownloadStatus.toMozillaStatus(): mozilla.components.browser.state.state.content.DownloadState.Status {
return when (this) {
eu.lensai.flutter_mozilla_components.pigeons.DownloadStatus.INITIATED -> mozilla.components.browser.state.state.content.DownloadState.Status.INITIATED
eu.lensai.flutter_mozilla_components.pigeons.DownloadStatus.DOWNLOADING -> mozilla.components.browser.state.state.content.DownloadState.Status.DOWNLOADING
eu.lensai.flutter_mozilla_components.pigeons.DownloadStatus.PAUSED -> mozilla.components.browser.state.state.content.DownloadState.Status.PAUSED
eu.lensai.flutter_mozilla_components.pigeons.DownloadStatus.CANCELLED -> mozilla.components.browser.state.state.content.DownloadState.Status.CANCELLED
eu.lensai.flutter_mozilla_components.pigeons.DownloadStatus.FAILED -> mozilla.components.browser.state.state.content.DownloadState.Status.FAILED
eu.lensai.flutter_mozilla_components.pigeons.DownloadStatus.COMPLETED -> mozilla.components.browser.state.state.content.DownloadState.Status.COMPLETED
}
}
}
@@ -8,7 +8,15 @@ import android.util.Log
import eu.lensai.flutter_mozilla_components.GlobalComponents
import eu.lensai.flutter_mozilla_components.ext.resize
import eu.lensai.flutter_mozilla_components.ext.toWebPBytes
import eu.lensai.flutter_mozilla_components.pigeons.AudioHitResult
import eu.lensai.flutter_mozilla_components.pigeons.EmailHitResult
import eu.lensai.flutter_mozilla_components.pigeons.GeckoStateEvents
import eu.lensai.flutter_mozilla_components.pigeons.GeoHitResult
import eu.lensai.flutter_mozilla_components.pigeons.ImageHitResult
import eu.lensai.flutter_mozilla_components.pigeons.ImageSrcHitResult
import eu.lensai.flutter_mozilla_components.pigeons.PhoneHitResult
import eu.lensai.flutter_mozilla_components.pigeons.UnknownHitResult
import eu.lensai.flutter_mozilla_components.pigeons.VideoHitResult
import mozilla.components.browser.state.action.BrowserAction
import mozilla.components.browser.state.action.ContentAction
import mozilla.components.browser.state.action.LastAccessAction
@@ -16,6 +24,7 @@ import mozilla.components.browser.state.action.ReaderAction
import mozilla.components.browser.state.action.TabListAction
import mozilla.components.browser.state.action.WebExtensionAction
import mozilla.components.browser.state.state.BrowserState
import mozilla.components.concept.engine.HitResult
import mozilla.components.feature.addons.logger
import mozilla.components.lib.state.Middleware
import mozilla.components.lib.state.MiddlewareContext
@@ -81,6 +90,24 @@ class FlutterEventMiddleware(private val flutterEvents: GeckoStateEvents) : Midd
) { _ -> }
}
}
is ContentAction.UpdateHitResultAction -> {
runOnUiThread {
flutterEvents.onLongPress(
System.currentTimeMillis(),
action.sessionId,
when(val result = action.hitResult) {
is HitResult.AUDIO -> AudioHitResult(result.src, result.title)
is HitResult.EMAIL -> EmailHitResult(result.src)
is HitResult.GEO -> GeoHitResult(result.src)
is HitResult.IMAGE -> ImageHitResult(result.src, result.title)
is HitResult.IMAGE_SRC -> ImageSrcHitResult(result.src, result.uri)
is HitResult.PHONE -> PhoneHitResult(result.src)
is HitResult.UNKNOWN -> UnknownHitResult(result.src)
is HitResult.VIDEO -> VideoHitResult(result.src, result.title)
}
) { _ -> }
}
}
else -> {
//logger.debug("Event fired: " + action.javaClass.name)
}
@@ -229,6 +229,31 @@ enum class WebContentIsolationStrategy(val raw: Int) {
}
}
/** Status that represents every state that a download can be in. */
enum class DownloadStatus(val raw: Int) {
/** Indicates that the download is in the first state after creation but not yet [DOWNLOADING]. */
INITIATED(0),
/** Indicates that an [INITIATED] download is now actively being downloaded. */
DOWNLOADING(1),
/** Indicates that the download that has been [DOWNLOADING] has been paused. */
PAUSED(2),
/** Indicates that the download that has been [DOWNLOADING] has been cancelled. */
CANCELLED(3),
/**
* Indicates that the download that has been [DOWNLOADING] has moved to failed because
* something unexpected has happened.
*/
FAILED(4),
/** Indicates that the [DOWNLOADING] download has been completed. */
COMPLETED(5);
companion object {
fun ofRaw(raw: Int): DownloadStatus? {
return values().firstOrNull { it.raw == raw }
}
}
}
/**
* Translation options that map to the Gecko Translations Options.
*
@@ -1187,6 +1212,295 @@ data class AutocompleteResult (
)
}
}
/**
* Represents all the different supported types of data that can be found from long clicking
* an element.
*
* Generated class from Pigeon that represents data sent in messages.
* This class should not be extended by any user class outside of the generated file.
*/
sealed class HitResult
/**
* Default type if we're unable to match the type to anything. It may or may not have a src.
*
* Generated class from Pigeon that represents data sent in messages.
*/
data class UnknownHitResult (
val src: String
) : HitResult()
{
companion object {
fun fromList(pigeonVar_list: List<Any?>): UnknownHitResult {
val src = pigeonVar_list[0] as String
return UnknownHitResult(src)
}
}
fun toList(): List<Any?> {
return listOf(
src,
)
}
}
/**
* If the HTML element was of type 'HTMLImageElement'.
*
* Generated class from Pigeon that represents data sent in messages.
*/
data class ImageHitResult (
val src: String,
val title: String? = null
) : HitResult()
{
companion object {
fun fromList(pigeonVar_list: List<Any?>): ImageHitResult {
val src = pigeonVar_list[0] as String
val title = pigeonVar_list[1] as String?
return ImageHitResult(src, title)
}
}
fun toList(): List<Any?> {
return listOf(
src,
title,
)
}
}
/**
* If the HTML element was of type 'HTMLVideoElement'.
*
* Generated class from Pigeon that represents data sent in messages.
*/
data class VideoHitResult (
val src: String,
val title: String? = null
) : HitResult()
{
companion object {
fun fromList(pigeonVar_list: List<Any?>): VideoHitResult {
val src = pigeonVar_list[0] as String
val title = pigeonVar_list[1] as String?
return VideoHitResult(src, title)
}
}
fun toList(): List<Any?> {
return listOf(
src,
title,
)
}
}
/**
* If the HTML element was of type 'HTMLAudioElement'.
*
* Generated class from Pigeon that represents data sent in messages.
*/
data class AudioHitResult (
val src: String,
val title: String? = null
) : HitResult()
{
companion object {
fun fromList(pigeonVar_list: List<Any?>): AudioHitResult {
val src = pigeonVar_list[0] as String
val title = pigeonVar_list[1] as String?
return AudioHitResult(src, title)
}
}
fun toList(): List<Any?> {
return listOf(
src,
title,
)
}
}
/**
* If the HTML element was of type 'HTMLImageElement' and contained a URI.
*
* Generated class from Pigeon that represents data sent in messages.
*/
data class ImageSrcHitResult (
val src: String,
val uri: String
) : HitResult()
{
companion object {
fun fromList(pigeonVar_list: List<Any?>): ImageSrcHitResult {
val src = pigeonVar_list[0] as String
val uri = pigeonVar_list[1] as String
return ImageSrcHitResult(src, uri)
}
}
fun toList(): List<Any?> {
return listOf(
src,
uri,
)
}
}
/**
* The type used if the URI is prepended with 'tel:'.
*
* Generated class from Pigeon that represents data sent in messages.
*/
data class PhoneHitResult (
val src: String
) : HitResult()
{
companion object {
fun fromList(pigeonVar_list: List<Any?>): PhoneHitResult {
val src = pigeonVar_list[0] as String
return PhoneHitResult(src)
}
}
fun toList(): List<Any?> {
return listOf(
src,
)
}
}
/**
* The type used if the URI is prepended with 'mailto:'.
*
* Generated class from Pigeon that represents data sent in messages.
*/
data class EmailHitResult (
val src: String
) : HitResult()
{
companion object {
fun fromList(pigeonVar_list: List<Any?>): EmailHitResult {
val src = pigeonVar_list[0] as String
return EmailHitResult(src)
}
}
fun toList(): List<Any?> {
return listOf(
src,
)
}
}
/**
* The type used if the URI is prepended with 'geo:'.
*
* Generated class from Pigeon that represents data sent in messages.
*/
data class GeoHitResult (
val src: String
) : HitResult()
{
companion object {
fun fromList(pigeonVar_list: List<Any?>): GeoHitResult {
val src = pigeonVar_list[0] as String
return GeoHitResult(src)
}
}
fun toList(): List<Any?> {
return listOf(
src,
)
}
}
/** Generated class from Pigeon that represents data sent in messages. */
data class DownloadState (
val url: String,
val fileName: String? = null,
val contentType: String? = null,
val contentLength: Long? = null,
val currentBytesCopied: Long? = null,
val status: DownloadStatus? = null,
val userAgent: String? = null,
val destinationDirectory: String? = null,
val directoryPath: String? = null,
val referrerUrl: String? = null,
val skipConfirmation: Boolean? = null,
val openInApp: Boolean? = null,
val id: String? = null,
val sessionId: String? = null,
val private: Boolean? = null,
val createdTime: Long? = null,
val notificationId: Long? = null
)
{
companion object {
fun fromList(pigeonVar_list: List<Any?>): DownloadState {
val url = pigeonVar_list[0] as String
val fileName = pigeonVar_list[1] as String?
val contentType = pigeonVar_list[2] as String?
val contentLength = pigeonVar_list[3] as Long?
val currentBytesCopied = pigeonVar_list[4] as Long?
val status = pigeonVar_list[5] as DownloadStatus?
val userAgent = pigeonVar_list[6] as String?
val destinationDirectory = pigeonVar_list[7] as String?
val directoryPath = pigeonVar_list[8] as String?
val referrerUrl = pigeonVar_list[9] as String?
val skipConfirmation = pigeonVar_list[10] as Boolean?
val openInApp = pigeonVar_list[11] as Boolean?
val id = pigeonVar_list[12] as String?
val sessionId = pigeonVar_list[13] as String?
val private = pigeonVar_list[14] as Boolean?
val createdTime = pigeonVar_list[15] as Long?
val notificationId = pigeonVar_list[16] as Long?
return DownloadState(url, fileName, contentType, contentLength, currentBytesCopied, status, userAgent, destinationDirectory, directoryPath, referrerUrl, skipConfirmation, openInApp, id, sessionId, private, createdTime, notificationId)
}
}
fun toList(): List<Any?> {
return listOf(
url,
fileName,
contentType,
contentLength,
currentBytesCopied,
status,
userAgent,
destinationDirectory,
directoryPath,
referrerUrl,
skipConfirmation,
openInApp,
id,
sessionId,
private,
createdTime,
notificationId,
)
}
}
/** Generated class from Pigeon that represents data sent in messages. */
data class ShareInternetResourceState (
val url: String,
val contentType: String? = null,
val private: Boolean,
val referrerUrl: String? = null
)
{
companion object {
fun fromList(pigeonVar_list: List<Any?>): ShareInternetResourceState {
val url = pigeonVar_list[0] as String
val contentType = pigeonVar_list[1] as String?
val private = pigeonVar_list[2] as Boolean
val referrerUrl = pigeonVar_list[3] as String?
return ShareInternetResourceState(url, contentType, private, referrerUrl)
}
}
fun toList(): List<Any?> {
return listOf(
url,
contentType,
private,
referrerUrl,
)
}
}
private open class GeckoPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
return when (type) {
@@ -1256,150 +1570,205 @@ private open class GeckoPigeonCodec : StandardMessageCodec() {
}
}
142.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
TranslationOptions.fromList(it)
return (readValue(buffer) as Long?)?.let {
DownloadStatus.ofRaw(it.toInt())
}
}
143.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
ReaderState.fromList(it)
TranslationOptions.fromList(it)
}
}
144.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
LastMediaAccessState.fromList(it)
ReaderState.fromList(it)
}
}
145.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
HistoryMetadataKey.fromList(it)
LastMediaAccessState.fromList(it)
}
}
146.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
PackageCategoryValue.fromList(it)
HistoryMetadataKey.fromList(it)
}
}
147.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
ExternalPackage.fromList(it)
PackageCategoryValue.fromList(it)
}
}
148.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
LoadUrlFlagsValue.fromList(it)
ExternalPackage.fromList(it)
}
}
149.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
SourceValue.fromList(it)
LoadUrlFlagsValue.fromList(it)
}
}
150.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
TabState.fromList(it)
SourceValue.fromList(it)
}
}
151.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
RecoverableTab.fromList(it)
TabState.fromList(it)
}
}
152.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
RecoverableBrowserState.fromList(it)
RecoverableTab.fromList(it)
}
}
153.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
IconRequest.fromList(it)
RecoverableBrowserState.fromList(it)
}
}
154.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
ResourceSize.fromList(it)
IconRequest.fromList(it)
}
}
155.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
Resource.fromList(it)
ResourceSize.fromList(it)
}
}
156.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
IconResult.fromList(it)
Resource.fromList(it)
}
}
157.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
CookiePartitionKey.fromList(it)
IconResult.fromList(it)
}
}
158.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
Cookie.fromList(it)
CookiePartitionKey.fromList(it)
}
}
159.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
HistoryItem.fromList(it)
Cookie.fromList(it)
}
}
160.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
HistoryState.fromList(it)
HistoryItem.fromList(it)
}
}
161.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
ReaderableState.fromList(it)
HistoryState.fromList(it)
}
}
162.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
SecurityInfoState.fromList(it)
ReaderableState.fromList(it)
}
}
163.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
TabContentState.fromList(it)
SecurityInfoState.fromList(it)
}
}
164.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
FindResultState.fromList(it)
TabContentState.fromList(it)
}
}
165.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
CustomSelectionAction.fromList(it)
FindResultState.fromList(it)
}
}
166.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
WebExtensionData.fromList(it)
CustomSelectionAction.fromList(it)
}
}
167.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
GeckoSuggestion.fromList(it)
WebExtensionData.fromList(it)
}
}
168.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
TabContent.fromList(it)
GeckoSuggestion.fromList(it)
}
}
169.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
GeckoEngineSettings.fromList(it)
TabContent.fromList(it)
}
}
170.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
GeckoEngineSettings.fromList(it)
}
}
171.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
AutocompleteResult.fromList(it)
}
}
172.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
UnknownHitResult.fromList(it)
}
}
173.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
ImageHitResult.fromList(it)
}
}
174.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
VideoHitResult.fromList(it)
}
}
175.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
AudioHitResult.fromList(it)
}
}
176.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
ImageSrcHitResult.fromList(it)
}
}
177.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
PhoneHitResult.fromList(it)
}
}
178.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
EmailHitResult.fromList(it)
}
}
179.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
GeoHitResult.fromList(it)
}
}
180.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
DownloadState.fromList(it)
}
}
181.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
ShareInternetResourceState.fromList(it)
}
}
else -> super.readValueOfType(type, buffer)
}
}
@@ -1457,122 +1826,166 @@ private open class GeckoPigeonCodec : StandardMessageCodec() {
stream.write(141)
writeValue(stream, value.raw)
}
is TranslationOptions -> {
is DownloadStatus -> {
stream.write(142)
writeValue(stream, value.toList())
writeValue(stream, value.raw)
}
is ReaderState -> {
is TranslationOptions -> {
stream.write(143)
writeValue(stream, value.toList())
}
is LastMediaAccessState -> {
is ReaderState -> {
stream.write(144)
writeValue(stream, value.toList())
}
is HistoryMetadataKey -> {
is LastMediaAccessState -> {
stream.write(145)
writeValue(stream, value.toList())
}
is PackageCategoryValue -> {
is HistoryMetadataKey -> {
stream.write(146)
writeValue(stream, value.toList())
}
is ExternalPackage -> {
is PackageCategoryValue -> {
stream.write(147)
writeValue(stream, value.toList())
}
is LoadUrlFlagsValue -> {
is ExternalPackage -> {
stream.write(148)
writeValue(stream, value.toList())
}
is SourceValue -> {
is LoadUrlFlagsValue -> {
stream.write(149)
writeValue(stream, value.toList())
}
is TabState -> {
is SourceValue -> {
stream.write(150)
writeValue(stream, value.toList())
}
is RecoverableTab -> {
is TabState -> {
stream.write(151)
writeValue(stream, value.toList())
}
is RecoverableBrowserState -> {
is RecoverableTab -> {
stream.write(152)
writeValue(stream, value.toList())
}
is IconRequest -> {
is RecoverableBrowserState -> {
stream.write(153)
writeValue(stream, value.toList())
}
is ResourceSize -> {
is IconRequest -> {
stream.write(154)
writeValue(stream, value.toList())
}
is Resource -> {
is ResourceSize -> {
stream.write(155)
writeValue(stream, value.toList())
}
is IconResult -> {
is Resource -> {
stream.write(156)
writeValue(stream, value.toList())
}
is CookiePartitionKey -> {
is IconResult -> {
stream.write(157)
writeValue(stream, value.toList())
}
is Cookie -> {
is CookiePartitionKey -> {
stream.write(158)
writeValue(stream, value.toList())
}
is HistoryItem -> {
is Cookie -> {
stream.write(159)
writeValue(stream, value.toList())
}
is HistoryState -> {
is HistoryItem -> {
stream.write(160)
writeValue(stream, value.toList())
}
is ReaderableState -> {
is HistoryState -> {
stream.write(161)
writeValue(stream, value.toList())
}
is SecurityInfoState -> {
is ReaderableState -> {
stream.write(162)
writeValue(stream, value.toList())
}
is TabContentState -> {
is SecurityInfoState -> {
stream.write(163)
writeValue(stream, value.toList())
}
is FindResultState -> {
is TabContentState -> {
stream.write(164)
writeValue(stream, value.toList())
}
is CustomSelectionAction -> {
is FindResultState -> {
stream.write(165)
writeValue(stream, value.toList())
}
is WebExtensionData -> {
is CustomSelectionAction -> {
stream.write(166)
writeValue(stream, value.toList())
}
is GeckoSuggestion -> {
is WebExtensionData -> {
stream.write(167)
writeValue(stream, value.toList())
}
is TabContent -> {
is GeckoSuggestion -> {
stream.write(168)
writeValue(stream, value.toList())
}
is GeckoEngineSettings -> {
is TabContent -> {
stream.write(169)
writeValue(stream, value.toList())
}
is AutocompleteResult -> {
is GeckoEngineSettings -> {
stream.write(170)
writeValue(stream, value.toList())
}
is AutocompleteResult -> {
stream.write(171)
writeValue(stream, value.toList())
}
is UnknownHitResult -> {
stream.write(172)
writeValue(stream, value.toList())
}
is ImageHitResult -> {
stream.write(173)
writeValue(stream, value.toList())
}
is VideoHitResult -> {
stream.write(174)
writeValue(stream, value.toList())
}
is AudioHitResult -> {
stream.write(175)
writeValue(stream, value.toList())
}
is ImageSrcHitResult -> {
stream.write(176)
writeValue(stream, value.toList())
}
is PhoneHitResult -> {
stream.write(177)
writeValue(stream, value.toList())
}
is EmailHitResult -> {
stream.write(178)
writeValue(stream, value.toList())
}
is GeoHitResult -> {
stream.write(179)
writeValue(stream, value.toList())
}
is DownloadState -> {
stream.write(180)
writeValue(stream, value.toList())
}
is ShareInternetResourceState -> {
stream.write(181)
writeValue(stream, value.toList())
}
else -> super.writeValue(stream, value)
}
}
@@ -2988,6 +3401,23 @@ class GeckoStateEvents(private val binaryMessenger: BinaryMessenger, private val
}
}
}
fun onLongPress(timestampArg: Long, idArg: String, hitResultArg: HitResult, callback: (Result<Unit>) -> Unit)
{
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
val channelName = "dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onLongPress$separatedMessageChannelSuffix"
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
channel.send(listOf(timestampArg, idArg, hitResultArg)) {
if (it is List<*>) {
if (it.size > 1) {
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
} else {
callback(Result.success(Unit))
}
} else {
callback(Result.failure(createConnectionError(channelName)))
}
}
}
}
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
interface ReaderViewEvents {
@@ -3469,3 +3899,78 @@ interface GeckoDeleteBrowsingDataController {
}
}
}
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
interface GeckoDownloadsApi {
fun requestDownload(tabId: String, state: DownloadState)
fun copyInternetResource(tabId: String, state: ShareInternetResourceState)
fun shareInternetResource(tabId: String, state: ShareInternetResourceState)
companion object {
/** The codec used by GeckoDownloadsApi. */
val codec: MessageCodec<Any?> by lazy {
GeckoPigeonCodec()
}
/** Sets up an instance of `GeckoDownloadsApi` to handle messages through the `binaryMessenger`. */
@JvmOverloads
fun setUp(binaryMessenger: BinaryMessenger, api: GeckoDownloadsApi?, messageChannelSuffix: String = "") {
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.flutter_mozilla_components.GeckoDownloadsApi.requestDownload$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val tabIdArg = args[0] as String
val stateArg = args[1] as DownloadState
val wrapped: List<Any?> = try {
api.requestDownload(tabIdArg, stateArg)
listOf(null)
} catch (exception: Throwable) {
wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.flutter_mozilla_components.GeckoDownloadsApi.copyInternetResource$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val tabIdArg = args[0] as String
val stateArg = args[1] as ShareInternetResourceState
val wrapped: List<Any?> = try {
api.copyInternetResource(tabIdArg, stateArg)
listOf(null)
} catch (exception: Throwable) {
wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.flutter_mozilla_components.GeckoDownloadsApi.shareInternetResource$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val tabIdArg = args[0] as String
val stateArg = args[1] as ShareInternetResourceState
val wrapped: List<Any?> = try {
api.shareInternetResource(tabIdArg, stateArg)
listOf(null)
} catch (exception: Throwable) {
wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
}
}
}
@@ -6,6 +6,7 @@ export 'src/domain/services/gecko_addon.dart';
export 'src/domain/services/gecko_container_proxy.dart';
export 'src/domain/services/gecko_cookie.dart';
export 'src/domain/services/gecko_delete_browser_data.dart';
export 'src/domain/services/gecko_downloads.dart';
export 'src/domain/services/gecko_engine_settings.dart';
export 'src/domain/services/gecko_event.dart';
export 'src/domain/services/gecko_find_in_page.dart';
@@ -20,22 +21,31 @@ export 'src/domain/services/gecko_tab_content.dart';
export 'src/geckoview_widget.dart';
export 'src/pigeons/gecko.g.dart'
show
AudioHitResult,
ColorScheme,
CookieBannerHandlingMode,
CookieSameSiteStatus,
EmailHitResult,
GeckoEngineSettings,
GeckoSuggestion,
GeckoSuggestionType,
GeoHitResult,
HistoryMetadataKey,
HitResult,
HttpsOnlyMode,
IconSource,
IconType,
ImageHitResult,
ImageSrcHitResult,
PhoneHitResult,
Resource,
ResourceSize,
SecurityInfoState,
TabContent,
TabContentState,
TrackingProtectionPolicy,
UnknownHitResult,
VideoHitResult,
WebContentIsolationStrategy,
WebExtensionActionType,
WebExtensionData;
@@ -0,0 +1,69 @@
import 'package:flutter_mozilla_components/src/pigeons/gecko.g.dart';
final _apiInstance = GeckoDownloadsApi();
class GeckoDownloadsService {
final GeckoDownloadsApi _api;
GeckoDownloadsService({GeckoDownloadsApi? api}) : _api = api ?? _apiInstance;
Future<void> copyInternetResource(
String tabId, {
required Uri url,
Uri? referrerUrl,
String? contentType,
bool isPrivate = false,
}) {
return _api.copyInternetResource(
tabId,
ShareInternetResourceState(
url: url.toString(),
referrerUrl: referrerUrl?.toString(),
private: isPrivate,
contentType: contentType,
),
);
}
Future<void> shareInternetResource(
String tabId, {
required Uri url,
Uri? referrerUrl,
String? contentType,
bool isPrivate = false,
}) {
return _api.shareInternetResource(
tabId,
ShareInternetResourceState(
url: url.toString(),
referrerUrl: referrerUrl?.toString(),
private: isPrivate,
contentType: contentType,
),
);
}
Future<void> requestDownload(
String tabId, {
required Uri url,
String? fileName,
bool? openInApp,
bool? skipConfirmation,
Uri? referrerUrl,
bool isPrivate = false,
}) {
return _api.requestDownload(
tabId,
DownloadState(
url: url.toString(),
fileName: fileName,
openInApp: openInApp,
skipConfirmation: skipConfirmation,
referrerUrl: referrerUrl?.toString(),
private: isPrivate,
),
);
}
}
@@ -12,6 +12,7 @@ typedef IconChangeEvent = ({String tabId, Uint8List? bytes});
typedef IconUpdateEvent = ({String url, Uint8List bytes});
typedef ThumbnailEvent = ({String tabId, Uint8List? bytes});
typedef FindResultsEvent = ({String tabId, List<FindResultState> results});
typedef LongPressEvent = ({String tabId, HitResult hitResult});
class GeckoEventService extends GeckoStateEvents {
// Stream controllers
@@ -29,6 +30,7 @@ class GeckoEventService extends GeckoStateEvents {
final _iconUpdateSubject = PublishSubject<IconUpdateEvent>();
final _thumbnailSubject = PublishSubject<ThumbnailEvent>();
final _findResultsSubject = PublishSubject<FindResultsEvent>();
final _longPressSubject = PublishSubject<LongPressEvent>();
final _tabAddedSubject = PublishSubject<String>();
@@ -47,6 +49,7 @@ class GeckoEventService extends GeckoStateEvents {
Stream<IconUpdateEvent> get iconUpdateEvents => _iconUpdateSubject.stream;
Stream<ThumbnailEvent> get thumbnailEvents => _thumbnailSubject.stream;
Stream<FindResultsEvent> get findResultsEvent => _findResultsSubject.stream;
Stream<LongPressEvent> get longPressEvent => _longPressSubject.stream;
Stream<String> get tabAddedStream => _tabAddedSubject.stream;
@@ -144,6 +147,14 @@ class GeckoEventService extends GeckoStateEvents {
));
}
@override
void onLongPress(int timestamp, String id, HitResult hitResult) {
_longPressSubject.addWhenMoreRecent(timestamp, id, (
tabId: id,
hitResult: hitResult,
));
}
@override
void onTabAdded(int timestamp, String tabId) {
_tabAddedSubject.addWhenMoreRecent(timestamp, null, tabId);
@@ -170,6 +181,7 @@ class GeckoEventService extends GeckoStateEvents {
unawaited(_iconChangeSubject.close());
unawaited(_thumbnailSubject.close());
unawaited(_findResultsSubject.close());
unawaited(_longPressSubject.close());
unawaited(_tabAddedSubject.close());
}
}
@@ -125,6 +125,23 @@ enum WebContentIsolationStrategy {
isolateHighValue,
}
/// Status that represents every state that a download can be in.
enum DownloadStatus {
/// Indicates that the download is in the first state after creation but not yet [DOWNLOADING].
initiated,
/// Indicates that an [INITIATED] download is now actively being downloaded.
downloading,
/// Indicates that the download that has been [DOWNLOADING] has been paused.
paused,
/// Indicates that the download that has been [DOWNLOADING] has been cancelled.
cancelled,
/// Indicates that the download that has been [DOWNLOADING] has moved to failed because
/// something unexpected has happened.
failed,
/// Indicates that the [DOWNLOADING] download has been completed.
completed,
}
/// Translation options that map to the Gecko Translations Options.
///
/// @property downloadModel If the necessary models should be downloaded on request. If false, then
@@ -1314,6 +1331,344 @@ class AutocompleteResult {
}
}
/// Represents all the different supported types of data that can be found from long clicking
/// an element.
sealed class HitResult {
}
/// Default type if we're unable to match the type to anything. It may or may not have a src.
class UnknownHitResult extends HitResult {
UnknownHitResult({
required this.src,
});
String src;
Object encode() {
return <Object?>[
src,
];
}
static UnknownHitResult decode(Object result) {
result as List<Object?>;
return UnknownHitResult(
src: result[0]! as String,
);
}
}
/// If the HTML element was of type 'HTMLImageElement'.
class ImageHitResult extends HitResult {
ImageHitResult({
required this.src,
this.title,
});
String src;
String? title;
Object encode() {
return <Object?>[
src,
title,
];
}
static ImageHitResult decode(Object result) {
result as List<Object?>;
return ImageHitResult(
src: result[0]! as String,
title: result[1] as String?,
);
}
}
/// If the HTML element was of type 'HTMLVideoElement'.
class VideoHitResult extends HitResult {
VideoHitResult({
required this.src,
this.title,
});
String src;
String? title;
Object encode() {
return <Object?>[
src,
title,
];
}
static VideoHitResult decode(Object result) {
result as List<Object?>;
return VideoHitResult(
src: result[0]! as String,
title: result[1] as String?,
);
}
}
/// If the HTML element was of type 'HTMLAudioElement'.
class AudioHitResult extends HitResult {
AudioHitResult({
required this.src,
this.title,
});
String src;
String? title;
Object encode() {
return <Object?>[
src,
title,
];
}
static AudioHitResult decode(Object result) {
result as List<Object?>;
return AudioHitResult(
src: result[0]! as String,
title: result[1] as String?,
);
}
}
/// If the HTML element was of type 'HTMLImageElement' and contained a URI.
class ImageSrcHitResult extends HitResult {
ImageSrcHitResult({
required this.src,
required this.uri,
});
String src;
String uri;
Object encode() {
return <Object?>[
src,
uri,
];
}
static ImageSrcHitResult decode(Object result) {
result as List<Object?>;
return ImageSrcHitResult(
src: result[0]! as String,
uri: result[1]! as String,
);
}
}
/// The type used if the URI is prepended with 'tel:'.
class PhoneHitResult extends HitResult {
PhoneHitResult({
required this.src,
});
String src;
Object encode() {
return <Object?>[
src,
];
}
static PhoneHitResult decode(Object result) {
result as List<Object?>;
return PhoneHitResult(
src: result[0]! as String,
);
}
}
/// The type used if the URI is prepended with 'mailto:'.
class EmailHitResult extends HitResult {
EmailHitResult({
required this.src,
});
String src;
Object encode() {
return <Object?>[
src,
];
}
static EmailHitResult decode(Object result) {
result as List<Object?>;
return EmailHitResult(
src: result[0]! as String,
);
}
}
/// The type used if the URI is prepended with 'geo:'.
class GeoHitResult extends HitResult {
GeoHitResult({
required this.src,
});
String src;
Object encode() {
return <Object?>[
src,
];
}
static GeoHitResult decode(Object result) {
result as List<Object?>;
return GeoHitResult(
src: result[0]! as String,
);
}
}
class DownloadState {
DownloadState({
required this.url,
this.fileName,
this.contentType,
this.contentLength,
this.currentBytesCopied,
this.status,
this.userAgent,
this.destinationDirectory,
this.directoryPath,
this.referrerUrl,
this.skipConfirmation,
this.openInApp,
this.id,
this.sessionId,
this.private,
this.createdTime,
this.notificationId,
});
String url;
String? fileName;
String? contentType;
int? contentLength;
int? currentBytesCopied;
DownloadStatus? status;
String? userAgent;
String? destinationDirectory;
String? directoryPath;
String? referrerUrl;
bool? skipConfirmation;
bool? openInApp;
String? id;
String? sessionId;
bool? private;
int? createdTime;
int? notificationId;
Object encode() {
return <Object?>[
url,
fileName,
contentType,
contentLength,
currentBytesCopied,
status,
userAgent,
destinationDirectory,
directoryPath,
referrerUrl,
skipConfirmation,
openInApp,
id,
sessionId,
private,
createdTime,
notificationId,
];
}
static DownloadState decode(Object result) {
result as List<Object?>;
return DownloadState(
url: result[0]! as String,
fileName: result[1] as String?,
contentType: result[2] as String?,
contentLength: result[3] as int?,
currentBytesCopied: result[4] as int?,
status: result[5] as DownloadStatus?,
userAgent: result[6] as String?,
destinationDirectory: result[7] as String?,
directoryPath: result[8] as String?,
referrerUrl: result[9] as String?,
skipConfirmation: result[10] as bool?,
openInApp: result[11] as bool?,
id: result[12] as String?,
sessionId: result[13] as String?,
private: result[14] as bool?,
createdTime: result[15] as int?,
notificationId: result[16] as int?,
);
}
}
class ShareInternetResourceState {
ShareInternetResourceState({
required this.url,
this.contentType,
required this.private,
this.referrerUrl,
});
String url;
String? contentType;
bool private;
String? referrerUrl;
Object encode() {
return <Object?>[
url,
contentType,
private,
referrerUrl,
];
}
static ShareInternetResourceState decode(Object result) {
result as List<Object?>;
return ShareInternetResourceState(
url: result[0]! as String,
contentType: result[1] as String?,
private: result[2]! as bool,
referrerUrl: result[3] as String?,
);
}
}
class _PigeonCodec extends StandardMessageCodec {
const _PigeonCodec();
@@ -1361,93 +1716,126 @@ class _PigeonCodec extends StandardMessageCodec {
} else if (value is WebContentIsolationStrategy) {
buffer.putUint8(141);
writeValue(buffer, value.index);
} else if (value is TranslationOptions) {
} else if (value is DownloadStatus) {
buffer.putUint8(142);
writeValue(buffer, value.encode());
} else if (value is ReaderState) {
writeValue(buffer, value.index);
} else if (value is TranslationOptions) {
buffer.putUint8(143);
writeValue(buffer, value.encode());
} else if (value is LastMediaAccessState) {
} else if (value is ReaderState) {
buffer.putUint8(144);
writeValue(buffer, value.encode());
} else if (value is HistoryMetadataKey) {
} else if (value is LastMediaAccessState) {
buffer.putUint8(145);
writeValue(buffer, value.encode());
} else if (value is PackageCategoryValue) {
} else if (value is HistoryMetadataKey) {
buffer.putUint8(146);
writeValue(buffer, value.encode());
} else if (value is ExternalPackage) {
} else if (value is PackageCategoryValue) {
buffer.putUint8(147);
writeValue(buffer, value.encode());
} else if (value is LoadUrlFlagsValue) {
} else if (value is ExternalPackage) {
buffer.putUint8(148);
writeValue(buffer, value.encode());
} else if (value is SourceValue) {
} else if (value is LoadUrlFlagsValue) {
buffer.putUint8(149);
writeValue(buffer, value.encode());
} else if (value is TabState) {
} else if (value is SourceValue) {
buffer.putUint8(150);
writeValue(buffer, value.encode());
} else if (value is RecoverableTab) {
} else if (value is TabState) {
buffer.putUint8(151);
writeValue(buffer, value.encode());
} else if (value is RecoverableBrowserState) {
} else if (value is RecoverableTab) {
buffer.putUint8(152);
writeValue(buffer, value.encode());
} else if (value is IconRequest) {
} else if (value is RecoverableBrowserState) {
buffer.putUint8(153);
writeValue(buffer, value.encode());
} else if (value is ResourceSize) {
} else if (value is IconRequest) {
buffer.putUint8(154);
writeValue(buffer, value.encode());
} else if (value is Resource) {
} else if (value is ResourceSize) {
buffer.putUint8(155);
writeValue(buffer, value.encode());
} else if (value is IconResult) {
} else if (value is Resource) {
buffer.putUint8(156);
writeValue(buffer, value.encode());
} else if (value is CookiePartitionKey) {
} else if (value is IconResult) {
buffer.putUint8(157);
writeValue(buffer, value.encode());
} else if (value is Cookie) {
} else if (value is CookiePartitionKey) {
buffer.putUint8(158);
writeValue(buffer, value.encode());
} else if (value is HistoryItem) {
} else if (value is Cookie) {
buffer.putUint8(159);
writeValue(buffer, value.encode());
} else if (value is HistoryState) {
} else if (value is HistoryItem) {
buffer.putUint8(160);
writeValue(buffer, value.encode());
} else if (value is ReaderableState) {
} else if (value is HistoryState) {
buffer.putUint8(161);
writeValue(buffer, value.encode());
} else if (value is SecurityInfoState) {
} else if (value is ReaderableState) {
buffer.putUint8(162);
writeValue(buffer, value.encode());
} else if (value is TabContentState) {
} else if (value is SecurityInfoState) {
buffer.putUint8(163);
writeValue(buffer, value.encode());
} else if (value is FindResultState) {
} else if (value is TabContentState) {
buffer.putUint8(164);
writeValue(buffer, value.encode());
} else if (value is CustomSelectionAction) {
} else if (value is FindResultState) {
buffer.putUint8(165);
writeValue(buffer, value.encode());
} else if (value is WebExtensionData) {
} else if (value is CustomSelectionAction) {
buffer.putUint8(166);
writeValue(buffer, value.encode());
} else if (value is GeckoSuggestion) {
} else if (value is WebExtensionData) {
buffer.putUint8(167);
writeValue(buffer, value.encode());
} else if (value is TabContent) {
} else if (value is GeckoSuggestion) {
buffer.putUint8(168);
writeValue(buffer, value.encode());
} else if (value is GeckoEngineSettings) {
} else if (value is TabContent) {
buffer.putUint8(169);
writeValue(buffer, value.encode());
} else if (value is AutocompleteResult) {
} else if (value is GeckoEngineSettings) {
buffer.putUint8(170);
writeValue(buffer, value.encode());
} else if (value is AutocompleteResult) {
buffer.putUint8(171);
writeValue(buffer, value.encode());
} else if (value is UnknownHitResult) {
buffer.putUint8(172);
writeValue(buffer, value.encode());
} else if (value is ImageHitResult) {
buffer.putUint8(173);
writeValue(buffer, value.encode());
} else if (value is VideoHitResult) {
buffer.putUint8(174);
writeValue(buffer, value.encode());
} else if (value is AudioHitResult) {
buffer.putUint8(175);
writeValue(buffer, value.encode());
} else if (value is ImageSrcHitResult) {
buffer.putUint8(176);
writeValue(buffer, value.encode());
} else if (value is PhoneHitResult) {
buffer.putUint8(177);
writeValue(buffer, value.encode());
} else if (value is EmailHitResult) {
buffer.putUint8(178);
writeValue(buffer, value.encode());
} else if (value is GeoHitResult) {
buffer.putUint8(179);
writeValue(buffer, value.encode());
} else if (value is DownloadState) {
buffer.putUint8(180);
writeValue(buffer, value.encode());
} else if (value is ShareInternetResourceState) {
buffer.putUint8(181);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
}
@@ -1496,63 +1884,86 @@ class _PigeonCodec extends StandardMessageCodec {
final int? value = readValue(buffer) as int?;
return value == null ? null : WebContentIsolationStrategy.values[value];
case 142:
return TranslationOptions.decode(readValue(buffer)!);
final int? value = readValue(buffer) as int?;
return value == null ? null : DownloadStatus.values[value];
case 143:
return ReaderState.decode(readValue(buffer)!);
return TranslationOptions.decode(readValue(buffer)!);
case 144:
return LastMediaAccessState.decode(readValue(buffer)!);
return ReaderState.decode(readValue(buffer)!);
case 145:
return HistoryMetadataKey.decode(readValue(buffer)!);
return LastMediaAccessState.decode(readValue(buffer)!);
case 146:
return PackageCategoryValue.decode(readValue(buffer)!);
return HistoryMetadataKey.decode(readValue(buffer)!);
case 147:
return ExternalPackage.decode(readValue(buffer)!);
return PackageCategoryValue.decode(readValue(buffer)!);
case 148:
return LoadUrlFlagsValue.decode(readValue(buffer)!);
return ExternalPackage.decode(readValue(buffer)!);
case 149:
return SourceValue.decode(readValue(buffer)!);
return LoadUrlFlagsValue.decode(readValue(buffer)!);
case 150:
return TabState.decode(readValue(buffer)!);
return SourceValue.decode(readValue(buffer)!);
case 151:
return RecoverableTab.decode(readValue(buffer)!);
return TabState.decode(readValue(buffer)!);
case 152:
return RecoverableBrowserState.decode(readValue(buffer)!);
return RecoverableTab.decode(readValue(buffer)!);
case 153:
return IconRequest.decode(readValue(buffer)!);
return RecoverableBrowserState.decode(readValue(buffer)!);
case 154:
return ResourceSize.decode(readValue(buffer)!);
return IconRequest.decode(readValue(buffer)!);
case 155:
return Resource.decode(readValue(buffer)!);
return ResourceSize.decode(readValue(buffer)!);
case 156:
return IconResult.decode(readValue(buffer)!);
return Resource.decode(readValue(buffer)!);
case 157:
return CookiePartitionKey.decode(readValue(buffer)!);
return IconResult.decode(readValue(buffer)!);
case 158:
return Cookie.decode(readValue(buffer)!);
return CookiePartitionKey.decode(readValue(buffer)!);
case 159:
return HistoryItem.decode(readValue(buffer)!);
return Cookie.decode(readValue(buffer)!);
case 160:
return HistoryState.decode(readValue(buffer)!);
return HistoryItem.decode(readValue(buffer)!);
case 161:
return ReaderableState.decode(readValue(buffer)!);
return HistoryState.decode(readValue(buffer)!);
case 162:
return SecurityInfoState.decode(readValue(buffer)!);
return ReaderableState.decode(readValue(buffer)!);
case 163:
return TabContentState.decode(readValue(buffer)!);
return SecurityInfoState.decode(readValue(buffer)!);
case 164:
return FindResultState.decode(readValue(buffer)!);
return TabContentState.decode(readValue(buffer)!);
case 165:
return CustomSelectionAction.decode(readValue(buffer)!);
return FindResultState.decode(readValue(buffer)!);
case 166:
return WebExtensionData.decode(readValue(buffer)!);
return CustomSelectionAction.decode(readValue(buffer)!);
case 167:
return GeckoSuggestion.decode(readValue(buffer)!);
return WebExtensionData.decode(readValue(buffer)!);
case 168:
return TabContent.decode(readValue(buffer)!);
return GeckoSuggestion.decode(readValue(buffer)!);
case 169:
return GeckoEngineSettings.decode(readValue(buffer)!);
return TabContent.decode(readValue(buffer)!);
case 170:
return GeckoEngineSettings.decode(readValue(buffer)!);
case 171:
return AutocompleteResult.decode(readValue(buffer)!);
case 172:
return UnknownHitResult.decode(readValue(buffer)!);
case 173:
return ImageHitResult.decode(readValue(buffer)!);
case 174:
return VideoHitResult.decode(readValue(buffer)!);
case 175:
return AudioHitResult.decode(readValue(buffer)!);
case 176:
return ImageSrcHitResult.decode(readValue(buffer)!);
case 177:
return PhoneHitResult.decode(readValue(buffer)!);
case 178:
return EmailHitResult.decode(readValue(buffer)!);
case 179:
return GeoHitResult.decode(readValue(buffer)!);
case 180:
return DownloadState.decode(readValue(buffer)!);
case 181:
return ShareInternetResourceState.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
}
@@ -2940,6 +3351,8 @@ abstract class GeckoStateEvents {
void onFindResults(int timestamp, String id, List<FindResultState> results);
void onLongPress(int timestamp, String id, HitResult hitResult);
static void setUp(GeckoStateEvents? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) {
messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
{
@@ -3321,6 +3734,37 @@ abstract class GeckoStateEvents {
});
}
}
{
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onLongPress$messageChannelSuffix', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
pigeonVar_channel.setMessageHandler(null);
} else {
pigeonVar_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onLongPress was null.');
final List<Object?> args = (message as List<Object?>?)!;
final int? arg_timestamp = (args[0] as int?);
assert(arg_timestamp != null,
'Argument for dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onLongPress was null, expected non-null int.');
final String? arg_id = (args[1] as String?);
assert(arg_id != null,
'Argument for dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onLongPress was null, expected non-null String.');
final HitResult? arg_hitResult = (args[2] as HitResult?);
assert(arg_hitResult != null,
'Argument for dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onLongPress was null, expected non-null HitResult.');
try {
api.onLongPress(arg_timestamp!, arg_id!, arg_hitResult!);
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
}
});
}
}
}
}
@@ -3960,3 +4404,86 @@ class GeckoDeleteBrowsingDataController {
}
}
}
class GeckoDownloadsApi {
/// Constructor for [GeckoDownloadsApi]. The [binaryMessenger] named argument is
/// available for dependency injection. If it is left null, the default
/// BinaryMessenger will be used which routes to the host platform.
GeckoDownloadsApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
: pigeonVar_binaryMessenger = binaryMessenger,
pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
final BinaryMessenger? pigeonVar_binaryMessenger;
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
final String pigeonVar_messageChannelSuffix;
Future<void> requestDownload(String tabId, DownloadState state) async {
final String pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDownloadsApi.requestDownload$pigeonVar_messageChannelSuffix';
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[tabId, state]);
final List<Object?>? pigeonVar_replyList =
await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else {
return;
}
}
Future<void> copyInternetResource(String tabId, ShareInternetResourceState state) async {
final String pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDownloadsApi.copyInternetResource$pigeonVar_messageChannelSuffix';
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[tabId, state]);
final List<Object?>? pigeonVar_replyList =
await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else {
return;
}
}
Future<void> shareInternetResource(String tabId, ShareInternetResourceState state) async {
final String pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDownloadsApi.shareInternetResource$pigeonVar_messageChannelSuffix';
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[tabId, state]);
final List<Object?>? pigeonVar_replyList =
await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else {
return;
}
}
}
@@ -580,61 +580,147 @@ class AutocompleteResult {
);
}
// /// Represents all the different supported types of data that can be found from long clicking
// /// an element.
// sealed class HitResult {
// final String src;
/// Represents all the different supported types of data that can be found from long clicking
/// an element.
sealed class HitResult {}
// HitResult(this.src);
// }
/// Default type if we're unable to match the type to anything. It may or may not have a src.
class UnknownHitResult extends HitResult {
final String src;
// /// Default type if we're unable to match the type to anything. It may or may not have a src.
// class UnknownHitResult extends HitResult {
// UnknownHitResult(super.src);
// }
UnknownHitResult(this.src);
}
// /// If the HTML element was of type 'HTMLImageElement'.
// class ImageHitResult extends HitResult {
// final String? title;
/// If the HTML element was of type 'HTMLImageElement'.
class ImageHitResult extends HitResult {
final String src;
final String? title;
// ImageHitResult(super.src, {this.title});
// }
ImageHitResult(this.src, {this.title});
}
// /// If the HTML element was of type 'HTMLVideoElement'.
// class VideoHitResult extends HitResult {
// final String? title;
/// If the HTML element was of type 'HTMLVideoElement'.
class VideoHitResult extends HitResult {
final String src;
final String? title;
// VideoHitResult(super.src, {this.title});
// }
VideoHitResult(this.src, {this.title});
}
// /// If the HTML element was of type 'HTMLAudioElement'.
// class AudioHitResult extends HitResult {
// final String? title;
/// If the HTML element was of type 'HTMLAudioElement'.
class AudioHitResult extends HitResult {
final String src;
final String? title;
// AudioHitResult(super.src, {this.title});
// }
AudioHitResult(this.src, {this.title});
}
// /// If the HTML element was of type 'HTMLImageElement' and contained a URI.
// class ImageSrcHitResult extends HitResult {
// final String uri;
/// If the HTML element was of type 'HTMLImageElement' and contained a URI.
class ImageSrcHitResult extends HitResult {
final String src;
final String uri;
// ImageSrcHitResult(super.src, this.uri);
// }
ImageSrcHitResult(this.src, this.uri);
}
// /// The type used if the URI is prepended with 'tel:'.
// class PhoneHitResult extends HitResult {
// PhoneHitResult(super.src);
// }
/// The type used if the URI is prepended with 'tel:'.
class PhoneHitResult extends HitResult {
final String src;
// /// The type used if the URI is prepended with 'mailto:'.
// class EmailHitResult extends HitResult {
// EmailHitResult(super.src);
// }
PhoneHitResult(this.src);
}
// /// The type used if the URI is prepended with 'geo:'.
// class GeoHitResult extends HitResult {
// GeoHitResult(super.src);
// }
/// The type used if the URI is prepended with 'mailto:'.
class EmailHitResult extends HitResult {
final String src;
EmailHitResult(this.src);
}
/// The type used if the URI is prepended with 'geo:'.
class GeoHitResult extends HitResult {
final String src;
GeoHitResult(this.src);
}
/// Status that represents every state that a download can be in.
enum DownloadStatus {
/// Indicates that the download is in the first state after creation but not yet [DOWNLOADING].
initiated,
/// Indicates that an [INITIATED] download is now actively being downloaded.
downloading,
/// Indicates that the download that has been [DOWNLOADING] has been paused.
paused,
/// Indicates that the download that has been [DOWNLOADING] has been cancelled.
cancelled,
/// Indicates that the download that has been [DOWNLOADING] has moved to failed because
/// something unexpected has happened.
failed,
/// Indicates that the [DOWNLOADING] download has been completed.
completed,
}
class DownloadState {
final String url;
final String? fileName;
final String? contentType;
final int? contentLength;
final int? currentBytesCopied;
final DownloadStatus? status;
final String? userAgent;
final String? destinationDirectory;
final String? directoryPath;
final String? referrerUrl;
final bool? skipConfirmation;
final bool? openInApp;
final String? id;
final String? sessionId;
final bool? private;
final int? createdTime;
//final Response? response;
final int? notificationId;
DownloadState(
this.url,
this.fileName,
this.contentType,
this.contentLength,
this.currentBytesCopied,
this.status,
this.userAgent,
this.destinationDirectory,
this.directoryPath,
this.referrerUrl,
this.skipConfirmation,
this.openInApp,
this.id,
this.sessionId,
this.private,
this.createdTime,
this.notificationId,
);
}
class ShareInternetResourceState {
final String url;
final String? contentType;
final bool private;
// final Response? response ;
final String? referrerUrl;
ShareInternetResourceState(
this.url,
this.contentType,
this.private,
this.referrerUrl,
);
}
@ConfigurePigeon(
PigeonOptions(
@@ -933,6 +1019,7 @@ abstract class GeckoStateEvents {
void onThumbnailChange(int timestamp, String id, Uint8List? bytes);
void onFindResults(int timestamp, String id, List<FindResultState> results);
void onLongPress(int timestamp, String id, HitResult hitResult);
}
@HostApi()
@@ -1022,3 +1109,10 @@ abstract class GeckoDeleteBrowsingDataController {
@async
void deleteDownloads();
}
@HostApi()
abstract class GeckoDownloadsApi {
void requestDownload(String tabId, DownloadState state);
void copyInternetResource(String tabId, ShareInternetResourceState state);
void shareInternetResource(String tabId, ShareInternetResourceState state);
}