mirror of
https://github.com/GopeedLab/gopeed.git
synced 2026-11-07 00:50:27 +00:00
Preserve existing profile connections when opening more pages
This commit is contained in:
1 parent
ca98806dcc
commit
c47b735fc4
8 files changed
+46
-11
No files matched your search
@@ -1,9 +1,9 @@
|
||||
name: WebView host profiles
|
||||
on:
|
||||
push:
|
||||
paths: ['internal/webview/**', 'pkg/download/extension_webview*', 'ui/flutter/third_party/**', 'ui/flutter/lib/app/rpc/webview*', 'ui/flutter/tool/webview_profile_check.dart', '.github/workflows/webview-profiles.yml']
|
||||
paths: ['go.mod', 'go.sum', 'internal/webview/**', 'pkg/download/extension_webview*', 'ui/flutter/third_party/**', 'ui/flutter/lib/app/rpc/webview*', 'ui/flutter/tool/webview_profile_check.dart', '.github/workflows/webview-profiles.yml']
|
||||
pull_request:
|
||||
paths: ['internal/webview/**', 'pkg/download/extension_webview*', 'ui/flutter/third_party/**', 'ui/flutter/lib/app/rpc/webview*', 'ui/flutter/tool/webview_profile_check.dart', '.github/workflows/webview-profiles.yml']
|
||||
paths: ['go.mod', 'go.sum', 'internal/webview/**', 'pkg/download/extension_webview*', 'ui/flutter/third_party/**', 'ui/flutter/lib/app/rpc/webview*', 'ui/flutter/tool/webview_profile_check.dart', '.github/workflows/webview-profiles.yml']
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
android-plugin:
|
||||
|
||||
@@ -3,7 +3,7 @@ module github.com/GopeedLab/gopeed
|
||||
go 1.25.4
|
||||
|
||||
require (
|
||||
github.com/GopeedLab/webview_go v0.0.0-20260913163011-2273ba19d2db
|
||||
github.com/GopeedLab/webview_go v0.0.0-20260913163948-312792cc8833
|
||||
github.com/anacrolix/torrent v1.60.1-0.20251217073903-486bcbe758e0
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
|
||||
github.com/bodgit/sevenzip v1.6.1
|
||||
|
||||
@@ -23,12 +23,8 @@ filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmG
|
||||
filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/GopeedLab/webview_go v0.0.0-20260423085439-7a2f88b6e9b5 h1:86LVTaNDM/j/uTAD2HedkXNO9LIQlt642VAdbU/0D/M=
|
||||
github.com/GopeedLab/webview_go v0.0.0-20260423085439-7a2f88b6e9b5/go.mod h1:FvV19lu9rQ9NcbczN5y8pbWecURRRbWa8tbfFARBDa0=
|
||||
github.com/GopeedLab/webview_go v0.0.0-20260913162656-5f4deb099005 h1:4jyEJfmP5tpx+qaWqTF6Y04jy4xTTTGWo3l2alh9uZM=
|
||||
github.com/GopeedLab/webview_go v0.0.0-20260913162656-5f4deb099005/go.mod h1:FvV19lu9rQ9NcbczN5y8pbWecURRRbWa8tbfFARBDa0=
|
||||
github.com/GopeedLab/webview_go v0.0.0-20260913163011-2273ba19d2db h1:kZya8+v61mZx7ys0eN1MePyXJPoB1HGRE9O4cValX9M=
|
||||
github.com/GopeedLab/webview_go v0.0.0-20260913163011-2273ba19d2db/go.mod h1:FvV19lu9rQ9NcbczN5y8pbWecURRRbWa8tbfFARBDa0=
|
||||
github.com/GopeedLab/webview_go v0.0.0-20260913163948-312792cc8833 h1:g0jFsuDhGZvALiBr1rxiNZlPC5eb4H9k7KUpkQ//MuI=
|
||||
github.com/GopeedLab/webview_go v0.0.0-20260913163948-312792cc8833/go.mod h1:FvV19lu9rQ9NcbczN5y8pbWecURRRbWa8tbfFARBDa0=
|
||||
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
|
||||
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'dart:collection';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import '../../core/common/start_config.dart';
|
||||
@@ -273,6 +274,9 @@ class WebViewRpcService {
|
||||
if (error is WebViewRpcException) {
|
||||
return {'code': error.code, 'message': error.message};
|
||||
}
|
||||
if (error is PlatformException && error.code == 'UNAVAILABLE') {
|
||||
return {'code': error.code, 'message': error.message ?? 'WebView is unavailable'};
|
||||
}
|
||||
final code = switch (method) {
|
||||
'page.goto' => 'NAVIGATION_FAILED',
|
||||
'page.execute' => 'EVALUATION_FAILED',
|
||||
|
||||
+24
-2
@@ -10,6 +10,9 @@ import io.flutter.plugin.common.MethodChannel;
|
||||
|
||||
// Internal host bridge: profile creation and proxy completion precede navigation.
|
||||
final class GopeedProfiles {
|
||||
private static String appliedProxy;
|
||||
private static String pendingProxy;
|
||||
private static final java.util.List<MethodChannel.Result> pending = new java.util.ArrayList<>();
|
||||
static void prepare(MethodCall call, MethodChannel.Result result) {
|
||||
if (!WebViewFeature.isFeatureSupported(WebViewFeature.MULTI_PROFILE) ||
|
||||
!WebViewFeature.isFeatureSupported(WebViewFeature.PROXY_OVERRIDE)) {
|
||||
@@ -24,10 +27,29 @@ final class GopeedProfiles {
|
||||
if (!"http".equals(uri.getScheme()) || !"127.0.0.1".equals(uri.getHost()) || uri.getPort() <= 0)
|
||||
throw new IllegalArgumentException("Invalid host proxy configuration");
|
||||
ProfileStore.getInstance().getOrCreateProfile(id);
|
||||
if (proxy.equals(appliedProxy)) { result.success(true); return; }
|
||||
if (pendingProxy != null) {
|
||||
if (proxy.equals(pendingProxy)) pending.add(result);
|
||||
else result.error("UNAVAILABLE", "A different WebView proxy is being configured", null);
|
||||
return;
|
||||
}
|
||||
pendingProxy = proxy;
|
||||
pending.add(result);
|
||||
ProxyConfig config = new ProxyConfig.Builder().addProxyRule(proxy).removeImplicitRules().build();
|
||||
ProxyController.getInstance().setProxyOverride(config, Runnable::run, () -> result.success(true));
|
||||
ProxyController.getInstance().setProxyOverride(config, task -> new android.os.Handler(android.os.Looper.getMainLooper()).post(task), () -> {
|
||||
appliedProxy = proxy;
|
||||
pendingProxy = null;
|
||||
java.util.List<MethodChannel.Result> completed = new java.util.ArrayList<>(pending);
|
||||
pending.clear();
|
||||
for (MethodChannel.Result callback : completed) callback.success(true);
|
||||
});
|
||||
} catch (RuntimeException e) {
|
||||
result.error("UNAVAILABLE", "Unable to configure WebView profile and proxy", null);
|
||||
if (pendingProxy != null && pending.contains(result)) {
|
||||
pendingProxy = null;
|
||||
java.util.List<MethodChannel.Result> failed = new java.util.ArrayList<>(pending);
|
||||
pending.clear();
|
||||
for (MethodChannel.Result callback : failed) callback.error("UNAVAILABLE", "Unable to configure WebView profile and proxy", null);
|
||||
} else result.error("UNAVAILABLE", "Unable to configure WebView profile and proxy", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -5,6 +5,7 @@ import Network
|
||||
import Flutter
|
||||
|
||||
final class GopeedProfiles {
|
||||
private static var proxyURLs: [String: String] = [:]
|
||||
private static var stores: [String: WKWebsiteDataStore] = [:]
|
||||
static func store(_ identifier: String) -> WKWebsiteDataStore? { stores[identifier] }
|
||||
|
||||
@@ -19,11 +20,16 @@ final class GopeedProfiles {
|
||||
result(FlutterError(code: "UNAVAILABLE", message: "Isolated WebView profiles and proxy require macOS 14 / iOS 17 or newer and valid host configuration", details: nil))
|
||||
return
|
||||
}
|
||||
if stores[identifier] != nil && proxyURLs[identifier] == proxyURL {
|
||||
result(true)
|
||||
return
|
||||
}
|
||||
let store = stores[identifier] ?? WKWebsiteDataStore(forIdentifier: uuid)
|
||||
let endpoint = nw_endpoint_create_host(host, String(port))
|
||||
let proxy = nw_proxy_config_create_socksv5(endpoint)
|
||||
store.__proxyConfigurations = [proxy]
|
||||
stores[identifier] = store
|
||||
proxyURLs[identifier] = proxyURL
|
||||
result(true)
|
||||
}
|
||||
}
|
||||
+6
@@ -5,6 +5,7 @@ import Network
|
||||
import FlutterMacOS
|
||||
|
||||
final class GopeedProfiles {
|
||||
private static var proxyURLs: [String: String] = [:]
|
||||
private static var stores: [String: WKWebsiteDataStore] = [:]
|
||||
static func store(_ identifier: String) -> WKWebsiteDataStore? { stores[identifier] }
|
||||
|
||||
@@ -19,11 +20,16 @@ final class GopeedProfiles {
|
||||
result(FlutterError(code: "UNAVAILABLE", message: "Isolated WebView profiles and proxy require macOS 14 / iOS 17 or newer and valid host configuration", details: nil))
|
||||
return
|
||||
}
|
||||
if stores[identifier] != nil && proxyURLs[identifier] == proxyURL {
|
||||
result(true)
|
||||
return
|
||||
}
|
||||
let store = stores[identifier] ?? WKWebsiteDataStore(forIdentifier: uuid)
|
||||
let endpoint = nw_endpoint_create_host(host, String(port))
|
||||
let proxy = nw_proxy_config_create_socksv5(endpoint)
|
||||
store.__proxyConfigurations = [proxy]
|
||||
stores[identifier] = store
|
||||
proxyURLs[identifier] = proxyURL
|
||||
result(true)
|
||||
}
|
||||
}
|
||||
@@ -97,6 +97,7 @@ Future<void> checkProfiles() async {
|
||||
final target = WebUri('https://profiles.invalid/');
|
||||
final pages = <HeadlessInAppWebView>[];
|
||||
Future<InAppWebViewController> open(WebViewProfile profile) async {
|
||||
await profile.prepare(proxyUrl);
|
||||
final ready = Completer<InAppWebViewController>();
|
||||
final page = HeadlessInAppWebView(
|
||||
onReceivedServerTrustAuthRequest: (_, _) async =>
|
||||
|
||||
Reference in new issue
Block a user