Add proxy routing and sing-box support
This commit is contained in:
+48
-1
@@ -10,6 +10,7 @@ import eu.weblibre.flutter_mozilla_components.feature.BrowserExtensionFeature
|
||||
import eu.weblibre.flutter_mozilla_components.feature.ContainerProxyFeature
|
||||
import eu.weblibre.flutter_mozilla_components.feature.ResultConsumer
|
||||
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoContainerProxyApi
|
||||
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoProxySettings
|
||||
import org.json.JSONObject
|
||||
|
||||
class GeckoContainerProxyApiImpl : GeckoContainerProxyApi {
|
||||
@@ -25,6 +26,38 @@ class GeckoContainerProxyApiImpl : GeckoContainerProxyApi {
|
||||
ContainerProxyFeature.scheduleRequest("removeContainerProxy", contextId)
|
||||
}
|
||||
|
||||
override fun upsertProxy(proxy: GeckoProxySettings) {
|
||||
ContainerProxyFeature.scheduleRequest("upsertProxy", proxy.toJson())
|
||||
}
|
||||
|
||||
override fun removeProxy(proxyId: String) {
|
||||
ContainerProxyFeature.scheduleRequest("removeProxy", proxyId)
|
||||
}
|
||||
|
||||
override fun setContainerProxy(contextId: String, proxyId: String) {
|
||||
ContainerProxyFeature.scheduleRequest(
|
||||
"setContainerProxy",
|
||||
JSONObject().apply {
|
||||
put("contextId", contextId)
|
||||
put("proxyId", proxyId)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun clearContainerProxy(contextId: String) {
|
||||
ContainerProxyFeature.scheduleRequest("clearContainerProxy", contextId)
|
||||
}
|
||||
|
||||
override fun removeContainerProxyRelation(contextId: String, proxyId: String) {
|
||||
ContainerProxyFeature.scheduleRequest(
|
||||
"removeContainerProxyRelation",
|
||||
JSONObject().apply {
|
||||
put("contextId", contextId)
|
||||
put("proxyId", proxyId)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun setSiteAssignments(assignments: Map<String, String>) {
|
||||
ContainerProxyFeature.scheduleRequest("setSiteAssignments", JSONObject(assignments))
|
||||
}
|
||||
@@ -42,4 +75,18 @@ class GeckoContainerProxyApiImpl : GeckoContainerProxyApi {
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun GeckoProxySettings.toJson(): JSONObject {
|
||||
return JSONObject().apply {
|
||||
put("id", id)
|
||||
put("title", title)
|
||||
put("type", type)
|
||||
put("host", host)
|
||||
put("port", port)
|
||||
username?.let { put("username", it) }
|
||||
password?.let { put("password", it) }
|
||||
put("proxyDNS", proxyDNS)
|
||||
put("doNotProxyLocal", doNotProxyLocal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+17
@@ -12,9 +12,11 @@ import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.util.Log
|
||||
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
||||
import eu.weblibre.flutter_mozilla_components.ext.EventSequence
|
||||
import eu.weblibre.flutter_mozilla_components.feature.InertExternalSchemes
|
||||
import eu.weblibre.flutter_mozilla_components.feature.SandboxCaptureBridge
|
||||
import eu.weblibre.flutter_mozilla_components.feature.SandboxCaptureRegistry
|
||||
import eu.weblibre.flutter_mozilla_components.pigeons.ProxyLoadError
|
||||
import mozilla.components.browser.errorpages.ErrorPages
|
||||
import mozilla.components.browser.errorpages.ErrorType
|
||||
import mozilla.components.browser.state.selector.findTabOrCustomTab
|
||||
@@ -145,6 +147,21 @@ class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
|
||||
errorType: ErrorType,
|
||||
uri: String?,
|
||||
): RequestInterceptor.ErrorResponse {
|
||||
if (errorType == ErrorType.ERROR_PROXY_CONNECTION_REFUSED ||
|
||||
errorType == ErrorType.ERROR_UNKNOWN_PROXY_HOST
|
||||
) {
|
||||
val tab = components.core.store.state.findTabOrCustomTab(session)
|
||||
components.flutterEvents.onProxyLoadError(
|
||||
EventSequence.next(),
|
||||
ProxyLoadError(
|
||||
tabId = tab?.id,
|
||||
contextId = tab?.contextId,
|
||||
url = uri,
|
||||
errorType = errorType.name,
|
||||
)
|
||||
) { _ -> }
|
||||
}
|
||||
|
||||
val errorPage = ErrorPages.createUrlEncodedErrorPage(context, errorType, uri)
|
||||
return RequestInterceptor.ErrorResponse(errorPage)
|
||||
}
|
||||
|
||||
+273
-29
@@ -4573,6 +4573,72 @@ data class MlProgressData (
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class GeckoProxySettings (
|
||||
val id: String,
|
||||
val title: String,
|
||||
val type: String,
|
||||
val host: String,
|
||||
val port: Long,
|
||||
val username: String? = null,
|
||||
val password: String? = null,
|
||||
val proxyDNS: Boolean,
|
||||
val doNotProxyLocal: Boolean
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): GeckoProxySettings {
|
||||
val id = pigeonVar_list[0] as String
|
||||
val title = pigeonVar_list[1] as String
|
||||
val type = pigeonVar_list[2] as String
|
||||
val host = pigeonVar_list[3] as String
|
||||
val port = pigeonVar_list[4] as Long
|
||||
val username = pigeonVar_list[5] as String?
|
||||
val password = pigeonVar_list[6] as String?
|
||||
val proxyDNS = pigeonVar_list[7] as Boolean
|
||||
val doNotProxyLocal = pigeonVar_list[8] as Boolean
|
||||
return GeckoProxySettings(id, title, type, host, port, username, password, proxyDNS, doNotProxyLocal)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
id,
|
||||
title,
|
||||
type,
|
||||
host,
|
||||
port,
|
||||
username,
|
||||
password,
|
||||
proxyDNS,
|
||||
doNotProxyLocal,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as GeckoProxySettings
|
||||
return GeckoPigeonUtils.deepEquals(this.id, other.id) && GeckoPigeonUtils.deepEquals(this.title, other.title) && GeckoPigeonUtils.deepEquals(this.type, other.type) && GeckoPigeonUtils.deepEquals(this.host, other.host) && GeckoPigeonUtils.deepEquals(this.port, other.port) && GeckoPigeonUtils.deepEquals(this.username, other.username) && GeckoPigeonUtils.deepEquals(this.password, other.password) && GeckoPigeonUtils.deepEquals(this.proxyDNS, other.proxyDNS) && GeckoPigeonUtils.deepEquals(this.doNotProxyLocal, other.doNotProxyLocal)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + GeckoPigeonUtils.deepHash(this.id)
|
||||
result = 31 * result + GeckoPigeonUtils.deepHash(this.title)
|
||||
result = 31 * result + GeckoPigeonUtils.deepHash(this.type)
|
||||
result = 31 * result + GeckoPigeonUtils.deepHash(this.host)
|
||||
result = 31 * result + GeckoPigeonUtils.deepHash(this.port)
|
||||
result = 31 * result + GeckoPigeonUtils.deepHash(this.username)
|
||||
result = 31 * result + GeckoPigeonUtils.deepHash(this.password)
|
||||
result = 31 * result + GeckoPigeonUtils.deepHash(this.proxyDNS)
|
||||
result = 31 * result + GeckoPigeonUtils.deepHash(this.doNotProxyLocal)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class ContainerSiteAssignment (
|
||||
val requestId: String,
|
||||
@@ -4623,6 +4689,52 @@ data class ContainerSiteAssignment (
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class ProxyLoadError (
|
||||
val tabId: String? = null,
|
||||
val contextId: String? = null,
|
||||
val url: String? = null,
|
||||
val errorType: String
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): ProxyLoadError {
|
||||
val tabId = pigeonVar_list[0] as String?
|
||||
val contextId = pigeonVar_list[1] as String?
|
||||
val url = pigeonVar_list[2] as String?
|
||||
val errorType = pigeonVar_list[3] as String
|
||||
return ProxyLoadError(tabId, contextId, url, errorType)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
tabId,
|
||||
contextId,
|
||||
url,
|
||||
errorType,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as ProxyLoadError
|
||||
return GeckoPigeonUtils.deepEquals(this.tabId, other.tabId) && GeckoPigeonUtils.deepEquals(this.contextId, other.contextId) && GeckoPigeonUtils.deepEquals(this.url, other.url) && GeckoPigeonUtils.deepEquals(this.errorType, other.errorType)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + GeckoPigeonUtils.deepHash(this.tabId)
|
||||
result = 31 * result + GeckoPigeonUtils.deepHash(this.contextId)
|
||||
result = 31 * result + GeckoPigeonUtils.deepHash(this.url)
|
||||
result = 31 * result + GeckoPigeonUtils.deepHash(this.errorType)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class GeckoHeader (
|
||||
val key: String,
|
||||
@@ -5995,75 +6107,85 @@ private open class GeckoPigeonCodec : StandardMessageCodec() {
|
||||
}
|
||||
235.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
ContainerSiteAssignment.fromList(it)
|
||||
GeckoProxySettings.fromList(it)
|
||||
}
|
||||
}
|
||||
236.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
GeckoHeader.fromList(it)
|
||||
ContainerSiteAssignment.fromList(it)
|
||||
}
|
||||
}
|
||||
237.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
GeckoFetchRequest.fromList(it)
|
||||
ProxyLoadError.fromList(it)
|
||||
}
|
||||
}
|
||||
238.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
GeckoFetchResponse.fromList(it)
|
||||
GeckoHeader.fromList(it)
|
||||
}
|
||||
}
|
||||
239.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
BookmarkNode.fromList(it)
|
||||
GeckoFetchRequest.fromList(it)
|
||||
}
|
||||
}
|
||||
240.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
BookmarkInfo.fromList(it)
|
||||
GeckoFetchResponse.fromList(it)
|
||||
}
|
||||
}
|
||||
241.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
SitePermissions.fromList(it)
|
||||
BookmarkNode.fromList(it)
|
||||
}
|
||||
}
|
||||
242.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
TrackingProtectionException.fromList(it)
|
||||
BookmarkInfo.fromList(it)
|
||||
}
|
||||
}
|
||||
243.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
PwaIcon.fromList(it)
|
||||
SitePermissions.fromList(it)
|
||||
}
|
||||
}
|
||||
244.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
ShareTargetFiles.fromList(it)
|
||||
TrackingProtectionException.fromList(it)
|
||||
}
|
||||
}
|
||||
245.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
ShareTargetParams.fromList(it)
|
||||
PwaIcon.fromList(it)
|
||||
}
|
||||
}
|
||||
246.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
ShareTarget.fromList(it)
|
||||
ShareTargetFiles.fromList(it)
|
||||
}
|
||||
}
|
||||
247.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
ExternalApplicationResource.fromList(it)
|
||||
ShareTargetParams.fromList(it)
|
||||
}
|
||||
}
|
||||
248.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
PwaManifest.fromList(it)
|
||||
ShareTarget.fromList(it)
|
||||
}
|
||||
}
|
||||
249.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
ExternalApplicationResource.fromList(it)
|
||||
}
|
||||
}
|
||||
250.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
PwaManifest.fromList(it)
|
||||
}
|
||||
}
|
||||
251.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
SandboxCaptureEntry.fromList(it)
|
||||
}
|
||||
@@ -6497,66 +6619,74 @@ private open class GeckoPigeonCodec : StandardMessageCodec() {
|
||||
stream.write(234)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is ContainerSiteAssignment -> {
|
||||
is GeckoProxySettings -> {
|
||||
stream.write(235)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is GeckoHeader -> {
|
||||
is ContainerSiteAssignment -> {
|
||||
stream.write(236)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is GeckoFetchRequest -> {
|
||||
is ProxyLoadError -> {
|
||||
stream.write(237)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is GeckoFetchResponse -> {
|
||||
is GeckoHeader -> {
|
||||
stream.write(238)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is BookmarkNode -> {
|
||||
is GeckoFetchRequest -> {
|
||||
stream.write(239)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is BookmarkInfo -> {
|
||||
is GeckoFetchResponse -> {
|
||||
stream.write(240)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is SitePermissions -> {
|
||||
is BookmarkNode -> {
|
||||
stream.write(241)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is TrackingProtectionException -> {
|
||||
is BookmarkInfo -> {
|
||||
stream.write(242)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is PwaIcon -> {
|
||||
is SitePermissions -> {
|
||||
stream.write(243)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is ShareTargetFiles -> {
|
||||
is TrackingProtectionException -> {
|
||||
stream.write(244)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is ShareTargetParams -> {
|
||||
is PwaIcon -> {
|
||||
stream.write(245)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is ShareTarget -> {
|
||||
is ShareTargetFiles -> {
|
||||
stream.write(246)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is ExternalApplicationResource -> {
|
||||
is ShareTargetParams -> {
|
||||
stream.write(247)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is PwaManifest -> {
|
||||
is ShareTarget -> {
|
||||
stream.write(248)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is SandboxCaptureEntry -> {
|
||||
is ExternalApplicationResource -> {
|
||||
stream.write(249)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is PwaManifest -> {
|
||||
stream.write(250)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is SandboxCaptureEntry -> {
|
||||
stream.write(251)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
else -> super.writeValue(stream, value)
|
||||
}
|
||||
}
|
||||
@@ -8279,6 +8409,11 @@ interface GeckoContainerProxyApi {
|
||||
fun setProxyPort(port: Long)
|
||||
fun addContainerProxy(contextId: String)
|
||||
fun removeContainerProxy(contextId: String)
|
||||
fun upsertProxy(proxy: GeckoProxySettings)
|
||||
fun removeProxy(proxyId: String)
|
||||
fun setContainerProxy(contextId: String, proxyId: String)
|
||||
fun clearContainerProxy(contextId: String)
|
||||
fun removeContainerProxyRelation(contextId: String, proxyId: String)
|
||||
fun setSiteAssignments(assignments: Map<String, String>)
|
||||
fun healthcheck(callback: (Result<Boolean>) -> Unit)
|
||||
|
||||
@@ -8345,6 +8480,98 @@ interface GeckoContainerProxyApi {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.upsertProxy$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val proxyArg = args[0] as GeckoProxySettings
|
||||
val wrapped: List<Any?> = try {
|
||||
api.upsertProxy(proxyArg)
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
GeckoPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.removeProxy$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val proxyIdArg = args[0] as String
|
||||
val wrapped: List<Any?> = try {
|
||||
api.removeProxy(proxyIdArg)
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
GeckoPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.setContainerProxy$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val contextIdArg = args[0] as String
|
||||
val proxyIdArg = args[1] as String
|
||||
val wrapped: List<Any?> = try {
|
||||
api.setContainerProxy(contextIdArg, proxyIdArg)
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
GeckoPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.clearContainerProxy$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val contextIdArg = args[0] as String
|
||||
val wrapped: List<Any?> = try {
|
||||
api.clearContainerProxy(contextIdArg)
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
GeckoPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.removeContainerProxyRelation$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val contextIdArg = args[0] as String
|
||||
val proxyIdArg = args[1] as String
|
||||
val wrapped: List<Any?> = try {
|
||||
api.removeContainerProxyRelation(contextIdArg, proxyIdArg)
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
GeckoPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.setSiteAssignments$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
@@ -8785,6 +9012,23 @@ class GeckoStateEvents(private val binaryMessenger: BinaryMessenger, private val
|
||||
}
|
||||
}
|
||||
}
|
||||
fun onProxyLoadError(sequenceArg: Long, detailsArg: ProxyLoadError, callback: (Result<Unit>) -> Unit)
|
||||
{
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
val channelName = "dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onProxyLoadError$separatedMessageChannelSuffix"
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
||||
channel.send(listOf(sequenceArg, detailsArg)) {
|
||||
if (it is List<*>) {
|
||||
if (it.size > 1) {
|
||||
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
||||
} else {
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(GeckoPigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
fun onMlProgress(sequenceArg: Long, progressArg: MlProgressData, callback: (Result<Unit>) -> Unit)
|
||||
{
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ const privateIdentifier = 'firefox-private'
|
||||
type DoNotProxy = never[]
|
||||
export const doNotProxy: DoNotProxy = []
|
||||
|
||||
const emergencyBreak: Socks5ProxyInfo = {
|
||||
export const emergencyBreak: Socks5ProxyInfo = {
|
||||
type: ProxyType.Socks5,
|
||||
host: 'emergency-break-proxy.localhost',
|
||||
port: 1,
|
||||
|
||||
+37
-2
@@ -1,4 +1,4 @@
|
||||
import { Socks5ProxySettings } from 'src/domain/ProxySettings';
|
||||
import { ProxySettings, Socks5ProxySettings } from 'src/domain/ProxySettings';
|
||||
import { Store } from '../store/Store'
|
||||
import BackgroundMain from './BackgroundMain'
|
||||
|
||||
@@ -8,7 +8,16 @@ const store = new Store()
|
||||
|
||||
interface Message {
|
||||
id: String | undefined;
|
||||
action: 'setProxyPort' | 'addContainerProxy' | 'removeContainerProxy' | 'healthcheck' | 'setSiteAssignments';
|
||||
action: 'setProxyPort' |
|
||||
'addContainerProxy' |
|
||||
'removeContainerProxy' |
|
||||
'upsertProxy' |
|
||||
'removeProxy' |
|
||||
'setContainerProxy' |
|
||||
'clearContainerProxy' |
|
||||
'removeContainerProxyRelation' |
|
||||
'healthcheck' |
|
||||
'setSiteAssignments';
|
||||
args: any;
|
||||
}
|
||||
|
||||
@@ -42,6 +51,32 @@ port.onMessage.addListener((raw: unknown): void => {
|
||||
store.removeContainerProxyRelation(message.args, "tor")
|
||||
console.log('removed container relation ' + message.args)
|
||||
break
|
||||
case "upsertProxy": {
|
||||
const proxy = ProxySettings.tryFromDao(message.args)
|
||||
if (proxy === undefined) {
|
||||
console.error('invalid proxy settings ' + JSON.stringify(message.args))
|
||||
break
|
||||
}
|
||||
store.putProxy(proxy)
|
||||
console.log('upsert proxy ' + message.args.id)
|
||||
break
|
||||
}
|
||||
case "removeProxy":
|
||||
store.deleteProxyById(message.args)
|
||||
console.log('removed proxy ' + message.args)
|
||||
break
|
||||
case "setContainerProxy":
|
||||
store.setContainerProxyRelation(message.args.contextId, message.args.proxyId)
|
||||
console.log('set container relation ' + message.args.contextId + ' -> ' + message.args.proxyId)
|
||||
break
|
||||
case "clearContainerProxy":
|
||||
store.clearContainerProxyRelation(message.args)
|
||||
console.log('cleared container relation ' + message.args)
|
||||
break
|
||||
case "removeContainerProxyRelation":
|
||||
store.removeContainerProxyRelation(message.args.contextId, message.args.proxyId)
|
||||
console.log('removed container relation ' + message.args.contextId + ' -> ' + message.args.proxyId)
|
||||
break
|
||||
case "setSiteAssignments":
|
||||
const entries = new Map(Object.entries(message.args))
|
||||
console.log('set site assignments ' + JSON.stringify(message.args))
|
||||
|
||||
@@ -224,6 +224,10 @@ export class Store {
|
||||
this.relations[cookieStoreId] = [proxyId]
|
||||
}
|
||||
|
||||
clearContainerProxyRelation(cookieStoreId: string): void {
|
||||
delete this.relations[cookieStoreId]
|
||||
}
|
||||
|
||||
removeContainerProxyRelation(cookieStoreId: string, proxyId: string): void {
|
||||
const currentRelations = this.relations[cookieStoreId] ?? []
|
||||
this.relations[cookieStoreId] = currentRelations.filter(id => id !== proxyId)
|
||||
|
||||
+11
-1
@@ -1,4 +1,4 @@
|
||||
import BackgroundMain, { doNotProxy } from '../../src/background/BackgroundMain'
|
||||
import BackgroundMain, { doNotProxy, emergencyBreak } from '../../src/background/BackgroundMain'
|
||||
import { Store } from '../../src/store/Store'
|
||||
|
||||
import { expect } from 'chai'
|
||||
@@ -41,6 +41,16 @@ describe('BackgroundMain', function () {
|
||||
expect(result).to.be.not.empty
|
||||
})
|
||||
|
||||
it('should block if an assigned proxy no longer exists', async () => {
|
||||
const isolatedStore = new Store()
|
||||
const isolatedBackgroundMain = new BackgroundMain({ store: isolatedStore })
|
||||
isolatedStore.setContainerProxyRelation('general', 'missing-proxy')
|
||||
|
||||
const result = await isolatedBackgroundMain.onRequest({ cookieStoreId: 'firefox-default', url: 'https://google.com', tabId: 0 })
|
||||
|
||||
expect(result).to.be.deep.equal([emergencyBreak])
|
||||
})
|
||||
|
||||
it('should remove doNotProxyLocal flag from proxy settings if proxy is set up', async () => {
|
||||
await givenSomeProxyIsSetUpForContainer({ containerId: 'firefox-default', host: undefined, doNotProxyLocal: undefined })
|
||||
|
||||
|
||||
@@ -163,6 +163,15 @@ describe('Store', () => {
|
||||
expect(relations.container1).to.be.deep.equal(['proxy1'])
|
||||
expect(relations.container2).to.be.deep.equal(['proxy2'])
|
||||
})
|
||||
|
||||
it('should keep a missing proxy relation distinguishable from no relation', () => {
|
||||
const isolatedStore = new Store()
|
||||
isolatedStore.setContainerProxyRelation('container1', 'deleted-proxy')
|
||||
|
||||
const result = isolatedStore.getProxiesForContainer('container1')
|
||||
|
||||
expect(result).to.be.deep.equal([])
|
||||
})
|
||||
})
|
||||
|
||||
describe('wildcard site assignments', function () {
|
||||
|
||||
@@ -69,6 +69,7 @@ export 'src/pigeons/gecko.g.dart'
|
||||
GeckoDeleteBrowsingDataController,
|
||||
GeckoEngineSettings,
|
||||
GeckoFetchResponse,
|
||||
GeckoProxySettings,
|
||||
GeckoPref,
|
||||
GeckoPublicSuffixListApi,
|
||||
GeckoPwaApi,
|
||||
@@ -93,6 +94,7 @@ export 'src/pigeons/gecko.g.dart'
|
||||
MlProgressStatus,
|
||||
MlProgressType,
|
||||
PhoneHitResult,
|
||||
ProxyLoadError,
|
||||
PwaIcon,
|
||||
PwaManifest,
|
||||
QueryParameterStripping,
|
||||
|
||||
+20
@@ -24,6 +24,26 @@ class GeckoContainerProxyService {
|
||||
return _apiInstance.removeContainerProxy(contextId);
|
||||
}
|
||||
|
||||
Future<void> upsertProxy(GeckoProxySettings proxy) {
|
||||
return _apiInstance.upsertProxy(proxy);
|
||||
}
|
||||
|
||||
Future<void> removeProxy(String proxyId) {
|
||||
return _apiInstance.removeProxy(proxyId);
|
||||
}
|
||||
|
||||
Future<void> setContainerProxy(String contextId, String proxyId) {
|
||||
return _apiInstance.setContainerProxy(contextId, proxyId);
|
||||
}
|
||||
|
||||
Future<void> clearContainerProxy(String contextId) {
|
||||
return _apiInstance.clearContainerProxy(contextId);
|
||||
}
|
||||
|
||||
Future<void> removeContainerProxyRelation(String contextId, String proxyId) {
|
||||
return _apiInstance.removeContainerProxyRelation(contextId, proxyId);
|
||||
}
|
||||
|
||||
Future<void> setSiteAssignments(Map<String, String> assignments) {
|
||||
return _apiInstance.setSiteAssignments(assignments);
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ class GeckoEventService extends GeckoStateEvents {
|
||||
// final _scrollEventSubject = PublishSubject<ScrollEvent>();
|
||||
final _prefUpdateSubject = PublishSubject<GeckoPref>();
|
||||
final _siteAssignementSubject = PublishSubject<ContainerSiteAssignment>();
|
||||
final _proxyLoadErrorSubject = PublishSubject<ProxyLoadError>();
|
||||
|
||||
final _tabAddedSubject = PublishSubject<String>();
|
||||
final _mlProgressSubject = PublishSubject<MlProgressData>();
|
||||
@@ -71,6 +72,8 @@ class GeckoEventService extends GeckoStateEvents {
|
||||
Stream<GeckoPref> get prefUpdateEvent => _prefUpdateSubject.stream;
|
||||
Stream<ContainerSiteAssignment> get siteAssignementEvent =>
|
||||
_siteAssignementSubject.stream;
|
||||
Stream<ProxyLoadError> get proxyLoadErrorEvents =>
|
||||
_proxyLoadErrorSubject.stream;
|
||||
|
||||
Stream<String> get tabAddedStream => _tabAddedSubject.stream;
|
||||
Stream<MlProgressData> get mlProgressEvents => _mlProgressSubject.stream;
|
||||
@@ -205,6 +208,11 @@ class GeckoEventService extends GeckoStateEvents {
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void onProxyLoadError(int sequence, ProxyLoadError details) {
|
||||
_proxyLoadErrorSubject.addWhenMoreRecent(sequence, details.tabId, details);
|
||||
}
|
||||
|
||||
@override
|
||||
void onMlProgress(int sequence, MlProgressData progress) {
|
||||
_mlProgressSubject.addWhenMoreRecent(sequence, null, progress);
|
||||
@@ -266,6 +274,7 @@ class GeckoEventService extends GeckoStateEvents {
|
||||
await _tabAddedSubject.close();
|
||||
await _prefUpdateSubject.close();
|
||||
await _siteAssignementSubject.close();
|
||||
await _proxyLoadErrorSubject.close();
|
||||
await _mlProgressSubject.close();
|
||||
await _manifestUpdateSubject.close();
|
||||
await _translationEngineSubject.close();
|
||||
|
||||
@@ -91,7 +91,10 @@ class GeckoHistoryService {
|
||||
return _api.getVisited(urls);
|
||||
}
|
||||
|
||||
Future<List<HistorySuggestion>> getSuggestions(String query, {int limit = 10}) {
|
||||
Future<List<HistorySuggestion>> getSuggestions(
|
||||
String query, {
|
||||
int limit = 10,
|
||||
}) {
|
||||
return _api.getSuggestions(query, limit);
|
||||
}
|
||||
|
||||
@@ -140,6 +143,8 @@ class GeckoHistoryService {
|
||||
}
|
||||
|
||||
Future<void> deleteHistoryMetadataOlderThan(DateTime olderThan) {
|
||||
return _api.deleteHistoryMetadataOlderThan(olderThan.millisecondsSinceEpoch);
|
||||
return _api.deleteHistoryMetadataOlderThan(
|
||||
olderThan.millisecondsSinceEpoch,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1856,11 +1856,40 @@ abstract class GeckoBrowserExtensionApi {
|
||||
List<Object> getMarkdown(List<String> htmlList);
|
||||
}
|
||||
|
||||
class GeckoProxySettings {
|
||||
final String id;
|
||||
final String title;
|
||||
final String type;
|
||||
final String host;
|
||||
final int port;
|
||||
final String? username;
|
||||
final String? password;
|
||||
final bool proxyDNS;
|
||||
final bool doNotProxyLocal;
|
||||
|
||||
const GeckoProxySettings({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.type,
|
||||
required this.host,
|
||||
required this.port,
|
||||
this.username,
|
||||
this.password,
|
||||
this.proxyDNS = true,
|
||||
this.doNotProxyLocal = true,
|
||||
});
|
||||
}
|
||||
|
||||
@HostApi()
|
||||
abstract class GeckoContainerProxyApi {
|
||||
void setProxyPort(int port);
|
||||
void addContainerProxy(String contextId);
|
||||
void removeContainerProxy(String contextId);
|
||||
void upsertProxy(GeckoProxySettings proxy);
|
||||
void removeProxy(String proxyId);
|
||||
void setContainerProxy(String contextId, String proxyId);
|
||||
void clearContainerProxy(String contextId);
|
||||
void removeContainerProxyRelation(String contextId, String proxyId);
|
||||
void setSiteAssignments(Map<String, String> assignments);
|
||||
|
||||
@async
|
||||
@@ -1930,6 +1959,20 @@ class ContainerSiteAssignment {
|
||||
});
|
||||
}
|
||||
|
||||
class ProxyLoadError {
|
||||
final String? tabId;
|
||||
final String? contextId;
|
||||
final String? url;
|
||||
final String errorType;
|
||||
|
||||
ProxyLoadError({
|
||||
required this.tabId,
|
||||
required this.contextId,
|
||||
required this.url,
|
||||
required this.errorType,
|
||||
});
|
||||
}
|
||||
|
||||
@FlutterApi()
|
||||
abstract class GeckoStateEvents {
|
||||
void onViewReadyStateChange(int sequence, bool state);
|
||||
@@ -1960,6 +2003,8 @@ abstract class GeckoStateEvents {
|
||||
|
||||
void onContainerSiteAssignment(int sequence, ContainerSiteAssignment details);
|
||||
|
||||
void onProxyLoadError(int sequence, ProxyLoadError details);
|
||||
|
||||
void onMlProgress(int sequence, MlProgressData progress);
|
||||
|
||||
void onManifestUpdate(int sequence, String tabId, PwaManifest? manifest);
|
||||
|
||||
Reference in New Issue
Block a user