detached ee29e14

feat(port): add Engine interface and supporting types

Defines the Engine interface and all supporting types (CookiePolicy,
EngineOptions, SchemeHandler, MessageRouter, SettingsApplier,
FilterApplier, FaviconDatabase, ScriptRefresher) in port/engine.go
as the first step in making the webview engine swappable.
commit
ee29e14142b106e6840f67d5dd64f4fefec015f5
author
brice · · 2026-03-15 16:05 UTC
parent
1c398d3
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
1 file · +134 -0
A internal/application/port/engine.go +134 -0
@@ -0,0 +1,134 @@
1+// Package port defines application-layer interfaces for external capabilities.
2+// Ports abstract infrastructure concerns, allowing the application layer to
3+// remain independent of specific implementations (WebKit, GTK, etc.).
4+package port
5+
6+import "context"
7+
8+// CookiePolicy controls cookie acceptance behavior for the engine's network session.
9+type CookiePolicy string
10+
11+const (
12+ // CookiePolicyAlways accepts all cookies.
13+ CookiePolicyAlways CookiePolicy = "always"
14+ // CookiePolicyNoThirdParty rejects third-party cookies.
15+ CookiePolicyNoThirdParty CookiePolicy = "no_third_party"
16+ // CookiePolicyNever rejects all cookies.
17+ CookiePolicyNever CookiePolicy = "never"
18+)
19+
20+// EngineOptions configures engine initialization.
21+type EngineOptions struct {
22+ // DataDir is the directory for persistent data (cookies, storage, etc.).
23+ DataDir string
24+
25+ // CacheDir is the directory for cache data.
26+ CacheDir string
27+
28+ // CookiePolicy controls cookie acceptance behavior.
29+ // Empty value means runtime defaults are used.
30+ CookiePolicy CookiePolicy
31+
32+ // WebProcessMemory configures memory pressure for web processes.
33+ // nil means use engine defaults.
34+ WebProcessMemory *MemoryPressureConfig
35+
36+ // NetworkProcessMemory configures memory pressure for the network process.
37+ // nil means use engine defaults.
38+ NetworkProcessMemory *MemoryPressureConfig
39+}
40+
41+// Engine is the top-level interface for a browser engine implementation.
42+// It provides access to all engine subsystems and manages the lifecycle
43+// of the underlying browser context.
44+type Engine interface {
45+ // Init initializes the engine with the given options.
46+ // Must be called before any other methods.
47+ Init(ctx context.Context, opts EngineOptions) error
48+
49+ // Factory returns the WebViewFactory for creating new WebView instances.
50+ Factory() WebViewFactory
51+
52+ // Pool returns the WebViewPool for acquiring pre-warmed WebView instances.
53+ Pool() WebViewPool
54+
55+ // SchemeHandler returns the SchemeHandler for registering custom URI schemes.
56+ SchemeHandler() SchemeHandler
57+
58+ // ContentInjector returns the ContentInjector for injecting scripts and styles.
59+ ContentInjector() ContentInjector
60+
61+ // MessageRouter returns the MessageRouter for JS-to-Go message passing.
62+ MessageRouter() MessageRouter
63+
64+ // SettingsApplier returns the SettingsApplier for applying browser settings.
65+ SettingsApplier() SettingsApplier
66+
67+ // FilterApplier returns the FilterApplier for applying content filters.
68+ // Returns nil if content filtering is not supported by this engine.
69+ FilterApplier() FilterApplier
70+
71+ // FaviconDatabase returns the FaviconDatabase for async favicon lookups.
72+ FaviconDatabase() FaviconDatabase
73+
74+ // InternalSchemePath returns the URI scheme used for internal app resources.
75+ InternalSchemePath() string
76+
77+ // Close releases all resources held by the engine.
78+ Close() error
79+}
80+
81+// SchemeHandler defines the port interface for registering custom URI schemes.
82+// Implementations intercept navigation to registered schemes and serve content
83+// from application code.
84+type SchemeHandler interface {
85+ // RegisterScheme registers a handler for the given URI scheme.
86+ // The handler receives the full URI and returns the response body,
87+ // MIME type, and any error.
88+ RegisterScheme(scheme string, handler func(uri string) ([]byte, string, error))
89+}
90+
91+// MessageRouter defines the port interface for bidirectional JS-to-Go messaging.
92+// It allows JavaScript running in a WebView to invoke named Go handlers,
93+// and allows Go code to post messages back to a specific WebView.
94+type MessageRouter interface {
95+ // RegisterHandler registers a named message handler callable from JavaScript.
96+ // The handler receives a JSON-encoded message string and returns a
97+ // JSON-encoded response string.
98+ RegisterHandler(name string, handler func(message string) (string, error))
99+
100+ // PostMessage sends a message to the JavaScript context of the given WebView.
101+ PostMessage(webviewID WebViewID, message string) error
102+}
103+
104+// SettingsApplier defines the port interface for applying browser settings to WebViews.
105+// Implementations apply engine-specific settings (security, features, etc.) uniformly
106+// across a set of WebView instances.
107+type SettingsApplier interface {
108+ // ApplyToAll applies settings to all provided WebView instances.
109+ ApplyToAll(ctx context.Context, webviews []WebView)
110+}
111+
112+// FilterApplier defines the port interface for applying content filters to WebViews.
113+// Implementations configure content blocking rules on a set of WebView instances.
114+// This interface is optional; Engine.FilterApplier() returns nil if not supported.
115+type FilterApplier interface {
116+ // ApplyToAll applies content filters to all provided WebView instances.
117+ ApplyToAll(ctx context.Context, webviews []WebView)
118+}
119+
120+// FaviconDatabase defines the port interface for async favicon lookups.
121+// Implementations retrieve favicons from an engine-managed database and
122+// deliver them via callback on the main thread.
123+type FaviconDatabase interface {
124+ // GetFaviconAsync retrieves the favicon for the given page URL asynchronously.
125+ // The callback is invoked with the favicon Texture when available.
126+ GetFaviconAsync(pageURL string, callback func(Texture))
127+}
128+
129+// ScriptRefresher defines the port interface for refreshing injected scripts
130+// across multiple WebView instances (e.g., after a settings change).
131+type ScriptRefresher interface {
132+ // RefreshAll re-injects scripts into all provided WebView instances.
133+ RefreshAll(ctx context.Context, webviews []WebView)
134+}
@@ -0,0 +1,134 @@
1+// Package port defines application-layer interfaces for external capabilities.
2+// Ports abstract infrastructure concerns, allowing the application layer to
3+// remain independent of specific implementations (WebKit, GTK, etc.).
4+package port
5+
6+import "context"
7+
8+// CookiePolicy controls cookie acceptance behavior for the engine's network session.
9+type CookiePolicy string
10+
11+const (
12+ // CookiePolicyAlways accepts all cookies.
13+ CookiePolicyAlways CookiePolicy = "always"
14+ // CookiePolicyNoThirdParty rejects third-party cookies.
15+ CookiePolicyNoThirdParty CookiePolicy = "no_third_party"
16+ // CookiePolicyNever rejects all cookies.
17+ CookiePolicyNever CookiePolicy = "never"
18+)
19+
20+// EngineOptions configures engine initialization.
21+type EngineOptions struct {
22+ // DataDir is the directory for persistent data (cookies, storage, etc.).
23+ DataDir string
24+
25+ // CacheDir is the directory for cache data.
26+ CacheDir string
27+
28+ // CookiePolicy controls cookie acceptance behavior.
29+ // Empty value means runtime defaults are used.
30+ CookiePolicy CookiePolicy
31+
32+ // WebProcessMemory configures memory pressure for web processes.
33+ // nil means use engine defaults.
34+ WebProcessMemory *MemoryPressureConfig
35+
36+ // NetworkProcessMemory configures memory pressure for the network process.
37+ // nil means use engine defaults.
38+ NetworkProcessMemory *MemoryPressureConfig
39+}
40+
41+// Engine is the top-level interface for a browser engine implementation.
42+// It provides access to all engine subsystems and manages the lifecycle
43+// of the underlying browser context.
44+type Engine interface {
45+ // Init initializes the engine with the given options.
46+ // Must be called before any other methods.
47+ Init(ctx context.Context, opts EngineOptions) error
48+
49+ // Factory returns the WebViewFactory for creating new WebView instances.
50+ Factory() WebViewFactory
51+
52+ // Pool returns the WebViewPool for acquiring pre-warmed WebView instances.
53+ Pool() WebViewPool
54+
55+ // SchemeHandler returns the SchemeHandler for registering custom URI schemes.
56+ SchemeHandler() SchemeHandler
57+
58+ // ContentInjector returns the ContentInjector for injecting scripts and styles.
59+ ContentInjector() ContentInjector
60+
61+ // MessageRouter returns the MessageRouter for JS-to-Go message passing.
62+ MessageRouter() MessageRouter
63+
64+ // SettingsApplier returns the SettingsApplier for applying browser settings.
65+ SettingsApplier() SettingsApplier
66+
67+ // FilterApplier returns the FilterApplier for applying content filters.
68+ // Returns nil if content filtering is not supported by this engine.
69+ FilterApplier() FilterApplier
70+
71+ // FaviconDatabase returns the FaviconDatabase for async favicon lookups.
72+ FaviconDatabase() FaviconDatabase
73+
74+ // InternalSchemePath returns the URI scheme used for internal app resources.
75+ InternalSchemePath() string
76+
77+ // Close releases all resources held by the engine.
78+ Close() error
79+}
80+
81+// SchemeHandler defines the port interface for registering custom URI schemes.
82+// Implementations intercept navigation to registered schemes and serve content
83+// from application code.
84+type SchemeHandler interface {
85+ // RegisterScheme registers a handler for the given URI scheme.
86+ // The handler receives the full URI and returns the response body,
87+ // MIME type, and any error.
88+ RegisterScheme(scheme string, handler func(uri string) ([]byte, string, error))
89+}
90+
91+// MessageRouter defines the port interface for bidirectional JS-to-Go messaging.
92+// It allows JavaScript running in a WebView to invoke named Go handlers,
93+// and allows Go code to post messages back to a specific WebView.
94+type MessageRouter interface {
95+ // RegisterHandler registers a named message handler callable from JavaScript.
96+ // The handler receives a JSON-encoded message string and returns a
97+ // JSON-encoded response string.
98+ RegisterHandler(name string, handler func(message string) (string, error))
99+
100+ // PostMessage sends a message to the JavaScript context of the given WebView.
101+ PostMessage(webviewID WebViewID, message string) error
102+}
103+
104+// SettingsApplier defines the port interface for applying browser settings to WebViews.
105+// Implementations apply engine-specific settings (security, features, etc.) uniformly
106+// across a set of WebView instances.
107+type SettingsApplier interface {
108+ // ApplyToAll applies settings to all provided WebView instances.
109+ ApplyToAll(ctx context.Context, webviews []WebView)
110+}
111+
112+// FilterApplier defines the port interface for applying content filters to WebViews.
113+// Implementations configure content blocking rules on a set of WebView instances.
114+// This interface is optional; Engine.FilterApplier() returns nil if not supported.
115+type FilterApplier interface {
116+ // ApplyToAll applies content filters to all provided WebView instances.
117+ ApplyToAll(ctx context.Context, webviews []WebView)
118+}
119+
120+// FaviconDatabase defines the port interface for async favicon lookups.
121+// Implementations retrieve favicons from an engine-managed database and
122+// deliver them via callback on the main thread.
123+type FaviconDatabase interface {
124+ // GetFaviconAsync retrieves the favicon for the given page URL asynchronously.
125+ // The callback is invoked with the favicon Texture when available.
126+ GetFaviconAsync(pageURL string, callback func(Texture))
127+}
128+
129+// ScriptRefresher defines the port interface for refreshing injected scripts
130+// across multiple WebView instances (e.g., after a settings change).
131+type ScriptRefresher interface {
132+ // RefreshAll re-injects scripts into all provided WebView instances.
133+ RefreshAll(ctx context.Context, webviews []WebView)
134+}

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