1package webkit
2
3import (
4 "context"
5 "fmt"
6
7 "github.com/bnema/dumber/internal/application/port"
8 "github.com/bnema/dumber/internal/infrastructure/filtering"
9 "github.com/bnema/dumber/internal/logging"
10 "github.com/bnema/puregotk/v4/gio"
11)
12
13// --- WebViewFactory adapter ---
14
15// webViewFactoryAdapter bridges *WebViewFactory to port.WebViewFactory.
16// WebViewFactory.Create and CreateRelated return *WebView, not port.WebView,
17// so this adapter wraps the return values.
18type webViewFactoryAdapter struct {
19 factory *WebViewFactory
20}
21
22func (a *webViewFactoryAdapter) Create(ctx context.Context) (port.WebView, error) {
23 wv, err := a.factory.Create(ctx)
24 if err != nil {
25 return nil, err
26 }
27 return wv, nil
28}
29
30func (a *webViewFactoryAdapter) CreateRelated(ctx context.Context, parentID port.WebViewID) (port.WebView, error) {
31 wv, err := a.factory.CreateRelated(ctx, parentID)
32 if err != nil {
33 return nil, err
34 }
35 return wv, nil
36}
37
38// --- WebViewPool adapter ---
39
40// webViewPoolAdapter bridges *WebViewPool to port.WebViewPool.
41// WebViewPool methods use *WebView and require a context; this adapter adapts
42// the signatures to match the port interface.
43type webViewPoolAdapter struct {
44 pool *WebViewPool
45 ctx context.Context
46}
47
48func (a *webViewPoolAdapter) Acquire(ctx context.Context) (port.WebView, error) {
49 wv, err := a.pool.Acquire(ctx)
50 if err != nil {
51 return nil, err
52 }
53 return wv, nil
54}
55
56func (a *webViewPoolAdapter) Release(wv port.WebView) {
57 if wv == nil {
58 return
59 }
60 wwv, ok := wv.(*WebView)
61 if !ok {
62 logging.FromContext(a.ctx).Warn().
63 Str("concrete_type", fmt.Sprintf("%T", wv)).
64 Msg("webViewPoolAdapter.Release: unexpected type, cannot release to pool")
65 return
66 }
67 a.pool.Release(a.ctx, wwv)
68}
69
70func (a *webViewPoolAdapter) Prewarm(count int) {
71 a.pool.Prewarm(a.ctx, count)
72}
73
74func (a *webViewPoolAdapter) PrewarmAsync(ctx context.Context, count int) {
75 a.pool.PrewarmAsync(ctx, count)
76}
77
78func (a *webViewPoolAdapter) Size() int {
79 return a.pool.Size()
80}
81
82func (a *webViewPoolAdapter) Close() {
83 a.pool.Close(a.ctx)
84}
85
86// --- SettingsApplier adapter ---
87
88// settingsApplierAdapter bridges *SettingsManager to port.SettingsApplier.
89type settingsApplierAdapter struct {
90 settings *SettingsManager
91}
92
93func (a *settingsApplierAdapter) ApplyToAll(ctx context.Context, webviews []port.WebView) {
94 for _, wv := range webviews {
95 if wwv, ok := wv.(*WebView); ok && !wwv.IsDestroyed() {
96 a.settings.ApplyToWebView(ctx, wwv.Widget())
97 }
98 }
99}
100
101// --- FilterApplier adapter ---
102
103// filterApplierAdapter bridges *filtering.Manager to port.FilterApplier.
104type filterApplierAdapter struct {
105 manager *filtering.Manager
106}
107
108func (a *filterApplierAdapter) ApplyToAll(ctx context.Context, webviews []port.WebView) {
109 for _, wv := range webviews {
110 if wwv, ok := wv.(*WebView); ok && !wwv.IsDestroyed() {
111 a.manager.ApplyTo(ctx, wwv.UserContentManager())
112 }
113 }
114}
115
116// --- FaviconDatabase adapter ---
117
118// faviconDatabaseAdapter bridges *WebKitContext to port.FaviconDatabase.
119// The WebKitContext exposes the favicon database; async lookup is a stub until
120// the coordinator layer is migrated to use this port.
121type faviconDatabaseAdapter struct {
122 wkCtx *WebKitContext
123}
124
125func (a *faviconDatabaseAdapter) GetFaviconAsync(pageURL string, callback func(port.Texture)) {
126 db := a.wkCtx.FaviconDatabase()
127 if db == nil {
128 callback(nil)
129 return
130 }
131
132 asyncCb := gio.AsyncReadyCallback(func(_ uintptr, resultPtr uintptr, _ uintptr) {
133 if resultPtr == 0 {
134 callback(nil)
135 return
136 }
137
138 result := &gio.AsyncResultBase{Ptr: resultPtr}
139 texture, err := db.GetFaviconFinish(result)
140 if err != nil || texture == nil {
141 callback(nil)
142 return
143 }
144
145 callback(texture)
146 })
147
148 db.GetFavicon(pageURL, nil, &asyncCb, 0)
149}