detached 3ef6fdf

fix(webkit): use default WebContext to prevent dumb:// scheme mismatch

commit
3ef6fdfb408bea07421d1ca05fc74621b509c7b2
author
brice · · 2025-12-28 17:20 UTC
committer
brice · · 2025-12-29 17:28 UTC
parent
95e4a50
signature
unsigned
2 files · +27 -21
M internal/infrastructure/webkit/context.go +11 -20
@@ -74,30 +74,21 @@ func NewWebKitContextWithOptions(ctx context.Context, opts port.WebKitContextOpt
7474 return nil, fmt.Errorf("failed to init network session: %w", err)
7575 }
7676
77- // Create WebContext - with memory pressure settings if configured
77+ // WebViews in this codebase are created via WebKit's default WebContext.
78+ // If we create a separate WebContext here and only register our custom
79+ // dumb:// scheme on it, internal pages will break with "The URL can't be shown".
80+ //
81+ // Additionally, WebKit's "memory-pressure-settings" is a construct-only property,
82+ // so setting it after `webkit.NewWebContext()` triggers a GLib critical and has no effect.
83+ // Until we can reliably construct a WebContext with memory-pressure-settings AND ensure
84+ // all WebViews use that context, we intentionally stick to the default WebContext.
7885 if opts.IsWebProcessMemoryConfigured() {
79- applier := NewMemoryPressureApplier()
80- settings, err := applier.ApplyWebProcessSettings(ctx, opts.WebProcessMemory)
81- if err != nil {
82- log.Warn().Err(err).Msg("failed to prepare web process memory pressure settings")
83- }
84- if settings != nil {
85- wkCtx.webContext = createWebContextWithMemorySettings(settings.(*webkit.MemoryPressureSettings))
86- if wkCtx.webContext != nil {
87- log.Debug().Msg("created WebContext with memory pressure settings")
88- }
89- }
86+ log.Warn().Msg("web process memory pressure settings requested but not applied (construct-only WebContext property; would break dumb:// scheme registration)")
9087 }
9188
92- // Fall back to default WebContext if not created above
93- if wkCtx.webContext == nil {
94- wkCtx.webContext = webkit.WebContextGetDefault()
95- if wkCtx.webContext == nil {
96- wkCtx.webContext = webkit.NewWebContext()
97- }
98- }
89+ wkCtx.webContext = webkit.WebContextGetDefault()
9990 if wkCtx.webContext == nil {
100- return nil, fmt.Errorf("failed to get or create WebContext")
91+ return nil, fmt.Errorf("failed to get default WebContext")
10192 }
10293
10394 // Set cache model for browser-style caching
@@ -74,30 +74,21 @@ func NewWebKitContextWithOptions(ctx context.Context, opts port.WebKitContextOpt
74 return nil, fmt.Errorf("failed to init network session: %w", err)74 return nil, fmt.Errorf("failed to init network session: %w", err)
75 }75 }
76 76
77- // Create WebContext - with memory pressure settings if configured77+ // WebViews in this codebase are created via WebKit's default WebContext.
78+ // If we create a separate WebContext here and only register our custom
79+ // dumb:// scheme on it, internal pages will break with "The URL can't be shown".
80+ //
81+ // Additionally, WebKit's "memory-pressure-settings" is a construct-only property,
82+ // so setting it after `webkit.NewWebContext()` triggers a GLib critical and has no effect.
83+ // Until we can reliably construct a WebContext with memory-pressure-settings AND ensure
84+ // all WebViews use that context, we intentionally stick to the default WebContext.
78 if opts.IsWebProcessMemoryConfigured() {85 if opts.IsWebProcessMemoryConfigured() {
79- applier := NewMemoryPressureApplier()86+ log.Warn().Msg("web process memory pressure settings requested but not applied (construct-only WebContext property; would break dumb:// scheme registration)")
80- settings, err := applier.ApplyWebProcessSettings(ctx, opts.WebProcessMemory)
81- if err != nil {
82- log.Warn().Err(err).Msg("failed to prepare web process memory pressure settings")
83- }
84- if settings != nil {
85- wkCtx.webContext = createWebContextWithMemorySettings(settings.(*webkit.MemoryPressureSettings))
86- if wkCtx.webContext != nil {
87- log.Debug().Msg("created WebContext with memory pressure settings")
88- }
89- }
90 }87 }
91 88
92- // Fall back to default WebContext if not created above89+ wkCtx.webContext = webkit.WebContextGetDefault()
93- if wkCtx.webContext == nil {
94- wkCtx.webContext = webkit.WebContextGetDefault()
95- if wkCtx.webContext == nil {
96- wkCtx.webContext = webkit.NewWebContext()
97- }
98- }
99 if wkCtx.webContext == nil {90 if wkCtx.webContext == nil {
100- return nil, fmt.Errorf("failed to get or create WebContext")91+ return nil, fmt.Errorf("failed to get default WebContext")
101 }92 }
102 93
103 // Set cache model for browser-style caching94 // Set cache model for browser-style caching
M internal/infrastructure/webkit/webview.go +16 -1
@@ -248,12 +248,27 @@ func NewWebView(ctx context.Context, wkCtx *WebKitContext, settings *SettingsMan
248248 return nil, fmt.Errorf("webkit context not initialized")
249249 }
250250
251- // Use NetworkSession-aware constructor for persistent cookie storage
251+ // Use NetworkSession-aware constructor for persistent cookie/storage.
252252 inner := webkit.NewWebViewWithNetworkSession(wkCtx.NetworkSession())
253253 if inner == nil {
254254 return nil, fmt.Errorf("failed to create webkit webview with network session")
255255 }
256256
257+ // Sanity check: our internal dumb:// scheme must be registered on the same WebContext
258+ // that the WebView is actually using.
259+ if expectedCtx := wkCtx.Context(); expectedCtx != nil {
260+ if actualCtx := inner.GetContext(); actualCtx != nil {
261+ expectedPtr := expectedCtx.GoPointer()
262+ actualPtr := actualCtx.GoPointer()
263+ if expectedPtr != 0 && actualPtr != 0 && expectedPtr != actualPtr {
264+ log.Warn().
265+ Uint64("expected_web_context", uint64(expectedPtr)).
266+ Uint64("actual_web_context", uint64(actualPtr)).
267+ Msg("webview WebContext mismatch; internal dumb:// pages may fail")
268+ }
269+ }
270+ }
271+
257272 // Set background color IMMEDIATELY after creation, before any other operations.
258273 // This prevents white flash by ensuring WebKit's renderer starts with correct color.
259274 if bgColor != nil {
@@ -248,12 +248,27 @@ func NewWebView(ctx context.Context, wkCtx *WebKitContext, settings *SettingsMan
248 return nil, fmt.Errorf("webkit context not initialized")248 return nil, fmt.Errorf("webkit context not initialized")
249 }249 }
250 250
251- // Use NetworkSession-aware constructor for persistent cookie storage251+ // Use NetworkSession-aware constructor for persistent cookie/storage.
252 inner := webkit.NewWebViewWithNetworkSession(wkCtx.NetworkSession())252 inner := webkit.NewWebViewWithNetworkSession(wkCtx.NetworkSession())
253 if inner == nil {253 if inner == nil {
254 return nil, fmt.Errorf("failed to create webkit webview with network session")254 return nil, fmt.Errorf("failed to create webkit webview with network session")
255 }255 }
256 256
257+ // Sanity check: our internal dumb:// scheme must be registered on the same WebContext
258+ // that the WebView is actually using.
259+ if expectedCtx := wkCtx.Context(); expectedCtx != nil {
260+ if actualCtx := inner.GetContext(); actualCtx != nil {
261+ expectedPtr := expectedCtx.GoPointer()
262+ actualPtr := actualCtx.GoPointer()
263+ if expectedPtr != 0 && actualPtr != 0 && expectedPtr != actualPtr {
264+ log.Warn().
265+ Uint64("expected_web_context", uint64(expectedPtr)).
266+ Uint64("actual_web_context", uint64(actualPtr)).
267+ Msg("webview WebContext mismatch; internal dumb:// pages may fail")
268+ }
269+ }
270+ }
271+
257 // Set background color IMMEDIATELY after creation, before any other operations.272 // Set background color IMMEDIATELY after creation, before any other operations.
258 // This prevents white flash by ensuring WebKit's renderer starts with correct color.273 // This prevents white flash by ensuring WebKit's renderer starts with correct color.
259 if bgColor != nil {274 if bgColor != nil {

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close