mirror of
https://github.com/GopeedLab/gopeed.git
synced 2026-11-04 15:49:49 +00:00
fix(webview): ignore load notifications from browser error documents
This commit is contained in:
1 parent
1776b05782
commit
2fd8a96c5d
4 files changed
+57
-5
No files matched your search
@@ -0,0 +1,49 @@
|
||||
//go:build cgo
|
||||
|
||||
package goprovider
|
||||
|
||||
import (
|
||||
enginewebview "github.com/GopeedLab/gopeed/pkg/download/engine/webview"
|
||||
webview "github.com/GopeedLab/webview_go"
|
||||
"github.com/dop251/goja"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestInternalErrorDocumentDoesNotReportPageEvents(t *testing.T) {
|
||||
vm := goja.New()
|
||||
if _, err := vm.RunString(`
|
||||
var window = globalThis;
|
||||
window.top = window;
|
||||
var location = {protocol: "chrome-error:", href: "chrome-error://chromewebdata/"};
|
||||
var notifications = [];
|
||||
var listeners = [];
|
||||
function notify(payload) { notifications.push(payload); }
|
||||
window.addEventListener = (name) => listeners.push(name);
|
||||
`); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := vm.RunString(buildLoadNotifyScript("notify")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, name := range []string{"notifications", "listeners"} {
|
||||
value, err := vm.RunString(name + ".length")
|
||||
if err != nil || value.ToInteger() != 0 {
|
||||
t.Fatalf("internal error page registered %s: %v (%v)", name, value, err)
|
||||
}
|
||||
}
|
||||
// The provider must wait for the native failure, preserving the failed URL.
|
||||
page := newPageWrapper(enginewebview.OpenOptions{})
|
||||
got := make(chan string, 1)
|
||||
_, err := page.On("load-error", func(e enginewebview.Event) { got <- e.Data["url"].(string) })
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
page.handleNativeEvent(webview.Event{Name: "load-error", URL: "https://example.test/failure", Message: "TLS handshake failed"})
|
||||
if err := page.waitForNavigation(time.Second, "load"); err == nil {
|
||||
t.Fatal("native failure completed navigation successfully")
|
||||
}
|
||||
if url := <-got; url != "https://example.test/failure" {
|
||||
t.Fatal(url)
|
||||
}
|
||||
}
|
||||
@@ -369,7 +369,7 @@ func (p *pageWrapper) Close() error {
|
||||
}
|
||||
|
||||
func (p *pageWrapper) tracef(format string, args ...any) {
|
||||
if !strings.Contains(p.opts.Title, "youtube-sabr") && p.opts.Title != "WebView event contract" {
|
||||
if !strings.Contains(p.opts.Title, "youtube-sabr") {
|
||||
return
|
||||
}
|
||||
fmt.Printf("goprovider "+format+"\n", args...)
|
||||
@@ -387,14 +387,12 @@ func (p *pageWrapper) waitForNavigation(timeout time.Duration, waitUntil string)
|
||||
case <-timer.C:
|
||||
return fmt.Errorf("webview navigation timeout")
|
||||
case <-p.sameDocument:
|
||||
p.tracef("goto completed via same-document notification")
|
||||
return nil
|
||||
case <-p.domReady:
|
||||
if waitUntil == "domcontentloaded" {
|
||||
return nil
|
||||
}
|
||||
case <-p.loads:
|
||||
p.tracef("goto completed via load notification")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -479,7 +477,6 @@ func (p *pageWrapper) handleCallback(payload string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
p.tracef("page event: event=%s load=%v url=%s sameDocument=%v", msg.Event, msg.Load, msg.URL, msg.SameDocument)
|
||||
if msg.Event == "domcontentloaded" {
|
||||
select {
|
||||
case p.domReady <- struct{}{}:
|
||||
@@ -607,6 +604,9 @@ func buildLoadNotifyScript(callbackName string) string {
|
||||
callbackJSON, _ := json.Marshal(callbackName)
|
||||
return fmt.Sprintf(`(() => {
|
||||
if (window !== window.top) return;
|
||||
// WebView2 runs init scripts in its internal error document too. Its load
|
||||
// must not complete goto() before the native NavigationCompleted failure.
|
||||
if (location.protocol === "chrome-error:") return;
|
||||
const send = (message) => {
|
||||
const cb = globalThis[%s];
|
||||
if (typeof cb === "function") cb(JSON.stringify(message));
|
||||
@@ -650,7 +650,6 @@ func (p *pageWrapper) failPendingLocked() {
|
||||
}
|
||||
|
||||
func (p *pageWrapper) handleNativeEvent(event webview.Event) {
|
||||
p.tracef("native event: %+v", event)
|
||||
switch event.Name {
|
||||
case "load-error":
|
||||
p.events.Emit(enginewebview.Event{Name: "load-error", Data: map[string]any{"url": event.URL, "message": event.Message}})
|
||||
|
||||
@@ -5,6 +5,8 @@ String buildWebViewEventScript(String channel) =>
|
||||
'''
|
||||
(() => {
|
||||
if (window !== window.top) return;
|
||||
// Browser error documents are reported by native load-error callbacks.
|
||||
if (location.protocol === 'chrome-error:') return;
|
||||
const pending = [];
|
||||
const flush = () => {
|
||||
const bridge = window.flutter_inappwebview;
|
||||
|
||||
@@ -4,6 +4,8 @@ import 'dart:convert';
|
||||
String buildWebViewEventScript(String channel) => '''
|
||||
(() => {
|
||||
if (window !== window.top) return;
|
||||
// Browser error documents are reported by native load-error callbacks.
|
||||
if (location.protocol === 'chrome-error:') return;
|
||||
const pending = [];
|
||||
const flush = () => {
|
||||
const bridge = window.flutter_inappwebview;
|
||||
|
||||
Reference in new issue
Block a user