diff --git a/app/lib/features/geckoview/features/history/domain/providers.dart b/app/lib/features/geckoview/features/history/domain/providers.dart new file mode 100644 index 00000000..0a01ddab --- /dev/null +++ b/app/lib/features/geckoview/features/history/domain/providers.dart @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024-2025 Fabian Freund. + * + * This file is part of WebLibre + * (see https://weblibre.eu). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +import 'package:flutter_mozilla_components/flutter_mozilla_components.dart'; +import 'package:riverpod/riverpod.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'providers.g.dart'; + +@Riverpod() +Future> browsingHistory( + Ref red, { + required DateTime start, + required DateTime end, + required Set types, +}) { + final service = GeckoHistoryService(); + return service.getDetailedVisits(start, end, types); +} diff --git a/app/lib/features/geckoview/features/history/domain/providers.g.dart b/app/lib/features/geckoview/features/history/domain/providers.g.dart new file mode 100644 index 00000000..ed2b7655 --- /dev/null +++ b/app/lib/features/geckoview/features/history/domain/providers.g.dart @@ -0,0 +1,191 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'providers.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$browsingHistoryHash() => r'1f644757c60473f00dd94c9d312647baeaec525a'; + +/// Copied from Dart SDK +class _SystemHash { + _SystemHash._(); + + static int combine(int hash, int value) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + value); + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + return hash ^ (hash >> 6); + } + + static int finish(int hash) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + // ignore: parameter_assignments + hash = hash ^ (hash >> 11); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); + } +} + +/// See also [browsingHistory]. +@ProviderFor(browsingHistory) +const browsingHistoryProvider = BrowsingHistoryFamily(); + +/// See also [browsingHistory]. +class BrowsingHistoryFamily extends Family>> { + /// See also [browsingHistory]. + const BrowsingHistoryFamily(); + + /// See also [browsingHistory]. + BrowsingHistoryProvider call({ + required DateTime start, + required DateTime end, + required Set types, + }) { + return BrowsingHistoryProvider(start: start, end: end, types: types); + } + + @override + BrowsingHistoryProvider getProviderOverride( + covariant BrowsingHistoryProvider provider, + ) { + return call( + start: provider.start, + end: provider.end, + types: provider.types, + ); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'browsingHistoryProvider'; +} + +/// See also [browsingHistory]. +class BrowsingHistoryProvider + extends AutoDisposeFutureProvider> { + /// See also [browsingHistory]. + BrowsingHistoryProvider({ + required DateTime start, + required DateTime end, + required Set types, + }) : this._internal( + (ref) => browsingHistory( + ref as BrowsingHistoryRef, + start: start, + end: end, + types: types, + ), + from: browsingHistoryProvider, + name: r'browsingHistoryProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$browsingHistoryHash, + dependencies: BrowsingHistoryFamily._dependencies, + allTransitiveDependencies: + BrowsingHistoryFamily._allTransitiveDependencies, + start: start, + end: end, + types: types, + ); + + BrowsingHistoryProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.start, + required this.end, + required this.types, + }) : super.internal(); + + final DateTime start; + final DateTime end; + final Set types; + + @override + Override overrideWith( + FutureOr> Function(BrowsingHistoryRef provider) create, + ) { + return ProviderOverride( + origin: this, + override: BrowsingHistoryProvider._internal( + (ref) => create(ref as BrowsingHistoryRef), + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + start: start, + end: end, + types: types, + ), + ); + } + + @override + AutoDisposeFutureProviderElement> createElement() { + return _BrowsingHistoryProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is BrowsingHistoryProvider && + other.start == start && + other.end == end && + other.types == types; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, start.hashCode); + hash = _SystemHash.combine(hash, end.hashCode); + hash = _SystemHash.combine(hash, types.hashCode); + + return _SystemHash.finish(hash); + } +} + +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element +mixin BrowsingHistoryRef on AutoDisposeFutureProviderRef> { + /// The parameter `start` of this provider. + DateTime get start; + + /// The parameter `end` of this provider. + DateTime get end; + + /// The parameter `types` of this provider. + Set get types; +} + +class _BrowsingHistoryProviderElement + extends AutoDisposeFutureProviderElement> + with BrowsingHistoryRef { + _BrowsingHistoryProviderElement(super.provider); + + @override + DateTime get start => (origin as BrowsingHistoryProvider).start; + @override + DateTime get end => (origin as BrowsingHistoryProvider).end; + @override + Set get types => (origin as BrowsingHistoryProvider).types; +} + +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/app/lib/features/geckoview/features/history/presentation/screens/history.dart b/app/lib/features/geckoview/features/history/presentation/screens/history.dart new file mode 100644 index 00000000..93c7e991 --- /dev/null +++ b/app/lib/features/geckoview/features/history/presentation/screens/history.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_mozilla_components/flutter_mozilla_components.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:weblibre/features/geckoview/features/history/domain/providers.dart'; + +class HistoryScreen extends HookConsumerWidget { + const HistoryScreen({super.key}); + @override + Widget build(BuildContext context, WidgetRef ref) { + final history = ref.watch( + browsingHistoryProvider( + start: DateTime(0), + end: DateTime.now(), + types: { + VisitType.link, + VisitType.redirectPermanent, + VisitType.redirectTemporary, + VisitType.typed, + }, + ), + ); + } +} diff --git a/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/api/GeckoBrowserApiImpl.kt b/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/api/GeckoBrowserApiImpl.kt index f2f9b8ae..2c9f4c9c 100644 --- a/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/api/GeckoBrowserApiImpl.kt +++ b/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/api/GeckoBrowserApiImpl.kt @@ -27,6 +27,7 @@ import eu.weblibre.flutter_mozilla_components.pigeons.GeckoDeleteBrowsingDataCon import eu.weblibre.flutter_mozilla_components.pigeons.GeckoDownloadsApi import eu.weblibre.flutter_mozilla_components.pigeons.GeckoEngineSettingsApi import eu.weblibre.flutter_mozilla_components.pigeons.GeckoFindApi +import eu.weblibre.flutter_mozilla_components.pigeons.GeckoHistoryApi import eu.weblibre.flutter_mozilla_components.pigeons.GeckoIconsApi import eu.weblibre.flutter_mozilla_components.pigeons.GeckoLogging import eu.weblibre.flutter_mozilla_components.pigeons.GeckoMlApi @@ -214,6 +215,7 @@ class GeckoBrowserApiImpl : GeckoBrowserApi { GeckoDeleteBrowsingDataController.setUp(_flutterPluginBinding.binaryMessenger, GeckoDeleteBrowsingDataControllerImpl()) GeckoDownloadsApi.setUp(_flutterPluginBinding.binaryMessenger, GeckoDownloadsApiImpl()) GeckoBrowserExtensionApi.setUp(_flutterPluginBinding.binaryMessenger, GeckoBrowserExtensionApiImpl()) + GeckoHistoryApi.setUp(_flutterPluginBinding.binaryMessenger, GeckoHistoryApiImpl()) ReaderViewEvents.setUp( _flutterPluginBinding.binaryMessenger, diff --git a/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/api/GeckoHistoryApiImpl.kt b/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/api/GeckoHistoryApiImpl.kt new file mode 100644 index 00000000..269507c0 --- /dev/null +++ b/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/api/GeckoHistoryApiImpl.kt @@ -0,0 +1,72 @@ +package eu.weblibre.flutter_mozilla_components.api + +import eu.weblibre.flutter_mozilla_components.GlobalComponents +import eu.weblibre.flutter_mozilla_components.pigeons.AutocompleteResult +import eu.weblibre.flutter_mozilla_components.pigeons.GeckoHistoryApi +import eu.weblibre.flutter_mozilla_components.pigeons.VisitInfo +import eu.weblibre.flutter_mozilla_components.pigeons.VisitType +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +class GeckoHistoryApiImpl() : GeckoHistoryApi { + companion object { + private val coroutineScope = CoroutineScope(Dispatchers.Main + SupervisorJob()) + } + + private val components by lazy { + requireNotNull(GlobalComponents.components) { "Components not initialized" } + } + + override fun getDetailedVisits( + startMillis: Long, + endMillis: Long, + excludeTypes: List, + callback: (Result>) -> Unit + ) { + coroutineScope.launch { + withContext(Dispatchers.Main) { + val visits = components.core.historyStorage.getDetailedVisits( + startMillis, + endMillis, + excludeTypes.map { + when (it) { + VisitType.LINK -> mozilla.components.concept.storage.VisitType.LINK + VisitType.TYPED -> mozilla.components.concept.storage.VisitType.TYPED + VisitType.BOOKMARK -> mozilla.components.concept.storage.VisitType.BOOKMARK + VisitType.EMBED -> mozilla.components.concept.storage.VisitType.EMBED + VisitType.REDIRECT_PERMANENT -> mozilla.components.concept.storage.VisitType.REDIRECT_PERMANENT + VisitType.REDIRECT_TEMPORARY -> mozilla.components.concept.storage.VisitType.REDIRECT_TEMPORARY + VisitType.DOWNLOAD -> mozilla.components.concept.storage.VisitType.DOWNLOAD + VisitType.FRAMED_LINK -> mozilla.components.concept.storage.VisitType.FRAMED_LINK + VisitType.RELOAD -> mozilla.components.concept.storage.VisitType.RELOAD + } + }) + + callback(Result.success(visits.map { + VisitInfo( + url = it.url, + title = it.title, + visitTime = it.visitTime, + visitType = when (it.visitType) { + mozilla.components.concept.storage.VisitType.LINK -> VisitType.LINK + mozilla.components.concept.storage.VisitType.TYPED -> VisitType.TYPED + mozilla.components.concept.storage.VisitType.BOOKMARK -> VisitType.BOOKMARK + mozilla.components.concept.storage.VisitType.EMBED -> VisitType.EMBED + mozilla.components.concept.storage.VisitType.REDIRECT_PERMANENT -> VisitType.REDIRECT_PERMANENT + mozilla.components.concept.storage.VisitType.REDIRECT_TEMPORARY -> VisitType.REDIRECT_TEMPORARY + mozilla.components.concept.storage.VisitType.DOWNLOAD -> VisitType.DOWNLOAD + mozilla.components.concept.storage.VisitType.FRAMED_LINK -> VisitType.FRAMED_LINK + mozilla.components.concept.storage.VisitType.RELOAD -> VisitType.RELOAD + }, + previewImageUrl = it.previewImageUrl, + isRemote = it.isRemote + ) + } + )) + } + } + } +} \ No newline at end of file diff --git a/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/pigeons/Gecko.g.kt b/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/pigeons/Gecko.g.kt index 8429e87d..7f891028 100644 --- a/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/pigeons/Gecko.g.kt +++ b/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/pigeons/Gecko.g.kt @@ -166,6 +166,24 @@ enum class CookieSameSiteStatus(val raw: Int) { } } +enum class VisitType(val raw: Int) { + LINK(0), + TYPED(1), + BOOKMARK(2), + EMBED(3), + REDIRECT_PERMANENT(4), + REDIRECT_TEMPORARY(5), + DOWNLOAD(6), + FRAMED_LINK(7), + RELOAD(8); + + companion object { + fun ofRaw(raw: Int): VisitType? { + return values().firstOrNull { it.raw == raw } + } + } +} + enum class SelectionPattern(val raw: Int) { PHONE(0), EMAIL(1); @@ -1102,6 +1120,49 @@ data class Cookie ( override fun hashCode(): Int = toList().hashCode() } +/** Generated class from Pigeon that represents data sent in messages. */ +data class VisitInfo ( + val url: String, + val title: String? = null, + val visitTime: Long, + val visitType: VisitType, + val previewImageUrl: String? = null, + val isRemote: Boolean +) + { + companion object { + fun fromList(pigeonVar_list: List): VisitInfo { + val url = pigeonVar_list[0] as String + val title = pigeonVar_list[1] as String? + val visitTime = pigeonVar_list[2] as Long + val visitType = pigeonVar_list[3] as VisitType + val previewImageUrl = pigeonVar_list[4] as String? + val isRemote = pigeonVar_list[5] as Boolean + return VisitInfo(url, title, visitTime, visitType, previewImageUrl, isRemote) + } + } + fun toList(): List { + return listOf( + url, + title, + visitTime, + visitType, + previewImageUrl, + isRemote, + ) + } + override fun equals(other: Any?): Boolean { + if (other !is VisitInfo) { + return false + } + if (this === other) { + return true + } + return GeckoPigeonUtils.deepEquals(toList(), other.toList()) } + + override fun hashCode(): Int = toList().hashCode() +} + /** Generated class from Pigeon that represents data sent in messages. */ data class HistoryItem ( val url: String, @@ -2051,260 +2112,270 @@ private open class GeckoPigeonCodec : StandardMessageCodec() { } 134.toByte() -> { return (readValue(buffer) as Long?)?.let { - SelectionPattern.ofRaw(it.toInt()) + VisitType.ofRaw(it.toInt()) } } 135.toByte() -> { return (readValue(buffer) as Long?)?.let { - WebExtensionActionType.ofRaw(it.toInt()) + SelectionPattern.ofRaw(it.toInt()) } } 136.toByte() -> { return (readValue(buffer) as Long?)?.let { - GeckoSuggestionType.ofRaw(it.toInt()) + WebExtensionActionType.ofRaw(it.toInt()) } } 137.toByte() -> { return (readValue(buffer) as Long?)?.let { - TrackingProtectionPolicy.ofRaw(it.toInt()) + GeckoSuggestionType.ofRaw(it.toInt()) } } 138.toByte() -> { return (readValue(buffer) as Long?)?.let { - HttpsOnlyMode.ofRaw(it.toInt()) + TrackingProtectionPolicy.ofRaw(it.toInt()) } } 139.toByte() -> { return (readValue(buffer) as Long?)?.let { - QueryParameterStripping.ofRaw(it.toInt()) + HttpsOnlyMode.ofRaw(it.toInt()) } } 140.toByte() -> { return (readValue(buffer) as Long?)?.let { - BounceTrackingProtectionMode.ofRaw(it.toInt()) + QueryParameterStripping.ofRaw(it.toInt()) } } 141.toByte() -> { return (readValue(buffer) as Long?)?.let { - ColorScheme.ofRaw(it.toInt()) + BounceTrackingProtectionMode.ofRaw(it.toInt()) } } 142.toByte() -> { return (readValue(buffer) as Long?)?.let { - CookieBannerHandlingMode.ofRaw(it.toInt()) + ColorScheme.ofRaw(it.toInt()) } } 143.toByte() -> { return (readValue(buffer) as Long?)?.let { - WebContentIsolationStrategy.ofRaw(it.toInt()) + CookieBannerHandlingMode.ofRaw(it.toInt()) } } 144.toByte() -> { return (readValue(buffer) as Long?)?.let { - DownloadStatus.ofRaw(it.toInt()) + WebContentIsolationStrategy.ofRaw(it.toInt()) } } 145.toByte() -> { return (readValue(buffer) as Long?)?.let { - LogLevel.ofRaw(it.toInt()) + DownloadStatus.ofRaw(it.toInt()) } } 146.toByte() -> { - return (readValue(buffer) as? List)?.let { - TranslationOptions.fromList(it) + return (readValue(buffer) as Long?)?.let { + LogLevel.ofRaw(it.toInt()) } } 147.toByte() -> { return (readValue(buffer) as? List)?.let { - ReaderState.fromList(it) + TranslationOptions.fromList(it) } } 148.toByte() -> { return (readValue(buffer) as? List)?.let { - LastMediaAccessState.fromList(it) + ReaderState.fromList(it) } } 149.toByte() -> { return (readValue(buffer) as? List)?.let { - HistoryMetadataKey.fromList(it) + LastMediaAccessState.fromList(it) } } 150.toByte() -> { return (readValue(buffer) as? List)?.let { - PackageCategoryValue.fromList(it) + HistoryMetadataKey.fromList(it) } } 151.toByte() -> { return (readValue(buffer) as? List)?.let { - ExternalPackage.fromList(it) + PackageCategoryValue.fromList(it) } } 152.toByte() -> { return (readValue(buffer) as? List)?.let { - LoadUrlFlagsValue.fromList(it) + ExternalPackage.fromList(it) } } 153.toByte() -> { return (readValue(buffer) as? List)?.let { - SourceValue.fromList(it) + LoadUrlFlagsValue.fromList(it) } } 154.toByte() -> { return (readValue(buffer) as? List)?.let { - TabState.fromList(it) + SourceValue.fromList(it) } } 155.toByte() -> { return (readValue(buffer) as? List)?.let { - RecoverableTab.fromList(it) + TabState.fromList(it) } } 156.toByte() -> { return (readValue(buffer) as? List)?.let { - RecoverableBrowserState.fromList(it) + RecoverableTab.fromList(it) } } 157.toByte() -> { return (readValue(buffer) as? List)?.let { - IconRequest.fromList(it) + RecoverableBrowserState.fromList(it) } } 158.toByte() -> { return (readValue(buffer) as? List)?.let { - ResourceSize.fromList(it) + IconRequest.fromList(it) } } 159.toByte() -> { return (readValue(buffer) as? List)?.let { - Resource.fromList(it) + ResourceSize.fromList(it) } } 160.toByte() -> { return (readValue(buffer) as? List)?.let { - IconResult.fromList(it) + Resource.fromList(it) } } 161.toByte() -> { return (readValue(buffer) as? List)?.let { - CookiePartitionKey.fromList(it) + IconResult.fromList(it) } } 162.toByte() -> { return (readValue(buffer) as? List)?.let { - Cookie.fromList(it) + CookiePartitionKey.fromList(it) } } 163.toByte() -> { return (readValue(buffer) as? List)?.let { - HistoryItem.fromList(it) + Cookie.fromList(it) } } 164.toByte() -> { return (readValue(buffer) as? List)?.let { - HistoryState.fromList(it) + VisitInfo.fromList(it) } } 165.toByte() -> { return (readValue(buffer) as? List)?.let { - ReaderableState.fromList(it) + HistoryItem.fromList(it) } } 166.toByte() -> { return (readValue(buffer) as? List)?.let { - SecurityInfoState.fromList(it) + HistoryState.fromList(it) } } 167.toByte() -> { return (readValue(buffer) as? List)?.let { - TabContentState.fromList(it) + ReaderableState.fromList(it) } } 168.toByte() -> { return (readValue(buffer) as? List)?.let { - FindResultState.fromList(it) + SecurityInfoState.fromList(it) } } 169.toByte() -> { return (readValue(buffer) as? List)?.let { - CustomSelectionAction.fromList(it) + TabContentState.fromList(it) } } 170.toByte() -> { return (readValue(buffer) as? List)?.let { - WebExtensionData.fromList(it) + FindResultState.fromList(it) } } 171.toByte() -> { return (readValue(buffer) as? List)?.let { - GeckoSuggestion.fromList(it) + CustomSelectionAction.fromList(it) } } 172.toByte() -> { return (readValue(buffer) as? List)?.let { - TabContent.fromList(it) + WebExtensionData.fromList(it) } } 173.toByte() -> { return (readValue(buffer) as? List)?.let { - ContentBlocking.fromList(it) + GeckoSuggestion.fromList(it) } } 174.toByte() -> { return (readValue(buffer) as? List)?.let { - GeckoEngineSettings.fromList(it) + TabContent.fromList(it) } } 175.toByte() -> { return (readValue(buffer) as? List)?.let { - AutocompleteResult.fromList(it) + ContentBlocking.fromList(it) } } 176.toByte() -> { return (readValue(buffer) as? List)?.let { - UnknownHitResult.fromList(it) + GeckoEngineSettings.fromList(it) } } 177.toByte() -> { return (readValue(buffer) as? List)?.let { - ImageHitResult.fromList(it) + AutocompleteResult.fromList(it) } } 178.toByte() -> { return (readValue(buffer) as? List)?.let { - VideoHitResult.fromList(it) + UnknownHitResult.fromList(it) } } 179.toByte() -> { return (readValue(buffer) as? List)?.let { - AudioHitResult.fromList(it) + ImageHitResult.fromList(it) } } 180.toByte() -> { return (readValue(buffer) as? List)?.let { - ImageSrcHitResult.fromList(it) + VideoHitResult.fromList(it) } } 181.toByte() -> { return (readValue(buffer) as? List)?.let { - PhoneHitResult.fromList(it) + AudioHitResult.fromList(it) } } 182.toByte() -> { return (readValue(buffer) as? List)?.let { - EmailHitResult.fromList(it) + ImageSrcHitResult.fromList(it) } } 183.toByte() -> { return (readValue(buffer) as? List)?.let { - GeoHitResult.fromList(it) + PhoneHitResult.fromList(it) } } 184.toByte() -> { return (readValue(buffer) as? List)?.let { - DownloadState.fromList(it) + EmailHitResult.fromList(it) } } 185.toByte() -> { + return (readValue(buffer) as? List)?.let { + GeoHitResult.fromList(it) + } + } + 186.toByte() -> { + return (readValue(buffer) as? List)?.let { + DownloadState.fromList(it) + } + } + 187.toByte() -> { return (readValue(buffer) as? List)?.let { ShareInternetResourceState.fromList(it) } @@ -2334,214 +2405,222 @@ private open class GeckoPigeonCodec : StandardMessageCodec() { stream.write(133) writeValue(stream, value.raw) } - is SelectionPattern -> { + is VisitType -> { stream.write(134) writeValue(stream, value.raw) } - is WebExtensionActionType -> { + is SelectionPattern -> { stream.write(135) writeValue(stream, value.raw) } - is GeckoSuggestionType -> { + is WebExtensionActionType -> { stream.write(136) writeValue(stream, value.raw) } - is TrackingProtectionPolicy -> { + is GeckoSuggestionType -> { stream.write(137) writeValue(stream, value.raw) } - is HttpsOnlyMode -> { + is TrackingProtectionPolicy -> { stream.write(138) writeValue(stream, value.raw) } - is QueryParameterStripping -> { + is HttpsOnlyMode -> { stream.write(139) writeValue(stream, value.raw) } - is BounceTrackingProtectionMode -> { + is QueryParameterStripping -> { stream.write(140) writeValue(stream, value.raw) } - is ColorScheme -> { + is BounceTrackingProtectionMode -> { stream.write(141) writeValue(stream, value.raw) } - is CookieBannerHandlingMode -> { + is ColorScheme -> { stream.write(142) writeValue(stream, value.raw) } - is WebContentIsolationStrategy -> { + is CookieBannerHandlingMode -> { stream.write(143) writeValue(stream, value.raw) } - is DownloadStatus -> { + is WebContentIsolationStrategy -> { stream.write(144) writeValue(stream, value.raw) } - is LogLevel -> { + is DownloadStatus -> { stream.write(145) writeValue(stream, value.raw) } - is TranslationOptions -> { + is LogLevel -> { stream.write(146) - writeValue(stream, value.toList()) + writeValue(stream, value.raw) } - is ReaderState -> { + is TranslationOptions -> { stream.write(147) writeValue(stream, value.toList()) } - is LastMediaAccessState -> { + is ReaderState -> { stream.write(148) writeValue(stream, value.toList()) } - is HistoryMetadataKey -> { + is LastMediaAccessState -> { stream.write(149) writeValue(stream, value.toList()) } - is PackageCategoryValue -> { + is HistoryMetadataKey -> { stream.write(150) writeValue(stream, value.toList()) } - is ExternalPackage -> { + is PackageCategoryValue -> { stream.write(151) writeValue(stream, value.toList()) } - is LoadUrlFlagsValue -> { + is ExternalPackage -> { stream.write(152) writeValue(stream, value.toList()) } - is SourceValue -> { + is LoadUrlFlagsValue -> { stream.write(153) writeValue(stream, value.toList()) } - is TabState -> { + is SourceValue -> { stream.write(154) writeValue(stream, value.toList()) } - is RecoverableTab -> { + is TabState -> { stream.write(155) writeValue(stream, value.toList()) } - is RecoverableBrowserState -> { + is RecoverableTab -> { stream.write(156) writeValue(stream, value.toList()) } - is IconRequest -> { + is RecoverableBrowserState -> { stream.write(157) writeValue(stream, value.toList()) } - is ResourceSize -> { + is IconRequest -> { stream.write(158) writeValue(stream, value.toList()) } - is Resource -> { + is ResourceSize -> { stream.write(159) writeValue(stream, value.toList()) } - is IconResult -> { + is Resource -> { stream.write(160) writeValue(stream, value.toList()) } - is CookiePartitionKey -> { + is IconResult -> { stream.write(161) writeValue(stream, value.toList()) } - is Cookie -> { + is CookiePartitionKey -> { stream.write(162) writeValue(stream, value.toList()) } - is HistoryItem -> { + is Cookie -> { stream.write(163) writeValue(stream, value.toList()) } - is HistoryState -> { + is VisitInfo -> { stream.write(164) writeValue(stream, value.toList()) } - is ReaderableState -> { + is HistoryItem -> { stream.write(165) writeValue(stream, value.toList()) } - is SecurityInfoState -> { + is HistoryState -> { stream.write(166) writeValue(stream, value.toList()) } - is TabContentState -> { + is ReaderableState -> { stream.write(167) writeValue(stream, value.toList()) } - is FindResultState -> { + is SecurityInfoState -> { stream.write(168) writeValue(stream, value.toList()) } - is CustomSelectionAction -> { + is TabContentState -> { stream.write(169) writeValue(stream, value.toList()) } - is WebExtensionData -> { + is FindResultState -> { stream.write(170) writeValue(stream, value.toList()) } - is GeckoSuggestion -> { + is CustomSelectionAction -> { stream.write(171) writeValue(stream, value.toList()) } - is TabContent -> { + is WebExtensionData -> { stream.write(172) writeValue(stream, value.toList()) } - is ContentBlocking -> { + is GeckoSuggestion -> { stream.write(173) writeValue(stream, value.toList()) } - is GeckoEngineSettings -> { + is TabContent -> { stream.write(174) writeValue(stream, value.toList()) } - is AutocompleteResult -> { + is ContentBlocking -> { stream.write(175) writeValue(stream, value.toList()) } - is UnknownHitResult -> { + is GeckoEngineSettings -> { stream.write(176) writeValue(stream, value.toList()) } - is ImageHitResult -> { + is AutocompleteResult -> { stream.write(177) writeValue(stream, value.toList()) } - is VideoHitResult -> { + is UnknownHitResult -> { stream.write(178) writeValue(stream, value.toList()) } - is AudioHitResult -> { + is ImageHitResult -> { stream.write(179) writeValue(stream, value.toList()) } - is ImageSrcHitResult -> { + is VideoHitResult -> { stream.write(180) writeValue(stream, value.toList()) } - is PhoneHitResult -> { + is AudioHitResult -> { stream.write(181) writeValue(stream, value.toList()) } - is EmailHitResult -> { + is ImageSrcHitResult -> { stream.write(182) writeValue(stream, value.toList()) } - is GeoHitResult -> { + is PhoneHitResult -> { stream.write(183) writeValue(stream, value.toList()) } - is DownloadState -> { + is EmailHitResult -> { stream.write(184) writeValue(stream, value.toList()) } - is ShareInternetResourceState -> { + is GeoHitResult -> { stream.write(185) writeValue(stream, value.toList()) } + is DownloadState -> { + stream.write(186) + writeValue(stream, value.toList()) + } + is ShareInternetResourceState -> { + stream.write(187) + writeValue(stream, value.toList()) + } else -> super.writeValue(stream, value) } } @@ -4650,6 +4729,44 @@ interface GeckoDeleteBrowsingDataController { } } /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ +interface GeckoHistoryApi { + fun getDetailedVisits(startMillis: Long, endMillis: Long, excludeTypes: List, callback: (Result>) -> Unit) + + companion object { + /** The codec used by GeckoHistoryApi. */ + val codec: MessageCodec by lazy { + GeckoPigeonCodec() + } + /** Sets up an instance of `GeckoHistoryApi` to handle messages through the `binaryMessenger`. */ + @JvmOverloads + fun setUp(binaryMessenger: BinaryMessenger, api: GeckoHistoryApi?, messageChannelSuffix: String = "") { + val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.getDetailedVisits$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val startMillisArg = args[0] as Long + val endMillisArg = args[1] as Long + val excludeTypesArg = args[2] as List + api.getDetailedVisits(startMillisArg, endMillisArg, excludeTypesArg) { result: Result> -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(GeckoPigeonUtils.wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(GeckoPigeonUtils.wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + } + } +} +/** 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) diff --git a/packages/flutter_mozilla_components/lib/flutter_mozilla_components.dart b/packages/flutter_mozilla_components/lib/flutter_mozilla_components.dart index 7052636a..4eb58b22 100644 --- a/packages/flutter_mozilla_components/lib/flutter_mozilla_components.dart +++ b/packages/flutter_mozilla_components/lib/flutter_mozilla_components.dart @@ -17,6 +17,7 @@ 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'; +export 'src/domain/services/gecko_history.dart'; export 'src/domain/services/gecko_icon.dart'; export 'src/domain/services/gecko_logging.dart'; export 'src/domain/services/gecko_ml.dart'; @@ -59,6 +60,8 @@ export 'src/pigeons/gecko.g.dart' TrackingProtectionPolicy, UnknownHitResult, VideoHitResult, + VisitInfo, + VisitType, WebContentIsolationStrategy, WebExtensionActionType, WebExtensionData; diff --git a/packages/flutter_mozilla_components/lib/src/domain/services/gecko_history.dart b/packages/flutter_mozilla_components/lib/src/domain/services/gecko_history.dart new file mode 100644 index 00000000..01f1a383 --- /dev/null +++ b/packages/flutter_mozilla_components/lib/src/domain/services/gecko_history.dart @@ -0,0 +1,27 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import 'package:flutter_mozilla_components/src/pigeons/gecko.g.dart'; + +final _apiInstance = GeckoHistoryApi(); + +class GeckoHistoryService { + final GeckoHistoryApi _api; + + GeckoHistoryService({GeckoHistoryApi? api}) : _api = api ?? _apiInstance; + + Future> getDetailedVisits( + DateTime start, + DateTime end, + Set types, + ) { + return _api.getDetailedVisits( + start.millisecondsSinceEpoch, + end.millisecondsSinceEpoch, + VisitType.values.toSet().difference(types).toList(), + ); + } +} diff --git a/packages/flutter_mozilla_components/lib/src/pigeons/gecko.g.dart b/packages/flutter_mozilla_components/lib/src/pigeons/gecko.g.dart index a4a2ff0f..e734c3d9 100644 --- a/packages/flutter_mozilla_components/lib/src/pigeons/gecko.g.dart +++ b/packages/flutter_mozilla_components/lib/src/pigeons/gecko.g.dart @@ -92,6 +92,18 @@ enum CookieSameSiteStatus { unspecified, } +enum VisitType { + link, + typed, + bookmark, + embed, + redirectPermanent, + redirectTemporary, + download, + framedLink, + reload, +} + enum SelectionPattern { phone, email, @@ -1222,6 +1234,72 @@ class Cookie { ; } +class VisitInfo { + VisitInfo({ + required this.url, + this.title, + required this.visitTime, + required this.visitType, + this.previewImageUrl, + required this.isRemote, + }); + + String url; + + String? title; + + int visitTime; + + VisitType visitType; + + String? previewImageUrl; + + bool isRemote; + + List _toList() { + return [ + url, + title, + visitTime, + visitType, + previewImageUrl, + isRemote, + ]; + } + + Object encode() { + return _toList(); } + + static VisitInfo decode(Object result) { + result as List; + return VisitInfo( + url: result[0]! as String, + title: result[1] as String?, + visitTime: result[2]! as int, + visitType: result[3]! as VisitType, + previewImageUrl: result[4] as String?, + isRemote: result[5]! as bool, + ); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! VisitInfo || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(encode(), other.encode()); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => Object.hashAll(_toList()) +; +} + class HistoryItem { HistoryItem({ required this.url, @@ -2589,162 +2667,168 @@ class _PigeonCodec extends StandardMessageCodec { } else if (value is CookieSameSiteStatus) { buffer.putUint8(133); writeValue(buffer, value.index); - } else if (value is SelectionPattern) { + } else if (value is VisitType) { buffer.putUint8(134); writeValue(buffer, value.index); - } else if (value is WebExtensionActionType) { + } else if (value is SelectionPattern) { buffer.putUint8(135); writeValue(buffer, value.index); - } else if (value is GeckoSuggestionType) { + } else if (value is WebExtensionActionType) { buffer.putUint8(136); writeValue(buffer, value.index); - } else if (value is TrackingProtectionPolicy) { + } else if (value is GeckoSuggestionType) { buffer.putUint8(137); writeValue(buffer, value.index); - } else if (value is HttpsOnlyMode) { + } else if (value is TrackingProtectionPolicy) { buffer.putUint8(138); writeValue(buffer, value.index); - } else if (value is QueryParameterStripping) { + } else if (value is HttpsOnlyMode) { buffer.putUint8(139); writeValue(buffer, value.index); - } else if (value is BounceTrackingProtectionMode) { + } else if (value is QueryParameterStripping) { buffer.putUint8(140); writeValue(buffer, value.index); - } else if (value is ColorScheme) { + } else if (value is BounceTrackingProtectionMode) { buffer.putUint8(141); writeValue(buffer, value.index); - } else if (value is CookieBannerHandlingMode) { + } else if (value is ColorScheme) { buffer.putUint8(142); writeValue(buffer, value.index); - } else if (value is WebContentIsolationStrategy) { + } else if (value is CookieBannerHandlingMode) { buffer.putUint8(143); writeValue(buffer, value.index); - } else if (value is DownloadStatus) { + } else if (value is WebContentIsolationStrategy) { buffer.putUint8(144); writeValue(buffer, value.index); - } else if (value is LogLevel) { + } else if (value is DownloadStatus) { buffer.putUint8(145); writeValue(buffer, value.index); - } else if (value is TranslationOptions) { + } else if (value is LogLevel) { buffer.putUint8(146); - writeValue(buffer, value.encode()); - } else if (value is ReaderState) { + writeValue(buffer, value.index); + } else if (value is TranslationOptions) { buffer.putUint8(147); writeValue(buffer, value.encode()); - } else if (value is LastMediaAccessState) { + } else if (value is ReaderState) { buffer.putUint8(148); writeValue(buffer, value.encode()); - } else if (value is HistoryMetadataKey) { + } else if (value is LastMediaAccessState) { buffer.putUint8(149); writeValue(buffer, value.encode()); - } else if (value is PackageCategoryValue) { + } else if (value is HistoryMetadataKey) { buffer.putUint8(150); writeValue(buffer, value.encode()); - } else if (value is ExternalPackage) { + } else if (value is PackageCategoryValue) { buffer.putUint8(151); writeValue(buffer, value.encode()); - } else if (value is LoadUrlFlagsValue) { + } else if (value is ExternalPackage) { buffer.putUint8(152); writeValue(buffer, value.encode()); - } else if (value is SourceValue) { + } else if (value is LoadUrlFlagsValue) { buffer.putUint8(153); writeValue(buffer, value.encode()); - } else if (value is TabState) { + } else if (value is SourceValue) { buffer.putUint8(154); writeValue(buffer, value.encode()); - } else if (value is RecoverableTab) { + } else if (value is TabState) { buffer.putUint8(155); writeValue(buffer, value.encode()); - } else if (value is RecoverableBrowserState) { + } else if (value is RecoverableTab) { buffer.putUint8(156); writeValue(buffer, value.encode()); - } else if (value is IconRequest) { + } else if (value is RecoverableBrowserState) { buffer.putUint8(157); writeValue(buffer, value.encode()); - } else if (value is ResourceSize) { + } else if (value is IconRequest) { buffer.putUint8(158); writeValue(buffer, value.encode()); - } else if (value is Resource) { + } else if (value is ResourceSize) { buffer.putUint8(159); writeValue(buffer, value.encode()); - } else if (value is IconResult) { + } else if (value is Resource) { buffer.putUint8(160); writeValue(buffer, value.encode()); - } else if (value is CookiePartitionKey) { + } else if (value is IconResult) { buffer.putUint8(161); writeValue(buffer, value.encode()); - } else if (value is Cookie) { + } else if (value is CookiePartitionKey) { buffer.putUint8(162); writeValue(buffer, value.encode()); - } else if (value is HistoryItem) { + } else if (value is Cookie) { buffer.putUint8(163); writeValue(buffer, value.encode()); - } else if (value is HistoryState) { + } else if (value is VisitInfo) { buffer.putUint8(164); writeValue(buffer, value.encode()); - } else if (value is ReaderableState) { + } else if (value is HistoryItem) { buffer.putUint8(165); writeValue(buffer, value.encode()); - } else if (value is SecurityInfoState) { + } else if (value is HistoryState) { buffer.putUint8(166); writeValue(buffer, value.encode()); - } else if (value is TabContentState) { + } else if (value is ReaderableState) { buffer.putUint8(167); writeValue(buffer, value.encode()); - } else if (value is FindResultState) { + } else if (value is SecurityInfoState) { buffer.putUint8(168); writeValue(buffer, value.encode()); - } else if (value is CustomSelectionAction) { + } else if (value is TabContentState) { buffer.putUint8(169); writeValue(buffer, value.encode()); - } else if (value is WebExtensionData) { + } else if (value is FindResultState) { buffer.putUint8(170); writeValue(buffer, value.encode()); - } else if (value is GeckoSuggestion) { + } else if (value is CustomSelectionAction) { buffer.putUint8(171); writeValue(buffer, value.encode()); - } else if (value is TabContent) { + } else if (value is WebExtensionData) { buffer.putUint8(172); writeValue(buffer, value.encode()); - } else if (value is ContentBlocking) { + } else if (value is GeckoSuggestion) { buffer.putUint8(173); writeValue(buffer, value.encode()); - } else if (value is GeckoEngineSettings) { + } else if (value is TabContent) { buffer.putUint8(174); writeValue(buffer, value.encode()); - } else if (value is AutocompleteResult) { + } else if (value is ContentBlocking) { buffer.putUint8(175); writeValue(buffer, value.encode()); - } else if (value is UnknownHitResult) { + } else if (value is GeckoEngineSettings) { buffer.putUint8(176); writeValue(buffer, value.encode()); - } else if (value is ImageHitResult) { + } else if (value is AutocompleteResult) { buffer.putUint8(177); writeValue(buffer, value.encode()); - } else if (value is VideoHitResult) { + } else if (value is UnknownHitResult) { buffer.putUint8(178); writeValue(buffer, value.encode()); - } else if (value is AudioHitResult) { + } else if (value is ImageHitResult) { buffer.putUint8(179); writeValue(buffer, value.encode()); - } else if (value is ImageSrcHitResult) { + } else if (value is VideoHitResult) { buffer.putUint8(180); writeValue(buffer, value.encode()); - } else if (value is PhoneHitResult) { + } else if (value is AudioHitResult) { buffer.putUint8(181); writeValue(buffer, value.encode()); - } else if (value is EmailHitResult) { + } else if (value is ImageSrcHitResult) { buffer.putUint8(182); writeValue(buffer, value.encode()); - } else if (value is GeoHitResult) { + } else if (value is PhoneHitResult) { buffer.putUint8(183); writeValue(buffer, value.encode()); - } else if (value is DownloadState) { + } else if (value is EmailHitResult) { buffer.putUint8(184); writeValue(buffer, value.encode()); - } else if (value is ShareInternetResourceState) { + } else if (value is GeoHitResult) { buffer.putUint8(185); writeValue(buffer, value.encode()); + } else if (value is DownloadState) { + buffer.putUint8(186); + writeValue(buffer, value.encode()); + } else if (value is ShareInternetResourceState) { + buffer.putUint8(187); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -2770,119 +2854,124 @@ class _PigeonCodec extends StandardMessageCodec { return value == null ? null : CookieSameSiteStatus.values[value]; case 134: final int? value = readValue(buffer) as int?; - return value == null ? null : SelectionPattern.values[value]; + return value == null ? null : VisitType.values[value]; case 135: final int? value = readValue(buffer) as int?; - return value == null ? null : WebExtensionActionType.values[value]; + return value == null ? null : SelectionPattern.values[value]; case 136: final int? value = readValue(buffer) as int?; - return value == null ? null : GeckoSuggestionType.values[value]; + return value == null ? null : WebExtensionActionType.values[value]; case 137: final int? value = readValue(buffer) as int?; - return value == null ? null : TrackingProtectionPolicy.values[value]; + return value == null ? null : GeckoSuggestionType.values[value]; case 138: final int? value = readValue(buffer) as int?; - return value == null ? null : HttpsOnlyMode.values[value]; + return value == null ? null : TrackingProtectionPolicy.values[value]; case 139: final int? value = readValue(buffer) as int?; - return value == null ? null : QueryParameterStripping.values[value]; + return value == null ? null : HttpsOnlyMode.values[value]; case 140: final int? value = readValue(buffer) as int?; - return value == null ? null : BounceTrackingProtectionMode.values[value]; + return value == null ? null : QueryParameterStripping.values[value]; case 141: final int? value = readValue(buffer) as int?; - return value == null ? null : ColorScheme.values[value]; + return value == null ? null : BounceTrackingProtectionMode.values[value]; case 142: final int? value = readValue(buffer) as int?; - return value == null ? null : CookieBannerHandlingMode.values[value]; + return value == null ? null : ColorScheme.values[value]; case 143: final int? value = readValue(buffer) as int?; - return value == null ? null : WebContentIsolationStrategy.values[value]; + return value == null ? null : CookieBannerHandlingMode.values[value]; case 144: final int? value = readValue(buffer) as int?; - return value == null ? null : DownloadStatus.values[value]; + return value == null ? null : WebContentIsolationStrategy.values[value]; case 145: final int? value = readValue(buffer) as int?; - return value == null ? null : LogLevel.values[value]; + return value == null ? null : DownloadStatus.values[value]; case 146: - return TranslationOptions.decode(readValue(buffer)!); + final int? value = readValue(buffer) as int?; + return value == null ? null : LogLevel.values[value]; case 147: - return ReaderState.decode(readValue(buffer)!); + return TranslationOptions.decode(readValue(buffer)!); case 148: - return LastMediaAccessState.decode(readValue(buffer)!); + return ReaderState.decode(readValue(buffer)!); case 149: - return HistoryMetadataKey.decode(readValue(buffer)!); + return LastMediaAccessState.decode(readValue(buffer)!); case 150: - return PackageCategoryValue.decode(readValue(buffer)!); + return HistoryMetadataKey.decode(readValue(buffer)!); case 151: - return ExternalPackage.decode(readValue(buffer)!); + return PackageCategoryValue.decode(readValue(buffer)!); case 152: - return LoadUrlFlagsValue.decode(readValue(buffer)!); + return ExternalPackage.decode(readValue(buffer)!); case 153: - return SourceValue.decode(readValue(buffer)!); + return LoadUrlFlagsValue.decode(readValue(buffer)!); case 154: - return TabState.decode(readValue(buffer)!); + return SourceValue.decode(readValue(buffer)!); case 155: - return RecoverableTab.decode(readValue(buffer)!); + return TabState.decode(readValue(buffer)!); case 156: - return RecoverableBrowserState.decode(readValue(buffer)!); + return RecoverableTab.decode(readValue(buffer)!); case 157: - return IconRequest.decode(readValue(buffer)!); + return RecoverableBrowserState.decode(readValue(buffer)!); case 158: - return ResourceSize.decode(readValue(buffer)!); + return IconRequest.decode(readValue(buffer)!); case 159: - return Resource.decode(readValue(buffer)!); + return ResourceSize.decode(readValue(buffer)!); case 160: - return IconResult.decode(readValue(buffer)!); + return Resource.decode(readValue(buffer)!); case 161: - return CookiePartitionKey.decode(readValue(buffer)!); + return IconResult.decode(readValue(buffer)!); case 162: - return Cookie.decode(readValue(buffer)!); + return CookiePartitionKey.decode(readValue(buffer)!); case 163: - return HistoryItem.decode(readValue(buffer)!); + return Cookie.decode(readValue(buffer)!); case 164: - return HistoryState.decode(readValue(buffer)!); + return VisitInfo.decode(readValue(buffer)!); case 165: - return ReaderableState.decode(readValue(buffer)!); + return HistoryItem.decode(readValue(buffer)!); case 166: - return SecurityInfoState.decode(readValue(buffer)!); + return HistoryState.decode(readValue(buffer)!); case 167: - return TabContentState.decode(readValue(buffer)!); + return ReaderableState.decode(readValue(buffer)!); case 168: - return FindResultState.decode(readValue(buffer)!); + return SecurityInfoState.decode(readValue(buffer)!); case 169: - return CustomSelectionAction.decode(readValue(buffer)!); + return TabContentState.decode(readValue(buffer)!); case 170: - return WebExtensionData.decode(readValue(buffer)!); + return FindResultState.decode(readValue(buffer)!); case 171: - return GeckoSuggestion.decode(readValue(buffer)!); + return CustomSelectionAction.decode(readValue(buffer)!); case 172: - return TabContent.decode(readValue(buffer)!); + return WebExtensionData.decode(readValue(buffer)!); case 173: - return ContentBlocking.decode(readValue(buffer)!); + return GeckoSuggestion.decode(readValue(buffer)!); case 174: - return GeckoEngineSettings.decode(readValue(buffer)!); + return TabContent.decode(readValue(buffer)!); case 175: - return AutocompleteResult.decode(readValue(buffer)!); + return ContentBlocking.decode(readValue(buffer)!); case 176: - return UnknownHitResult.decode(readValue(buffer)!); + return GeckoEngineSettings.decode(readValue(buffer)!); case 177: - return ImageHitResult.decode(readValue(buffer)!); + return AutocompleteResult.decode(readValue(buffer)!); case 178: - return VideoHitResult.decode(readValue(buffer)!); + return UnknownHitResult.decode(readValue(buffer)!); case 179: - return AudioHitResult.decode(readValue(buffer)!); + return ImageHitResult.decode(readValue(buffer)!); case 180: - return ImageSrcHitResult.decode(readValue(buffer)!); + return VideoHitResult.decode(readValue(buffer)!); case 181: - return PhoneHitResult.decode(readValue(buffer)!); + return AudioHitResult.decode(readValue(buffer)!); case 182: - return EmailHitResult.decode(readValue(buffer)!); + return ImageSrcHitResult.decode(readValue(buffer)!); case 183: - return GeoHitResult.decode(readValue(buffer)!); + return PhoneHitResult.decode(readValue(buffer)!); case 184: - return DownloadState.decode(readValue(buffer)!); + return EmailHitResult.decode(readValue(buffer)!); case 185: + return GeoHitResult.decode(readValue(buffer)!); + case 186: + return DownloadState.decode(readValue(buffer)!); + case 187: return ShareInternetResourceState.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -5587,6 +5676,48 @@ class GeckoDeleteBrowsingDataController { } } +class GeckoHistoryApi { + /// Constructor for [GeckoHistoryApi]. 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. + GeckoHistoryApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + final BinaryMessenger? pigeonVar_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); + + final String pigeonVar_messageChannelSuffix; + + Future> getDetailedVisits(int startMillis, int endMillis, List excludeTypes) async { + final String pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.getDetailedVisits$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([startMillis, endMillis, excludeTypes]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + 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 if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as List?)!.cast(); + } + } +} + class GeckoDownloadsApi { /// Constructor for [GeckoDownloadsApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default diff --git a/packages/flutter_mozilla_components/pigeons/gecko.dart b/packages/flutter_mozilla_components/pigeons/gecko.dart index 11cf719c..6d24ae64 100644 --- a/packages/flutter_mozilla_components/pigeons/gecko.dart +++ b/packages/flutter_mozilla_components/pigeons/gecko.dart @@ -382,6 +382,36 @@ class Cookie { ); } +enum VisitType { + link, + typed, + bookmark, + embed, + redirectPermanent, + redirectTemporary, + download, + framedLink, + reload, +} + +class VisitInfo { + final String url; + final String? title; + final int visitTime; + final VisitType visitType; + final String? previewImageUrl; + final bool isRemote; + + VisitInfo( + this.url, + this.title, + this.visitTime, + this.visitType, + this.previewImageUrl, + this.isRemote, + ); +} + class HistoryItem { final String url; final String title; @@ -1187,6 +1217,16 @@ abstract class GeckoDeleteBrowsingDataController { void deleteDownloads(); } +@HostApi() +abstract class GeckoHistoryApi { + @async + List getDetailedVisits( + int startMillis, + int endMillis, + List excludeTypes, + ); +} + @HostApi() abstract class GeckoDownloadsApi { void requestDownload(String tabId, DownloadState state);