Merge latest main into 2.0.0-beta.2

# Conflicts:
#	internal/webview/README.md
#	ui/flutter/lib/app/rpc/webview_rpc_service.dart
#	ui/flutter/pubspec.lock
#	ui/flutter/pubspec.yaml
This commit is contained in:
Levi committed 2026-09-17 21:47:43 +08:00
commit 88dd35cc46
7 files changed
+185 -32

No files matched your search

+4 -1
View File
@@ -3,7 +3,10 @@
The downloader wraps each provider with the extension's stable identity before
constructing the runtime. `OpenOptions.ProfileID`, `DataPath`, and `ProxyURL` are
host-only fields. `parseOpenOptions` never reads them from extension JavaScript.
The extension API is unchanged.
The extension API is unchanged. The Flutter host uses the fork's public
`WebViewProfile`, `InAppWebViewSettings.profileId`, and profile-scoped
`CookieManager` APIs; the library has no Gopeed-specific method-channel bridge.
Only the Gopeed extension JavaScript boundary keeps these options host-only.
Profiles are persistent and shared across invocations/pages of the same extension.
Different identities use different native stores. Go providers use a SHA-256-based
+6
View File
@@ -1,5 +1,11 @@
# rpcprovider
The private Flutter native profile bridge is maintained in the
[GopeedLab flutter_inappwebview fork](https://github.com/GopeedLab/flutter_inappwebview/tree/codex/gopeed-profiles).
All three platform overrides pin one commit in `ui/flutter/pubspec.yaml`;
see the fork’s [GOPEED.md](https://github.com/GopeedLab/flutter_inappwebview/blob/codex/gopeed-profiles/GOPEED.md)
for patch scope and upstream synchronization.
`rpcprovider` is the RPC-backed implementation of Gopeed's `webview.Provider` interface.
It is intended for environments where WebView capability is owned by another process, most notably mobile hosts. This package does not implement a WebView itself. Instead, it translates the `pkg/download/engine/webview` page API into single-request `POST + JSON` calls sent to a local host-side RPC service.
@@ -32,6 +32,7 @@ final class GopeedContinuedProcessingManager: NSObject {
private var expiringTasks:
[String: ExpiringTaskState] = [:]
private var taskGenerations: [String: UUID] = [:]
private var progressRecoveryTokens: [String: UUID] = [:]
private var activeTasks:
[String: BGContinuedProcessingTask] = [:]
@@ -224,6 +225,10 @@ final class GopeedContinuedProcessingManager: NSObject {
switch type {
case "task.start":
progressRecoveryTokens.removeValue(
forKey: taskID
)
beginTask(
taskID: taskID,
name: name
@@ -237,6 +242,11 @@ final class GopeedContinuedProcessingManager: NSObject {
generation: generation,
force: false
)
} else {
recoverTaskFromProgress(
taskID: taskID,
name: name
)
}
case "task.pause":
@@ -285,6 +295,72 @@ final class GopeedContinuedProcessingManager: NSObject {
}
// MARK: - Recover active task after setting changes
private func recoverTaskFromProgress(
taskID: String,
name: String
) {
guard
currentEnabledSnapshot(),
taskGenerations[taskID] == nil,
!pendingTaskIDs.contains(taskID),
activeTasks[taskID] == nil,
expiringTasks[taskID] == nil,
progressRecoveryTokens[taskID] == nil
else {
return
}
let recoveryToken = UUID()
progressRecoveryTokens[taskID] =
recoveryToken
getRuntimeStatus(
taskID: taskID
) { [weak self] runtime in
guard
let self,
self.progressRecoveryTokens[taskID]
== recoveryToken
else {
return
}
// The status request has completed. Remove the token so
// another progress event may retry if recovery is still
// necessary.
self.progressRecoveryTokens.removeValue(
forKey: taskID
)
guard
self.currentEnabledSnapshot(),
let runtime,
runtime.status == "running",
self.taskGenerations[taskID] == nil,
!self.pendingTaskIDs.contains(taskID),
self.activeTasks[taskID] == nil,
self.expiringTasks[taskID] == nil
else {
return
}
print(
"ContinuedProcessing:",
"recovering active task:",
taskID
)
self.beginTask(
taskID: taskID,
name: name
)
}
}
// MARK: - Used by Objective-C forwarder
@objc(isHandlingTaskId:)
@@ -825,6 +901,10 @@ final class GopeedContinuedProcessingManager: NSObject {
success: Bool,
finalSubtitle: String
) {
progressRecoveryTokens.removeValue(
forKey: taskID
)
taskGenerations.removeValue(
forKey: taskID
)
@@ -1063,6 +1143,7 @@ final class GopeedContinuedProcessingManager: NSObject {
pendingTaskIDs.removeAll()
expiringTasks.removeAll()
taskGenerations.removeAll()
progressRecoveryTokens.removeAll()
taskIdentifiers.removeAll()
taskNames.removeAll()
lastProgressUpdate.removeAll()
@@ -108,6 +108,39 @@ final class GopeedLiveActivityManager: NSObject {
return generation
}
private func generationForProgress(
taskID: String
) -> UUID? {
stateLock.lock()
defer { stateLock.unlock() }
guard
!suppressedTaskIDs.contains(taskID)
else {
return nil
}
if let generation =
taskGenerations[taskID] {
return generation
}
// Progress may be the first event after Continued Processing
// releases ownership. Establish a fresh lifecycle generation.
// refreshActivity still verifies that Gopeed reports the task
// as running before it can create a Live Activity.
let generation = UUID()
taskGenerations[taskID] =
generation
lastUpdateTime.removeValue(
forKey: taskID
)
return generation
}
@discardableResult
private func invalidateGeneration(
taskID: String
@@ -252,7 +285,7 @@ final class GopeedLiveActivityManager: NSObject {
case "task.progress":
guard
let generation =
currentGeneration(
generationForProgress(
taskID: taskID
)
else {
@@ -167,11 +167,11 @@ class WebViewRpcService {
Future<Map<String, dynamic>> _openPage(Map<String, dynamic> params) async {
final profile = WebViewProfile(_string(params, 'profileId'));
await profile.prepare(_string(params, 'proxyUrl'));
await profile.prepare(proxyUrl: Uri.parse(_string(params, 'proxyUrl')));
final pageId = 'page-${++_pageSeq}';
final session = WebViewRpcPageSession(
pageId: pageId,
cookieManager: profile,
profile: profile,
headless: params['headless'] as bool? ?? false,
debug: params['debug'] as bool? ?? false,
title: params['title'] as String? ?? '',
@@ -192,7 +192,7 @@ class WebViewRpcService {
}
Future<void> _removeProfile(String id) async {
for (final page in _pagesById.values.where((page) => page.cookieManager.id == id).toList()) {
for (final page in _pagesById.values.where((page) => page.profile.id == id).toList()) {
await _closePage(page.pageId);
}
// Let visible platform views unmount before releasing their native store.
@@ -301,7 +301,7 @@ class WebViewRpcService {
class WebViewRpcPageSession {
WebViewRpcPageSession({
required this.pageId,
required this.cookieManager,
required this.profile,
required this.headless,
required this.debug,
required this.title,
@@ -311,7 +311,8 @@ class WebViewRpcPageSession {
});
final String pageId;
final WebViewProfile cookieManager;
final WebViewProfile profile;
late final CookieManager cookieManager = profile.cookieManager;
final bool headless;
final bool debug;
final String title;
@@ -543,9 +544,11 @@ class WebViewRpcPageSession {
);
}
InAppWebViewSettings get _settings => WebViewProfileSettings(
profileId: cookieManager.id,
debug: debug,
InAppWebViewSettings get _settings => InAppWebViewSettings(
profileId: profile.id,
javaScriptEnabled: true,
transparentBackground: true,
isInspectable: debug,
userAgent: userAgent.isNotEmpty ? userAgent : null,
);
+26 -18
View File
@@ -457,17 +457,20 @@ packages:
flutter_inappwebview:
dependency: "direct main"
description:
name: flutter_inappwebview
sha256: "80092d13d3e29b6227e25b67973c67c7210bd5e35c4b747ca908e31eb71a46d5"
url: "https://pub.dev"
source: hosted
path: flutter_inappwebview
ref: d579215760e1c1e58a4ff7601a6055b5e6adf8e8
resolved-ref: d579215760e1c1e58a4ff7601a6055b5e6adf8e8
url: "https://github.com/GopeedLab/flutter_inappwebview.git"
source: git
version: "6.1.5"
flutter_inappwebview_android:
dependency: "direct overridden"
description:
path: "third_party/flutter_inappwebview_android"
relative: true
source: path
path: flutter_inappwebview_android
ref: d579215760e1c1e58a4ff7601a6055b5e6adf8e8
resolved-ref: d579215760e1c1e58a4ff7601a6055b5e6adf8e8
url: "https://github.com/GopeedLab/flutter_inappwebview.git"
source: git
version: "1.1.3"
flutter_inappwebview_internal_annotations:
dependency: transitive
@@ -480,24 +483,29 @@ packages:
flutter_inappwebview_ios:
dependency: "direct overridden"
description:
path: "third_party/flutter_inappwebview_ios"
relative: true
source: path
path: flutter_inappwebview_ios
ref: d579215760e1c1e58a4ff7601a6055b5e6adf8e8
resolved-ref: d579215760e1c1e58a4ff7601a6055b5e6adf8e8
url: "https://github.com/GopeedLab/flutter_inappwebview.git"
source: git
version: "1.1.2"
flutter_inappwebview_macos:
dependency: "direct overridden"
description:
path: "third_party/flutter_inappwebview_macos"
relative: true
source: path
path: flutter_inappwebview_macos
ref: d579215760e1c1e58a4ff7601a6055b5e6adf8e8
resolved-ref: d579215760e1c1e58a4ff7601a6055b5e6adf8e8
url: "https://github.com/GopeedLab/flutter_inappwebview.git"
source: git
version: "1.1.2"
flutter_inappwebview_platform_interface:
dependency: transitive
dependency: "direct overridden"
description:
name: flutter_inappwebview_platform_interface
sha256: cf5323e194096b6ede7a1ca808c3e0a078e4b33cc3f6338977d75b4024ba2500
url: "https://pub.dev"
source: hosted
path: flutter_inappwebview_platform_interface
ref: d579215760e1c1e58a4ff7601a6055b5e6adf8e8
resolved-ref: d579215760e1c1e58a4ff7601a6055b5e6adf8e8
url: "https://github.com/GopeedLab/flutter_inappwebview.git"
source: git
version: "1.3.0+1"
flutter_inappwebview_web:
dependency: transitive
+23 -4
View File
@@ -86,13 +86,32 @@ dependencies:
go_router: ^16.2.1
dependency_overrides:
# Host-only native WebView profile/proxy bridge.
# Public persistent-profile and proxy APIs; keep all packages on one commit.
flutter_inappwebview:
git:
url: https://github.com/GopeedLab/flutter_inappwebview.git
ref: d579215760e1c1e58a4ff7601a6055b5e6adf8e8
path: flutter_inappwebview
flutter_inappwebview_platform_interface:
git:
url: https://github.com/GopeedLab/flutter_inappwebview.git
ref: d579215760e1c1e58a4ff7601a6055b5e6adf8e8
path: flutter_inappwebview_platform_interface
flutter_inappwebview_macos:
path: third_party/flutter_inappwebview_macos
git:
url: https://github.com/GopeedLab/flutter_inappwebview.git
ref: d579215760e1c1e58a4ff7601a6055b5e6adf8e8
path: flutter_inappwebview_macos
flutter_inappwebview_ios:
path: third_party/flutter_inappwebview_ios
git:
url: https://github.com/GopeedLab/flutter_inappwebview.git
ref: d579215760e1c1e58a4ff7601a6055b5e6adf8e8
path: flutter_inappwebview_ios
flutter_inappwebview_android:
path: third_party/flutter_inappwebview_android
git:
url: https://github.com/GopeedLab/flutter_inappwebview.git
ref: d579215760e1c1e58a4ff7601a6055b5e6adf8e8
path: flutter_inappwebview_android
# Prevent a native Windows crash when the push notification service is unavailable.
# Keep this fork until https://github.com/MaikuB/flutter_local_notifications/pull/2813 is merged and released.
flutter_local_notifications: