refactor(webkit): consume typed settings payload
- commit
- 5294200ee699203df0b7ca58827593e492f2df01
- author
- brice · · 2026-06-23 13:31 UTC
- committer
- brice · · 2026-06-23 20:01 UTC
- parent
- 4ed4d97
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
6 files · +106 -65
M internal/bootstrap/engine.go +1 -0
| @@ -71,6 +71,7 @@ func BuildEngine(input EngineInput) (port.Engine, error) { | |||
| 71 | 71 | ||
| 72 | 72 | return webkit.NewEngine( | |
| 73 | 73 | input.Ctx, cfg, opts, profile, wkCfg, | |
| 74 | + | EngineSettingsPayloadFromConfig(cfg), | |
| 74 | 75 | currentConfigPayload, defaultConfigPayload, | |
| 75 | 76 | input.ThemeManager, input.ColorResolver, | |
| 76 | 77 | contextMenuBuilder, contextMenuExecutorFactory, | |
| @@ -71,6 +71,7 @@ func BuildEngine(input EngineInput) (port.Engine, error) { | |||||
| 71 | 71 | ||||
| 72 | return webkit.NewEngine( | 72 | return webkit.NewEngine( | ||
| 73 | input.Ctx, cfg, opts, profile, wkCfg, | 73 | input.Ctx, cfg, opts, profile, wkCfg, | ||
| 74 | + | EngineSettingsPayloadFromConfig(cfg), | |||
| 74 | currentConfigPayload, defaultConfigPayload, | 75 | currentConfigPayload, defaultConfigPayload, | ||
| 75 | input.ThemeManager, input.ColorResolver, | 76 | input.ThemeManager, input.ColorResolver, | ||
| 76 | contextMenuBuilder, contextMenuExecutorFactory, | 77 | contextMenuBuilder, contextMenuExecutorFactory, | ||
M internal/infrastructure/webkit/engine.go +1 -6
| @@ -5,7 +5,6 @@ import ( | |||
| 5 | 5 | "fmt" | |
| 6 | 6 | ||
| 7 | 7 | "github.com/bnema/dumber/internal/application/port" | |
| 8 | - | "github.com/bnema/dumber/internal/infrastructure/config" | |
| 9 | 8 | "github.com/bnema/dumber/internal/infrastructure/filtering" | |
| 10 | 9 | "github.com/bnema/dumber/internal/infrastructure/handlers" | |
| 11 | 10 | "github.com/rs/zerolog" | |
| @@ -157,12 +156,8 @@ func (e *Engine) UpdateAppearance(_ context.Context, r, g, b, alpha float64) err | |||
| 157 | 156 | ||
| 158 | 157 | // UpdateSettings applies runtime config changes to engine settings. | |
| 159 | 158 | func (e *Engine) UpdateSettings(ctx context.Context, update port.EngineSettingsUpdate) error { | |
| 160 | - | cfg, ok := update.Raw.(*config.Config) | |
| 161 | - | if !ok { | |
| 162 | - | return fmt.Errorf("UpdateSettings: expected *config.Config, got %T", update.Raw) | |
| 163 | - | } | |
| 164 | 159 | if e.settings != nil { | |
| 165 | - | e.settings.UpdateFromConfig(ctx, cfg) | |
| 160 | + | e.settings.UpdateFromPayload(ctx, update.Settings) | |
| 166 | 161 | } | |
| 167 | 162 | return nil | |
| 168 | 163 | } | |
| @@ -5,7 +5,6 @@ import ( | |||||
| 5 | "fmt" | 5 | "fmt" | ||
| 6 | 6 | ||||
| 7 | "github.com/bnema/dumber/internal/application/port" | 7 | "github.com/bnema/dumber/internal/application/port" | ||
| 8 | - | "github.com/bnema/dumber/internal/infrastructure/config" | |||
| 9 | "github.com/bnema/dumber/internal/infrastructure/filtering" | 8 | "github.com/bnema/dumber/internal/infrastructure/filtering" | ||
| 10 | "github.com/bnema/dumber/internal/infrastructure/handlers" | 9 | "github.com/bnema/dumber/internal/infrastructure/handlers" | ||
| 11 | "github.com/rs/zerolog" | 10 | "github.com/rs/zerolog" | ||
| @@ -157,12 +156,8 @@ func (e *Engine) UpdateAppearance(_ context.Context, r, g, b, alpha float64) err | |||||
| 157 | 156 | ||||
| 158 | // UpdateSettings applies runtime config changes to engine settings. | 157 | // UpdateSettings applies runtime config changes to engine settings. | ||
| 159 | func (e *Engine) UpdateSettings(ctx context.Context, update port.EngineSettingsUpdate) error { | 158 | func (e *Engine) UpdateSettings(ctx context.Context, update port.EngineSettingsUpdate) error { | ||
| 160 | - | cfg, ok := update.Raw.(*config.Config) | |||
| 161 | - | if !ok { | |||
| 162 | - | return fmt.Errorf("UpdateSettings: expected *config.Config, got %T", update.Raw) | |||
| 163 | - | } | |||
| 164 | if e.settings != nil { | 159 | if e.settings != nil { | ||
| 165 | - | e.settings.UpdateFromConfig(ctx, cfg) | 160 | + | e.settings.UpdateFromPayload(ctx, update.Settings) |
| 166 | } | 161 | } | ||
| 167 | return nil | 162 | return nil | ||
| 168 | } | 163 | } | ||
M internal/infrastructure/webkit/engine_init.go +2 -1
| @@ -25,6 +25,7 @@ func NewEngine( | |||
| 25 | 25 | opts port.EngineOptions, | |
| 26 | 26 | profile runtimeprofile.Profile, | |
| 27 | 27 | wkCfg WebKitEngineConfig, | |
| 28 | + | initialSettings port.EngineSettingsPayload, | |
| 28 | 29 | currentConfigPayload func() ([]byte, error), | |
| 29 | 30 | defaultConfigPayload func() ([]byte, error), | |
| 30 | 31 | themeManager *theme.Manager, | |
| @@ -63,7 +64,7 @@ func NewEngine( | |||
| 63 | 64 | schemeHandler.RegisterWithContext(wkCtx) | |
| 64 | 65 | ||
| 65 | 66 | // --- Settings, injector, message router --- | |
| 66 | - | settings := NewSettingsManager(ctx, cfg) | |
| 67 | + | settings := NewSettingsManager(ctx, initialSettings) | |
| 67 | 68 | injector := NewContentInjector(colorResolver) | |
| 68 | 69 | ||
| 69 | 70 | injector.SetAutoCopyConfigGetter(func() bool { | |
| @@ -25,6 +25,7 @@ func NewEngine( | |||||
| 25 | opts port.EngineOptions, | 25 | opts port.EngineOptions, | ||
| 26 | profile runtimeprofile.Profile, | 26 | profile runtimeprofile.Profile, | ||
| 27 | wkCfg WebKitEngineConfig, | 27 | wkCfg WebKitEngineConfig, | ||
| 28 | + | initialSettings port.EngineSettingsPayload, | |||
| 28 | currentConfigPayload func() ([]byte, error), | 29 | currentConfigPayload func() ([]byte, error), | ||
| 29 | defaultConfigPayload func() ([]byte, error), | 30 | defaultConfigPayload func() ([]byte, error), | ||
| 30 | themeManager *theme.Manager, | 31 | themeManager *theme.Manager, | ||
| @@ -63,7 +64,7 @@ func NewEngine( | |||||
| 63 | schemeHandler.RegisterWithContext(wkCtx) | 64 | schemeHandler.RegisterWithContext(wkCtx) | ||
| 64 | 65 | ||||
| 65 | // --- Settings, injector, message router --- | 66 | // --- Settings, injector, message router --- | ||
| 66 | - | settings := NewSettingsManager(ctx, cfg) | 67 | + | settings := NewSettingsManager(ctx, initialSettings) |
| 67 | injector := NewContentInjector(colorResolver) | 68 | injector := NewContentInjector(colorResolver) | ||
| 68 | 69 | ||||
| 69 | injector.SetAutoCopyConfigGetter(func() bool { | 70 | injector.SetAutoCopyConfigGetter(func() bool { | ||
M internal/infrastructure/webkit/engine_runtime_test.go +22 -9
| @@ -5,23 +5,36 @@ import ( | |||
| 5 | 5 | "testing" | |
| 6 | 6 | ||
| 7 | 7 | "github.com/bnema/dumber/internal/application/port" | |
| 8 | - | "github.com/bnema/dumber/internal/infrastructure/config" | |
| 9 | 8 | "github.com/stretchr/testify/require" | |
| 10 | 9 | ) | |
| 11 | 10 | ||
| 12 | - | func TestEngine_UpdateSettings_WrongType(t *testing.T) { | |
| 13 | - | e := &Engine{} | |
| 14 | - | err := e.UpdateSettings(context.Background(), port.EngineSettingsUpdate{Raw: "wrong"}) | |
| 15 | - | require.Error(t, err) | |
| 16 | - | require.Contains(t, err.Error(), "expected *config.Config") | |
| 11 | + | func TestEngine_UpdateSettings_AcceptsTypedSettingsPayload(t *testing.T) { | |
| 12 | + | e := &Engine{settings: NewSettingsManager(context.Background(), port.EngineSettingsPayload{})} | |
| 13 | + | ||
| 14 | + | err := e.UpdateSettings(context.Background(), port.EngineSettingsUpdate{ | |
| 15 | + | Settings: port.EngineSettingsPayload{ | |
| 16 | + | DefaultUIScale: 1.25, | |
| 17 | + | WebContent: port.EngineWebContentSettingsPayload{ | |
| 18 | + | SansFont: "Inter", | |
| 19 | + | EnableDevTools: true, | |
| 20 | + | CaptureConsole: true, | |
| 21 | + | DrawCompositingIndicators: true, | |
| 22 | + | HardwareDecoding: port.EngineHardwareDecodingDisable, | |
| 23 | + | }, | |
| 24 | + | }, | |
| 25 | + | }) | |
| 26 | + | require.NoError(t, err) | |
| 27 | + | require.Equal(t, "Inter", e.settings.current().WebContent.SansFont) | |
| 28 | + | require.True(t, e.settings.current().WebContent.EnableDevTools) | |
| 29 | + | require.True(t, e.settings.current().WebContent.CaptureConsole) | |
| 30 | + | require.True(t, e.settings.current().WebContent.DrawCompositingIndicators) | |
| 31 | + | require.Equal(t, port.EngineHardwareDecodingDisable, e.settings.current().WebContent.HardwareDecoding) | |
| 17 | 32 | } | |
| 18 | 33 | ||
| 19 | 34 | func TestEngine_UpdateSettings_NilSettings(t *testing.T) { | |
| 20 | 35 | // settings is nil — should not panic, just be a no-op. | |
| 21 | 36 | e := &Engine{} | |
| 22 | - | // Use a nil *config.Config to pass the type assertion. | |
| 23 | - | var cfg *config.Config | |
| 24 | - | err := e.UpdateSettings(context.Background(), port.EngineSettingsUpdate{Raw: cfg}) | |
| 37 | + | err := e.UpdateSettings(context.Background(), port.EngineSettingsUpdate{}) | |
| 25 | 38 | require.NoError(t, err) | |
| 26 | 39 | } | |
| 27 | 40 | ||
| @@ -5,23 +5,36 @@ import ( | |||||
| 5 | "testing" | 5 | "testing" | ||
| 6 | 6 | ||||
| 7 | "github.com/bnema/dumber/internal/application/port" | 7 | "github.com/bnema/dumber/internal/application/port" | ||
| 8 | - | "github.com/bnema/dumber/internal/infrastructure/config" | |||
| 9 | "github.com/stretchr/testify/require" | 8 | "github.com/stretchr/testify/require" | ||
| 10 | ) | 9 | ) | ||
| 11 | 10 | ||||
| 12 | - | func TestEngine_UpdateSettings_WrongType(t *testing.T) { | 11 | + | func TestEngine_UpdateSettings_AcceptsTypedSettingsPayload(t *testing.T) { |
| 13 | - | e := &Engine{} | 12 | + | e := &Engine{settings: NewSettingsManager(context.Background(), port.EngineSettingsPayload{})} |
| 14 | - | err := e.UpdateSettings(context.Background(), port.EngineSettingsUpdate{Raw: "wrong"}) | 13 | + | |
| 15 | - | require.Error(t, err) | 14 | + | err := e.UpdateSettings(context.Background(), port.EngineSettingsUpdate{ |
| 16 | - | require.Contains(t, err.Error(), "expected *config.Config") | 15 | + | Settings: port.EngineSettingsPayload{ |
| 16 | + | DefaultUIScale: 1.25, | |||
| 17 | + | WebContent: port.EngineWebContentSettingsPayload{ | |||
| 18 | + | SansFont: "Inter", | |||
| 19 | + | EnableDevTools: true, | |||
| 20 | + | CaptureConsole: true, | |||
| 21 | + | DrawCompositingIndicators: true, | |||
| 22 | + | HardwareDecoding: port.EngineHardwareDecodingDisable, | |||
| 23 | + | }, | |||
| 24 | + | }, | |||
| 25 | + | }) | |||
| 26 | + | require.NoError(t, err) | |||
| 27 | + | require.Equal(t, "Inter", e.settings.current().WebContent.SansFont) | |||
| 28 | + | require.True(t, e.settings.current().WebContent.EnableDevTools) | |||
| 29 | + | require.True(t, e.settings.current().WebContent.CaptureConsole) | |||
| 30 | + | require.True(t, e.settings.current().WebContent.DrawCompositingIndicators) | |||
| 31 | + | require.Equal(t, port.EngineHardwareDecodingDisable, e.settings.current().WebContent.HardwareDecoding) | |||
| 17 | } | 32 | } | ||
| 18 | 33 | ||||
| 19 | func TestEngine_UpdateSettings_NilSettings(t *testing.T) { | 34 | func TestEngine_UpdateSettings_NilSettings(t *testing.T) { | ||
| 20 | // settings is nil — should not panic, just be a no-op. | 35 | // settings is nil — should not panic, just be a no-op. | ||
| 21 | e := &Engine{} | 36 | e := &Engine{} | ||
| 22 | - | // Use a nil *config.Config to pass the type assertion. | 37 | + | err := e.UpdateSettings(context.Background(), port.EngineSettingsUpdate{}) |
| 23 | - | var cfg *config.Config | |||
| 24 | - | err := e.UpdateSettings(context.Background(), port.EngineSettingsUpdate{Raw: cfg}) | |||
| 25 | require.NoError(t, err) | 38 | require.NoError(t, err) | ||
| 26 | } | 39 | } | ||
| 27 | 40 | ||||
M internal/infrastructure/webkit/settings.go +48 -49
| @@ -4,34 +4,35 @@ import ( | |||
| 4 | 4 | "context" | |
| 5 | 5 | "sync" | |
| 6 | 6 | ||
| 7 | - | "github.com/bnema/dumber/internal/infrastructure/config" | |
| 7 | + | "github.com/bnema/dumber/internal/application/port" | |
| 8 | 8 | "github.com/bnema/dumber/internal/logging" | |
| 9 | 9 | "github.com/bnema/puregotk/v4/webkit" | |
| 10 | 10 | "github.com/rs/zerolog" | |
| 11 | 11 | ) | |
| 12 | 12 | ||
| 13 | - | // SettingsManager creates and manages WebKit Settings instances from config. | |
| 13 | + | // SettingsManager creates and manages WebKit Settings instances from payloads. | |
| 14 | 14 | type SettingsManager struct { | |
| 15 | - | cfg *config.Config | |
| 16 | - | mu sync.RWMutex | |
| 15 | + | settings port.EngineSettingsPayload | |
| 16 | + | mu sync.RWMutex | |
| 17 | 17 | } | |
| 18 | 18 | ||
| 19 | - | // NewSettingsManager creates a new SettingsManager with the given config. | |
| 20 | - | func NewSettingsManager(ctx context.Context, cfg *config.Config) *SettingsManager { | |
| 19 | + | // NewSettingsManager creates a new SettingsManager with the given payload. | |
| 20 | + | func NewSettingsManager(ctx context.Context, settings port.EngineSettingsPayload) *SettingsManager { | |
| 21 | 21 | log := logging.FromContext(ctx) | |
| 22 | 22 | log.Debug().Msg("creating settings manager") | |
| 23 | - | return &SettingsManager{ | |
| 24 | - | cfg: cfg, | |
| 25 | - | } | |
| 23 | + | return &SettingsManager{settings: settings} | |
| 24 | + | } | |
| 25 | + | ||
| 26 | + | func (sm *SettingsManager) current() port.EngineSettingsPayload { | |
| 27 | + | sm.mu.RLock() | |
| 28 | + | defer sm.mu.RUnlock() | |
| 29 | + | return sm.settings | |
| 26 | 30 | } | |
| 27 | 31 | ||
| 28 | - | // CreateSettings creates a new webkit.Settings instance configured from the current config. | |
| 32 | + | // CreateSettings creates a new webkit.Settings instance configured from the current payload. | |
| 29 | 33 | func (sm *SettingsManager) CreateSettings(ctx context.Context) *webkit.Settings { | |
| 30 | 34 | log := logging.FromContext(ctx) | |
| 31 | - | ||
| 32 | - | sm.mu.RLock() | |
| 33 | - | cfg := sm.cfg | |
| 34 | - | sm.mu.RUnlock() | |
| 35 | + | payload := sm.current() | |
| 35 | 36 | ||
| 36 | 37 | settings := webkit.NewSettings() | |
| 37 | 38 | if settings == nil { | |
| @@ -39,21 +40,21 @@ func (sm *SettingsManager) CreateSettings(ctx context.Context) *webkit.Settings | |||
| 39 | 40 | return nil | |
| 40 | 41 | } | |
| 41 | 42 | ||
| 42 | - | sm.applySettings(ctx, settings, cfg) | |
| 43 | + | sm.applySettings(ctx, settings, payload) | |
| 43 | 44 | return settings | |
| 44 | 45 | } | |
| 45 | 46 | ||
| 46 | - | // applySettings applies configuration to a webkit.Settings instance. | |
| 47 | - | func (sm *SettingsManager) applySettings(ctx context.Context, settings *webkit.Settings, cfg *config.Config) { | |
| 47 | + | // applySettings applies settings payload to a webkit.Settings instance. | |
| 48 | + | func (sm *SettingsManager) applySettings(ctx context.Context, settings *webkit.Settings, payload port.EngineSettingsPayload) { | |
| 48 | 49 | if sm == nil { | |
| 49 | 50 | return | |
| 50 | 51 | } | |
| 51 | 52 | log := logging.FromContext(ctx) | |
| 52 | 53 | applyJavaScriptSettings(settings) | |
| 53 | - | applyFontSettings(settings, cfg) | |
| 54 | - | applyDebugSettings(settings, cfg) | |
| 54 | + | applyFontSettings(settings, payload.WebContent) | |
| 55 | + | applyDebugSettings(settings, payload.WebContent) | |
| 55 | 56 | applyBrowsingSettings(settings) | |
| 56 | - | applyMediaSettings(settings, cfg, log) | |
| 57 | + | applyMediaSettings(settings, payload.WebContent.HardwareDecoding, log) | |
| 57 | 58 | applyStorageSettings(settings) | |
| 58 | 59 | applyUISettings(settings) | |
| 59 | 60 | applyCanvasSettings(settings) | |
| @@ -63,8 +64,8 @@ func (sm *SettingsManager) applySettings(ctx context.Context, settings *webkit.S | |||
| 63 | 64 | mediaStreamEnabled := settings.GetPropertyEnableMediaStream() | |
| 64 | 65 | ||
| 65 | 66 | log.Debug(). | |
| 66 | - | Str("sans_font", cfg.Appearance.SansFont). | |
| 67 | - | Bool("developer_extras", cfg.Debug.EnableDevTools). | |
| 67 | + | Str("sans_font", payload.WebContent.SansFont). | |
| 68 | + | Bool("developer_extras", payload.WebContent.EnableDevTools). | |
| 68 | 69 | Bool("webrtc_enabled", webrtcEnabled). | |
| 69 | 70 | Bool("media_stream_enabled", mediaStreamEnabled). | |
| 70 | 71 | Msg("settings applied") | |
| @@ -75,26 +76,26 @@ func applyJavaScriptSettings(settings *webkit.Settings) { | |||
| 75 | 76 | settings.SetEnableJavascriptMarkup(true) | |
| 76 | 77 | } | |
| 77 | 78 | ||
| 78 | - | func applyFontSettings(settings *webkit.Settings, cfg *config.Config) { | |
| 79 | - | if cfg.Appearance.SansFont != "" { | |
| 80 | - | settings.SetDefaultFontFamily(cfg.Appearance.SansFont) | |
| 81 | - | settings.SetSansSerifFontFamily(cfg.Appearance.SansFont) | |
| 79 | + | func applyFontSettings(settings *webkit.Settings, payload port.EngineWebContentSettingsPayload) { | |
| 80 | + | if payload.SansFont != "" { | |
| 81 | + | settings.SetDefaultFontFamily(payload.SansFont) | |
| 82 | + | settings.SetSansSerifFontFamily(payload.SansFont) | |
| 82 | 83 | } | |
| 83 | - | if cfg.Appearance.SerifFont != "" { | |
| 84 | - | settings.SetSerifFontFamily(cfg.Appearance.SerifFont) | |
| 84 | + | if payload.SerifFont != "" { | |
| 85 | + | settings.SetSerifFontFamily(payload.SerifFont) | |
| 85 | 86 | } | |
| 86 | - | if cfg.Appearance.MonospaceFont != "" { | |
| 87 | - | settings.SetMonospaceFontFamily(cfg.Appearance.MonospaceFont) | |
| 87 | + | if payload.MonospaceFont != "" { | |
| 88 | + | settings.SetMonospaceFontFamily(payload.MonospaceFont) | |
| 88 | 89 | } | |
| 89 | - | if cfg.Appearance.DefaultFontSize > 0 { | |
| 90 | - | settings.SetDefaultFontSize(uint32(cfg.Appearance.DefaultFontSize)) | |
| 90 | + | if payload.DefaultFontSize > 0 { | |
| 91 | + | settings.SetDefaultFontSize(uint32(payload.DefaultFontSize)) | |
| 91 | 92 | } | |
| 92 | 93 | } | |
| 93 | 94 | ||
| 94 | - | func applyDebugSettings(settings *webkit.Settings, cfg *config.Config) { | |
| 95 | - | settings.SetEnableDeveloperExtras(cfg.Debug.EnableDevTools) | |
| 96 | - | settings.SetEnableWriteConsoleMessagesToStdout(cfg.Logging.CaptureConsole) | |
| 97 | - | settings.SetDrawCompositingIndicators(cfg.Engine.WebKit.DrawCompositingIndicators) | |
| 95 | + | func applyDebugSettings(settings *webkit.Settings, payload port.EngineWebContentSettingsPayload) { | |
| 96 | + | settings.SetEnableDeveloperExtras(payload.EnableDevTools) | |
| 97 | + | settings.SetEnableWriteConsoleMessagesToStdout(payload.CaptureConsole) | |
| 98 | + | settings.SetDrawCompositingIndicators(payload.DrawCompositingIndicators) | |
| 98 | 99 | } | |
| 99 | 100 | ||
| 100 | 101 | func applyBrowsingSettings(settings *webkit.Settings) { | |
| @@ -103,7 +104,7 @@ func applyBrowsingSettings(settings *webkit.Settings) { | |||
| 103 | 104 | settings.SetEnableSiteSpecificQuirks(true) | |
| 104 | 105 | } | |
| 105 | 106 | ||
| 106 | - | func applyMediaSettings(settings *webkit.Settings, cfg *config.Config, log *zerolog.Logger) { | |
| 107 | + | func applyMediaSettings(settings *webkit.Settings, mode port.EngineHardwareDecodingMode, log *zerolog.Logger) { | |
| 107 | 108 | settings.SetEnableWebaudio(true) | |
| 108 | 109 | settings.SetEnableWebgl(true) | |
| 109 | 110 | settings.SetEnableMedia(true) | |
| @@ -113,12 +114,12 @@ func applyMediaSettings(settings *webkit.Settings, cfg *config.Config, log *zero | |||
| 113 | 114 | settings.SetMediaPlaybackRequiresUserGesture(true) | |
| 114 | 115 | settings.SetMediaPlaybackAllowsInline(true) | |
| 115 | 116 | ||
| 116 | - | switch cfg.Media.HardwareDecodingMode { | |
| 117 | - | case config.HardwareDecodingForce: | |
| 117 | + | switch mode { | |
| 118 | + | case port.EngineHardwareDecodingForce: | |
| 118 | 119 | hwTypes := "video/av01;video/mp4;video/webm;video/x-h264;video/x-h265" | |
| 119 | 120 | settings.SetMediaContentTypesRequiringHardwareSupport(&hwTypes) | |
| 120 | 121 | log.Debug().Msg("hardware decoding: forced (may fail without hw support)") | |
| 121 | - | case config.HardwareDecodingDisable: | |
| 122 | + | case port.EngineHardwareDecodingDisable: | |
| 122 | 123 | settings.SetHardwareAccelerationPolicy(webkit.HardwareAccelerationPolicyNeverValue) | |
| 123 | 124 | log.Debug().Msg("hardware decoding: disabled (software only)") | |
| 124 | 125 | default: | |
| @@ -151,15 +152,15 @@ func applyWebRTCSettings(settings *webkit.Settings) { | |||
| 151 | 152 | settings.SetEnableWebrtc(true) | |
| 152 | 153 | } | |
| 153 | 154 | ||
| 154 | - | // UpdateFromConfig updates the manager with a new config (for hot-reload). | |
| 155 | + | // UpdateFromPayload updates the manager with a new payload (for hot-reload). | |
| 155 | 156 | // Note: This doesn't update already-created Settings instances. | |
| 156 | - | // New WebViews will use the updated config. | |
| 157 | - | func (sm *SettingsManager) UpdateFromConfig(ctx context.Context, cfg *config.Config) { | |
| 157 | + | // New WebViews will use the updated payload. | |
| 158 | + | func (sm *SettingsManager) UpdateFromPayload(ctx context.Context, settings port.EngineSettingsPayload) { | |
| 158 | 159 | log := logging.FromContext(ctx) | |
| 159 | 160 | sm.mu.Lock() | |
| 160 | 161 | defer sm.mu.Unlock() | |
| 161 | - | sm.cfg = cfg | |
| 162 | - | log.Debug().Msg("settings config updated") | |
| 162 | + | sm.settings = settings | |
| 163 | + | log.Debug().Msg("settings payload updated") | |
| 163 | 164 | } | |
| 164 | 165 | ||
| 165 | 166 | // ApplyToWebView applies current settings to an existing WebView. | |
| @@ -175,9 +176,7 @@ func (sm *SettingsManager) ApplyToWebView(ctx context.Context, wv *webkit.WebVie | |||
| 175 | 176 | // Apply to the existing settings object attached to the WebView | |
| 176 | 177 | existingSettings := wv.GetSettings() | |
| 177 | 178 | if existingSettings != nil { | |
| 178 | - | sm.mu.RLock() | |
| 179 | - | cfg := sm.cfg | |
| 180 | - | sm.mu.RUnlock() | |
| 181 | - | sm.applySettings(ctx, existingSettings, cfg) | |
| 179 | + | payload := sm.current() | |
| 180 | + | sm.applySettings(ctx, existingSettings, payload) | |
| 182 | 181 | } | |
| 183 | 182 | } | |
| @@ -4,34 +4,35 @@ import ( | |||||
| 4 | "context" | 4 | "context" | ||
| 5 | "sync" | 5 | "sync" | ||
| 6 | 6 | ||||
| 7 | - | "github.com/bnema/dumber/internal/infrastructure/config" | 7 | + | "github.com/bnema/dumber/internal/application/port" |
| 8 | "github.com/bnema/dumber/internal/logging" | 8 | "github.com/bnema/dumber/internal/logging" | ||
| 9 | "github.com/bnema/puregotk/v4/webkit" | 9 | "github.com/bnema/puregotk/v4/webkit" | ||
| 10 | "github.com/rs/zerolog" | 10 | "github.com/rs/zerolog" | ||
| 11 | ) | 11 | ) | ||
| 12 | 12 | ||||
| 13 | - | // SettingsManager creates and manages WebKit Settings instances from config. | 13 | + | // SettingsManager creates and manages WebKit Settings instances from payloads. |
| 14 | type SettingsManager struct { | 14 | type SettingsManager struct { | ||
| 15 | - | cfg *config.Config | 15 | + | settings port.EngineSettingsPayload |
| 16 | - | mu sync.RWMutex | 16 | + | mu sync.RWMutex |
| 17 | } | 17 | } | ||
| 18 | 18 | ||||
| 19 | - | // NewSettingsManager creates a new SettingsManager with the given config. | 19 | + | // NewSettingsManager creates a new SettingsManager with the given payload. |
| 20 | - | func NewSettingsManager(ctx context.Context, cfg *config.Config) *SettingsManager { | 20 | + | func NewSettingsManager(ctx context.Context, settings port.EngineSettingsPayload) *SettingsManager { |
| 21 | log := logging.FromContext(ctx) | 21 | log := logging.FromContext(ctx) | ||
| 22 | log.Debug().Msg("creating settings manager") | 22 | log.Debug().Msg("creating settings manager") | ||
| 23 | - | return &SettingsManager{ | 23 | + | return &SettingsManager{settings: settings} |
| 24 | - | cfg: cfg, | 24 | + | } |
| 25 | - | } | 25 | + | |
| 26 | + | func (sm *SettingsManager) current() port.EngineSettingsPayload { | |||
| 27 | + | sm.mu.RLock() | |||
| 28 | + | defer sm.mu.RUnlock() | |||
| 29 | + | return sm.settings | |||
| 26 | } | 30 | } | ||
| 27 | 31 | ||||
| 28 | - | // CreateSettings creates a new webkit.Settings instance configured from the current config. | 32 | + | // CreateSettings creates a new webkit.Settings instance configured from the current payload. |
| 29 | func (sm *SettingsManager) CreateSettings(ctx context.Context) *webkit.Settings { | 33 | func (sm *SettingsManager) CreateSettings(ctx context.Context) *webkit.Settings { | ||
| 30 | log := logging.FromContext(ctx) | 34 | log := logging.FromContext(ctx) | ||
| 31 | - | 35 | + | payload := sm.current() | |
| 32 | - | sm.mu.RLock() | |||
| 33 | - | cfg := sm.cfg | |||
| 34 | - | sm.mu.RUnlock() | |||
| 35 | 36 | ||||
| 36 | settings := webkit.NewSettings() | 37 | settings := webkit.NewSettings() | ||
| 37 | if settings == nil { | 38 | if settings == nil { | ||
| @@ -39,21 +40,21 @@ func (sm *SettingsManager) CreateSettings(ctx context.Context) *webkit.Settings | |||||
| 39 | return nil | 40 | return nil | ||
| 40 | } | 41 | } | ||
| 41 | 42 | ||||
| 42 | - | sm.applySettings(ctx, settings, cfg) | 43 | + | sm.applySettings(ctx, settings, payload) |
| 43 | return settings | 44 | return settings | ||
| 44 | } | 45 | } | ||
| 45 | 46 | ||||
| 46 | - | // applySettings applies configuration to a webkit.Settings instance. | 47 | + | // applySettings applies settings payload to a webkit.Settings instance. |
| 47 | - | func (sm *SettingsManager) applySettings(ctx context.Context, settings *webkit.Settings, cfg *config.Config) { | 48 | + | func (sm *SettingsManager) applySettings(ctx context.Context, settings *webkit.Settings, payload port.EngineSettingsPayload) { |
| 48 | if sm == nil { | 49 | if sm == nil { | ||
| 49 | return | 50 | return | ||
| 50 | } | 51 | } | ||
| 51 | log := logging.FromContext(ctx) | 52 | log := logging.FromContext(ctx) | ||
| 52 | applyJavaScriptSettings(settings) | 53 | applyJavaScriptSettings(settings) | ||
| 53 | - | applyFontSettings(settings, cfg) | 54 | + | applyFontSettings(settings, payload.WebContent) |
| 54 | - | applyDebugSettings(settings, cfg) | 55 | + | applyDebugSettings(settings, payload.WebContent) |
| 55 | applyBrowsingSettings(settings) | 56 | applyBrowsingSettings(settings) | ||
| 56 | - | applyMediaSettings(settings, cfg, log) | 57 | + | applyMediaSettings(settings, payload.WebContent.HardwareDecoding, log) |
| 57 | applyStorageSettings(settings) | 58 | applyStorageSettings(settings) | ||
| 58 | applyUISettings(settings) | 59 | applyUISettings(settings) | ||
| 59 | applyCanvasSettings(settings) | 60 | applyCanvasSettings(settings) | ||
| @@ -63,8 +64,8 @@ func (sm *SettingsManager) applySettings(ctx context.Context, settings *webkit.S | |||||
| 63 | mediaStreamEnabled := settings.GetPropertyEnableMediaStream() | 64 | mediaStreamEnabled := settings.GetPropertyEnableMediaStream() | ||
| 64 | 65 | ||||
| 65 | log.Debug(). | 66 | log.Debug(). | ||
| 66 | - | Str("sans_font", cfg.Appearance.SansFont). | 67 | + | Str("sans_font", payload.WebContent.SansFont). |
| 67 | - | Bool("developer_extras", cfg.Debug.EnableDevTools). | 68 | + | Bool("developer_extras", payload.WebContent.EnableDevTools). |
| 68 | Bool("webrtc_enabled", webrtcEnabled). | 69 | Bool("webrtc_enabled", webrtcEnabled). | ||
| 69 | Bool("media_stream_enabled", mediaStreamEnabled). | 70 | Bool("media_stream_enabled", mediaStreamEnabled). | ||
| 70 | Msg("settings applied") | 71 | Msg("settings applied") | ||
| @@ -75,26 +76,26 @@ func applyJavaScriptSettings(settings *webkit.Settings) { | |||||
| 75 | settings.SetEnableJavascriptMarkup(true) | 76 | settings.SetEnableJavascriptMarkup(true) | ||
| 76 | } | 77 | } | ||
| 77 | 78 | ||||
| 78 | - | func applyFontSettings(settings *webkit.Settings, cfg *config.Config) { | 79 | + | func applyFontSettings(settings *webkit.Settings, payload port.EngineWebContentSettingsPayload) { |
| 79 | - | if cfg.Appearance.SansFont != "" { | 80 | + | if payload.SansFont != "" { |
| 80 | - | settings.SetDefaultFontFamily(cfg.Appearance.SansFont) | 81 | + | settings.SetDefaultFontFamily(payload.SansFont) |
| 81 | - | settings.SetSansSerifFontFamily(cfg.Appearance.SansFont) | 82 | + | settings.SetSansSerifFontFamily(payload.SansFont) |
| 82 | } | 83 | } | ||
| 83 | - | if cfg.Appearance.SerifFont != "" { | 84 | + | if payload.SerifFont != "" { |
| 84 | - | settings.SetSerifFontFamily(cfg.Appearance.SerifFont) | 85 | + | settings.SetSerifFontFamily(payload.SerifFont) |
| 85 | } | 86 | } | ||
| 86 | - | if cfg.Appearance.MonospaceFont != "" { | 87 | + | if payload.MonospaceFont != "" { |
| 87 | - | settings.SetMonospaceFontFamily(cfg.Appearance.MonospaceFont) | 88 | + | settings.SetMonospaceFontFamily(payload.MonospaceFont) |
| 88 | } | 89 | } | ||
| 89 | - | if cfg.Appearance.DefaultFontSize > 0 { | 90 | + | if payload.DefaultFontSize > 0 { |
| 90 | - | settings.SetDefaultFontSize(uint32(cfg.Appearance.DefaultFontSize)) | 91 | + | settings.SetDefaultFontSize(uint32(payload.DefaultFontSize)) |
| 91 | } | 92 | } | ||
| 92 | } | 93 | } | ||
| 93 | 94 | ||||
| 94 | - | func applyDebugSettings(settings *webkit.Settings, cfg *config.Config) { | 95 | + | func applyDebugSettings(settings *webkit.Settings, payload port.EngineWebContentSettingsPayload) { |
| 95 | - | settings.SetEnableDeveloperExtras(cfg.Debug.EnableDevTools) | 96 | + | settings.SetEnableDeveloperExtras(payload.EnableDevTools) |
| 96 | - | settings.SetEnableWriteConsoleMessagesToStdout(cfg.Logging.CaptureConsole) | 97 | + | settings.SetEnableWriteConsoleMessagesToStdout(payload.CaptureConsole) |
| 97 | - | settings.SetDrawCompositingIndicators(cfg.Engine.WebKit.DrawCompositingIndicators) | 98 | + | settings.SetDrawCompositingIndicators(payload.DrawCompositingIndicators) |
| 98 | } | 99 | } | ||
| 99 | 100 | ||||
| 100 | func applyBrowsingSettings(settings *webkit.Settings) { | 101 | func applyBrowsingSettings(settings *webkit.Settings) { | ||
| @@ -103,7 +104,7 @@ func applyBrowsingSettings(settings *webkit.Settings) { | |||||
| 103 | settings.SetEnableSiteSpecificQuirks(true) | 104 | settings.SetEnableSiteSpecificQuirks(true) | ||
| 104 | } | 105 | } | ||
| 105 | 106 | ||||
| 106 | - | func applyMediaSettings(settings *webkit.Settings, cfg *config.Config, log *zerolog.Logger) { | 107 | + | func applyMediaSettings(settings *webkit.Settings, mode port.EngineHardwareDecodingMode, log *zerolog.Logger) { |
| 107 | settings.SetEnableWebaudio(true) | 108 | settings.SetEnableWebaudio(true) | ||
| 108 | settings.SetEnableWebgl(true) | 109 | settings.SetEnableWebgl(true) | ||
| 109 | settings.SetEnableMedia(true) | 110 | settings.SetEnableMedia(true) | ||
| @@ -113,12 +114,12 @@ func applyMediaSettings(settings *webkit.Settings, cfg *config.Config, log *zero | |||||
| 113 | settings.SetMediaPlaybackRequiresUserGesture(true) | 114 | settings.SetMediaPlaybackRequiresUserGesture(true) | ||
| 114 | settings.SetMediaPlaybackAllowsInline(true) | 115 | settings.SetMediaPlaybackAllowsInline(true) | ||
| 115 | 116 | ||||
| 116 | - | switch cfg.Media.HardwareDecodingMode { | 117 | + | switch mode { |
| 117 | - | case config.HardwareDecodingForce: | 118 | + | case port.EngineHardwareDecodingForce: |
| 118 | hwTypes := "video/av01;video/mp4;video/webm;video/x-h264;video/x-h265" | 119 | hwTypes := "video/av01;video/mp4;video/webm;video/x-h264;video/x-h265" | ||
| 119 | settings.SetMediaContentTypesRequiringHardwareSupport(&hwTypes) | 120 | settings.SetMediaContentTypesRequiringHardwareSupport(&hwTypes) | ||
| 120 | log.Debug().Msg("hardware decoding: forced (may fail without hw support)") | 121 | log.Debug().Msg("hardware decoding: forced (may fail without hw support)") | ||
| 121 | - | case config.HardwareDecodingDisable: | 122 | + | case port.EngineHardwareDecodingDisable: |
| 122 | settings.SetHardwareAccelerationPolicy(webkit.HardwareAccelerationPolicyNeverValue) | 123 | settings.SetHardwareAccelerationPolicy(webkit.HardwareAccelerationPolicyNeverValue) | ||
| 123 | log.Debug().Msg("hardware decoding: disabled (software only)") | 124 | log.Debug().Msg("hardware decoding: disabled (software only)") | ||
| 124 | default: | 125 | default: | ||
| @@ -151,15 +152,15 @@ func applyWebRTCSettings(settings *webkit.Settings) { | |||||
| 151 | settings.SetEnableWebrtc(true) | 152 | settings.SetEnableWebrtc(true) | ||
| 152 | } | 153 | } | ||
| 153 | 154 | ||||
| 154 | - | // UpdateFromConfig updates the manager with a new config (for hot-reload). | 155 | + | // UpdateFromPayload updates the manager with a new payload (for hot-reload). |
| 155 | // Note: This doesn't update already-created Settings instances. | 156 | // Note: This doesn't update already-created Settings instances. | ||
| 156 | - | // New WebViews will use the updated config. | 157 | + | // New WebViews will use the updated payload. |
| 157 | - | func (sm *SettingsManager) UpdateFromConfig(ctx context.Context, cfg *config.Config) { | 158 | + | func (sm *SettingsManager) UpdateFromPayload(ctx context.Context, settings port.EngineSettingsPayload) { |
| 158 | log := logging.FromContext(ctx) | 159 | log := logging.FromContext(ctx) | ||
| 159 | sm.mu.Lock() | 160 | sm.mu.Lock() | ||
| 160 | defer sm.mu.Unlock() | 161 | defer sm.mu.Unlock() | ||
| 161 | - | sm.cfg = cfg | 162 | + | sm.settings = settings |
| 162 | - | log.Debug().Msg("settings config updated") | 163 | + | log.Debug().Msg("settings payload updated") |
| 163 | } | 164 | } | ||
| 164 | 165 | ||||
| 165 | // ApplyToWebView applies current settings to an existing WebView. | 166 | // ApplyToWebView applies current settings to an existing WebView. | ||
| @@ -175,9 +176,7 @@ func (sm *SettingsManager) ApplyToWebView(ctx context.Context, wv *webkit.WebVie | |||||
| 175 | // Apply to the existing settings object attached to the WebView | 176 | // Apply to the existing settings object attached to the WebView | ||
| 176 | existingSettings := wv.GetSettings() | 177 | existingSettings := wv.GetSettings() | ||
| 177 | if existingSettings != nil { | 178 | if existingSettings != nil { | ||
| 178 | - | sm.mu.RLock() | 179 | + | payload := sm.current() |
| 179 | - | cfg := sm.cfg | 180 | + | sm.applySettings(ctx, existingSettings, payload) |
| 180 | - | sm.mu.RUnlock() | |||
| 181 | - | sm.applySettings(ctx, existingSettings, cfg) | |||
| 182 | } | 181 | } | ||
| 183 | } | 182 | } | ||
A internal/infrastructure/webkit/settings_runtime_test.go +32 -0
| @@ -0,0 +1,32 @@ | |||
| 1 | + | package webkit | |
| 2 | + | ||
| 3 | + | import ( | |
| 4 | + | "context" | |
| 5 | + | "testing" | |
| 6 | + | ||
| 7 | + | "github.com/bnema/dumber/internal/application/port" | |
| 8 | + | ) | |
| 9 | + | ||
| 10 | + | func TestSettingsManagerUpdateFromPayloadStoresTypedRuntimeSettings(t *testing.T) { | |
| 11 | + | sm := NewSettingsManager(context.Background(), port.EngineSettingsPayload{}) | |
| 12 | + | payload := port.EngineSettingsPayload{ | |
| 13 | + | WebContent: port.EngineWebContentSettingsPayload{ | |
| 14 | + | SansFont: "Inter", | |
| 15 | + | SerifFont: "Literata", | |
| 16 | + | MonospaceFont: "Fira Code", | |
| 17 | + | DefaultFontSize: 16, | |
| 18 | + | HardwareDecoding: port.EngineHardwareDecodingForce, | |
| 19 | + | }, | |
| 20 | + | } | |
| 21 | + | ||
| 22 | + | sm.UpdateFromPayload(context.Background(), payload) | |
| 23 | + | ||
| 24 | + | got := sm.current() | |
| 25 | + | if got.WebContent.SansFont != "Inter" || | |
| 26 | + | got.WebContent.SerifFont != "Literata" || | |
| 27 | + | got.WebContent.MonospaceFont != "Fira Code" || | |
| 28 | + | got.WebContent.DefaultFontSize != 16 || | |
| 29 | + | got.WebContent.HardwareDecoding != port.EngineHardwareDecodingForce { | |
| 30 | + | t.Fatalf("stored payload=%#v", got) | |
| 31 | + | } | |
| 32 | + | } | |
| @@ -0,0 +1,32 @@ | |||||
| 1 | + | package webkit | |||
| 2 | + | ||||
| 3 | + | import ( | |||
| 4 | + | "context" | |||
| 5 | + | "testing" | |||
| 6 | + | ||||
| 7 | + | "github.com/bnema/dumber/internal/application/port" | |||
| 8 | + | ) | |||
| 9 | + | ||||
| 10 | + | func TestSettingsManagerUpdateFromPayloadStoresTypedRuntimeSettings(t *testing.T) { | |||
| 11 | + | sm := NewSettingsManager(context.Background(), port.EngineSettingsPayload{}) | |||
| 12 | + | payload := port.EngineSettingsPayload{ | |||
| 13 | + | WebContent: port.EngineWebContentSettingsPayload{ | |||
| 14 | + | SansFont: "Inter", | |||
| 15 | + | SerifFont: "Literata", | |||
| 16 | + | MonospaceFont: "Fira Code", | |||
| 17 | + | DefaultFontSize: 16, | |||
| 18 | + | HardwareDecoding: port.EngineHardwareDecodingForce, | |||
| 19 | + | }, | |||
| 20 | + | } | |||
| 21 | + | ||||
| 22 | + | sm.UpdateFromPayload(context.Background(), payload) | |||
| 23 | + | ||||
| 24 | + | got := sm.current() | |||
| 25 | + | if got.WebContent.SansFont != "Inter" || | |||
| 26 | + | got.WebContent.SerifFont != "Literata" || | |||
| 27 | + | got.WebContent.MonospaceFont != "Fira Code" || | |||
| 28 | + | got.WebContent.DefaultFontSize != 16 || | |||
| 29 | + | got.WebContent.HardwareDecoding != port.EngineHardwareDecodingForce { | |||
| 30 | + | t.Fatalf("stored payload=%#v", got) | |||
| 31 | + | } | |||
| 32 | + | } | |||