fix site clear for cookies/cache
This commit is contained in:
+50
-23
@@ -21,7 +21,9 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:nullability/nullability.dart';
|
||||||
import 'package:weblibre/core/logger.dart';
|
import 'package:weblibre/core/logger.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/domain/controllers/bottom_sheet.dart';
|
||||||
import 'package:weblibre/features/geckoview/domain/providers/tab_session.dart';
|
import 'package:weblibre/features/geckoview/domain/providers/tab_session.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/presentation/dialogs/clear_site_data_dialog.dart';
|
import 'package:weblibre/features/geckoview/features/browser/presentation/dialogs/clear_site_data_dialog.dart';
|
||||||
import 'package:weblibre/utils/ui_helper.dart';
|
import 'package:weblibre/utils/ui_helper.dart';
|
||||||
@@ -52,6 +54,13 @@ class ClearSiteDataSection extends HookConsumerWidget {
|
|||||||
newTypes.remove(type);
|
newTypes.remove(type);
|
||||||
} else {
|
} else {
|
||||||
newTypes.add(type);
|
newTypes.add(type);
|
||||||
|
|
||||||
|
if (type == ClearDataType.allSiteData) {
|
||||||
|
newTypes.removeAll([
|
||||||
|
ClearDataType.onlyCaches,
|
||||||
|
ClearDataType.onlyCookies,
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
selectedTypes.value = newTypes;
|
selectedTypes.value = newTypes;
|
||||||
}
|
}
|
||||||
@@ -79,18 +88,13 @@ class ClearSiteDataSection extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
if (isExpanded.value) ...[
|
if (isExpanded.value) ...[
|
||||||
_DataTypeCheckbox(
|
_DataTypeCheckbox(
|
||||||
label: 'Cookies',
|
label: 'Auth Sessions',
|
||||||
subtitle: 'Login tokens, preferences, tracking data',
|
subtitle: 'Saved logins, active sessions',
|
||||||
type: ClearDataType.cookies,
|
type: ClearDataType.authSessions,
|
||||||
isSelected: selectedTypes.value.contains(ClearDataType.cookies),
|
isSelected: selectedTypes.value.contains(
|
||||||
onChanged: (selected) => toggleType(ClearDataType.cookies),
|
ClearDataType.authSessions,
|
||||||
),
|
),
|
||||||
_DataTypeCheckbox(
|
onChanged: (selected) => toggleType(ClearDataType.authSessions),
|
||||||
label: 'Cached Files',
|
|
||||||
subtitle: 'Images, scripts, stylesheets',
|
|
||||||
type: ClearDataType.allCaches,
|
|
||||||
isSelected: selectedTypes.value.contains(ClearDataType.allCaches),
|
|
||||||
onChanged: (selected) => toggleType(ClearDataType.allCaches),
|
|
||||||
),
|
),
|
||||||
_DataTypeCheckbox(
|
_DataTypeCheckbox(
|
||||||
label: 'Site Data',
|
label: 'Site Data',
|
||||||
@@ -99,14 +103,33 @@ class ClearSiteDataSection extends HookConsumerWidget {
|
|||||||
isSelected: selectedTypes.value.contains(ClearDataType.allSiteData),
|
isSelected: selectedTypes.value.contains(ClearDataType.allSiteData),
|
||||||
onChanged: (selected) => toggleType(ClearDataType.allSiteData),
|
onChanged: (selected) => toggleType(ClearDataType.allSiteData),
|
||||||
),
|
),
|
||||||
_DataTypeCheckbox(
|
Padding(
|
||||||
label: 'Auth Sessions',
|
padding: const EdgeInsets.only(left: 16.0),
|
||||||
subtitle: 'Saved logins, active sessions',
|
child: _DataTypeCheckbox(
|
||||||
type: ClearDataType.authSessions,
|
label: 'Cookies',
|
||||||
isSelected: selectedTypes.value.contains(
|
subtitle: 'Login tokens, preferences, tracking data',
|
||||||
ClearDataType.authSessions,
|
type: ClearDataType.onlyCookies,
|
||||||
|
isSelected:
|
||||||
|
selectedTypes.value.contains(ClearDataType.allSiteData) ||
|
||||||
|
selectedTypes.value.contains(ClearDataType.onlyCookies),
|
||||||
|
onChanged: selectedTypes.value.contains(ClearDataType.allSiteData)
|
||||||
|
? null
|
||||||
|
: (selected) => toggleType(ClearDataType.onlyCookies),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 16.0),
|
||||||
|
child: _DataTypeCheckbox(
|
||||||
|
label: 'Cached Files',
|
||||||
|
subtitle: 'Images, scripts, stylesheets',
|
||||||
|
type: ClearDataType.onlyCaches,
|
||||||
|
isSelected:
|
||||||
|
selectedTypes.value.contains(ClearDataType.allSiteData) ||
|
||||||
|
selectedTypes.value.contains(ClearDataType.onlyCaches),
|
||||||
|
onChanged: selectedTypes.value.contains(ClearDataType.allSiteData)
|
||||||
|
? null
|
||||||
|
: (selected) => toggleType(ClearDataType.onlyCaches),
|
||||||
),
|
),
|
||||||
onChanged: (selected) => toggleType(ClearDataType.authSessions),
|
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
@@ -163,6 +186,7 @@ class ClearSiteDataSection extends HookConsumerWidget {
|
|||||||
await _clearData(ref, selectedTypes);
|
await _clearData(ref, selectedTypes);
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
showInfoMessage(context, 'Site data cleared');
|
showInfoMessage(context, 'Site data cleared');
|
||||||
|
ref.read(bottomSheetControllerProvider.notifier).requestDismiss();
|
||||||
}
|
}
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
logger.e('Failed to clear site data', error: e, stackTrace: s);
|
logger.e('Failed to clear site data', error: e, stackTrace: s);
|
||||||
@@ -178,9 +202,9 @@ class ClearSiteDataSection extends HookConsumerWidget {
|
|||||||
String _formatTypes(Set<ClearDataType> types) {
|
String _formatTypes(Set<ClearDataType> types) {
|
||||||
final labels = types.map((t) {
|
final labels = types.map((t) {
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case ClearDataType.cookies:
|
case ClearDataType.onlyCookies:
|
||||||
return 'cookies';
|
return 'cookies';
|
||||||
case ClearDataType.allCaches:
|
case ClearDataType.onlyCaches:
|
||||||
return 'cached files';
|
return 'cached files';
|
||||||
case ClearDataType.allSiteData:
|
case ClearDataType.allSiteData:
|
||||||
return 'site data';
|
return 'site data';
|
||||||
@@ -218,7 +242,7 @@ class _DataTypeCheckbox extends StatelessWidget {
|
|||||||
final String subtitle;
|
final String subtitle;
|
||||||
final ClearDataType type;
|
final ClearDataType type;
|
||||||
final bool isSelected;
|
final bool isSelected;
|
||||||
final ValueChanged<bool> onChanged;
|
final ValueChanged<bool>? onChanged;
|
||||||
|
|
||||||
const _DataTypeCheckbox({
|
const _DataTypeCheckbox({
|
||||||
required this.label,
|
required this.label,
|
||||||
@@ -234,7 +258,10 @@ class _DataTypeCheckbox extends StatelessWidget {
|
|||||||
title: Text(label),
|
title: Text(label),
|
||||||
subtitle: Text(subtitle),
|
subtitle: Text(subtitle),
|
||||||
value: isSelected,
|
value: isSelected,
|
||||||
onChanged: (value) => onChanged(value ?? false),
|
onChanged: onChanged.mapNotNull(
|
||||||
|
(onChanged) =>
|
||||||
|
(value) => onChanged(value ?? false),
|
||||||
|
),
|
||||||
controlAffinity: ListTileControlAffinity.trailing,
|
controlAffinity: ListTileControlAffinity.trailing,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+99
-12
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
package eu.weblibre.flutter_mozilla_components.api
|
package eu.weblibre.flutter_mozilla_components.api
|
||||||
|
|
||||||
|
import androidx.core.net.toUri
|
||||||
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.ClearDataType
|
import eu.weblibre.flutter_mozilla_components.pigeons.ClearDataType
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoDeleteBrowsingDataController
|
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoDeleteBrowsingDataController
|
||||||
@@ -16,6 +17,9 @@ import kotlinx.coroutines.launch
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import mozilla.components.browser.state.action.EngineAction
|
import mozilla.components.browser.state.action.EngineAction
|
||||||
import mozilla.components.browser.state.action.RecentlyClosedAction
|
import mozilla.components.browser.state.action.RecentlyClosedAction
|
||||||
|
import mozilla.components.browser.state.selector.allTabs
|
||||||
|
import mozilla.components.browser.state.state.SessionState
|
||||||
|
import mozilla.components.browser.state.store.BrowserStore
|
||||||
import mozilla.components.concept.engine.Engine
|
import mozilla.components.concept.engine.Engine
|
||||||
import mozilla.components.concept.engine.translate.ModelManagementOptions
|
import mozilla.components.concept.engine.translate.ModelManagementOptions
|
||||||
import mozilla.components.concept.engine.translate.ModelOperation
|
import mozilla.components.concept.engine.translate.ModelOperation
|
||||||
@@ -30,6 +34,29 @@ class GeckoDeleteBrowsingDataControllerImpl : GeckoDeleteBrowsingDataController
|
|||||||
requireNotNull(GlobalComponents.components) { "Components not initialized" }
|
requireNotNull(GlobalComponents.components) { "Components not initialized" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GeckoView's storage clearing APIs warn that any open session may re-accumulate
|
||||||
|
* previously cleared data. We synchronously close the underlying [EngineSession]
|
||||||
|
* (so its in-memory cookie/storage state is torn down before the clear runs) and
|
||||||
|
* then unlink it from the browser store. The next reload spins up a fresh engine
|
||||||
|
* session that reads from the cleared storage.
|
||||||
|
*
|
||||||
|
* NOTE: We deliberately don't use [EngineAction.SuspendEngineSessionAction] here -
|
||||||
|
* its middleware runs `engineSession.close()` inside a `scope.launch`, racing with
|
||||||
|
* the `clearData` call we're about to issue.
|
||||||
|
*/
|
||||||
|
private fun closeMatchingSessions(
|
||||||
|
store: BrowserStore,
|
||||||
|
predicate: (SessionState) -> Boolean,
|
||||||
|
) {
|
||||||
|
val tabs = store.state.allTabs.filter {
|
||||||
|
it.engineState.engineSession != null && predicate(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
tabs.forEach { it.engineState.engineSession?.close() }
|
||||||
|
tabs.forEach { store.dispatch(EngineAction.UnlinkEngineSessionAction(it.id)) }
|
||||||
|
}
|
||||||
|
|
||||||
override fun deleteTabs(callback: (Result<Unit>) -> Unit) {
|
override fun deleteTabs(callback: (Result<Unit>) -> Unit) {
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
@@ -56,15 +83,22 @@ class GeckoDeleteBrowsingDataControllerImpl : GeckoDeleteBrowsingDataController
|
|||||||
override fun deleteCookiesAndSiteData(callback: (Result<Unit>) -> Unit) {
|
override fun deleteCookiesAndSiteData(callback: (Result<Unit>) -> Unit) {
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
|
closeMatchingSessions(components.core.store) { true }
|
||||||
|
|
||||||
components.core.engine.clearData(
|
components.core.engine.clearData(
|
||||||
Engine.BrowsingData.select(
|
Engine.BrowsingData.select(
|
||||||
Engine.BrowsingData.COOKIES,
|
Engine.BrowsingData.COOKIES,
|
||||||
Engine.BrowsingData.AUTH_SESSIONS,
|
Engine.BrowsingData.AUTH_SESSIONS,
|
||||||
),
|
),
|
||||||
|
onSuccess = {
|
||||||
|
components.core.engine.clearData(
|
||||||
|
Engine.BrowsingData.select(Engine.BrowsingData.DOM_STORAGES),
|
||||||
|
onSuccess = { callback(Result.success(Unit)) },
|
||||||
|
onError = { callback(Result.failure(it)) },
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onError = { callback(Result.failure(it)) },
|
||||||
)
|
)
|
||||||
components.core.engine.clearData(Engine.BrowsingData.select(Engine.BrowsingData.DOM_STORAGES))
|
|
||||||
|
|
||||||
callback(Result.success(Unit))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,9 +116,9 @@ class GeckoDeleteBrowsingDataControllerImpl : GeckoDeleteBrowsingDataController
|
|||||||
)
|
)
|
||||||
components.core.engine.clearData(
|
components.core.engine.clearData(
|
||||||
Engine.BrowsingData.select(Engine.BrowsingData.ALL_CACHES),
|
Engine.BrowsingData.select(Engine.BrowsingData.ALL_CACHES),
|
||||||
|
onSuccess = { callback(Result.success(Unit)) },
|
||||||
|
onError = { callback(Result.failure(it)) },
|
||||||
)
|
)
|
||||||
|
|
||||||
callback(Result.success(Unit))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,10 +128,18 @@ class GeckoDeleteBrowsingDataControllerImpl : GeckoDeleteBrowsingDataController
|
|||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
components.core.engine.clearData(
|
components.core.engine.clearData(
|
||||||
Engine.BrowsingData.select(Engine.BrowsingData.ALL_SITE_SETTINGS),
|
Engine.BrowsingData.select(Engine.BrowsingData.ALL_SITE_SETTINGS),
|
||||||
|
onSuccess = {
|
||||||
|
coroutineScope.launch {
|
||||||
|
try {
|
||||||
|
components.core.permissionStorage.deleteAllSitePermissions()
|
||||||
|
callback(Result.success(Unit))
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
callback(Result.failure(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onError = { callback(Result.failure(it)) },
|
||||||
)
|
)
|
||||||
components.core.permissionStorage.deleteAllSitePermissions()
|
|
||||||
|
|
||||||
callback(Result.success(Unit))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,6 +160,14 @@ class GeckoDeleteBrowsingDataControllerImpl : GeckoDeleteBrowsingDataController
|
|||||||
) {
|
) {
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
|
// Detach engine sessions for any tab in this context so they don't
|
||||||
|
// re-accumulate data while the (fire-and-forget) clear is processed.
|
||||||
|
closeMatchingSessions(components.core.store) { it.contextId == contextId }
|
||||||
|
|
||||||
|
// GeckoView's clearDataForSessionContext uses dispatch (fire-and-forget),
|
||||||
|
// so there's no completion signal we can chain against. Fire it and
|
||||||
|
// signal completion immediately - by suspending matching sessions above
|
||||||
|
// we've at least ensured the operation can take effect.
|
||||||
components.core.runtime.storageController.clearDataForSessionContext(contextId)
|
components.core.runtime.storageController.clearDataForSessionContext(contextId)
|
||||||
|
|
||||||
callback(Result.success(Unit))
|
callback(Result.success(Unit))
|
||||||
@@ -133,17 +183,54 @@ class GeckoDeleteBrowsingDataControllerImpl : GeckoDeleteBrowsingDataController
|
|||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
try {
|
try {
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
|
if (dataTypes.contains(ClearDataType.ALL_SITE_DATA) && (dataTypes.contains(
|
||||||
|
ClearDataType.ONLY_COOKIES
|
||||||
|
) || dataTypes.contains(ClearDataType.ONLY_CACHES))
|
||||||
|
) {
|
||||||
|
callback(Result.failure(Exception("Cookies/Cache must be exclusively!")))
|
||||||
|
}
|
||||||
|
|
||||||
// Convert ClearDataType to Engine.BrowsingData flags
|
// Convert ClearDataType to Engine.BrowsingData flags
|
||||||
val browsingDataTypes = dataTypes.map { dataType ->
|
val browsingDataTypes = dataTypes.map { dataType ->
|
||||||
when (dataType) {
|
when (dataType) {
|
||||||
ClearDataType.AUTH_SESSIONS -> Engine.BrowsingData.AUTH_SESSIONS
|
ClearDataType.AUTH_SESSIONS -> Engine.BrowsingData.AUTH_SESSIONS
|
||||||
ClearDataType.ALL_SITE_DATA -> Engine.BrowsingData.ALL_SITE_DATA
|
ClearDataType.ALL_SITE_DATA -> Engine.BrowsingData.ALL_SITE_DATA
|
||||||
ClearDataType.COOKIES -> Engine.BrowsingData.COOKIES
|
ClearDataType.ONLY_COOKIES -> Engine.BrowsingData.COOKIES
|
||||||
ClearDataType.ALL_CACHES -> Engine.BrowsingData.ALL_CACHES
|
ClearDataType.ONLY_CACHES -> Engine.BrowsingData.ALL_CACHES
|
||||||
}
|
}
|
||||||
}.toIntArray()
|
}.toIntArray()
|
||||||
|
|
||||||
// Clear data for the specific host
|
// Find tabs on this host (so we can detach their engine sessions and
|
||||||
|
// also discover any container/contextId partitions that need clearing).
|
||||||
|
val matchingTabs = components.core.store.state.allTabs.filter { tab ->
|
||||||
|
val tabHost = runCatching { tab.content.url.toUri().host }.getOrNull()
|
||||||
|
?: return@filter false
|
||||||
|
tabHost == host || tabHost.endsWith(".$host")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GeckoView warns that open sessions may re-accumulate previously
|
||||||
|
// cleared data. Close them synchronously before clearing.
|
||||||
|
matchingTabs.forEach { it.engineState.engineSession?.close() }
|
||||||
|
matchingTabs.forEach {
|
||||||
|
components.core.store.dispatch(EngineAction.UnlinkEngineSessionAction(it.id))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GeckoView's clearDataFromBaseDomain (used by engine.clearData(host=))
|
||||||
|
// only targets the default origin attributes partition. Tabs that live
|
||||||
|
// inside a contextual identity ("container") store their cookies/storage
|
||||||
|
// under a `geckoViewSessionContextId` origin attribute that the
|
||||||
|
// base-domain clear does not touch. To make clearing actually effective
|
||||||
|
// for container tabs, also fire clearDataForSessionContext for any
|
||||||
|
// contextIds we found. This is broader than ideal (it clears the whole
|
||||||
|
// container, not just this host) but there is no GeckoView API to
|
||||||
|
// combine host + context.
|
||||||
|
val contextIds = matchingTabs.mapNotNull { it.contextId }.toSet()
|
||||||
|
contextIds.forEach { contextId ->
|
||||||
|
components.core.runtime.storageController
|
||||||
|
.clearDataForSessionContext(contextId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear data for the specific host (default partition).
|
||||||
components.core.engine.clearData(
|
components.core.engine.clearData(
|
||||||
data = Engine.BrowsingData.select(*browsingDataTypes),
|
data = Engine.BrowsingData.select(*browsingDataTypes),
|
||||||
host = host,
|
host = host,
|
||||||
@@ -160,4 +247,4 @@ class GeckoDeleteBrowsingDataControllerImpl : GeckoDeleteBrowsingDataController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-3
@@ -681,12 +681,15 @@ enum class MlProgressStatus(val raw: Int) {
|
|||||||
enum class ClearDataType(val raw: Int) {
|
enum class ClearDataType(val raw: Int) {
|
||||||
/** Authentication sessions */
|
/** Authentication sessions */
|
||||||
AUTH_SESSIONS(0),
|
AUTH_SESSIONS(0),
|
||||||
/** All site data (cookies, storage, etc.) */
|
/**
|
||||||
|
* All site data (cookies, storage, etc.)
|
||||||
|
* WARNING: If this is set it already includes cookies and allCaches. Passing the additionally will lead to issues
|
||||||
|
*/
|
||||||
ALL_SITE_DATA(1),
|
ALL_SITE_DATA(1),
|
||||||
/** Cookies only */
|
/** Cookies only */
|
||||||
COOKIES(2),
|
ONLY_COOKIES(2),
|
||||||
/** Cache only */
|
/** Cache only */
|
||||||
ALL_CACHES(3);
|
ONLY_CACHES(3);
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun ofRaw(raw: Int): ClearDataType? {
|
fun ofRaw(raw: Int): ClearDataType? {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2087,13 +2087,14 @@ enum ClearDataType {
|
|||||||
authSessions,
|
authSessions,
|
||||||
|
|
||||||
/// All site data (cookies, storage, etc.)
|
/// All site data (cookies, storage, etc.)
|
||||||
|
/// WARNING: If this is set it already includes cookies and allCaches. Passing the additionally will lead to issues
|
||||||
allSiteData,
|
allSiteData,
|
||||||
|
|
||||||
/// Cookies only
|
/// Cookies only
|
||||||
cookies,
|
onlyCookies,
|
||||||
|
|
||||||
/// Cache only
|
/// Cache only
|
||||||
allCaches,
|
onlyCaches,
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostApi()
|
@HostApi()
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:meta/meta.dart' show immutable, protected, visibleForTesting;
|
import 'package:meta/meta.dart' show immutable, protected, visibleForTesting;
|
||||||
|
|
||||||
Object? _extractReplyValueOrThrow(
|
Object? _extractReplyValueOrThrow(
|
||||||
List<Object?>? replyList,
|
List<Object?>? replyList,
|
||||||
String channelName, {
|
String channelName, {
|
||||||
required bool isNullValid,
|
required bool isNullValid,
|
||||||
}) {
|
}) {
|
||||||
if (replyList == null) {
|
if (replyList == null) {
|
||||||
throw PlatformException(
|
throw PlatformException(
|
||||||
@@ -34,11 +34,8 @@ Object? _extractReplyValueOrThrow(
|
|||||||
return replyList.firstOrNull;
|
return replyList.firstOrNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Object?> wrapResponse({
|
|
||||||
Object? result,
|
List<Object?> wrapResponse({Object? result, PlatformException? error, bool empty = false}) {
|
||||||
PlatformException? error,
|
|
||||||
bool empty = false,
|
|
||||||
}) {
|
|
||||||
if (empty) {
|
if (empty) {
|
||||||
return <Object?>[];
|
return <Object?>[];
|
||||||
}
|
}
|
||||||
@@ -47,7 +44,6 @@ List<Object?> wrapResponse({
|
|||||||
}
|
}
|
||||||
return <Object?>[error.code, error.message, error.details];
|
return <Object?>[error.code, error.message, error.details];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _deepEquals(Object? a, Object? b) {
|
bool _deepEquals(Object? a, Object? b) {
|
||||||
if (identical(a, b)) {
|
if (identical(a, b)) {
|
||||||
return true;
|
return true;
|
||||||
@@ -60,9 +56,8 @@ bool _deepEquals(Object? a, Object? b) {
|
|||||||
}
|
}
|
||||||
if (a is List && b is List) {
|
if (a is List && b is List) {
|
||||||
return a.length == b.length &&
|
return a.length == b.length &&
|
||||||
a.indexed.every(
|
a.indexed
|
||||||
((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]),
|
.every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (a is Map && b is Map) {
|
if (a is Map && b is Map) {
|
||||||
if (a.length != b.length) {
|
if (a.length != b.length) {
|
||||||
@@ -111,29 +106,23 @@ int _deepHash(Object? value) {
|
|||||||
return value.hashCode;
|
return value.hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Transport types for Tor connections
|
/// Transport types for Tor connections
|
||||||
enum TransportType {
|
enum TransportType {
|
||||||
/// Direct Tor connection (no bridges)
|
/// Direct Tor connection (no bridges)
|
||||||
none,
|
none,
|
||||||
|
|
||||||
/// obfs4 pluggable transport
|
/// obfs4 pluggable transport
|
||||||
obfs4,
|
obfs4,
|
||||||
|
|
||||||
/// Snowflake pluggable transport (default broker)
|
/// Snowflake pluggable transport (default broker)
|
||||||
snowflake,
|
snowflake,
|
||||||
|
|
||||||
/// Snowflake via AMP cache
|
/// Snowflake via AMP cache
|
||||||
snowflakeAmp,
|
snowflakeAmp,
|
||||||
|
|
||||||
/// Meek pluggable transport
|
/// Meek pluggable transport
|
||||||
meek,
|
meek,
|
||||||
|
|
||||||
/// Meek via Azure CDN
|
/// Meek via Azure CDN
|
||||||
meekAzure,
|
meekAzure,
|
||||||
|
|
||||||
/// WebTunnel pluggable transport
|
/// WebTunnel pluggable transport
|
||||||
webtunnel,
|
webtunnel,
|
||||||
|
|
||||||
/// Custom bridge lines (passthrough)
|
/// Custom bridge lines (passthrough)
|
||||||
custom,
|
custom,
|
||||||
}
|
}
|
||||||
@@ -174,8 +163,7 @@ class TorConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Object encode() {
|
Object encode() {
|
||||||
return _toList();
|
return _toList(); }
|
||||||
}
|
|
||||||
|
|
||||||
static TorConfiguration decode(Object result) {
|
static TorConfiguration decode(Object result) {
|
||||||
result as List<Object?>;
|
result as List<Object?>;
|
||||||
@@ -197,11 +185,7 @@ class TorConfiguration {
|
|||||||
if (identical(this, other)) {
|
if (identical(this, other)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return _deepEquals(transport, other.transport) &&
|
return _deepEquals(transport, other.transport) && _deepEquals(bridgeLines, other.bridgeLines) && _deepEquals(entryNodeCountries, other.entryNodeCountries) && _deepEquals(exitNodeCountries, other.exitNodeCountries) && _deepEquals(strictNodes, other.strictNodes);
|
||||||
_deepEquals(bridgeLines, other.bridgeLines) &&
|
|
||||||
_deepEquals(entryNodeCountries, other.entryNodeCountries) &&
|
|
||||||
_deepEquals(exitNodeCountries, other.exitNodeCountries) &&
|
|
||||||
_deepEquals(strictNodes, other.strictNodes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -245,8 +229,7 @@ class TorStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Object encode() {
|
Object encode() {
|
||||||
return _toList();
|
return _toList(); }
|
||||||
}
|
|
||||||
|
|
||||||
static TorStatus decode(Object result) {
|
static TorStatus decode(Object result) {
|
||||||
result as List<Object?>;
|
result as List<Object?>;
|
||||||
@@ -268,11 +251,7 @@ class TorStatus {
|
|||||||
if (identical(this, other)) {
|
if (identical(this, other)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return _deepEquals(isRunning, other.isRunning) &&
|
return _deepEquals(isRunning, other.isRunning) && _deepEquals(socksPort, other.socksPort) && _deepEquals(bootstrapProgress, other.bootstrapProgress) && _deepEquals(currentCircuit, other.currentCircuit) && _deepEquals(exitNodeCountry, other.exitNodeCountry);
|
||||||
_deepEquals(socksPort, other.socksPort) &&
|
|
||||||
_deepEquals(bootstrapProgress, other.bootstrapProgress) &&
|
|
||||||
_deepEquals(currentCircuit, other.currentCircuit) &&
|
|
||||||
_deepEquals(exitNodeCountry, other.exitNodeCountry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -298,12 +277,15 @@ class TorLogMessage {
|
|||||||
int timestamp;
|
int timestamp;
|
||||||
|
|
||||||
List<Object?> _toList() {
|
List<Object?> _toList() {
|
||||||
return <Object?>[severity, message, timestamp];
|
return <Object?>[
|
||||||
|
severity,
|
||||||
|
message,
|
||||||
|
timestamp,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
Object encode() {
|
Object encode() {
|
||||||
return _toList();
|
return _toList(); }
|
||||||
}
|
|
||||||
|
|
||||||
static TorLogMessage decode(Object result) {
|
static TorLogMessage decode(Object result) {
|
||||||
result as List<Object?>;
|
result as List<Object?>;
|
||||||
@@ -323,9 +305,7 @@ class TorLogMessage {
|
|||||||
if (identical(this, other)) {
|
if (identical(this, other)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return _deepEquals(severity, other.severity) &&
|
return _deepEquals(severity, other.severity) && _deepEquals(message, other.message) && _deepEquals(timestamp, other.timestamp);
|
||||||
_deepEquals(message, other.message) &&
|
|
||||||
_deepEquals(timestamp, other.timestamp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -333,6 +313,7 @@ class TorLogMessage {
|
|||||||
int get hashCode => _deepHash(<Object?>[runtimeType, ..._toList()]);
|
int get hashCode => _deepHash(<Object?>[runtimeType, ..._toList()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class _PigeonCodec extends StandardMessageCodec {
|
class _PigeonCodec extends StandardMessageCodec {
|
||||||
const _PigeonCodec();
|
const _PigeonCodec();
|
||||||
@override
|
@override
|
||||||
@@ -340,16 +321,16 @@ class _PigeonCodec extends StandardMessageCodec {
|
|||||||
if (value is int) {
|
if (value is int) {
|
||||||
buffer.putUint8(4);
|
buffer.putUint8(4);
|
||||||
buffer.putInt64(value);
|
buffer.putInt64(value);
|
||||||
} else if (value is TransportType) {
|
} else if (value is TransportType) {
|
||||||
buffer.putUint8(129);
|
buffer.putUint8(129);
|
||||||
writeValue(buffer, value.index);
|
writeValue(buffer, value.index);
|
||||||
} else if (value is TorConfiguration) {
|
} else if (value is TorConfiguration) {
|
||||||
buffer.putUint8(130);
|
buffer.putUint8(130);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is TorStatus) {
|
} else if (value is TorStatus) {
|
||||||
buffer.putUint8(131);
|
buffer.putUint8(131);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is TorLogMessage) {
|
} else if (value is TorLogMessage) {
|
||||||
buffer.putUint8(132);
|
buffer.putUint8(132);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else {
|
} else {
|
||||||
@@ -381,10 +362,8 @@ class TorApi {
|
|||||||
/// available for dependency injection. If it is left null, the default
|
/// available for dependency injection. If it is left null, the default
|
||||||
/// BinaryMessenger will be used which routes to the host platform.
|
/// BinaryMessenger will be used which routes to the host platform.
|
||||||
TorApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
|
TorApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
|
||||||
: pigeonVar_binaryMessenger = binaryMessenger,
|
: pigeonVar_binaryMessenger = binaryMessenger,
|
||||||
pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty
|
pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
||||||
? '.$messageChannelSuffix'
|
|
||||||
: '';
|
|
||||||
final BinaryMessenger? pigeonVar_binaryMessenger;
|
final BinaryMessenger? pigeonVar_binaryMessenger;
|
||||||
|
|
||||||
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
|
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
|
||||||
@@ -394,30 +373,27 @@ class TorApi {
|
|||||||
/// Start Tor with the given configuration
|
/// Start Tor with the given configuration
|
||||||
/// Returns a Future to avoid blocking the main thread
|
/// Returns a Future to avoid blocking the main thread
|
||||||
Future<int> startTor(TorConfiguration config) async {
|
Future<int> startTor(TorConfiguration config) async {
|
||||||
final pigeonVar_channelName =
|
final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_tor.TorApi.startTor$pigeonVar_messageChannelSuffix';
|
||||||
'dev.flutter.pigeon.flutter_tor.TorApi.startTor$pigeonVar_messageChannelSuffix';
|
|
||||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
|
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[config]);
|
||||||
<Object?>[config],
|
|
||||||
);
|
|
||||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||||
|
|
||||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||||
pigeonVar_replyList,
|
pigeonVar_replyList,
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
isNullValid: false,
|
isNullValid: false,
|
||||||
);
|
)
|
||||||
|
;
|
||||||
return pigeonVar_replyValue! as int;
|
return pigeonVar_replyValue! as int;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stop Tor
|
/// Stop Tor
|
||||||
Future<void> stopTor() async {
|
Future<void> stopTor() async {
|
||||||
final pigeonVar_channelName =
|
final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_tor.TorApi.stopTor$pigeonVar_messageChannelSuffix';
|
||||||
'dev.flutter.pigeon.flutter_tor.TorApi.stopTor$pigeonVar_messageChannelSuffix';
|
|
||||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
@@ -427,16 +403,16 @@ class TorApi {
|
|||||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||||
|
|
||||||
_extractReplyValueOrThrow(
|
_extractReplyValueOrThrow(
|
||||||
pigeonVar_replyList,
|
pigeonVar_replyList,
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
isNullValid: true,
|
isNullValid: true,
|
||||||
);
|
)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get current status
|
/// Get current status
|
||||||
Future<TorStatus> getStatus() async {
|
Future<TorStatus> getStatus() async {
|
||||||
final pigeonVar_channelName =
|
final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_tor.TorApi.getStatus$pigeonVar_messageChannelSuffix';
|
||||||
'dev.flutter.pigeon.flutter_tor.TorApi.getStatus$pigeonVar_messageChannelSuffix';
|
|
||||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
@@ -446,17 +422,17 @@ class TorApi {
|
|||||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||||
|
|
||||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||||
pigeonVar_replyList,
|
pigeonVar_replyList,
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
isNullValid: false,
|
isNullValid: false,
|
||||||
);
|
)
|
||||||
|
;
|
||||||
return pigeonVar_replyValue! as TorStatus;
|
return pigeonVar_replyValue! as TorStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Request a new Tor identity (new circuit)
|
/// Request a new Tor identity (new circuit)
|
||||||
Future<void> requestNewIdentity() async {
|
Future<void> requestNewIdentity() async {
|
||||||
final pigeonVar_channelName =
|
final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_tor.TorApi.requestNewIdentity$pigeonVar_messageChannelSuffix';
|
||||||
'dev.flutter.pigeon.flutter_tor.TorApi.requestNewIdentity$pigeonVar_messageChannelSuffix';
|
|
||||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
@@ -466,10 +442,11 @@ class TorApi {
|
|||||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||||
|
|
||||||
_extractReplyValueOrThrow(
|
_extractReplyValueOrThrow(
|
||||||
pigeonVar_replyList,
|
pigeonVar_replyList,
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
isNullValid: true,
|
isNullValid: true,
|
||||||
);
|
)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -483,20 +460,12 @@ abstract class TorLogApi {
|
|||||||
/// Called when status changes
|
/// Called when status changes
|
||||||
void onStatusChanged(TorStatus status);
|
void onStatusChanged(TorStatus status);
|
||||||
|
|
||||||
static void setUp(
|
static void setUp(TorLogApi? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) {
|
||||||
TorLogApi? api, {
|
messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
||||||
BinaryMessenger? binaryMessenger,
|
|
||||||
String messageChannelSuffix = '',
|
|
||||||
}) {
|
|
||||||
messageChannelSuffix = messageChannelSuffix.isNotEmpty
|
|
||||||
? '.$messageChannelSuffix'
|
|
||||||
: '';
|
|
||||||
{
|
{
|
||||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
'dev.flutter.pigeon.flutter_tor.TorLogApi.onLogMessage$messageChannelSuffix',
|
'dev.flutter.pigeon.flutter_tor.TorLogApi.onLogMessage$messageChannelSuffix', pigeonChannelCodec,
|
||||||
pigeonChannelCodec,
|
binaryMessenger: binaryMessenger);
|
||||||
binaryMessenger: binaryMessenger,
|
|
||||||
);
|
|
||||||
if (api == null) {
|
if (api == null) {
|
||||||
pigeonVar_channel.setMessageHandler(null);
|
pigeonVar_channel.setMessageHandler(null);
|
||||||
} else {
|
} else {
|
||||||
@@ -508,20 +477,16 @@ abstract class TorLogApi {
|
|||||||
return wrapResponse(empty: true);
|
return wrapResponse(empty: true);
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
return wrapResponse(error: e);
|
return wrapResponse(error: e);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return wrapResponse(
|
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
|
||||||
error: PlatformException(code: 'error', message: e.toString()),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
'dev.flutter.pigeon.flutter_tor.TorLogApi.onStatusChanged$messageChannelSuffix',
|
'dev.flutter.pigeon.flutter_tor.TorLogApi.onStatusChanged$messageChannelSuffix', pigeonChannelCodec,
|
||||||
pigeonChannelCodec,
|
binaryMessenger: binaryMessenger);
|
||||||
binaryMessenger: binaryMessenger,
|
|
||||||
);
|
|
||||||
if (api == null) {
|
if (api == null) {
|
||||||
pigeonVar_channel.setMessageHandler(null);
|
pigeonVar_channel.setMessageHandler(null);
|
||||||
} else {
|
} else {
|
||||||
@@ -533,10 +498,8 @@ abstract class TorLogApi {
|
|||||||
return wrapResponse(empty: true);
|
return wrapResponse(empty: true);
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
return wrapResponse(error: e);
|
return wrapResponse(error: e);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return wrapResponse(
|
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
|
||||||
error: PlatformException(code: 'error', message: e.toString()),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -548,13 +511,9 @@ class IPtProxyController {
|
|||||||
/// Constructor for [IPtProxyController]. The [binaryMessenger] named argument is
|
/// Constructor for [IPtProxyController]. The [binaryMessenger] named argument is
|
||||||
/// available for dependency injection. If it is left null, the default
|
/// available for dependency injection. If it is left null, the default
|
||||||
/// BinaryMessenger will be used which routes to the host platform.
|
/// BinaryMessenger will be used which routes to the host platform.
|
||||||
IPtProxyController({
|
IPtProxyController({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
|
||||||
BinaryMessenger? binaryMessenger,
|
: pigeonVar_binaryMessenger = binaryMessenger,
|
||||||
String messageChannelSuffix = '',
|
pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
||||||
}) : pigeonVar_binaryMessenger = binaryMessenger,
|
|
||||||
pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty
|
|
||||||
? '.$messageChannelSuffix'
|
|
||||||
: '';
|
|
||||||
final BinaryMessenger? pigeonVar_binaryMessenger;
|
final BinaryMessenger? pigeonVar_binaryMessenger;
|
||||||
|
|
||||||
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
|
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
|
||||||
@@ -562,43 +521,39 @@ class IPtProxyController {
|
|||||||
final String pigeonVar_messageChannelSuffix;
|
final String pigeonVar_messageChannelSuffix;
|
||||||
|
|
||||||
Future<int> start(TransportType proxyType, String proxy) async {
|
Future<int> start(TransportType proxyType, String proxy) async {
|
||||||
final pigeonVar_channelName =
|
final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_tor.IPtProxyController.start$pigeonVar_messageChannelSuffix';
|
||||||
'dev.flutter.pigeon.flutter_tor.IPtProxyController.start$pigeonVar_messageChannelSuffix';
|
|
||||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
|
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[proxyType, proxy]);
|
||||||
<Object?>[proxyType, proxy],
|
|
||||||
);
|
|
||||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||||
|
|
||||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||||
pigeonVar_replyList,
|
pigeonVar_replyList,
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
isNullValid: false,
|
isNullValid: false,
|
||||||
);
|
)
|
||||||
|
;
|
||||||
return pigeonVar_replyValue! as int;
|
return pigeonVar_replyValue! as int;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> stop(TransportType proxyType) async {
|
Future<void> stop(TransportType proxyType) async {
|
||||||
final pigeonVar_channelName =
|
final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_tor.IPtProxyController.stop$pigeonVar_messageChannelSuffix';
|
||||||
'dev.flutter.pigeon.flutter_tor.IPtProxyController.stop$pigeonVar_messageChannelSuffix';
|
|
||||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
|
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[proxyType]);
|
||||||
<Object?>[proxyType],
|
|
||||||
);
|
|
||||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||||
|
|
||||||
_extractReplyValueOrThrow(
|
_extractReplyValueOrThrow(
|
||||||
pigeonVar_replyList,
|
pigeonVar_replyList,
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
isNullValid: true,
|
isNullValid: true,
|
||||||
);
|
)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:meta/meta.dart' show immutable, protected, visibleForTesting;
|
import 'package:meta/meta.dart' show immutable, protected, visibleForTesting;
|
||||||
|
|
||||||
Object? _extractReplyValueOrThrow(
|
Object? _extractReplyValueOrThrow(
|
||||||
List<Object?>? replyList,
|
List<Object?>? replyList,
|
||||||
String channelName, {
|
String channelName, {
|
||||||
required bool isNullValid,
|
required bool isNullValid,
|
||||||
}) {
|
}) {
|
||||||
if (replyList == null) {
|
if (replyList == null) {
|
||||||
throw PlatformException(
|
throw PlatformException(
|
||||||
@@ -46,9 +46,8 @@ bool _deepEquals(Object? a, Object? b) {
|
|||||||
}
|
}
|
||||||
if (a is List && b is List) {
|
if (a is List && b is List) {
|
||||||
return a.length == b.length &&
|
return a.length == b.length &&
|
||||||
a.indexed.every(
|
a.indexed
|
||||||
((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]),
|
.every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (a is Map && b is Map) {
|
if (a is Map && b is Map) {
|
||||||
if (a.length != b.length) {
|
if (a.length != b.length) {
|
||||||
@@ -97,20 +96,26 @@ int _deepHash(Object? value) {
|
|||||||
return value.hashCode;
|
return value.hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class LocalizedResult {
|
class LocalizedResult {
|
||||||
LocalizedResult({required this.languageName, this.countryName});
|
LocalizedResult({
|
||||||
|
required this.languageName,
|
||||||
|
this.countryName,
|
||||||
|
});
|
||||||
|
|
||||||
String languageName;
|
String languageName;
|
||||||
|
|
||||||
String? countryName;
|
String? countryName;
|
||||||
|
|
||||||
List<Object?> _toList() {
|
List<Object?> _toList() {
|
||||||
return <Object?>[languageName, countryName];
|
return <Object?>[
|
||||||
|
languageName,
|
||||||
|
countryName,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
Object encode() {
|
Object encode() {
|
||||||
return _toList();
|
return _toList(); }
|
||||||
}
|
|
||||||
|
|
||||||
static LocalizedResult decode(Object result) {
|
static LocalizedResult decode(Object result) {
|
||||||
result as List<Object?>;
|
result as List<Object?>;
|
||||||
@@ -129,8 +134,7 @@ class LocalizedResult {
|
|||||||
if (identical(this, other)) {
|
if (identical(this, other)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return _deepEquals(languageName, other.languageName) &&
|
return _deepEquals(languageName, other.languageName) && _deepEquals(countryName, other.countryName);
|
||||||
_deepEquals(countryName, other.countryName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -138,6 +142,7 @@ class LocalizedResult {
|
|||||||
int get hashCode => _deepHash(<Object?>[runtimeType, ..._toList()]);
|
int get hashCode => _deepHash(<Object?>[runtimeType, ..._toList()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class _PigeonCodec extends StandardMessageCodec {
|
class _PigeonCodec extends StandardMessageCodec {
|
||||||
const _PigeonCodec();
|
const _PigeonCodec();
|
||||||
@override
|
@override
|
||||||
@@ -145,7 +150,7 @@ class _PigeonCodec extends StandardMessageCodec {
|
|||||||
if (value is int) {
|
if (value is int) {
|
||||||
buffer.putUint8(4);
|
buffer.putUint8(4);
|
||||||
buffer.putInt64(value);
|
buffer.putInt64(value);
|
||||||
} else if (value is LocalizedResult) {
|
} else if (value is LocalizedResult) {
|
||||||
buffer.putUint8(129);
|
buffer.putUint8(129);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else {
|
} else {
|
||||||
@@ -168,40 +173,31 @@ class LocaleResolver {
|
|||||||
/// Constructor for [LocaleResolver]. The [binaryMessenger] named argument is
|
/// Constructor for [LocaleResolver]. The [binaryMessenger] named argument is
|
||||||
/// available for dependency injection. If it is left null, the default
|
/// available for dependency injection. If it is left null, the default
|
||||||
/// BinaryMessenger will be used which routes to the host platform.
|
/// BinaryMessenger will be used which routes to the host platform.
|
||||||
LocaleResolver({
|
LocaleResolver({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
|
||||||
BinaryMessenger? binaryMessenger,
|
: pigeonVar_binaryMessenger = binaryMessenger,
|
||||||
String messageChannelSuffix = '',
|
pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
||||||
}) : pigeonVar_binaryMessenger = binaryMessenger,
|
|
||||||
pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty
|
|
||||||
? '.$messageChannelSuffix'
|
|
||||||
: '';
|
|
||||||
final BinaryMessenger? pigeonVar_binaryMessenger;
|
final BinaryMessenger? pigeonVar_binaryMessenger;
|
||||||
|
|
||||||
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
|
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
|
||||||
|
|
||||||
final String pigeonVar_messageChannelSuffix;
|
final String pigeonVar_messageChannelSuffix;
|
||||||
|
|
||||||
Future<LocalizedResult> resolve(
|
Future<LocalizedResult> resolve(String languageTag, String targetLangouageTag) async {
|
||||||
String languageTag,
|
final pigeonVar_channelName = 'dev.flutter.pigeon.locale_resolver.LocaleResolver.resolve$pigeonVar_messageChannelSuffix';
|
||||||
String targetLangouageTag,
|
|
||||||
) async {
|
|
||||||
final pigeonVar_channelName =
|
|
||||||
'dev.flutter.pigeon.locale_resolver.LocaleResolver.resolve$pigeonVar_messageChannelSuffix';
|
|
||||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
|
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[languageTag, targetLangouageTag]);
|
||||||
<Object?>[languageTag, targetLangouageTag],
|
|
||||||
);
|
|
||||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||||
|
|
||||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||||
pigeonVar_replyList,
|
pigeonVar_replyList,
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
isNullValid: false,
|
isNullValid: false,
|
||||||
);
|
)
|
||||||
|
;
|
||||||
return pigeonVar_replyValue! as LocalizedResult;
|
return pigeonVar_replyValue! as LocalizedResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:meta/meta.dart' show immutable, protected, visibleForTesting;
|
import 'package:meta/meta.dart' show immutable, protected, visibleForTesting;
|
||||||
|
|
||||||
Object? _extractReplyValueOrThrow(
|
Object? _extractReplyValueOrThrow(
|
||||||
List<Object?>? replyList,
|
List<Object?>? replyList,
|
||||||
String channelName, {
|
String channelName, {
|
||||||
required bool isNullValid,
|
required bool isNullValid,
|
||||||
}) {
|
}) {
|
||||||
if (replyList == null) {
|
if (replyList == null) {
|
||||||
throw PlatformException(
|
throw PlatformException(
|
||||||
@@ -34,11 +34,8 @@ Object? _extractReplyValueOrThrow(
|
|||||||
return replyList.firstOrNull;
|
return replyList.firstOrNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Object?> wrapResponse({
|
|
||||||
Object? result,
|
List<Object?> wrapResponse({Object? result, PlatformException? error, bool empty = false}) {
|
||||||
PlatformException? error,
|
|
||||||
bool empty = false,
|
|
||||||
}) {
|
|
||||||
if (empty) {
|
if (empty) {
|
||||||
return <Object?>[];
|
return <Object?>[];
|
||||||
}
|
}
|
||||||
@@ -47,7 +44,6 @@ List<Object?> wrapResponse({
|
|||||||
}
|
}
|
||||||
return <Object?>[error.code, error.message, error.details];
|
return <Object?>[error.code, error.message, error.details];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _deepEquals(Object? a, Object? b) {
|
bool _deepEquals(Object? a, Object? b) {
|
||||||
if (identical(a, b)) {
|
if (identical(a, b)) {
|
||||||
return true;
|
return true;
|
||||||
@@ -60,9 +56,8 @@ bool _deepEquals(Object? a, Object? b) {
|
|||||||
}
|
}
|
||||||
if (a is List && b is List) {
|
if (a is List && b is List) {
|
||||||
return a.length == b.length &&
|
return a.length == b.length &&
|
||||||
a.indexed.every(
|
a.indexed
|
||||||
((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]),
|
.every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (a is Map && b is Map) {
|
if (a is Map && b is Map) {
|
||||||
if (a.length != b.length) {
|
if (a.length != b.length) {
|
||||||
@@ -111,6 +106,7 @@ int _deepHash(Object? value) {
|
|||||||
return value.hashCode;
|
return value.hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Intent {
|
class Intent {
|
||||||
Intent({
|
Intent({
|
||||||
this.fromPackageName,
|
this.fromPackageName,
|
||||||
@@ -145,8 +141,7 @@ class Intent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Object encode() {
|
Object encode() {
|
||||||
return _toList();
|
return _toList(); }
|
||||||
}
|
|
||||||
|
|
||||||
static Intent decode(Object result) {
|
static Intent decode(Object result) {
|
||||||
result as List<Object?>;
|
result as List<Object?>;
|
||||||
@@ -169,12 +164,7 @@ class Intent {
|
|||||||
if (identical(this, other)) {
|
if (identical(this, other)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return _deepEquals(fromPackageName, other.fromPackageName) &&
|
return _deepEquals(fromPackageName, other.fromPackageName) && _deepEquals(action, other.action) && _deepEquals(data, other.data) && _deepEquals(categories, other.categories) && _deepEquals(mimeType, other.mimeType) && _deepEquals(extra, other.extra);
|
||||||
_deepEquals(action, other.action) &&
|
|
||||||
_deepEquals(data, other.data) &&
|
|
||||||
_deepEquals(categories, other.categories) &&
|
|
||||||
_deepEquals(mimeType, other.mimeType) &&
|
|
||||||
_deepEquals(extra, other.extra);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -182,6 +172,7 @@ class Intent {
|
|||||||
int get hashCode => _deepHash(<Object?>[runtimeType, ..._toList()]);
|
int get hashCode => _deepHash(<Object?>[runtimeType, ..._toList()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class _PigeonCodec extends StandardMessageCodec {
|
class _PigeonCodec extends StandardMessageCodec {
|
||||||
const _PigeonCodec();
|
const _PigeonCodec();
|
||||||
@override
|
@override
|
||||||
@@ -189,7 +180,7 @@ class _PigeonCodec extends StandardMessageCodec {
|
|||||||
if (value is int) {
|
if (value is int) {
|
||||||
buffer.putUint8(4);
|
buffer.putUint8(4);
|
||||||
buffer.putInt64(value);
|
buffer.putInt64(value);
|
||||||
} else if (value is Intent) {
|
} else if (value is Intent) {
|
||||||
buffer.putUint8(129);
|
buffer.putUint8(129);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else {
|
} else {
|
||||||
@@ -213,20 +204,12 @@ abstract class IntentEvents {
|
|||||||
|
|
||||||
void onIntentReceived(int sequence, Intent intent);
|
void onIntentReceived(int sequence, Intent intent);
|
||||||
|
|
||||||
static void setUp(
|
static void setUp(IntentEvents? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) {
|
||||||
IntentEvents? api, {
|
messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
||||||
BinaryMessenger? binaryMessenger,
|
|
||||||
String messageChannelSuffix = '',
|
|
||||||
}) {
|
|
||||||
messageChannelSuffix = messageChannelSuffix.isNotEmpty
|
|
||||||
? '.$messageChannelSuffix'
|
|
||||||
: '';
|
|
||||||
{
|
{
|
||||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
'dev.flutter.pigeon.simple_intent_receiver.IntentEvents.onIntentReceived$messageChannelSuffix',
|
'dev.flutter.pigeon.simple_intent_receiver.IntentEvents.onIntentReceived$messageChannelSuffix', pigeonChannelCodec,
|
||||||
pigeonChannelCodec,
|
binaryMessenger: binaryMessenger);
|
||||||
binaryMessenger: binaryMessenger,
|
|
||||||
);
|
|
||||||
if (api == null) {
|
if (api == null) {
|
||||||
pigeonVar_channel.setMessageHandler(null);
|
pigeonVar_channel.setMessageHandler(null);
|
||||||
} else {
|
} else {
|
||||||
@@ -239,10 +222,8 @@ abstract class IntentEvents {
|
|||||||
return wrapResponse(empty: true);
|
return wrapResponse(empty: true);
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
return wrapResponse(error: e);
|
return wrapResponse(error: e);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return wrapResponse(
|
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
|
||||||
error: PlatformException(code: 'error', message: e.toString()),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -254,13 +235,9 @@ class IntentGatekeeperHostApi {
|
|||||||
/// Constructor for [IntentGatekeeperHostApi]. The [binaryMessenger] named argument is
|
/// Constructor for [IntentGatekeeperHostApi]. The [binaryMessenger] named argument is
|
||||||
/// available for dependency injection. If it is left null, the default
|
/// available for dependency injection. If it is left null, the default
|
||||||
/// BinaryMessenger will be used which routes to the host platform.
|
/// BinaryMessenger will be used which routes to the host platform.
|
||||||
IntentGatekeeperHostApi({
|
IntentGatekeeperHostApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
|
||||||
BinaryMessenger? binaryMessenger,
|
: pigeonVar_binaryMessenger = binaryMessenger,
|
||||||
String messageChannelSuffix = '',
|
pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
||||||
}) : pigeonVar_binaryMessenger = binaryMessenger,
|
|
||||||
pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty
|
|
||||||
? '.$messageChannelSuffix'
|
|
||||||
: '';
|
|
||||||
final BinaryMessenger? pigeonVar_binaryMessenger;
|
final BinaryMessenger? pigeonVar_binaryMessenger;
|
||||||
|
|
||||||
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
|
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
|
||||||
@@ -270,46 +247,42 @@ class IntentGatekeeperHostApi {
|
|||||||
/// Replicates the blocked-packages policy to the native side so the
|
/// Replicates the blocked-packages policy to the native side so the
|
||||||
/// [IntentReceiverActivity] can reject intents without launching Flutter.
|
/// [IntentReceiverActivity] can reject intents without launching Flutter.
|
||||||
Future<void> setConfig(bool enabled, List<String> blockedPackages) async {
|
Future<void> setConfig(bool enabled, List<String> blockedPackages) async {
|
||||||
final pigeonVar_channelName =
|
final pigeonVar_channelName = 'dev.flutter.pigeon.simple_intent_receiver.IntentGatekeeperHostApi.setConfig$pigeonVar_messageChannelSuffix';
|
||||||
'dev.flutter.pigeon.simple_intent_receiver.IntentGatekeeperHostApi.setConfig$pigeonVar_messageChannelSuffix';
|
|
||||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
|
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[enabled, blockedPackages]);
|
||||||
<Object?>[enabled, blockedPackages],
|
|
||||||
);
|
|
||||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||||
|
|
||||||
_extractReplyValueOrThrow(
|
_extractReplyValueOrThrow(
|
||||||
pigeonVar_replyList,
|
pigeonVar_replyList,
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
isNullValid: true,
|
isNullValid: true,
|
||||||
);
|
)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolves a package name to its user-visible application label via
|
/// Resolves a package name to its user-visible application label via
|
||||||
/// [PackageManager]. Returns `null` if the package is not installed or the
|
/// [PackageManager]. Returns `null` if the package is not installed or the
|
||||||
/// label cannot be resolved.
|
/// label cannot be resolved.
|
||||||
Future<String?> resolvePackageLabel(String packageName) async {
|
Future<String?> resolvePackageLabel(String packageName) async {
|
||||||
final pigeonVar_channelName =
|
final pigeonVar_channelName = 'dev.flutter.pigeon.simple_intent_receiver.IntentGatekeeperHostApi.resolvePackageLabel$pigeonVar_messageChannelSuffix';
|
||||||
'dev.flutter.pigeon.simple_intent_receiver.IntentGatekeeperHostApi.resolvePackageLabel$pigeonVar_messageChannelSuffix';
|
|
||||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
|
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[packageName]);
|
||||||
<Object?>[packageName],
|
|
||||||
);
|
|
||||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||||
|
|
||||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||||
pigeonVar_replyList,
|
pigeonVar_replyList,
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
isNullValid: true,
|
isNullValid: true,
|
||||||
);
|
)
|
||||||
|
;
|
||||||
return pigeonVar_replyValue as String?;
|
return pigeonVar_replyValue as String?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,8 +292,7 @@ class IntentGatekeeperHostApi {
|
|||||||
/// [ackPendingAlwaysAllows] after Flutter settings were updated
|
/// [ackPendingAlwaysAllows] after Flutter settings were updated
|
||||||
/// successfully.
|
/// successfully.
|
||||||
Future<List<String>> getPendingAlwaysAllows() async {
|
Future<List<String>> getPendingAlwaysAllows() async {
|
||||||
final pigeonVar_channelName =
|
final pigeonVar_channelName = 'dev.flutter.pigeon.simple_intent_receiver.IntentGatekeeperHostApi.getPendingAlwaysAllows$pigeonVar_messageChannelSuffix';
|
||||||
'dev.flutter.pigeon.simple_intent_receiver.IntentGatekeeperHostApi.getPendingAlwaysAllows$pigeonVar_messageChannelSuffix';
|
|
||||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
@@ -330,32 +302,31 @@ class IntentGatekeeperHostApi {
|
|||||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||||
|
|
||||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||||
pigeonVar_replyList,
|
pigeonVar_replyList,
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
isNullValid: false,
|
isNullValid: false,
|
||||||
);
|
)
|
||||||
|
;
|
||||||
return (pigeonVar_replyValue! as List<Object?>).cast<String>();
|
return (pigeonVar_replyValue! as List<Object?>).cast<String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes the given packages from the pending "Always allow" set after
|
/// Removes the given packages from the pending "Always allow" set after
|
||||||
/// Flutter has successfully persisted them into its own policy store.
|
/// Flutter has successfully persisted them into its own policy store.
|
||||||
Future<void> ackPendingAlwaysAllows(List<String> packageNames) async {
|
Future<void> ackPendingAlwaysAllows(List<String> packageNames) async {
|
||||||
final pigeonVar_channelName =
|
final pigeonVar_channelName = 'dev.flutter.pigeon.simple_intent_receiver.IntentGatekeeperHostApi.ackPendingAlwaysAllows$pigeonVar_messageChannelSuffix';
|
||||||
'dev.flutter.pigeon.simple_intent_receiver.IntentGatekeeperHostApi.ackPendingAlwaysAllows$pigeonVar_messageChannelSuffix';
|
|
||||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
|
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[packageNames]);
|
||||||
<Object?>[packageNames],
|
|
||||||
);
|
|
||||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||||
|
|
||||||
_extractReplyValueOrThrow(
|
_extractReplyValueOrThrow(
|
||||||
pigeonVar_replyList,
|
pigeonVar_replyList,
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
isNullValid: true,
|
isNullValid: true,
|
||||||
);
|
)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:meta/meta.dart' show immutable, protected, visibleForTesting;
|
import 'package:meta/meta.dart' show immutable, protected, visibleForTesting;
|
||||||
|
|
||||||
Object? _extractReplyValueOrThrow(
|
Object? _extractReplyValueOrThrow(
|
||||||
List<Object?>? replyList,
|
List<Object?>? replyList,
|
||||||
String channelName, {
|
String channelName, {
|
||||||
required bool isNullValid,
|
required bool isNullValid,
|
||||||
}) {
|
}) {
|
||||||
if (replyList == null) {
|
if (replyList == null) {
|
||||||
throw PlatformException(
|
throw PlatformException(
|
||||||
@@ -34,11 +34,8 @@ Object? _extractReplyValueOrThrow(
|
|||||||
return replyList.firstOrNull;
|
return replyList.firstOrNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Object?> wrapResponse({
|
|
||||||
Object? result,
|
List<Object?> wrapResponse({Object? result, PlatformException? error, bool empty = false}) {
|
||||||
PlatformException? error,
|
|
||||||
bool empty = false,
|
|
||||||
}) {
|
|
||||||
if (empty) {
|
if (empty) {
|
||||||
return <Object?>[];
|
return <Object?>[];
|
||||||
}
|
}
|
||||||
@@ -48,6 +45,7 @@ List<Object?> wrapResponse({
|
|||||||
return <Object?>[error.code, error.message, error.details];
|
return <Object?>[error.code, error.message, error.details];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class _PigeonCodec extends StandardMessageCodec {
|
class _PigeonCodec extends StandardMessageCodec {
|
||||||
const _PigeonCodec();
|
const _PigeonCodec();
|
||||||
@override
|
@override
|
||||||
@@ -74,13 +72,9 @@ class SpeechToTextApi {
|
|||||||
/// Constructor for [SpeechToTextApi]. The [binaryMessenger] named argument is
|
/// Constructor for [SpeechToTextApi]. The [binaryMessenger] named argument is
|
||||||
/// available for dependency injection. If it is left null, the default
|
/// available for dependency injection. If it is left null, the default
|
||||||
/// BinaryMessenger will be used which routes to the host platform.
|
/// BinaryMessenger will be used which routes to the host platform.
|
||||||
SpeechToTextApi({
|
SpeechToTextApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
|
||||||
BinaryMessenger? binaryMessenger,
|
: pigeonVar_binaryMessenger = binaryMessenger,
|
||||||
String messageChannelSuffix = '',
|
pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
||||||
}) : pigeonVar_binaryMessenger = binaryMessenger,
|
|
||||||
pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty
|
|
||||||
? '.$messageChannelSuffix'
|
|
||||||
: '';
|
|
||||||
final BinaryMessenger? pigeonVar_binaryMessenger;
|
final BinaryMessenger? pigeonVar_binaryMessenger;
|
||||||
|
|
||||||
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
|
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
|
||||||
@@ -95,23 +89,21 @@ class SpeechToTextApi {
|
|||||||
/// The [locale] parameter specifies the language locale for recognition
|
/// The [locale] parameter specifies the language locale for recognition
|
||||||
/// (e.g., 'en-US', 'de-DE'). If null, uses the device default.
|
/// (e.g., 'en-US', 'de-DE'). If null, uses the device default.
|
||||||
Future<bool> showDialog({String? locale}) async {
|
Future<bool> showDialog({String? locale}) async {
|
||||||
final pigeonVar_channelName =
|
final pigeonVar_channelName = 'dev.flutter.pigeon.speech_to_text_dialog.SpeechToTextApi.showDialog$pigeonVar_messageChannelSuffix';
|
||||||
'dev.flutter.pigeon.speech_to_text_dialog.SpeechToTextApi.showDialog$pigeonVar_messageChannelSuffix';
|
|
||||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
|
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[locale]);
|
||||||
<Object?>[locale],
|
|
||||||
);
|
|
||||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||||
|
|
||||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||||
pigeonVar_replyList,
|
pigeonVar_replyList,
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
isNullValid: false,
|
isNullValid: false,
|
||||||
);
|
)
|
||||||
|
;
|
||||||
return pigeonVar_replyValue! as bool;
|
return pigeonVar_replyValue! as bool;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,20 +118,12 @@ abstract class SpeechToTextEvents {
|
|||||||
/// recognition failed or was cancelled.
|
/// recognition failed or was cancelled.
|
||||||
void onTextReceived(String text);
|
void onTextReceived(String text);
|
||||||
|
|
||||||
static void setUp(
|
static void setUp(SpeechToTextEvents? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) {
|
||||||
SpeechToTextEvents? api, {
|
messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
||||||
BinaryMessenger? binaryMessenger,
|
|
||||||
String messageChannelSuffix = '',
|
|
||||||
}) {
|
|
||||||
messageChannelSuffix = messageChannelSuffix.isNotEmpty
|
|
||||||
? '.$messageChannelSuffix'
|
|
||||||
: '';
|
|
||||||
{
|
{
|
||||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
'dev.flutter.pigeon.speech_to_text_dialog.SpeechToTextEvents.onTextReceived$messageChannelSuffix',
|
'dev.flutter.pigeon.speech_to_text_dialog.SpeechToTextEvents.onTextReceived$messageChannelSuffix', pigeonChannelCodec,
|
||||||
pigeonChannelCodec,
|
binaryMessenger: binaryMessenger);
|
||||||
binaryMessenger: binaryMessenger,
|
|
||||||
);
|
|
||||||
if (api == null) {
|
if (api == null) {
|
||||||
pigeonVar_channel.setMessageHandler(null);
|
pigeonVar_channel.setMessageHandler(null);
|
||||||
} else {
|
} else {
|
||||||
@@ -151,10 +135,8 @@ abstract class SpeechToTextEvents {
|
|||||||
return wrapResponse(empty: true);
|
return wrapResponse(empty: true);
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
return wrapResponse(error: e);
|
return wrapResponse(error: e);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return wrapResponse(
|
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
|
||||||
error: PlatformException(code: 'error', message: e.toString()),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user