Merge pull request #198 from bnema/fix/permission-origin-and-dep-chain
fix: permission origin + cookie policy + puregotk migration
70 files · +256 -188
M cmd/dumber/main.go +1 -1
| @@ -34,7 +34,7 @@ import ( | |||
| 34 | 34 | "github.com/bnema/dumber/internal/ui/adapter" | |
| 35 | 35 | "github.com/bnema/dumber/internal/ui/component" | |
| 36 | 36 | "github.com/bnema/dumber/internal/ui/theme" | |
| 37 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 37 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 38 | 38 | "github.com/rs/zerolog" | |
| 39 | 39 | ) | |
| 40 | 40 | ||
| @@ -34,7 +34,7 @@ import ( | |||||
| 34 | "github.com/bnema/dumber/internal/ui/adapter" | 34 | "github.com/bnema/dumber/internal/ui/adapter" | ||
| 35 | "github.com/bnema/dumber/internal/ui/component" | 35 | "github.com/bnema/dumber/internal/ui/component" | ||
| 36 | "github.com/bnema/dumber/internal/ui/theme" | 36 | "github.com/bnema/dumber/internal/ui/theme" | ||
| 37 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 37 | + | "github.com/bnema/puregotk/v4/gtk" |
| 38 | "github.com/rs/zerolog" | 38 | "github.com/rs/zerolog" | ||
| 39 | ) | 39 | ) | ||
| 40 | 40 | ||||
M go.mod +5 -5
| @@ -1,16 +1,16 @@ | |||
| 1 | 1 | module github.com/bnema/dumber | |
| 2 | 2 | ||
| 3 | - | go 1.26 | |
| 3 | + | go 1.26.1 | |
| 4 | 4 | ||
| 5 | 5 | require ( | |
| 6 | - | github.com/bnema/puregotk-webkit v0.0.14 | |
| 6 | + | github.com/bnema/puregotk v0.2.0 | |
| 7 | + | github.com/bnema/puregotk-webkit v0.0.15 | |
| 7 | 8 | github.com/charmbracelet/bubbles v1.0.0 | |
| 8 | 9 | github.com/charmbracelet/bubbletea v1.3.10 | |
| 9 | 10 | github.com/charmbracelet/lipgloss v1.1.0 | |
| 11 | + | github.com/ebitengine/purego v0.10.0 | |
| 10 | 12 | github.com/fsnotify/fsnotify v1.9.0 | |
| 11 | 13 | github.com/godbus/dbus/v5 v5.2.2 | |
| 12 | - | github.com/jwijenbergh/purego v0.0.0-20251017112123-b71757b9ba42 | |
| 13 | - | github.com/jwijenbergh/puregotk v0.0.0-20260212181341-fb13c245f9f0 | |
| 14 | 14 | github.com/ncruces/go-sqlite3 v0.32.0 | |
| 15 | 15 | github.com/pelletier/go-toml/v2 v2.2.4 | |
| 16 | 16 | github.com/pressly/goose/v3 v3.27.0 | |
| @@ -23,7 +23,7 @@ require ( | |||
| 23 | 23 | gopkg.in/yaml.v3 v3.0.1 | |
| 24 | 24 | ) | |
| 25 | 25 | ||
| 26 | - | replace github.com/jwijenbergh/puregotk => github.com/bnema/puregotk v0.1.0 | |
| 26 | + | replace github.com/ebitengine/purego => github.com/bnema/purego v0.0.0-20260323095903-91aa177a2704 | |
| 27 | 27 | ||
| 28 | 28 | require ( | |
| 29 | 29 | github.com/atotto/clipboard v0.1.4 // indirect | |
| @@ -1,16 +1,16 @@ | |||||
| 1 | module github.com/bnema/dumber | 1 | module github.com/bnema/dumber | ||
| 2 | 2 | ||||
| 3 | - | go 1.26 | 3 | + | go 1.26.1 |
| 4 | 4 | ||||
| 5 | require ( | 5 | require ( | ||
| 6 | - | github.com/bnema/puregotk-webkit v0.0.14 | 6 | + | github.com/bnema/puregotk v0.2.0 |
| 7 | + | github.com/bnema/puregotk-webkit v0.0.15 | |||
| 7 | github.com/charmbracelet/bubbles v1.0.0 | 8 | github.com/charmbracelet/bubbles v1.0.0 | ||
| 8 | github.com/charmbracelet/bubbletea v1.3.10 | 9 | github.com/charmbracelet/bubbletea v1.3.10 | ||
| 9 | github.com/charmbracelet/lipgloss v1.1.0 | 10 | github.com/charmbracelet/lipgloss v1.1.0 | ||
| 11 | + | github.com/ebitengine/purego v0.10.0 | |||
| 10 | github.com/fsnotify/fsnotify v1.9.0 | 12 | github.com/fsnotify/fsnotify v1.9.0 | ||
| 11 | github.com/godbus/dbus/v5 v5.2.2 | 13 | github.com/godbus/dbus/v5 v5.2.2 | ||
| 12 | - | github.com/jwijenbergh/purego v0.0.0-20251017112123-b71757b9ba42 | |||
| 13 | - | github.com/jwijenbergh/puregotk v0.0.0-20260212181341-fb13c245f9f0 | |||
| 14 | github.com/ncruces/go-sqlite3 v0.32.0 | 14 | github.com/ncruces/go-sqlite3 v0.32.0 | ||
| 15 | github.com/pelletier/go-toml/v2 v2.2.4 | 15 | github.com/pelletier/go-toml/v2 v2.2.4 | ||
| 16 | github.com/pressly/goose/v3 v3.27.0 | 16 | github.com/pressly/goose/v3 v3.27.0 | ||
| @@ -23,7 +23,7 @@ require ( | |||||
| 23 | gopkg.in/yaml.v3 v3.0.1 | 23 | gopkg.in/yaml.v3 v3.0.1 | ||
| 24 | ) | 24 | ) | ||
| 25 | 25 | ||||
| 26 | - | replace github.com/jwijenbergh/puregotk => github.com/bnema/puregotk v0.1.0 | 26 | + | replace github.com/ebitengine/purego => github.com/bnema/purego v0.0.0-20260323095903-91aa177a2704 |
| 27 | 27 | ||||
| 28 | require ( | 28 | require ( | ||
| 29 | github.com/atotto/clipboard v0.1.4 // indirect | 29 | github.com/atotto/clipboard v0.1.4 // indirect | ||
M go.sum +6 -6
| @@ -4,10 +4,12 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE | |||
| 4 | 4 | github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= | |
| 5 | 5 | github.com/aymanbagabas/go-udiff v0.3.1 h1:LV+qyBQ2pqe0u42ZsUEtPiCaUoqgA9gYRDs3vj1nolY= | |
| 6 | 6 | github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl8ZBcNLgcbrw8E= | |
| 7 | - | github.com/bnema/puregotk v0.1.0 h1:fNdoWi0wAEk5/rfwtpSeQuuB4AgAxkpiPPlivXXQk3I= | |
| 8 | - | github.com/bnema/puregotk v0.1.0/go.mod h1:mZu8qSvCSqtVL+xoiebZuicnJijwrLfGRs6/eTVgFlc= | |
| 9 | - | github.com/bnema/puregotk-webkit v0.0.14 h1:fwJ9fE3UKWQ8+VWFueddtfLMvcmO3EvfieIX/AYgHhY= | |
| 10 | - | github.com/bnema/puregotk-webkit v0.0.14/go.mod h1:wc+zzGdAy51YgyG1N3iwkQIusgCY4lFHGJUQgi4svJ0= | |
| 7 | + | github.com/bnema/purego v0.0.0-20260323095903-91aa177a2704 h1:0GaiO4102gOdp0es0MO2d0bRSvyeMw5A2D4F4WdIw0k= | |
| 8 | + | github.com/bnema/purego v0.0.0-20260323095903-91aa177a2704/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= | |
| 9 | + | github.com/bnema/puregotk v0.2.0 h1:lQ3zKbSRbAej/OWRlknrVTRxSzjxynamULjutV83bWM= | |
| 10 | + | github.com/bnema/puregotk v0.2.0/go.mod h1:Sl24sbCl02M/HLCNUgaYVCckkYcGOi8yxMuGuQVWsL8= | |
| 11 | + | github.com/bnema/puregotk-webkit v0.0.15 h1:CUcuoHfx+7AO1Diig7+NrEb7i5m/+MKTiQFUMH3j72k= | |
| 12 | + | github.com/bnema/puregotk-webkit v0.0.15/go.mod h1:jbMK8QD+J34OE24HUc19v7FUcbSYvsTd7Cs8x1Ab/14= | |
| 11 | 13 | github.com/charmbracelet/bubbles v1.0.0 h1:12J8/ak/uCZEMQ6KU7pcfwceyjLlWsDLAxB5fXonfvc= | |
| 12 | 14 | github.com/charmbracelet/bubbles v1.0.0/go.mod h1:9d/Zd5GdnauMI5ivUIVisuEm3ave1XwXtD1ckyV6r3E= | |
| 13 | 15 | github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw= | |
| @@ -55,8 +57,6 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= | |||
| 55 | 57 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | |
| 56 | 58 | github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= | |
| 57 | 59 | github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= | |
| 58 | - | github.com/jwijenbergh/purego v0.0.0-20251017112123-b71757b9ba42 h1:kQ0LX4ffJvtONhymro3HzrB8XUa6dIGgrbnkl38Rgl0= | |
| 59 | - | github.com/jwijenbergh/purego v0.0.0-20251017112123-b71757b9ba42/go.mod h1:amE5lVGstyh2GTEIHFEbgJHmoMD0llIuapnzIlZx7Fc= | |
| 60 | 60 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= | |
| 61 | 61 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= | |
| 62 | 62 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= | |
| @@ -4,10 +4,12 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE | |||||
| 4 | github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= | 4 | github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= | ||
| 5 | github.com/aymanbagabas/go-udiff v0.3.1 h1:LV+qyBQ2pqe0u42ZsUEtPiCaUoqgA9gYRDs3vj1nolY= | 5 | github.com/aymanbagabas/go-udiff v0.3.1 h1:LV+qyBQ2pqe0u42ZsUEtPiCaUoqgA9gYRDs3vj1nolY= | ||
| 6 | github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl8ZBcNLgcbrw8E= | 6 | github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl8ZBcNLgcbrw8E= | ||
| 7 | - | github.com/bnema/puregotk v0.1.0 h1:fNdoWi0wAEk5/rfwtpSeQuuB4AgAxkpiPPlivXXQk3I= | 7 | + | github.com/bnema/purego v0.0.0-20260323095903-91aa177a2704 h1:0GaiO4102gOdp0es0MO2d0bRSvyeMw5A2D4F4WdIw0k= |
| 8 | - | github.com/bnema/puregotk v0.1.0/go.mod h1:mZu8qSvCSqtVL+xoiebZuicnJijwrLfGRs6/eTVgFlc= | 8 | + | github.com/bnema/purego v0.0.0-20260323095903-91aa177a2704/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= |
| 9 | - | github.com/bnema/puregotk-webkit v0.0.14 h1:fwJ9fE3UKWQ8+VWFueddtfLMvcmO3EvfieIX/AYgHhY= | 9 | + | github.com/bnema/puregotk v0.2.0 h1:lQ3zKbSRbAej/OWRlknrVTRxSzjxynamULjutV83bWM= |
| 10 | - | github.com/bnema/puregotk-webkit v0.0.14/go.mod h1:wc+zzGdAy51YgyG1N3iwkQIusgCY4lFHGJUQgi4svJ0= | 10 | + | github.com/bnema/puregotk v0.2.0/go.mod h1:Sl24sbCl02M/HLCNUgaYVCckkYcGOi8yxMuGuQVWsL8= |
| 11 | + | github.com/bnema/puregotk-webkit v0.0.15 h1:CUcuoHfx+7AO1Diig7+NrEb7i5m/+MKTiQFUMH3j72k= | |||
| 12 | + | github.com/bnema/puregotk-webkit v0.0.15/go.mod h1:jbMK8QD+J34OE24HUc19v7FUcbSYvsTd7Cs8x1Ab/14= | |||
| 11 | github.com/charmbracelet/bubbles v1.0.0 h1:12J8/ak/uCZEMQ6KU7pcfwceyjLlWsDLAxB5fXonfvc= | 13 | github.com/charmbracelet/bubbles v1.0.0 h1:12J8/ak/uCZEMQ6KU7pcfwceyjLlWsDLAxB5fXonfvc= | ||
| 12 | github.com/charmbracelet/bubbles v1.0.0/go.mod h1:9d/Zd5GdnauMI5ivUIVisuEm3ave1XwXtD1ckyV6r3E= | 14 | github.com/charmbracelet/bubbles v1.0.0/go.mod h1:9d/Zd5GdnauMI5ivUIVisuEm3ave1XwXtD1ckyV6r3E= | ||
| 13 | github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw= | 15 | github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw= | ||
| @@ -55,8 +57,6 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= | |||||
| 55 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | 57 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||
| 56 | github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= | 58 | github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= | ||
| 57 | github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= | 59 | github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= | ||
| 58 | - | github.com/jwijenbergh/purego v0.0.0-20251017112123-b71757b9ba42 h1:kQ0LX4ffJvtONhymro3HzrB8XUa6dIGgrbnkl38Rgl0= | |||
| 59 | - | github.com/jwijenbergh/purego v0.0.0-20251017112123-b71757b9ba42/go.mod h1:amE5lVGstyh2GTEIHFEbgJHmoMD0llIuapnzIlZx7Fc= | |||
| 60 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= | 60 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= | ||
| 61 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= | 61 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= | ||
| 62 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= | 62 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= | ||
M internal/application/port/mocks/mocks.go +14 -8
| @@ -8211,8 +8211,8 @@ func (_m *MockPermissionDialogPresenter) EXPECT() *MockPermissionDialogPresenter | |||
| 8211 | 8211 | } | |
| 8212 | 8212 | ||
| 8213 | 8213 | // ShowPermissionDialog provides a mock function for the type MockPermissionDialogPresenter | |
| 8214 | - | func (_mock *MockPermissionDialogPresenter) ShowPermissionDialog(ctx context.Context, origin string, permTypes []entity.PermissionType, callback func(result port.PermissionDialogResult)) { | |
| 8215 | - | _mock.Called(ctx, origin, permTypes, callback) | |
| 8214 | + | func (_mock *MockPermissionDialogPresenter) ShowPermissionDialog(ctx context.Context, origin string, permTypes []entity.PermissionType, metadata entity.PermissionMetadata, callback func(result port.PermissionDialogResult)) { | |
| 8215 | + | _mock.Called(ctx, origin, permTypes, metadata, callback) | |
| 8216 | 8216 | return | |
| 8217 | 8217 | } | |
| 8218 | 8218 | ||
| @@ -8225,12 +8225,13 @@ type MockPermissionDialogPresenter_ShowPermissionDialog_Call struct { | |||
| 8225 | 8225 | // - ctx context.Context | |
| 8226 | 8226 | // - origin string | |
| 8227 | 8227 | // - permTypes []entity.PermissionType | |
| 8228 | + | // - metadata entity.PermissionMetadata | |
| 8228 | 8229 | // - callback func(result port.PermissionDialogResult) | |
| 8229 | - | func (_e *MockPermissionDialogPresenter_Expecter) ShowPermissionDialog(ctx interface{}, origin interface{}, permTypes interface{}, callback interface{}) *MockPermissionDialogPresenter_ShowPermissionDialog_Call { | |
| 8230 | - | return &MockPermissionDialogPresenter_ShowPermissionDialog_Call{Call: _e.mock.On("ShowPermissionDialog", ctx, origin, permTypes, callback)} | |
| 8230 | + | func (_e *MockPermissionDialogPresenter_Expecter) ShowPermissionDialog(ctx interface{}, origin interface{}, permTypes interface{}, metadata interface{}, callback interface{}) *MockPermissionDialogPresenter_ShowPermissionDialog_Call { | |
| 8231 | + | return &MockPermissionDialogPresenter_ShowPermissionDialog_Call{Call: _e.mock.On("ShowPermissionDialog", ctx, origin, permTypes, metadata, callback)} | |
| 8231 | 8232 | } | |
| 8232 | 8233 | ||
| 8233 | - | func (_c *MockPermissionDialogPresenter_ShowPermissionDialog_Call) Run(run func(ctx context.Context, origin string, permTypes []entity.PermissionType, callback func(result port.PermissionDialogResult))) *MockPermissionDialogPresenter_ShowPermissionDialog_Call { | |
| 8234 | + | func (_c *MockPermissionDialogPresenter_ShowPermissionDialog_Call) Run(run func(ctx context.Context, origin string, permTypes []entity.PermissionType, metadata entity.PermissionMetadata, callback func(result port.PermissionDialogResult))) *MockPermissionDialogPresenter_ShowPermissionDialog_Call { | |
| 8234 | 8235 | _c.Call.Run(func(args mock.Arguments) { | |
| 8235 | 8236 | var arg0 context.Context | |
| 8236 | 8237 | if args[0] != nil { | |
| @@ -8244,15 +8245,20 @@ func (_c *MockPermissionDialogPresenter_ShowPermissionDialog_Call) Run(run func( | |||
| 8244 | 8245 | if args[2] != nil { | |
| 8245 | 8246 | arg2 = args[2].([]entity.PermissionType) | |
| 8246 | 8247 | } | |
| 8247 | - | var arg3 func(result port.PermissionDialogResult) | |
| 8248 | + | var arg3 entity.PermissionMetadata | |
| 8248 | 8249 | if args[3] != nil { | |
| 8249 | - | arg3 = args[3].(func(result port.PermissionDialogResult)) | |
| 8250 | + | arg3 = args[3].(entity.PermissionMetadata) | |
| 8251 | + | } | |
| 8252 | + | var arg4 func(result port.PermissionDialogResult) | |
| 8253 | + | if args[4] != nil { | |
| 8254 | + | arg4 = args[4].(func(result port.PermissionDialogResult)) | |
| 8250 | 8255 | } | |
| 8251 | 8256 | run( | |
| 8252 | 8257 | arg0, | |
| 8253 | 8258 | arg1, | |
| 8254 | 8259 | arg2, | |
| 8255 | 8260 | arg3, | |
| 8261 | + | arg4, | |
| 8256 | 8262 | ) | |
| 8257 | 8263 | }) | |
| 8258 | 8264 | return _c | |
| @@ -8263,7 +8269,7 @@ func (_c *MockPermissionDialogPresenter_ShowPermissionDialog_Call) Return() *Moc | |||
| 8263 | 8269 | return _c | |
| 8264 | 8270 | } | |
| 8265 | 8271 | ||
| 8266 | - | func (_c *MockPermissionDialogPresenter_ShowPermissionDialog_Call) RunAndReturn(run func(ctx context.Context, origin string, permTypes []entity.PermissionType, callback func(result port.PermissionDialogResult))) *MockPermissionDialogPresenter_ShowPermissionDialog_Call { | |
| 8272 | + | func (_c *MockPermissionDialogPresenter_ShowPermissionDialog_Call) RunAndReturn(run func(ctx context.Context, origin string, permTypes []entity.PermissionType, metadata entity.PermissionMetadata, callback func(result port.PermissionDialogResult))) *MockPermissionDialogPresenter_ShowPermissionDialog_Call { | |
| 8267 | 8273 | _c.Run(run) | |
| 8268 | 8274 | return _c | |
| 8269 | 8275 | } | |
| @@ -8211,8 +8211,8 @@ func (_m *MockPermissionDialogPresenter) EXPECT() *MockPermissionDialogPresenter | |||||
| 8211 | } | 8211 | } | ||
| 8212 | 8212 | ||||
| 8213 | // ShowPermissionDialog provides a mock function for the type MockPermissionDialogPresenter | 8213 | // ShowPermissionDialog provides a mock function for the type MockPermissionDialogPresenter | ||
| 8214 | - | func (_mock *MockPermissionDialogPresenter) ShowPermissionDialog(ctx context.Context, origin string, permTypes []entity.PermissionType, callback func(result port.PermissionDialogResult)) { | 8214 | + | func (_mock *MockPermissionDialogPresenter) ShowPermissionDialog(ctx context.Context, origin string, permTypes []entity.PermissionType, metadata entity.PermissionMetadata, callback func(result port.PermissionDialogResult)) { |
| 8215 | - | _mock.Called(ctx, origin, permTypes, callback) | 8215 | + | _mock.Called(ctx, origin, permTypes, metadata, callback) |
| 8216 | return | 8216 | return | ||
| 8217 | } | 8217 | } | ||
| 8218 | 8218 | ||||
| @@ -8225,12 +8225,13 @@ type MockPermissionDialogPresenter_ShowPermissionDialog_Call struct { | |||||
| 8225 | // - ctx context.Context | 8225 | // - ctx context.Context | ||
| 8226 | // - origin string | 8226 | // - origin string | ||
| 8227 | // - permTypes []entity.PermissionType | 8227 | // - permTypes []entity.PermissionType | ||
| 8228 | + | // - metadata entity.PermissionMetadata | |||
| 8228 | // - callback func(result port.PermissionDialogResult) | 8229 | // - callback func(result port.PermissionDialogResult) | ||
| 8229 | - | func (_e *MockPermissionDialogPresenter_Expecter) ShowPermissionDialog(ctx interface{}, origin interface{}, permTypes interface{}, callback interface{}) *MockPermissionDialogPresenter_ShowPermissionDialog_Call { | 8230 | + | func (_e *MockPermissionDialogPresenter_Expecter) ShowPermissionDialog(ctx interface{}, origin interface{}, permTypes interface{}, metadata interface{}, callback interface{}) *MockPermissionDialogPresenter_ShowPermissionDialog_Call { |
| 8230 | - | return &MockPermissionDialogPresenter_ShowPermissionDialog_Call{Call: _e.mock.On("ShowPermissionDialog", ctx, origin, permTypes, callback)} | 8231 | + | return &MockPermissionDialogPresenter_ShowPermissionDialog_Call{Call: _e.mock.On("ShowPermissionDialog", ctx, origin, permTypes, metadata, callback)} |
| 8231 | } | 8232 | } | ||
| 8232 | 8233 | ||||
| 8233 | - | func (_c *MockPermissionDialogPresenter_ShowPermissionDialog_Call) Run(run func(ctx context.Context, origin string, permTypes []entity.PermissionType, callback func(result port.PermissionDialogResult))) *MockPermissionDialogPresenter_ShowPermissionDialog_Call { | 8234 | + | func (_c *MockPermissionDialogPresenter_ShowPermissionDialog_Call) Run(run func(ctx context.Context, origin string, permTypes []entity.PermissionType, metadata entity.PermissionMetadata, callback func(result port.PermissionDialogResult))) *MockPermissionDialogPresenter_ShowPermissionDialog_Call { |
| 8234 | _c.Call.Run(func(args mock.Arguments) { | 8235 | _c.Call.Run(func(args mock.Arguments) { | ||
| 8235 | var arg0 context.Context | 8236 | var arg0 context.Context | ||
| 8236 | if args[0] != nil { | 8237 | if args[0] != nil { | ||
| @@ -8244,15 +8245,20 @@ func (_c *MockPermissionDialogPresenter_ShowPermissionDialog_Call) Run(run func( | |||||
| 8244 | if args[2] != nil { | 8245 | if args[2] != nil { | ||
| 8245 | arg2 = args[2].([]entity.PermissionType) | 8246 | arg2 = args[2].([]entity.PermissionType) | ||
| 8246 | } | 8247 | } | ||
| 8247 | - | var arg3 func(result port.PermissionDialogResult) | 8248 | + | var arg3 entity.PermissionMetadata |
| 8248 | if args[3] != nil { | 8249 | if args[3] != nil { | ||
| 8249 | - | arg3 = args[3].(func(result port.PermissionDialogResult)) | 8250 | + | arg3 = args[3].(entity.PermissionMetadata) |
| 8251 | + | } | |||
| 8252 | + | var arg4 func(result port.PermissionDialogResult) | |||
| 8253 | + | if args[4] != nil { | |||
| 8254 | + | arg4 = args[4].(func(result port.PermissionDialogResult)) | |||
| 8250 | } | 8255 | } | ||
| 8251 | run( | 8256 | run( | ||
| 8252 | arg0, | 8257 | arg0, | ||
| 8253 | arg1, | 8258 | arg1, | ||
| 8254 | arg2, | 8259 | arg2, | ||
| 8255 | arg3, | 8260 | arg3, | ||
| 8261 | + | arg4, | |||
| 8256 | ) | 8262 | ) | ||
| 8257 | }) | 8263 | }) | ||
| 8258 | return _c | 8264 | return _c | ||
| @@ -8263,7 +8269,7 @@ func (_c *MockPermissionDialogPresenter_ShowPermissionDialog_Call) Return() *Moc | |||||
| 8263 | return _c | 8269 | return _c | ||
| 8264 | } | 8270 | } | ||
| 8265 | 8271 | ||||
| 8266 | - | func (_c *MockPermissionDialogPresenter_ShowPermissionDialog_Call) RunAndReturn(run func(ctx context.Context, origin string, permTypes []entity.PermissionType, callback func(result port.PermissionDialogResult))) *MockPermissionDialogPresenter_ShowPermissionDialog_Call { | 8272 | + | func (_c *MockPermissionDialogPresenter_ShowPermissionDialog_Call) RunAndReturn(run func(ctx context.Context, origin string, permTypes []entity.PermissionType, metadata entity.PermissionMetadata, callback func(result port.PermissionDialogResult))) *MockPermissionDialogPresenter_ShowPermissionDialog_Call { |
| 8267 | _c.Run(run) | 8273 | _c.Run(run) | ||
| 8268 | return _c | 8274 | return _c | ||
| 8269 | } | 8275 | } | ||
M internal/application/port/permission.go +3 -0
| @@ -26,11 +26,14 @@ type PermissionDialogPresenter interface { | |||
| 26 | 26 | // - ctx: context for cancellation and logging | |
| 27 | 27 | // - origin: the website origin requesting permission (e.g., "https://meet.example.com") | |
| 28 | 28 | // - permTypes: the types of permissions being requested | |
| 29 | + | // - metadata: permission-type-specific context; for website_data_access both | |
| 30 | + | // entity.PermissionMetadataKeyRequestingDomain and entity.PermissionMetadataKeyCurrentDomain must be set | |
| 29 | 31 | // - callback: invoked when the user makes a decision or dialog is dismissed | |
| 30 | 32 | ShowPermissionDialog( | |
| 31 | 33 | ctx context.Context, | |
| 32 | 34 | origin string, | |
| 33 | 35 | permTypes []entity.PermissionType, | |
| 36 | + | metadata entity.PermissionMetadata, | |
| 34 | 37 | callback func(result PermissionDialogResult), | |
| 35 | 38 | ) | |
| 36 | 39 | } | |
| @@ -26,11 +26,14 @@ type PermissionDialogPresenter interface { | |||||
| 26 | // - ctx: context for cancellation and logging | 26 | // - ctx: context for cancellation and logging | ||
| 27 | // - origin: the website origin requesting permission (e.g., "https://meet.example.com") | 27 | // - origin: the website origin requesting permission (e.g., "https://meet.example.com") | ||
| 28 | // - permTypes: the types of permissions being requested | 28 | // - permTypes: the types of permissions being requested | ||
| 29 | + | // - metadata: permission-type-specific context; for website_data_access both | |||
| 30 | + | // entity.PermissionMetadataKeyRequestingDomain and entity.PermissionMetadataKeyCurrentDomain must be set | |||
| 29 | // - callback: invoked when the user makes a decision or dialog is dismissed | 31 | // - callback: invoked when the user makes a decision or dialog is dismissed | ||
| 30 | ShowPermissionDialog( | 32 | ShowPermissionDialog( | ||
| 31 | ctx context.Context, | 33 | ctx context.Context, | ||
| 32 | origin string, | 34 | origin string, | ||
| 33 | permTypes []entity.PermissionType, | 35 | permTypes []entity.PermissionType, | ||
| 36 | + | metadata entity.PermissionMetadata, | |||
| 34 | callback func(result PermissionDialogResult), | 37 | callback func(result PermissionDialogResult), | ||
| 35 | ) | 38 | ) | ||
| 36 | } | 39 | } | ||
M internal/application/port/webview.go +3 -1
| @@ -107,7 +107,9 @@ type WebViewCallbacks struct { | |||
| 107 | 107 | // OnPermissionRequest is called when a site requests permission (mic, camera, screen sharing). | |
| 108 | 108 | // Return true to indicate the request was handled. Call allow()/deny() to respond. | |
| 109 | 109 | // The permission types are passed as strings ("microphone", "camera", "display", etc.). | |
| 110 | - | OnPermissionRequest func(origin string, permTypes []string, allow, deny func()) bool | |
| 110 | + | // The metadata map carries permission-type-specific context; for website_data_access both | |
| 111 | + | // entity.PermissionMetadataKeyRequestingDomain and entity.PermissionMetadataKeyCurrentDomain must be populated. | |
| 112 | + | OnPermissionRequest func(origin string, permTypes []string, metadata map[string]string, allow, deny func()) bool | |
| 111 | 113 | ||
| 112 | 114 | // OnLinkMiddleClick is called when a link is middle-clicked. | |
| 113 | 115 | // Return true if handled (blocks default navigation). | |
| @@ -107,7 +107,9 @@ type WebViewCallbacks struct { | |||||
| 107 | // OnPermissionRequest is called when a site requests permission (mic, camera, screen sharing). | 107 | // OnPermissionRequest is called when a site requests permission (mic, camera, screen sharing). | ||
| 108 | // Return true to indicate the request was handled. Call allow()/deny() to respond. | 108 | // Return true to indicate the request was handled. Call allow()/deny() to respond. | ||
| 109 | // The permission types are passed as strings ("microphone", "camera", "display", etc.). | 109 | // The permission types are passed as strings ("microphone", "camera", "display", etc.). | ||
| 110 | - | OnPermissionRequest func(origin string, permTypes []string, allow, deny func()) bool | 110 | + | // The metadata map carries permission-type-specific context; for website_data_access both |
| 111 | + | // entity.PermissionMetadataKeyRequestingDomain and entity.PermissionMetadataKeyCurrentDomain must be populated. | |||
| 112 | + | OnPermissionRequest func(origin string, permTypes []string, metadata map[string]string, allow, deny func()) bool | |||
| 111 | 113 | ||||
| 112 | // OnLinkMiddleClick is called when a link is middle-clicked. | 114 | // OnLinkMiddleClick is called when a link is middle-clicked. | ||
| 113 | // Return true if handled (blocks default navigation). | 115 | // Return true if handled (blocks default navigation). | ||
M internal/application/usecase/handle_permission.go +7 -2
| @@ -79,11 +79,15 @@ func (uc *HandlePermissionUseCase) getDialog() port.PermissionDialogPresenter { | |||
| 79 | 79 | // - ctx: context for cancellation and logging | |
| 80 | 80 | // - origin: the website origin (URI) requesting permission | |
| 81 | 81 | // - permTypes: the types of permissions being requested | |
| 82 | + | // - metadata: permission-type-specific context; for website_data_access both keys must be present: | |
| 83 | + | // entity.PermissionMetadataKeyRequestingDomain — the origin requesting cross-site data access | |
| 84 | + | // entity.PermissionMetadataKeyCurrentDomain — the domain currently loaded in the WebView | |
| 82 | 85 | // - callback: callbacks to allow or deny the request (must call one) | |
| 83 | 86 | func (uc *HandlePermissionUseCase) HandlePermissionRequest( | |
| 84 | 87 | ctx context.Context, | |
| 85 | 88 | origin string, | |
| 86 | 89 | permTypes []entity.PermissionType, | |
| 90 | + | metadata entity.PermissionMetadata, | |
| 87 | 91 | callback PermissionCallback, | |
| 88 | 92 | ) { | |
| 89 | 93 | log := uc.logger(ctx).With(). | |
| @@ -135,7 +139,7 @@ func (uc *HandlePermissionUseCase) HandlePermissionRequest( | |||
| 135 | 139 | } | |
| 136 | 140 | ||
| 137 | 141 | // Show dialog for undecided permissions | |
| 138 | - | uc.showPermissionDialog(ctx, origin, permTypes, callback) | |
| 142 | + | uc.showPermissionDialog(ctx, origin, permTypes, metadata, callback) | |
| 139 | 143 | } | |
| 140 | 144 | ||
| 141 | 145 | // QueryPermissionState returns the current permission state for the W3C Permissions API. | |
| @@ -249,6 +253,7 @@ func (uc *HandlePermissionUseCase) showPermissionDialog( | |||
| 249 | 253 | ctx context.Context, | |
| 250 | 254 | origin string, | |
| 251 | 255 | permTypes []entity.PermissionType, | |
| 256 | + | metadata entity.PermissionMetadata, | |
| 252 | 257 | callback PermissionCallback, | |
| 253 | 258 | ) { | |
| 254 | 259 | log := uc.logger(ctx) | |
| @@ -262,7 +267,7 @@ func (uc *HandlePermissionUseCase) showPermissionDialog( | |||
| 262 | 267 | return | |
| 263 | 268 | } | |
| 264 | 269 | ||
| 265 | - | dialog.ShowPermissionDialog(ctx, origin, permTypes, func(result port.PermissionDialogResult) { | |
| 270 | + | dialog.ShowPermissionDialog(ctx, origin, permTypes, metadata, func(result port.PermissionDialogResult) { | |
| 266 | 271 | if result.Allowed { | |
| 267 | 272 | log.Debug().Bool("persistent", result.Persistent).Msg("user allowed permission") | |
| 268 | 273 | callback.Allow() | |
| @@ -79,11 +79,15 @@ func (uc *HandlePermissionUseCase) getDialog() port.PermissionDialogPresenter { | |||||
| 79 | // - ctx: context for cancellation and logging | 79 | // - ctx: context for cancellation and logging | ||
| 80 | // - origin: the website origin (URI) requesting permission | 80 | // - origin: the website origin (URI) requesting permission | ||
| 81 | // - permTypes: the types of permissions being requested | 81 | // - permTypes: the types of permissions being requested | ||
| 82 | + | // - metadata: permission-type-specific context; for website_data_access both keys must be present: | |||
| 83 | + | // entity.PermissionMetadataKeyRequestingDomain — the origin requesting cross-site data access | |||
| 84 | + | // entity.PermissionMetadataKeyCurrentDomain — the domain currently loaded in the WebView | |||
| 82 | // - callback: callbacks to allow or deny the request (must call one) | 85 | // - callback: callbacks to allow or deny the request (must call one) | ||
| 83 | func (uc *HandlePermissionUseCase) HandlePermissionRequest( | 86 | func (uc *HandlePermissionUseCase) HandlePermissionRequest( | ||
| 84 | ctx context.Context, | 87 | ctx context.Context, | ||
| 85 | origin string, | 88 | origin string, | ||
| 86 | permTypes []entity.PermissionType, | 89 | permTypes []entity.PermissionType, | ||
| 90 | + | metadata entity.PermissionMetadata, | |||
| 87 | callback PermissionCallback, | 91 | callback PermissionCallback, | ||
| 88 | ) { | 92 | ) { | ||
| 89 | log := uc.logger(ctx).With(). | 93 | log := uc.logger(ctx).With(). | ||
| @@ -135,7 +139,7 @@ func (uc *HandlePermissionUseCase) HandlePermissionRequest( | |||||
| 135 | } | 139 | } | ||
| 136 | 140 | ||||
| 137 | // Show dialog for undecided permissions | 141 | // Show dialog for undecided permissions | ||
| 138 | - | uc.showPermissionDialog(ctx, origin, permTypes, callback) | 142 | + | uc.showPermissionDialog(ctx, origin, permTypes, metadata, callback) |
| 139 | } | 143 | } | ||
| 140 | 144 | ||||
| 141 | // QueryPermissionState returns the current permission state for the W3C Permissions API. | 145 | // QueryPermissionState returns the current permission state for the W3C Permissions API. | ||
| @@ -249,6 +253,7 @@ func (uc *HandlePermissionUseCase) showPermissionDialog( | |||||
| 249 | ctx context.Context, | 253 | ctx context.Context, | ||
| 250 | origin string, | 254 | origin string, | ||
| 251 | permTypes []entity.PermissionType, | 255 | permTypes []entity.PermissionType, | ||
| 256 | + | metadata entity.PermissionMetadata, | |||
| 252 | callback PermissionCallback, | 257 | callback PermissionCallback, | ||
| 253 | ) { | 258 | ) { | ||
| 254 | log := uc.logger(ctx) | 259 | log := uc.logger(ctx) | ||
| @@ -262,7 +267,7 @@ func (uc *HandlePermissionUseCase) showPermissionDialog( | |||||
| 262 | return | 267 | return | ||
| 263 | } | 268 | } | ||
| 264 | 269 | ||||
| 265 | - | dialog.ShowPermissionDialog(ctx, origin, permTypes, func(result port.PermissionDialogResult) { | 270 | + | dialog.ShowPermissionDialog(ctx, origin, permTypes, metadata, func(result port.PermissionDialogResult) { |
| 266 | if result.Allowed { | 271 | if result.Allowed { | ||
| 267 | log.Debug().Bool("persistent", result.Persistent).Msg("user allowed permission") | 272 | log.Debug().Bool("persistent", result.Persistent).Msg("user allowed permission") | ||
| 268 | callback.Allow() | 273 | callback.Allow() | ||
M internal/application/usecase/handle_permission_test.go +32 -26
| @@ -39,7 +39,7 @@ func TestHandlePermissionUseCase_AutoAllowDisplayCapture(t *testing.T) { | |||
| 39 | 39 | // Display capture should be auto-allowed (portal handles UI) | |
| 40 | 40 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | |
| 41 | 41 | entity.PermissionTypeDisplay, | |
| 42 | - | }, callback) | |
| 42 | + | }, nil, callback) | |
| 43 | 43 | ||
| 44 | 44 | assert.True(t, allowed, "display capture should be auto-allowed") | |
| 45 | 45 | assert.False(t, denied) | |
| @@ -65,7 +65,7 @@ func TestHandlePermissionUseCase_AutoAllowDeviceInfo(t *testing.T) { | |||
| 65 | 65 | // Device info should be auto-allowed | |
| 66 | 66 | uc.HandlePermissionRequest(ctx, "https://example.com", []entity.PermissionType{ | |
| 67 | 67 | entity.PermissionTypeDeviceInfo, | |
| 68 | - | }, callback) | |
| 68 | + | }, nil, callback) | |
| 69 | 69 | ||
| 70 | 70 | assert.True(t, allowed, "device info should be auto-allowed") | |
| 71 | 71 | } | |
| @@ -94,7 +94,7 @@ func TestHandlePermissionUseCase_StoredPermissionGranted(t *testing.T) { | |||
| 94 | 94 | ||
| 95 | 95 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | |
| 96 | 96 | entity.PermissionTypeMicrophone, | |
| 97 | - | }, callback) | |
| 97 | + | }, nil, callback) | |
| 98 | 98 | ||
| 99 | 99 | assert.True(t, allowed, "should use stored granted permission") | |
| 100 | 100 | dialog.AssertNotCalled(t, "ShowPermissionDialog") | |
| @@ -124,7 +124,7 @@ func TestHandlePermissionUseCase_StoredPermissionDenied(t *testing.T) { | |||
| 124 | 124 | ||
| 125 | 125 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | |
| 126 | 126 | entity.PermissionTypeCamera, | |
| 127 | - | }, callback) | |
| 127 | + | }, nil, callback) | |
| 128 | 128 | ||
| 129 | 129 | assert.True(t, denied, "should use stored denied permission") | |
| 130 | 130 | dialog.AssertNotCalled(t, "ShowPermissionDialog") | |
| @@ -150,13 +150,13 @@ func TestHandlePermissionUseCase_ShowDialogForPrompt(t *testing.T) { | |||
| 150 | 150 | // Dialog shows and user clicks Allow (not persistent) | |
| 151 | 151 | dialog.EXPECT().ShowPermissionDialog(mock.Anything, "https://meet.example.com", []entity.PermissionType{ | |
| 152 | 152 | entity.PermissionTypeMicrophone, | |
| 153 | - | }, mock.Anything).Run(func(_ context.Context, _ string, _ []entity.PermissionType, callback func(port.PermissionDialogResult)) { | |
| 153 | + | }, mock.Anything, mock.Anything).Run(func(_ context.Context, _ string, _ []entity.PermissionType, _ entity.PermissionMetadata, callback func(port.PermissionDialogResult)) { | |
| 154 | 154 | callback(port.PermissionDialogResult{Allowed: true, Persistent: false}) | |
| 155 | 155 | }) | |
| 156 | 156 | ||
| 157 | 157 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | |
| 158 | 158 | entity.PermissionTypeMicrophone, | |
| 159 | - | }, callback) | |
| 159 | + | }, nil, callback) | |
| 160 | 160 | ||
| 161 | 161 | assert.True(t, allowed, "user allowed permission") | |
| 162 | 162 | // Should not persist since Persistent=false | |
| @@ -183,7 +183,7 @@ func TestHandlePermissionUseCase_PersistAllowed(t *testing.T) { | |||
| 183 | 183 | // Dialog shows and user clicks "Always Allow" | |
| 184 | 184 | dialog.EXPECT().ShowPermissionDialog(mock.Anything, "https://meet.example.com", []entity.PermissionType{ | |
| 185 | 185 | entity.PermissionTypeMicrophone, | |
| 186 | - | }, mock.Anything).Run(func(_ context.Context, _ string, _ []entity.PermissionType, cb func(port.PermissionDialogResult)) { | |
| 186 | + | }, mock.Anything, mock.Anything).Run(func(_ context.Context, _ string, _ []entity.PermissionType, _ entity.PermissionMetadata, cb func(port.PermissionDialogResult)) { | |
| 187 | 187 | cb(port.PermissionDialogResult{Allowed: true, Persistent: true}) | |
| 188 | 188 | }) | |
| 189 | 189 | ||
| @@ -197,7 +197,7 @@ func TestHandlePermissionUseCase_PersistAllowed(t *testing.T) { | |||
| 197 | 197 | ||
| 198 | 198 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | |
| 199 | 199 | entity.PermissionTypeMicrophone, | |
| 200 | - | }, callback) | |
| 200 | + | }, nil, callback) | |
| 201 | 201 | ||
| 202 | 202 | assert.True(t, allowed) | |
| 203 | 203 | } | |
| @@ -222,7 +222,7 @@ func TestHandlePermissionUseCase_PersistDenied(t *testing.T) { | |||
| 222 | 222 | // Dialog shows and user clicks "Always Deny" | |
| 223 | 223 | dialog.EXPECT().ShowPermissionDialog(mock.Anything, "https://meet.example.com", []entity.PermissionType{ | |
| 224 | 224 | entity.PermissionTypeCamera, | |
| 225 | - | }, mock.Anything).Run(func(_ context.Context, _ string, _ []entity.PermissionType, cb func(port.PermissionDialogResult)) { | |
| 225 | + | }, mock.Anything, mock.Anything).Run(func(_ context.Context, _ string, _ []entity.PermissionType, _ entity.PermissionMetadata, cb func(port.PermissionDialogResult)) { | |
| 226 | 226 | // User denied but wants to persist this decision | |
| 227 | 227 | cb(port.PermissionDialogResult{Allowed: false, Persistent: true}) | |
| 228 | 228 | }) | |
| @@ -235,7 +235,7 @@ func TestHandlePermissionUseCase_PersistDenied(t *testing.T) { | |||
| 235 | 235 | ||
| 236 | 236 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | |
| 237 | 237 | entity.PermissionTypeCamera, | |
| 238 | - | }, callback) | |
| 238 | + | }, nil, callback) | |
| 239 | 239 | ||
| 240 | 240 | assert.True(t, denied) | |
| 241 | 241 | } | |
| @@ -256,7 +256,7 @@ func TestHandlePermissionUseCase_EmptyOrigin(t *testing.T) { | |||
| 256 | 256 | // Empty origin should be denied | |
| 257 | 257 | uc.HandlePermissionRequest(ctx, "", []entity.PermissionType{ | |
| 258 | 258 | entity.PermissionTypeMicrophone, | |
| 259 | - | }, callback) | |
| 259 | + | }, nil, callback) | |
| 260 | 260 | ||
| 261 | 261 | assert.True(t, denied, "empty origin should be denied") | |
| 262 | 262 | } | |
| @@ -292,7 +292,7 @@ func TestHandlePermissionUseCase_CombinedPermissions(t *testing.T) { | |||
| 292 | 292 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | |
| 293 | 293 | entity.PermissionTypeMicrophone, | |
| 294 | 294 | entity.PermissionTypeCamera, | |
| 295 | - | }, callback) | |
| 295 | + | }, nil, callback) | |
| 296 | 296 | ||
| 297 | 297 | assert.True(t, denied, "if any permission is denied, whole request is denied") | |
| 298 | 298 | } | |
| @@ -398,7 +398,7 @@ func TestHandlePermissionUseCase_NonPersistableNotSaved(t *testing.T) { | |||
| 398 | 398 | ||
| 399 | 399 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | |
| 400 | 400 | entity.PermissionTypeDisplay, | |
| 401 | - | }, callback) | |
| 401 | + | }, nil, callback) | |
| 402 | 402 | ||
| 403 | 403 | assert.True(t, allowed) | |
| 404 | 404 | permRepo.AssertNotCalled(t, "Set") | |
| @@ -423,7 +423,7 @@ func TestHandlePermissionUseCase_NoDialogPresenter(t *testing.T) { | |||
| 423 | 423 | ||
| 424 | 424 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | |
| 425 | 425 | entity.PermissionTypeMicrophone, | |
| 426 | - | }, callback) | |
| 426 | + | }, nil, callback) | |
| 427 | 427 | ||
| 428 | 428 | assert.True(t, denied, "should deny when no dialog presenter is available") | |
| 429 | 429 | } | |
| @@ -450,7 +450,7 @@ func TestHandlePermissionUseCase_DisplayOverrideDenied(t *testing.T) { | |||
| 450 | 450 | ||
| 451 | 451 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | |
| 452 | 452 | entity.PermissionTypeDisplay, | |
| 453 | - | }, callback) | |
| 453 | + | }, nil, callback) | |
| 454 | 454 | ||
| 455 | 455 | assert.True(t, denied, "display should be denied when manual override is denied") | |
| 456 | 456 | dialog.AssertNotCalled(t, "ShowPermissionDialog") | |
| @@ -526,7 +526,7 @@ func TestHandlePermissionUseCase_UsesInjectedLoggerFactory(t *testing.T) { | |||
| 526 | 526 | } | |
| 527 | 527 | ||
| 528 | 528 | uc := usecase.NewHandlePermissionUseCase(permRepo, dialog, loggerFactory) | |
| 529 | - | uc.HandlePermissionRequest(ctx, "", []entity.PermissionType{entity.PermissionTypeMicrophone}, usecase.PermissionCallback{ | |
| 529 | + | uc.HandlePermissionRequest(ctx, "", []entity.PermissionType{entity.PermissionTypeMicrophone}, nil, usecase.PermissionCallback{ | |
| 530 | 530 | Allow: func() {}, | |
| 531 | 531 | Deny: func() {}, | |
| 532 | 532 | }) | |
| @@ -542,7 +542,7 @@ func TestHandlePermissionUseCase_WebsiteDataAccess_ShowsDialogAndPersists(t *tes | |||
| 542 | 542 | uc := usecase.NewHandlePermissionUseCase(permRepo, dialog, permissionLoggerFromContext) | |
| 543 | 543 | ||
| 544 | 544 | // No stored permission | |
| 545 | - | permRepo.EXPECT().Get(mock.Anything, "https://accounts.google.com", entity.PermissionTypeWebsiteDataAccess). | |
| 545 | + | permRepo.EXPECT().Get(mock.Anything, "https://shop.example.com", entity.PermissionTypeWebsiteDataAccess). | |
| 546 | 546 | Return(nil, nil) | |
| 547 | 547 | ||
| 548 | 548 | allowed := false | |
| @@ -551,27 +551,33 @@ func TestHandlePermissionUseCase_WebsiteDataAccess_ShowsDialogAndPersists(t *tes | |||
| 551 | 551 | Deny: func() {}, | |
| 552 | 552 | } | |
| 553 | 553 | ||
| 554 | + | meta := entity.PermissionMetadata{ | |
| 555 | + | entity.PermissionMetadataKeyRequestingDomain: "accounts.google.com", | |
| 556 | + | entity.PermissionMetadataKeyCurrentDomain: "shop.example.com", | |
| 557 | + | } | |
| 558 | + | ||
| 554 | 559 | // Dialog shows and user clicks "Always Allow" | |
| 555 | 560 | dialog.EXPECT().ShowPermissionDialog( | |
| 556 | 561 | mock.Anything, | |
| 557 | - | "https://accounts.google.com", | |
| 562 | + | "https://shop.example.com", | |
| 558 | 563 | []entity.PermissionType{entity.PermissionTypeWebsiteDataAccess}, | |
| 564 | + | meta, | |
| 559 | 565 | mock.Anything, | |
| 560 | - | ).Run(func(_ context.Context, _ string, _ []entity.PermissionType, cb func(port.PermissionDialogResult)) { | |
| 566 | + | ).Run(func(_ context.Context, _ string, _ []entity.PermissionType, _ entity.PermissionMetadata, cb func(port.PermissionDialogResult)) { | |
| 561 | 567 | cb(port.PermissionDialogResult{Allowed: true, Persistent: true}) | |
| 562 | 568 | }) | |
| 563 | 569 | ||
| 564 | 570 | // Should persist the granted permission | |
| 565 | 571 | permRepo.EXPECT().Set(mock.Anything, mock.AnythingOfType("*entity.PermissionRecord")). | |
| 566 | 572 | Run(func(_ context.Context, r *entity.PermissionRecord) { | |
| 567 | - | assert.Equal(t, "https://accounts.google.com", r.Origin) | |
| 573 | + | assert.Equal(t, "https://shop.example.com", r.Origin) | |
| 568 | 574 | assert.Equal(t, entity.PermissionTypeWebsiteDataAccess, r.Type) | |
| 569 | 575 | assert.Equal(t, entity.PermissionGranted, r.Decision) | |
| 570 | 576 | }).Return(nil) | |
| 571 | 577 | ||
| 572 | - | uc.HandlePermissionRequest(ctx, "https://accounts.google.com", []entity.PermissionType{ | |
| 578 | + | uc.HandlePermissionRequest(ctx, "https://shop.example.com", []entity.PermissionType{ | |
| 573 | 579 | entity.PermissionTypeWebsiteDataAccess, | |
| 574 | - | }, callback) | |
| 580 | + | }, meta, callback) | |
| 575 | 581 | ||
| 576 | 582 | assert.True(t, allowed) | |
| 577 | 583 | } | |
| @@ -584,9 +590,9 @@ func TestHandlePermissionUseCase_WebsiteDataAccess_UsesStoredGrant(t *testing.T) | |||
| 584 | 590 | uc := usecase.NewHandlePermissionUseCase(permRepo, dialog, permissionLoggerFromContext) | |
| 585 | 591 | ||
| 586 | 592 | // Stored granted permission | |
| 587 | - | permRepo.EXPECT().Get(mock.Anything, "https://accounts.google.com", entity.PermissionTypeWebsiteDataAccess). | |
| 593 | + | permRepo.EXPECT().Get(mock.Anything, "https://shop.example.com", entity.PermissionTypeWebsiteDataAccess). | |
| 588 | 594 | Return(&entity.PermissionRecord{ | |
| 589 | - | Origin: "https://accounts.google.com", | |
| 595 | + | Origin: "https://shop.example.com", | |
| 590 | 596 | Type: entity.PermissionTypeWebsiteDataAccess, | |
| 591 | 597 | Decision: entity.PermissionGranted, | |
| 592 | 598 | }, nil) | |
| @@ -597,9 +603,9 @@ func TestHandlePermissionUseCase_WebsiteDataAccess_UsesStoredGrant(t *testing.T) | |||
| 597 | 603 | Deny: func() {}, | |
| 598 | 604 | } | |
| 599 | 605 | ||
| 600 | - | uc.HandlePermissionRequest(ctx, "https://accounts.google.com", []entity.PermissionType{ | |
| 606 | + | uc.HandlePermissionRequest(ctx, "https://shop.example.com", []entity.PermissionType{ | |
| 601 | 607 | entity.PermissionTypeWebsiteDataAccess, | |
| 602 | - | }, callback) | |
| 608 | + | }, entity.PermissionMetadata{entity.PermissionMetadataKeyRequestingDomain: "accounts.google.com", entity.PermissionMetadataKeyCurrentDomain: "shop.example.com"}, callback) | |
| 603 | 609 | ||
| 604 | 610 | assert.True(t, allowed, "should use stored granted permission without dialog") | |
| 605 | 611 | dialog.AssertNotCalled(t, "ShowPermissionDialog") | |
| @@ -39,7 +39,7 @@ func TestHandlePermissionUseCase_AutoAllowDisplayCapture(t *testing.T) { | |||||
| 39 | // Display capture should be auto-allowed (portal handles UI) | 39 | // Display capture should be auto-allowed (portal handles UI) | ||
| 40 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | 40 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | ||
| 41 | entity.PermissionTypeDisplay, | 41 | entity.PermissionTypeDisplay, | ||
| 42 | - | }, callback) | 42 | + | }, nil, callback) |
| 43 | 43 | ||||
| 44 | assert.True(t, allowed, "display capture should be auto-allowed") | 44 | assert.True(t, allowed, "display capture should be auto-allowed") | ||
| 45 | assert.False(t, denied) | 45 | assert.False(t, denied) | ||
| @@ -65,7 +65,7 @@ func TestHandlePermissionUseCase_AutoAllowDeviceInfo(t *testing.T) { | |||||
| 65 | // Device info should be auto-allowed | 65 | // Device info should be auto-allowed | ||
| 66 | uc.HandlePermissionRequest(ctx, "https://example.com", []entity.PermissionType{ | 66 | uc.HandlePermissionRequest(ctx, "https://example.com", []entity.PermissionType{ | ||
| 67 | entity.PermissionTypeDeviceInfo, | 67 | entity.PermissionTypeDeviceInfo, | ||
| 68 | - | }, callback) | 68 | + | }, nil, callback) |
| 69 | 69 | ||||
| 70 | assert.True(t, allowed, "device info should be auto-allowed") | 70 | assert.True(t, allowed, "device info should be auto-allowed") | ||
| 71 | } | 71 | } | ||
| @@ -94,7 +94,7 @@ func TestHandlePermissionUseCase_StoredPermissionGranted(t *testing.T) { | |||||
| 94 | 94 | ||||
| 95 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | 95 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | ||
| 96 | entity.PermissionTypeMicrophone, | 96 | entity.PermissionTypeMicrophone, | ||
| 97 | - | }, callback) | 97 | + | }, nil, callback) |
| 98 | 98 | ||||
| 99 | assert.True(t, allowed, "should use stored granted permission") | 99 | assert.True(t, allowed, "should use stored granted permission") | ||
| 100 | dialog.AssertNotCalled(t, "ShowPermissionDialog") | 100 | dialog.AssertNotCalled(t, "ShowPermissionDialog") | ||
| @@ -124,7 +124,7 @@ func TestHandlePermissionUseCase_StoredPermissionDenied(t *testing.T) { | |||||
| 124 | 124 | ||||
| 125 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | 125 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | ||
| 126 | entity.PermissionTypeCamera, | 126 | entity.PermissionTypeCamera, | ||
| 127 | - | }, callback) | 127 | + | }, nil, callback) |
| 128 | 128 | ||||
| 129 | assert.True(t, denied, "should use stored denied permission") | 129 | assert.True(t, denied, "should use stored denied permission") | ||
| 130 | dialog.AssertNotCalled(t, "ShowPermissionDialog") | 130 | dialog.AssertNotCalled(t, "ShowPermissionDialog") | ||
| @@ -150,13 +150,13 @@ func TestHandlePermissionUseCase_ShowDialogForPrompt(t *testing.T) { | |||||
| 150 | // Dialog shows and user clicks Allow (not persistent) | 150 | // Dialog shows and user clicks Allow (not persistent) | ||
| 151 | dialog.EXPECT().ShowPermissionDialog(mock.Anything, "https://meet.example.com", []entity.PermissionType{ | 151 | dialog.EXPECT().ShowPermissionDialog(mock.Anything, "https://meet.example.com", []entity.PermissionType{ | ||
| 152 | entity.PermissionTypeMicrophone, | 152 | entity.PermissionTypeMicrophone, | ||
| 153 | - | }, mock.Anything).Run(func(_ context.Context, _ string, _ []entity.PermissionType, callback func(port.PermissionDialogResult)) { | 153 | + | }, mock.Anything, mock.Anything).Run(func(_ context.Context, _ string, _ []entity.PermissionType, _ entity.PermissionMetadata, callback func(port.PermissionDialogResult)) { |
| 154 | callback(port.PermissionDialogResult{Allowed: true, Persistent: false}) | 154 | callback(port.PermissionDialogResult{Allowed: true, Persistent: false}) | ||
| 155 | }) | 155 | }) | ||
| 156 | 156 | ||||
| 157 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | 157 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | ||
| 158 | entity.PermissionTypeMicrophone, | 158 | entity.PermissionTypeMicrophone, | ||
| 159 | - | }, callback) | 159 | + | }, nil, callback) |
| 160 | 160 | ||||
| 161 | assert.True(t, allowed, "user allowed permission") | 161 | assert.True(t, allowed, "user allowed permission") | ||
| 162 | // Should not persist since Persistent=false | 162 | // Should not persist since Persistent=false | ||
| @@ -183,7 +183,7 @@ func TestHandlePermissionUseCase_PersistAllowed(t *testing.T) { | |||||
| 183 | // Dialog shows and user clicks "Always Allow" | 183 | // Dialog shows and user clicks "Always Allow" | ||
| 184 | dialog.EXPECT().ShowPermissionDialog(mock.Anything, "https://meet.example.com", []entity.PermissionType{ | 184 | dialog.EXPECT().ShowPermissionDialog(mock.Anything, "https://meet.example.com", []entity.PermissionType{ | ||
| 185 | entity.PermissionTypeMicrophone, | 185 | entity.PermissionTypeMicrophone, | ||
| 186 | - | }, mock.Anything).Run(func(_ context.Context, _ string, _ []entity.PermissionType, cb func(port.PermissionDialogResult)) { | 186 | + | }, mock.Anything, mock.Anything).Run(func(_ context.Context, _ string, _ []entity.PermissionType, _ entity.PermissionMetadata, cb func(port.PermissionDialogResult)) { |
| 187 | cb(port.PermissionDialogResult{Allowed: true, Persistent: true}) | 187 | cb(port.PermissionDialogResult{Allowed: true, Persistent: true}) | ||
| 188 | }) | 188 | }) | ||
| 189 | 189 | ||||
| @@ -197,7 +197,7 @@ func TestHandlePermissionUseCase_PersistAllowed(t *testing.T) { | |||||
| 197 | 197 | ||||
| 198 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | 198 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | ||
| 199 | entity.PermissionTypeMicrophone, | 199 | entity.PermissionTypeMicrophone, | ||
| 200 | - | }, callback) | 200 | + | }, nil, callback) |
| 201 | 201 | ||||
| 202 | assert.True(t, allowed) | 202 | assert.True(t, allowed) | ||
| 203 | } | 203 | } | ||
| @@ -222,7 +222,7 @@ func TestHandlePermissionUseCase_PersistDenied(t *testing.T) { | |||||
| 222 | // Dialog shows and user clicks "Always Deny" | 222 | // Dialog shows and user clicks "Always Deny" | ||
| 223 | dialog.EXPECT().ShowPermissionDialog(mock.Anything, "https://meet.example.com", []entity.PermissionType{ | 223 | dialog.EXPECT().ShowPermissionDialog(mock.Anything, "https://meet.example.com", []entity.PermissionType{ | ||
| 224 | entity.PermissionTypeCamera, | 224 | entity.PermissionTypeCamera, | ||
| 225 | - | }, mock.Anything).Run(func(_ context.Context, _ string, _ []entity.PermissionType, cb func(port.PermissionDialogResult)) { | 225 | + | }, mock.Anything, mock.Anything).Run(func(_ context.Context, _ string, _ []entity.PermissionType, _ entity.PermissionMetadata, cb func(port.PermissionDialogResult)) { |
| 226 | // User denied but wants to persist this decision | 226 | // User denied but wants to persist this decision | ||
| 227 | cb(port.PermissionDialogResult{Allowed: false, Persistent: true}) | 227 | cb(port.PermissionDialogResult{Allowed: false, Persistent: true}) | ||
| 228 | }) | 228 | }) | ||
| @@ -235,7 +235,7 @@ func TestHandlePermissionUseCase_PersistDenied(t *testing.T) { | |||||
| 235 | 235 | ||||
| 236 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | 236 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | ||
| 237 | entity.PermissionTypeCamera, | 237 | entity.PermissionTypeCamera, | ||
| 238 | - | }, callback) | 238 | + | }, nil, callback) |
| 239 | 239 | ||||
| 240 | assert.True(t, denied) | 240 | assert.True(t, denied) | ||
| 241 | } | 241 | } | ||
| @@ -256,7 +256,7 @@ func TestHandlePermissionUseCase_EmptyOrigin(t *testing.T) { | |||||
| 256 | // Empty origin should be denied | 256 | // Empty origin should be denied | ||
| 257 | uc.HandlePermissionRequest(ctx, "", []entity.PermissionType{ | 257 | uc.HandlePermissionRequest(ctx, "", []entity.PermissionType{ | ||
| 258 | entity.PermissionTypeMicrophone, | 258 | entity.PermissionTypeMicrophone, | ||
| 259 | - | }, callback) | 259 | + | }, nil, callback) |
| 260 | 260 | ||||
| 261 | assert.True(t, denied, "empty origin should be denied") | 261 | assert.True(t, denied, "empty origin should be denied") | ||
| 262 | } | 262 | } | ||
| @@ -292,7 +292,7 @@ func TestHandlePermissionUseCase_CombinedPermissions(t *testing.T) { | |||||
| 292 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | 292 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | ||
| 293 | entity.PermissionTypeMicrophone, | 293 | entity.PermissionTypeMicrophone, | ||
| 294 | entity.PermissionTypeCamera, | 294 | entity.PermissionTypeCamera, | ||
| 295 | - | }, callback) | 295 | + | }, nil, callback) |
| 296 | 296 | ||||
| 297 | assert.True(t, denied, "if any permission is denied, whole request is denied") | 297 | assert.True(t, denied, "if any permission is denied, whole request is denied") | ||
| 298 | } | 298 | } | ||
| @@ -398,7 +398,7 @@ func TestHandlePermissionUseCase_NonPersistableNotSaved(t *testing.T) { | |||||
| 398 | 398 | ||||
| 399 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | 399 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | ||
| 400 | entity.PermissionTypeDisplay, | 400 | entity.PermissionTypeDisplay, | ||
| 401 | - | }, callback) | 401 | + | }, nil, callback) |
| 402 | 402 | ||||
| 403 | assert.True(t, allowed) | 403 | assert.True(t, allowed) | ||
| 404 | permRepo.AssertNotCalled(t, "Set") | 404 | permRepo.AssertNotCalled(t, "Set") | ||
| @@ -423,7 +423,7 @@ func TestHandlePermissionUseCase_NoDialogPresenter(t *testing.T) { | |||||
| 423 | 423 | ||||
| 424 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | 424 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | ||
| 425 | entity.PermissionTypeMicrophone, | 425 | entity.PermissionTypeMicrophone, | ||
| 426 | - | }, callback) | 426 | + | }, nil, callback) |
| 427 | 427 | ||||
| 428 | assert.True(t, denied, "should deny when no dialog presenter is available") | 428 | assert.True(t, denied, "should deny when no dialog presenter is available") | ||
| 429 | } | 429 | } | ||
| @@ -450,7 +450,7 @@ func TestHandlePermissionUseCase_DisplayOverrideDenied(t *testing.T) { | |||||
| 450 | 450 | ||||
| 451 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | 451 | uc.HandlePermissionRequest(ctx, "https://meet.example.com", []entity.PermissionType{ | ||
| 452 | entity.PermissionTypeDisplay, | 452 | entity.PermissionTypeDisplay, | ||
| 453 | - | }, callback) | 453 | + | }, nil, callback) |
| 454 | 454 | ||||
| 455 | assert.True(t, denied, "display should be denied when manual override is denied") | 455 | assert.True(t, denied, "display should be denied when manual override is denied") | ||
| 456 | dialog.AssertNotCalled(t, "ShowPermissionDialog") | 456 | dialog.AssertNotCalled(t, "ShowPermissionDialog") | ||
| @@ -526,7 +526,7 @@ func TestHandlePermissionUseCase_UsesInjectedLoggerFactory(t *testing.T) { | |||||
| 526 | } | 526 | } | ||
| 527 | 527 | ||||
| 528 | uc := usecase.NewHandlePermissionUseCase(permRepo, dialog, loggerFactory) | 528 | uc := usecase.NewHandlePermissionUseCase(permRepo, dialog, loggerFactory) | ||
| 529 | - | uc.HandlePermissionRequest(ctx, "", []entity.PermissionType{entity.PermissionTypeMicrophone}, usecase.PermissionCallback{ | 529 | + | uc.HandlePermissionRequest(ctx, "", []entity.PermissionType{entity.PermissionTypeMicrophone}, nil, usecase.PermissionCallback{ |
| 530 | Allow: func() {}, | 530 | Allow: func() {}, | ||
| 531 | Deny: func() {}, | 531 | Deny: func() {}, | ||
| 532 | }) | 532 | }) | ||
| @@ -542,7 +542,7 @@ func TestHandlePermissionUseCase_WebsiteDataAccess_ShowsDialogAndPersists(t *tes | |||||
| 542 | uc := usecase.NewHandlePermissionUseCase(permRepo, dialog, permissionLoggerFromContext) | 542 | uc := usecase.NewHandlePermissionUseCase(permRepo, dialog, permissionLoggerFromContext) | ||
| 543 | 543 | ||||
| 544 | // No stored permission | 544 | // No stored permission | ||
| 545 | - | permRepo.EXPECT().Get(mock.Anything, "https://accounts.google.com", entity.PermissionTypeWebsiteDataAccess). | 545 | + | permRepo.EXPECT().Get(mock.Anything, "https://shop.example.com", entity.PermissionTypeWebsiteDataAccess). |
| 546 | Return(nil, nil) | 546 | Return(nil, nil) | ||
| 547 | 547 | ||||
| 548 | allowed := false | 548 | allowed := false | ||
| @@ -551,27 +551,33 @@ func TestHandlePermissionUseCase_WebsiteDataAccess_ShowsDialogAndPersists(t *tes | |||||
| 551 | Deny: func() {}, | 551 | Deny: func() {}, | ||
| 552 | } | 552 | } | ||
| 553 | 553 | ||||
| 554 | + | meta := entity.PermissionMetadata{ | |||
| 555 | + | entity.PermissionMetadataKeyRequestingDomain: "accounts.google.com", | |||
| 556 | + | entity.PermissionMetadataKeyCurrentDomain: "shop.example.com", | |||
| 557 | + | } | |||
| 558 | + | ||||
| 554 | // Dialog shows and user clicks "Always Allow" | 559 | // Dialog shows and user clicks "Always Allow" | ||
| 555 | dialog.EXPECT().ShowPermissionDialog( | 560 | dialog.EXPECT().ShowPermissionDialog( | ||
| 556 | mock.Anything, | 561 | mock.Anything, | ||
| 557 | - | "https://accounts.google.com", | 562 | + | "https://shop.example.com", |
| 558 | []entity.PermissionType{entity.PermissionTypeWebsiteDataAccess}, | 563 | []entity.PermissionType{entity.PermissionTypeWebsiteDataAccess}, | ||
| 564 | + | meta, | |||
| 559 | mock.Anything, | 565 | mock.Anything, | ||
| 560 | - | ).Run(func(_ context.Context, _ string, _ []entity.PermissionType, cb func(port.PermissionDialogResult)) { | 566 | + | ).Run(func(_ context.Context, _ string, _ []entity.PermissionType, _ entity.PermissionMetadata, cb func(port.PermissionDialogResult)) { |
| 561 | cb(port.PermissionDialogResult{Allowed: true, Persistent: true}) | 567 | cb(port.PermissionDialogResult{Allowed: true, Persistent: true}) | ||
| 562 | }) | 568 | }) | ||
| 563 | 569 | ||||
| 564 | // Should persist the granted permission | 570 | // Should persist the granted permission | ||
| 565 | permRepo.EXPECT().Set(mock.Anything, mock.AnythingOfType("*entity.PermissionRecord")). | 571 | permRepo.EXPECT().Set(mock.Anything, mock.AnythingOfType("*entity.PermissionRecord")). | ||
| 566 | Run(func(_ context.Context, r *entity.PermissionRecord) { | 572 | Run(func(_ context.Context, r *entity.PermissionRecord) { | ||
| 567 | - | assert.Equal(t, "https://accounts.google.com", r.Origin) | 573 | + | assert.Equal(t, "https://shop.example.com", r.Origin) |
| 568 | assert.Equal(t, entity.PermissionTypeWebsiteDataAccess, r.Type) | 574 | assert.Equal(t, entity.PermissionTypeWebsiteDataAccess, r.Type) | ||
| 569 | assert.Equal(t, entity.PermissionGranted, r.Decision) | 575 | assert.Equal(t, entity.PermissionGranted, r.Decision) | ||
| 570 | }).Return(nil) | 576 | }).Return(nil) | ||
| 571 | 577 | ||||
| 572 | - | uc.HandlePermissionRequest(ctx, "https://accounts.google.com", []entity.PermissionType{ | 578 | + | uc.HandlePermissionRequest(ctx, "https://shop.example.com", []entity.PermissionType{ |
| 573 | entity.PermissionTypeWebsiteDataAccess, | 579 | entity.PermissionTypeWebsiteDataAccess, | ||
| 574 | - | }, callback) | 580 | + | }, meta, callback) |
| 575 | 581 | ||||
| 576 | assert.True(t, allowed) | 582 | assert.True(t, allowed) | ||
| 577 | } | 583 | } | ||
| @@ -584,9 +590,9 @@ func TestHandlePermissionUseCase_WebsiteDataAccess_UsesStoredGrant(t *testing.T) | |||||
| 584 | uc := usecase.NewHandlePermissionUseCase(permRepo, dialog, permissionLoggerFromContext) | 590 | uc := usecase.NewHandlePermissionUseCase(permRepo, dialog, permissionLoggerFromContext) | ||
| 585 | 591 | ||||
| 586 | // Stored granted permission | 592 | // Stored granted permission | ||
| 587 | - | permRepo.EXPECT().Get(mock.Anything, "https://accounts.google.com", entity.PermissionTypeWebsiteDataAccess). | 593 | + | permRepo.EXPECT().Get(mock.Anything, "https://shop.example.com", entity.PermissionTypeWebsiteDataAccess). |
| 588 | Return(&entity.PermissionRecord{ | 594 | Return(&entity.PermissionRecord{ | ||
| 589 | - | Origin: "https://accounts.google.com", | 595 | + | Origin: "https://shop.example.com", |
| 590 | Type: entity.PermissionTypeWebsiteDataAccess, | 596 | Type: entity.PermissionTypeWebsiteDataAccess, | ||
| 591 | Decision: entity.PermissionGranted, | 597 | Decision: entity.PermissionGranted, | ||
| 592 | }, nil) | 598 | }, nil) | ||
| @@ -597,9 +603,9 @@ func TestHandlePermissionUseCase_WebsiteDataAccess_UsesStoredGrant(t *testing.T) | |||||
| 597 | Deny: func() {}, | 603 | Deny: func() {}, | ||
| 598 | } | 604 | } | ||
| 599 | 605 | ||||
| 600 | - | uc.HandlePermissionRequest(ctx, "https://accounts.google.com", []entity.PermissionType{ | 606 | + | uc.HandlePermissionRequest(ctx, "https://shop.example.com", []entity.PermissionType{ |
| 601 | entity.PermissionTypeWebsiteDataAccess, | 607 | entity.PermissionTypeWebsiteDataAccess, | ||
| 602 | - | }, callback) | 608 | + | }, entity.PermissionMetadata{entity.PermissionMetadataKeyRequestingDomain: "accounts.google.com", entity.PermissionMetadataKeyCurrentDomain: "shop.example.com"}, callback) |
| 603 | 609 | ||||
| 604 | assert.True(t, allowed, "should use stored granted permission without dialog") | 610 | assert.True(t, allowed, "should use stored granted permission without dialog") | ||
| 605 | dialog.AssertNotCalled(t, "ShowPermissionDialog") | 611 | dialog.AssertNotCalled(t, "ShowPermissionDialog") | ||
M internal/domain/entity/permission.go +17 -0
| @@ -38,6 +38,23 @@ const ( | |||
| 38 | 38 | PermissionTypeWebsiteDataAccess PermissionType = "website_data_access" | |
| 39 | 39 | ) | |
| 40 | 40 | ||
| 41 | + | // Metadata keys for PermissionMetadata. | |
| 42 | + | const ( | |
| 43 | + | // PermissionMetadataKeyRequestingDomain is the origin that is requesting cross-site | |
| 44 | + | // data access (i.e. the third-party domain asking for its cookies/storage). | |
| 45 | + | PermissionMetadataKeyRequestingDomain = "requesting_domain" | |
| 46 | + | ||
| 47 | + | // PermissionMetadataKeyCurrentDomain is the first-party domain currently loaded in | |
| 48 | + | // the WebView — the context in which the cross-site request is happening. | |
| 49 | + | PermissionMetadataKeyCurrentDomain = "current_domain" | |
| 50 | + | ) | |
| 51 | + | ||
| 52 | + | // PermissionMetadata carries extra context for specific permission types. | |
| 53 | + | // For website_data_access, callers must populate both keys: | |
| 54 | + | // - PermissionMetadataKeyRequestingDomain: the origin requesting cross-site data access | |
| 55 | + | // - PermissionMetadataKeyCurrentDomain: the domain currently loaded in the WebView | |
| 56 | + | type PermissionMetadata map[string]string | |
| 57 | + | ||
| 41 | 58 | // PermissionDecision represents the user's decision for a permission. | |
| 42 | 59 | type PermissionDecision string | |
| 43 | 60 | ||
| @@ -38,6 +38,23 @@ const ( | |||||
| 38 | PermissionTypeWebsiteDataAccess PermissionType = "website_data_access" | 38 | PermissionTypeWebsiteDataAccess PermissionType = "website_data_access" | ||
| 39 | ) | 39 | ) | ||
| 40 | 40 | ||||
| 41 | + | // Metadata keys for PermissionMetadata. | |||
| 42 | + | const ( | |||
| 43 | + | // PermissionMetadataKeyRequestingDomain is the origin that is requesting cross-site | |||
| 44 | + | // data access (i.e. the third-party domain asking for its cookies/storage). | |||
| 45 | + | PermissionMetadataKeyRequestingDomain = "requesting_domain" | |||
| 46 | + | ||||
| 47 | + | // PermissionMetadataKeyCurrentDomain is the first-party domain currently loaded in | |||
| 48 | + | // the WebView — the context in which the cross-site request is happening. | |||
| 49 | + | PermissionMetadataKeyCurrentDomain = "current_domain" | |||
| 50 | + | ) | |||
| 51 | + | ||||
| 52 | + | // PermissionMetadata carries extra context for specific permission types. | |||
| 53 | + | // For website_data_access, callers must populate both keys: | |||
| 54 | + | // - PermissionMetadataKeyRequestingDomain: the origin requesting cross-site data access | |||
| 55 | + | // - PermissionMetadataKeyCurrentDomain: the domain currently loaded in the WebView | |||
| 56 | + | type PermissionMetadata map[string]string | |||
| 57 | + | ||||
| 41 | // PermissionDecision represents the user's decision for a permission. | 58 | // PermissionDecision represents the user's decision for a permission. | ||
| 42 | type PermissionDecision string | 59 | type PermissionDecision string | ||
| 43 | 60 | ||||
M internal/infrastructure/colorscheme/detector_adwaita.go +1 -1
| @@ -3,7 +3,7 @@ package colorscheme | |||
| 3 | 3 | import ( | |
| 4 | 4 | "sync/atomic" | |
| 5 | 5 | ||
| 6 | - | "github.com/jwijenbergh/puregotk/v4/adw" | |
| 6 | + | "github.com/bnema/puregotk/v4/adw" | |
| 7 | 7 | ) | |
| 8 | 8 | ||
| 9 | 9 | const ( | |
| @@ -3,7 +3,7 @@ package colorscheme | |||||
| 3 | import ( | 3 | import ( | ||
| 4 | "sync/atomic" | 4 | "sync/atomic" | ||
| 5 | 5 | ||||
| 6 | - | "github.com/jwijenbergh/puregotk/v4/adw" | 6 | + | "github.com/bnema/puregotk/v4/adw" |
| 7 | ) | 7 | ) | ||
| 8 | 8 | ||||
| 9 | const ( | 9 | const ( | ||
M internal/infrastructure/config/defaults.go +4 -1
| @@ -147,7 +147,10 @@ func DefaultConfig() *Config { | |||
| 147 | 147 | Profile: ProfileDefault, | |
| 148 | 148 | PoolPrewarmCount: defaultWebViewPoolPrewarmCount, | |
| 149 | 149 | ZoomCacheSize: defaultZoomCacheSize, | |
| 150 | - | CookiePolicy: CookiePolicyNoThirdParty, | |
| 150 | + | // With ITP enabled, WebKit ignores ACCEPT_NO_THIRD_PARTY — ITP handles | |
| 151 | + | // third-party cookie isolation more intelligently. Using Always + ITP | |
| 152 | + | // matches Epiphany's model and avoids a misleading setting. | |
| 153 | + | CookiePolicy: CookiePolicyAlways, | |
| 151 | 154 | WebKit: WebKitEngineConfig{ | |
| 152 | 155 | ITPEnabled: true, | |
| 153 | 156 | SkiaCPUPaintingThreads: defaultSkiaCPUPaintingThreads, | |
| @@ -147,7 +147,10 @@ func DefaultConfig() *Config { | |||||
| 147 | Profile: ProfileDefault, | 147 | Profile: ProfileDefault, | ||
| 148 | PoolPrewarmCount: defaultWebViewPoolPrewarmCount, | 148 | PoolPrewarmCount: defaultWebViewPoolPrewarmCount, | ||
| 149 | ZoomCacheSize: defaultZoomCacheSize, | 149 | ZoomCacheSize: defaultZoomCacheSize, | ||
| 150 | - | CookiePolicy: CookiePolicyNoThirdParty, | 150 | + | // With ITP enabled, WebKit ignores ACCEPT_NO_THIRD_PARTY — ITP handles |
| 151 | + | // third-party cookie isolation more intelligently. Using Always + ITP | |||
| 152 | + | // matches Epiphany's model and avoids a misleading setting. | |||
| 153 | + | CookiePolicy: CookiePolicyAlways, | |||
| 151 | WebKit: WebKitEngineConfig{ | 154 | WebKit: WebKitEngineConfig{ | ||
| 152 | ITPEnabled: true, | 155 | ITPEnabled: true, | ||
| 153 | SkiaCPUPaintingThreads: defaultSkiaCPUPaintingThreads, | 156 | SkiaCPUPaintingThreads: defaultSkiaCPUPaintingThreads, | ||
M internal/infrastructure/config/defaults_test.go +1 -1
| @@ -15,7 +15,7 @@ func TestDefaultConfig_CoreDefaults(t *testing.T) { | |||
| 15 | 15 | // Engine defaults (replaces old Performance/Privacy sections) | |
| 16 | 16 | assert.Equal(t, "webkit", cfg.Engine.Type) | |
| 17 | 17 | assert.Equal(t, ProfileDefault, cfg.Engine.Profile) | |
| 18 | - | assert.Equal(t, CookiePolicyNoThirdParty, cfg.Engine.CookiePolicy) | |
| 18 | + | assert.Equal(t, CookiePolicyAlways, cfg.Engine.CookiePolicy) | |
| 19 | 19 | assert.True(t, cfg.Engine.WebKit.ITPEnabled) | |
| 20 | 20 | ||
| 21 | 21 | // Old sections (Rendering, Privacy, Performance, Runtime) have been removed from Config. | |
| @@ -15,7 +15,7 @@ func TestDefaultConfig_CoreDefaults(t *testing.T) { | |||||
| 15 | // Engine defaults (replaces old Performance/Privacy sections) | 15 | // Engine defaults (replaces old Performance/Privacy sections) | ||
| 16 | assert.Equal(t, "webkit", cfg.Engine.Type) | 16 | assert.Equal(t, "webkit", cfg.Engine.Type) | ||
| 17 | assert.Equal(t, ProfileDefault, cfg.Engine.Profile) | 17 | assert.Equal(t, ProfileDefault, cfg.Engine.Profile) | ||
| 18 | - | assert.Equal(t, CookiePolicyNoThirdParty, cfg.Engine.CookiePolicy) | 18 | + | assert.Equal(t, CookiePolicyAlways, cfg.Engine.CookiePolicy) |
| 19 | assert.True(t, cfg.Engine.WebKit.ITPEnabled) | 19 | assert.True(t, cfg.Engine.WebKit.ITPEnabled) | ||
| 20 | 20 | ||||
| 21 | // Old sections (Rendering, Privacy, Performance, Runtime) have been removed from Config. | 21 | // Old sections (Rendering, Privacy, Performance, Runtime) have been removed from Config. | ||
M internal/infrastructure/config/loader.go +15 -4
| @@ -224,16 +224,27 @@ func normalizeEngineConfig(config *Config) { | |||
| 224 | 224 | config.Engine.WebKit.GSKRenderer = GSKRendererAuto | |
| 225 | 225 | } | |
| 226 | 226 | ||
| 227 | - | // Normalize cookie policy (engine) | |
| 227 | + | // Normalize cookie policy (engine). | |
| 228 | + | // When no value (or an invalid value) is set, respect the ITP setting: if ITP is | |
| 229 | + | // disabled the effective default is to block third-party cookies; if ITP is enabled | |
| 230 | + | // all cookies are accepted by default. An explicit "always" value always wins. | |
| 231 | + | itpDefault := func() CookiePolicy { | |
| 232 | + | if config.Engine.WebKit.ITPEnabled { | |
| 233 | + | return CookiePolicyAlways | |
| 234 | + | } | |
| 235 | + | return CookiePolicyNoThirdParty | |
| 236 | + | } | |
| 228 | 237 | switch strings.ToLower(string(config.Engine.CookiePolicy)) { | |
| 229 | - | case "", string(CookiePolicyNoThirdParty): | |
| 230 | - | config.Engine.CookiePolicy = CookiePolicyNoThirdParty | |
| 238 | + | case "": | |
| 239 | + | config.Engine.CookiePolicy = itpDefault() | |
| 231 | 240 | case string(CookiePolicyAlways): | |
| 232 | 241 | config.Engine.CookiePolicy = CookiePolicyAlways | |
| 242 | + | case string(CookiePolicyNoThirdParty): | |
| 243 | + | config.Engine.CookiePolicy = CookiePolicyNoThirdParty | |
| 233 | 244 | case string(CookiePolicyNever): | |
| 234 | 245 | config.Engine.CookiePolicy = CookiePolicyNever | |
| 235 | 246 | default: | |
| 236 | - | config.Engine.CookiePolicy = CookiePolicyNoThirdParty | |
| 247 | + | config.Engine.CookiePolicy = itpDefault() | |
| 237 | 248 | } | |
| 238 | 249 | ||
| 239 | 250 | // Normalize performance profile (engine) | |
| @@ -224,16 +224,27 @@ func normalizeEngineConfig(config *Config) { | |||||
| 224 | config.Engine.WebKit.GSKRenderer = GSKRendererAuto | 224 | config.Engine.WebKit.GSKRenderer = GSKRendererAuto | ||
| 225 | } | 225 | } | ||
| 226 | 226 | ||||
| 227 | - | // Normalize cookie policy (engine) | 227 | + | // Normalize cookie policy (engine). |
| 228 | + | // When no value (or an invalid value) is set, respect the ITP setting: if ITP is | |||
| 229 | + | // disabled the effective default is to block third-party cookies; if ITP is enabled | |||
| 230 | + | // all cookies are accepted by default. An explicit "always" value always wins. | |||
| 231 | + | itpDefault := func() CookiePolicy { | |||
| 232 | + | if config.Engine.WebKit.ITPEnabled { | |||
| 233 | + | return CookiePolicyAlways | |||
| 234 | + | } | |||
| 235 | + | return CookiePolicyNoThirdParty | |||
| 236 | + | } | |||
| 228 | switch strings.ToLower(string(config.Engine.CookiePolicy)) { | 237 | switch strings.ToLower(string(config.Engine.CookiePolicy)) { | ||
| 229 | - | case "", string(CookiePolicyNoThirdParty): | 238 | + | case "": |
| 230 | - | config.Engine.CookiePolicy = CookiePolicyNoThirdParty | 239 | + | config.Engine.CookiePolicy = itpDefault() |
| 231 | case string(CookiePolicyAlways): | 240 | case string(CookiePolicyAlways): | ||
| 232 | config.Engine.CookiePolicy = CookiePolicyAlways | 241 | config.Engine.CookiePolicy = CookiePolicyAlways | ||
| 242 | + | case string(CookiePolicyNoThirdParty): | |||
| 243 | + | config.Engine.CookiePolicy = CookiePolicyNoThirdParty | |||
| 233 | case string(CookiePolicyNever): | 244 | case string(CookiePolicyNever): | ||
| 234 | config.Engine.CookiePolicy = CookiePolicyNever | 245 | config.Engine.CookiePolicy = CookiePolicyNever | ||
| 235 | default: | 246 | default: | ||
| 236 | - | config.Engine.CookiePolicy = CookiePolicyNoThirdParty | 247 | + | config.Engine.CookiePolicy = itpDefault() |
| 237 | } | 248 | } | ||
| 238 | 249 | ||||
| 239 | // Normalize performance profile (engine) | 250 | // Normalize performance profile (engine) | ||
M internal/infrastructure/config/loader_test.go +2 -2
| @@ -14,7 +14,7 @@ func TestSetEngineDefaults(t *testing.T) { | |||
| 14 | 14 | // Universal engine fields | |
| 15 | 15 | assert.Equal(t, "webkit", mgr.viper.GetString("engine.type")) | |
| 16 | 16 | assert.Equal(t, "default", mgr.viper.GetString("engine.profile")) | |
| 17 | - | assert.Equal(t, "no_third_party", mgr.viper.GetString("engine.cookie_policy")) | |
| 17 | + | assert.Equal(t, "always", mgr.viper.GetString("engine.cookie_policy")) | |
| 18 | 18 | assert.Equal(t, 4, mgr.viper.GetInt("engine.pool_prewarm_count")) | |
| 19 | 19 | assert.Equal(t, 256, mgr.viper.GetInt("engine.zoom_cache_size")) | |
| 20 | 20 | ||
| @@ -37,5 +37,5 @@ func TestNormalizeConfig_EngineCookiePolicy(t *testing.T) { | |||
| 37 | 37 | ||
| 38 | 38 | normalizeConfig(cfg) | |
| 39 | 39 | ||
| 40 | - | assert.Equal(t, CookiePolicyNoThirdParty, cfg.Engine.CookiePolicy) | |
| 40 | + | assert.Equal(t, CookiePolicyAlways, cfg.Engine.CookiePolicy) | |
| 41 | 41 | } | |
| @@ -14,7 +14,7 @@ func TestSetEngineDefaults(t *testing.T) { | |||||
| 14 | // Universal engine fields | 14 | // Universal engine fields | ||
| 15 | assert.Equal(t, "webkit", mgr.viper.GetString("engine.type")) | 15 | assert.Equal(t, "webkit", mgr.viper.GetString("engine.type")) | ||
| 16 | assert.Equal(t, "default", mgr.viper.GetString("engine.profile")) | 16 | assert.Equal(t, "default", mgr.viper.GetString("engine.profile")) | ||
| 17 | - | assert.Equal(t, "no_third_party", mgr.viper.GetString("engine.cookie_policy")) | 17 | + | assert.Equal(t, "always", mgr.viper.GetString("engine.cookie_policy")) |
| 18 | assert.Equal(t, 4, mgr.viper.GetInt("engine.pool_prewarm_count")) | 18 | assert.Equal(t, 4, mgr.viper.GetInt("engine.pool_prewarm_count")) | ||
| 19 | assert.Equal(t, 256, mgr.viper.GetInt("engine.zoom_cache_size")) | 19 | assert.Equal(t, 256, mgr.viper.GetInt("engine.zoom_cache_size")) | ||
| 20 | 20 | ||||
| @@ -37,5 +37,5 @@ func TestNormalizeConfig_EngineCookiePolicy(t *testing.T) { | |||||
| 37 | 37 | ||||
| 38 | normalizeConfig(cfg) | 38 | normalizeConfig(cfg) | ||
| 39 | 39 | ||||
| 40 | - | assert.Equal(t, CookiePolicyNoThirdParty, cfg.Engine.CookiePolicy) | 40 | + | assert.Equal(t, CookiePolicyAlways, cfg.Engine.CookiePolicy) |
| 41 | } | 41 | } | ||
M internal/infrastructure/filtering/store.go +1 -1
| @@ -7,7 +7,7 @@ import ( | |||
| 7 | 7 | ||
| 8 | 8 | "github.com/bnema/dumber/internal/logging" | |
| 9 | 9 | "github.com/bnema/puregotk-webkit/webkit" | |
| 10 | - | "github.com/jwijenbergh/puregotk/v4/gio" | |
| 10 | + | "github.com/bnema/puregotk/v4/gio" | |
| 11 | 11 | ) | |
| 12 | 12 | ||
| 13 | 13 | // Store wraps webkit.UserContentFilterStore with Go-friendly async operations. | |
| @@ -7,7 +7,7 @@ import ( | |||||
| 7 | 7 | ||||
| 8 | "github.com/bnema/dumber/internal/logging" | 8 | "github.com/bnema/dumber/internal/logging" | ||
| 9 | "github.com/bnema/puregotk-webkit/webkit" | 9 | "github.com/bnema/puregotk-webkit/webkit" | ||
| 10 | - | "github.com/jwijenbergh/puregotk/v4/gio" | 10 | + | "github.com/bnema/puregotk/v4/gio" |
| 11 | ) | 11 | ) | ||
| 12 | 12 | ||||
| 13 | // Store wraps webkit.UserContentFilterStore with Go-friendly async operations. | 13 | // Store wraps webkit.UserContentFilterStore with Go-friendly async operations. | ||
M internal/infrastructure/textinput/gtk_entry_target.go +1 -1
| @@ -5,7 +5,7 @@ import ( | |||
| 5 | 5 | ||
| 6 | 6 | "github.com/bnema/dumber/internal/application/port" | |
| 7 | 7 | "github.com/bnema/dumber/internal/logging" | |
| 8 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 8 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 9 | 9 | ) | |
| 10 | 10 | ||
| 11 | 11 | // GTKEntryTarget implements TextInputTarget for GTK SearchEntry widgets. | |
| @@ -5,7 +5,7 @@ import ( | |||||
| 5 | 5 | ||||
| 6 | "github.com/bnema/dumber/internal/application/port" | 6 | "github.com/bnema/dumber/internal/application/port" | ||
| 7 | "github.com/bnema/dumber/internal/logging" | 7 | "github.com/bnema/dumber/internal/logging" | ||
| 8 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 8 | + | "github.com/bnema/puregotk/v4/gtk" |
| 9 | ) | 9 | ) | ||
| 10 | 10 | ||||
| 11 | // GTKEntryTarget implements TextInputTarget for GTK SearchEntry widgets. | 11 | // GTKEntryTarget implements TextInputTarget for GTK SearchEntry widgets. | ||
M internal/infrastructure/webkit/bgcolor.go +1 -1
| @@ -3,7 +3,7 @@ package webkit | |||
| 3 | 3 | import ( | |
| 4 | 4 | "sync" | |
| 5 | 5 | ||
| 6 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 6 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 7 | 7 | ) | |
| 8 | 8 | ||
| 9 | 9 | // bgColor holds RGBA components for WebView background color (eliminates white flash). | |
| @@ -3,7 +3,7 @@ package webkit | |||||
| 3 | import ( | 3 | import ( | ||
| 4 | "sync" | 4 | "sync" | ||
| 5 | 5 | ||||
| 6 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 6 | + | "github.com/bnema/puregotk/v4/gdk" |
| 7 | ) | 7 | ) | ||
| 8 | 8 | ||||
| 9 | // bgColor holds RGBA components for WebView background color (eliminates white flash). | 9 | // bgColor holds RGBA components for WebView background color (eliminates white flash). | ||
M internal/infrastructure/webkit/engine_adapters.go +1 -1
| @@ -7,7 +7,7 @@ import ( | |||
| 7 | 7 | "github.com/bnema/dumber/internal/application/port" | |
| 8 | 8 | "github.com/bnema/dumber/internal/infrastructure/filtering" | |
| 9 | 9 | "github.com/bnema/dumber/internal/logging" | |
| 10 | - | "github.com/jwijenbergh/puregotk/v4/gio" | |
| 10 | + | "github.com/bnema/puregotk/v4/gio" | |
| 11 | 11 | ) | |
| 12 | 12 | ||
| 13 | 13 | // --- WebViewFactory adapter --- | |
| @@ -7,7 +7,7 @@ import ( | |||||
| 7 | "github.com/bnema/dumber/internal/application/port" | 7 | "github.com/bnema/dumber/internal/application/port" | ||
| 8 | "github.com/bnema/dumber/internal/infrastructure/filtering" | 8 | "github.com/bnema/dumber/internal/infrastructure/filtering" | ||
| 9 | "github.com/bnema/dumber/internal/logging" | 9 | "github.com/bnema/dumber/internal/logging" | ||
| 10 | - | "github.com/jwijenbergh/puregotk/v4/gio" | 10 | + | "github.com/bnema/puregotk/v4/gio" |
| 11 | ) | 11 | ) | ||
| 12 | 12 | ||||
| 13 | // --- WebViewFactory adapter --- | 13 | // --- WebViewFactory adapter --- | ||
M internal/infrastructure/webkit/engine_init.go +1 -1
| @@ -12,7 +12,7 @@ import ( | |||
| 12 | 12 | "github.com/bnema/dumber/internal/infrastructure/filtering" | |
| 13 | 13 | "github.com/bnema/dumber/internal/logging" | |
| 14 | 14 | "github.com/bnema/dumber/internal/ui/theme" | |
| 15 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 15 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 16 | 16 | "github.com/rs/zerolog" | |
| 17 | 17 | ) | |
| 18 | 18 | ||
| @@ -12,7 +12,7 @@ import ( | |||||
| 12 | "github.com/bnema/dumber/internal/infrastructure/filtering" | 12 | "github.com/bnema/dumber/internal/infrastructure/filtering" | ||
| 13 | "github.com/bnema/dumber/internal/logging" | 13 | "github.com/bnema/dumber/internal/logging" | ||
| 14 | "github.com/bnema/dumber/internal/ui/theme" | 14 | "github.com/bnema/dumber/internal/ui/theme" | ||
| 15 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 15 | + | "github.com/bnema/puregotk/v4/gdk" |
| 16 | "github.com/rs/zerolog" | 16 | "github.com/rs/zerolog" | ||
| 17 | ) | 17 | ) | ||
| 18 | 18 | ||||
M internal/infrastructure/webkit/gobject_type_helpers.go +3 -3
| @@ -5,9 +5,9 @@ import ( | |||
| 5 | 5 | "sync" | |
| 6 | 6 | ||
| 7 | 7 | "github.com/bnema/dumber/internal/logging" | |
| 8 | - | "github.com/jwijenbergh/purego" | |
| 9 | - | "github.com/jwijenbergh/puregotk/pkg/core" | |
| 10 | - | gtypes "github.com/jwijenbergh/puregotk/v4/gobject/types" | |
| 8 | + | "github.com/bnema/puregotk/pkg/core" | |
| 9 | + | gtypes "github.com/bnema/puregotk/v4/gobject/types" | |
| 10 | + | "github.com/ebitengine/purego" | |
| 11 | 11 | ) | |
| 12 | 12 | ||
| 13 | 13 | var ( | |
| @@ -5,9 +5,9 @@ import ( | |||||
| 5 | "sync" | 5 | "sync" | ||
| 6 | 6 | ||||
| 7 | "github.com/bnema/dumber/internal/logging" | 7 | "github.com/bnema/dumber/internal/logging" | ||
| 8 | - | "github.com/jwijenbergh/purego" | 8 | + | "github.com/bnema/puregotk/pkg/core" |
| 9 | - | "github.com/jwijenbergh/puregotk/pkg/core" | 9 | + | gtypes "github.com/bnema/puregotk/v4/gobject/types" |
| 10 | - | gtypes "github.com/jwijenbergh/puregotk/v4/gobject/types" | 10 | + | "github.com/ebitengine/purego" |
| 11 | ) | 11 | ) | ||
| 12 | 12 | ||||
| 13 | var ( | 13 | var ( | ||
M internal/infrastructure/webkit/pool.go +1 -1
| @@ -11,7 +11,7 @@ import ( | |||
| 11 | 11 | ||
| 12 | 12 | "github.com/bnema/dumber/internal/logging" | |
| 13 | 13 | "github.com/bnema/puregotk-webkit/webkit" | |
| 14 | - | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 14 | + | "github.com/bnema/puregotk/v4/glib" | |
| 15 | 15 | ) | |
| 16 | 16 | ||
| 17 | 17 | // ErrPoolClosed is returned when operations are attempted on a closed pool. | |
| @@ -11,7 +11,7 @@ import ( | |||||
| 11 | 11 | ||||
| 12 | "github.com/bnema/dumber/internal/logging" | 12 | "github.com/bnema/dumber/internal/logging" | ||
| 13 | "github.com/bnema/puregotk-webkit/webkit" | 13 | "github.com/bnema/puregotk-webkit/webkit" | ||
| 14 | - | "github.com/jwijenbergh/puregotk/v4/glib" | 14 | + | "github.com/bnema/puregotk/v4/glib" |
| 15 | ) | 15 | ) | ||
| 16 | 16 | ||||
| 17 | // ErrPoolClosed is returned when operations are attempted on a closed pool. | 17 | // ErrPoolClosed is returned when operations are attempted on a closed pool. | ||
M internal/infrastructure/webkit/scheme_handler.go +1 -1
| @@ -20,7 +20,7 @@ import ( | |||
| 20 | 20 | "github.com/bnema/dumber/internal/logging" | |
| 21 | 21 | "github.com/bnema/puregotk-webkit/soup" | |
| 22 | 22 | "github.com/bnema/puregotk-webkit/webkit" | |
| 23 | - | "github.com/jwijenbergh/puregotk/v4/gio" | |
| 23 | + | "github.com/bnema/puregotk/v4/gio" | |
| 24 | 24 | "github.com/rs/zerolog" | |
| 25 | 25 | ) | |
| 26 | 26 | ||
| @@ -20,7 +20,7 @@ import ( | |||||
| 20 | "github.com/bnema/dumber/internal/logging" | 20 | "github.com/bnema/dumber/internal/logging" | ||
| 21 | "github.com/bnema/puregotk-webkit/soup" | 21 | "github.com/bnema/puregotk-webkit/soup" | ||
| 22 | "github.com/bnema/puregotk-webkit/webkit" | 22 | "github.com/bnema/puregotk-webkit/webkit" | ||
| 23 | - | "github.com/jwijenbergh/puregotk/v4/gio" | 23 | + | "github.com/bnema/puregotk/v4/gio" |
| 24 | "github.com/rs/zerolog" | 24 | "github.com/rs/zerolog" | ||
| 25 | ) | 25 | ) | ||
| 26 | 26 | ||||
M internal/infrastructure/webkit/webview.go +27 -34
| @@ -11,16 +11,17 @@ import ( | |||
| 11 | 11 | "time" | |
| 12 | 12 | ||
| 13 | 13 | "github.com/bnema/dumber/internal/application/port" | |
| 14 | + | "github.com/bnema/dumber/internal/domain/entity" | |
| 14 | 15 | urlutil "github.com/bnema/dumber/internal/domain/url" | |
| 15 | 16 | "github.com/bnema/dumber/internal/infrastructure/desktop" | |
| 16 | 17 | "github.com/bnema/dumber/internal/logging" | |
| 17 | 18 | "github.com/bnema/puregotk-webkit/webkit" | |
| 18 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 19 | - | "github.com/jwijenbergh/puregotk/v4/gio" | |
| 20 | - | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 21 | - | "github.com/jwijenbergh/puregotk/v4/gobject" | |
| 22 | - | gtypes "github.com/jwijenbergh/puregotk/v4/gobject/types" | |
| 23 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 19 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 20 | + | "github.com/bnema/puregotk/v4/gio" | |
| 21 | + | "github.com/bnema/puregotk/v4/glib" | |
| 22 | + | "github.com/bnema/puregotk/v4/gobject" | |
| 23 | + | gtypes "github.com/bnema/puregotk/v4/gobject/types" | |
| 24 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 24 | 25 | "github.com/rs/zerolog" | |
| 25 | 26 | ) | |
| 26 | 27 | ||
| @@ -162,7 +163,9 @@ type WebView struct { | |||
| 162 | 163 | // PermissionRequest is called when a site requests permission (mic, camera, screen sharing). | |
| 163 | 164 | // Return true to indicate the request was handled. Call allow()/deny() to respond. | |
| 164 | 165 | // The permission types are determined from the request object. | |
| 165 | - | OnPermissionRequest func(origin string, permTypes []string, allow, deny func()) bool | |
| 166 | + | // The metadata map carries permission-type-specific context; for website_data_access both | |
| 167 | + | // entity.PermissionMetadataKeyRequestingDomain and entity.PermissionMetadataKeyCurrentDomain are populated. | |
| 168 | + | OnPermissionRequest func(origin string, permTypes []string, metadata map[string]string, allow, deny func()) bool | |
| 166 | 169 | ||
| 167 | 170 | logger zerolog.Logger | |
| 168 | 171 | mu sync.RWMutex | |
| @@ -978,15 +981,17 @@ func (wv *WebView) connectWebProcessTerminatedSignal() { | |||
| 978 | 981 | // connectPermissionRequestSignal sets up the permission-request signal handler. | |
| 979 | 982 | // This is emitted when a site calls getUserMedia() or getDisplayMedia(). | |
| 980 | 983 | func (wv *WebView) connectPermissionRequestSignal() { | |
| 981 | - | permissionCb := func(_ webkit.WebView, requestPtr uintptr) bool { | |
| 984 | + | permissionCb := func(inner webkit.WebView, requestPtr uintptr) bool { | |
| 982 | 985 | ctx := logging.WithContext(context.Background(), wv.logger) | |
| 983 | 986 | ||
| 984 | 987 | if wv.OnPermissionRequest == nil { | |
| 985 | 988 | return false // Not handled, WebKit will deny by default | |
| 986 | 989 | } | |
| 987 | 990 | ||
| 988 | - | // Extract and normalize origin from current URI | |
| 989 | - | uri := wv.URI() | |
| 991 | + | // Use the live URI from the signal's WebView rather than the cached wv.URI(), | |
| 992 | + | // so permission lookups use the current page origin even if navigation has | |
| 993 | + | // occurred since the last load-changed signal. | |
| 994 | + | uri := inner.GetUri() | |
| 990 | 995 | if uri == "" { | |
| 991 | 996 | wv.logger.Debug().Msg("permission request with empty origin, denying") | |
| 992 | 997 | return false | |
| @@ -998,14 +1003,11 @@ func (wv *WebView) connectPermissionRequestSignal() { | |||
| 998 | 1003 | } | |
| 999 | 1004 | ||
| 1000 | 1005 | // Determine permission types from the request | |
| 1001 | - | permTypes, originOverride := wv.determinePermissionTypes(ctx, requestPtr) | |
| 1006 | + | permTypes, metadata := wv.determinePermissionTypes(ctx, requestPtr) | |
| 1002 | 1007 | if len(permTypes) == 0 { | |
| 1003 | 1008 | wv.logger.Warn().Msg("permission request with unknown type, denying") | |
| 1004 | 1009 | return false | |
| 1005 | 1010 | } | |
| 1006 | - | if originOverride != "" { | |
| 1007 | - | origin = originOverride | |
| 1008 | - | } | |
| 1009 | 1011 | ||
| 1010 | 1012 | // Ref the request object to prevent use-after-free | |
| 1011 | 1013 | // The request may outlive the signal handler if we show a dialog | |
| @@ -1039,7 +1041,7 @@ func (wv *WebView) connectPermissionRequestSignal() { | |||
| 1039 | 1041 | } | |
| 1040 | 1042 | ||
| 1041 | 1043 | // Call the handler | |
| 1042 | - | return wv.OnPermissionRequest(origin, permTypes, allow, deny) | |
| 1044 | + | return wv.OnPermissionRequest(origin, permTypes, metadata, allow, deny) | |
| 1043 | 1045 | } | |
| 1044 | 1046 | ||
| 1045 | 1047 | sigID := wv.inner.ConnectPermissionRequest(&permissionCb) | |
| @@ -1051,13 +1053,13 @@ func (wv *WebView) connectPermissionRequestSignal() { | |||
| 1051 | 1053 | // We use GObject property accessors for audio/video request flags. Display detection | |
| 1052 | 1054 | // uses the dedicated WebKit API because this WebKit build does not expose an | |
| 1053 | 1055 | // "is-for-display-device" GObject property. | |
| 1054 | - | func (wv *WebView) determinePermissionTypes(ctx context.Context, requestPtr uintptr) (types []string, originOverride string) { | |
| 1056 | + | func (wv *WebView) determinePermissionTypes(ctx context.Context, requestPtr uintptr) (types []string, metadata map[string]string) { | |
| 1055 | 1057 | requestKind := detectPermissionRequestKind(ctx, requestPtr) | |
| 1056 | 1058 | switch requestKind { | |
| 1057 | 1059 | case permissionRequestKindUserMedia: | |
| 1058 | 1060 | userMediaReq := webkit.UserMediaPermissionRequestNewFromInternalPtr(requestPtr) | |
| 1059 | 1061 | if userMediaReq == nil { | |
| 1060 | - | return nil, "" | |
| 1062 | + | return nil, nil | |
| 1061 | 1063 | } | |
| 1062 | 1064 | ||
| 1063 | 1065 | // Use GObject property accessors — more reliable than the C function wrappers | |
| @@ -1072,13 +1074,13 @@ func (wv *WebView) determinePermissionTypes(ctx context.Context, requestPtr uint | |||
| 1072 | 1074 | Bool("is_display", isDisplay). | |
| 1073 | 1075 | Msg("permission request type detection") | |
| 1074 | 1076 | ||
| 1075 | - | return classifyPermissionRequestTypes(ctx, requestKind, isAudio, isVideo, isDisplay), "" | |
| 1077 | + | return classifyPermissionRequestTypes(ctx, requestKind, isAudio, isVideo, isDisplay), nil | |
| 1076 | 1078 | case permissionRequestKindDeviceInfo: | |
| 1077 | - | return classifyPermissionRequestTypes(ctx, requestKind, false, false, false), "" | |
| 1079 | + | return classifyPermissionRequestTypes(ctx, requestKind, false, false, false), nil | |
| 1078 | 1080 | case permissionRequestKindWebsiteDataAccess: | |
| 1079 | 1081 | wdaReq := webkit.WebsiteDataAccessPermissionRequestNewFromInternalPtr(requestPtr) | |
| 1080 | 1082 | if wdaReq == nil { | |
| 1081 | - | return nil, "" | |
| 1083 | + | return nil, nil | |
| 1082 | 1084 | } | |
| 1083 | 1085 | currentDomain := wdaReq.GetCurrentDomain() | |
| 1084 | 1086 | requestingDomain := wdaReq.GetRequestingDomain() | |
| @@ -1086,20 +1088,11 @@ func (wv *WebView) determinePermissionTypes(ctx context.Context, requestPtr uint | |||
| 1086 | 1088 | Str("current_domain", currentDomain). | |
| 1087 | 1089 | Str("requesting_domain", requestingDomain). | |
| 1088 | 1090 | Msg("website data access permission request") | |
| 1089 | - | override := "" | |
| 1090 | - | if requestingDomain != "" { | |
| 1091 | - | candidate := "https://" + requestingDomain | |
| 1092 | - | if normalized, err := urlutil.ExtractOrigin(candidate); err == nil { | |
| 1093 | - | override = normalized | |
| 1094 | - | } else { | |
| 1095 | - | wv.logger.Warn(). | |
| 1096 | - | Str("requesting_domain", requestingDomain). | |
| 1097 | - | Err(err). | |
| 1098 | - | Msg("website data access: failed to normalize requesting domain, using raw") | |
| 1099 | - | override = candidate | |
| 1100 | - | } | |
| 1091 | + | meta := map[string]string{ | |
| 1092 | + | entity.PermissionMetadataKeyRequestingDomain: requestingDomain, | |
| 1093 | + | entity.PermissionMetadataKeyCurrentDomain: currentDomain, | |
| 1101 | 1094 | } | |
| 1102 | - | return classifyPermissionRequestTypes(ctx, requestKind, false, false, false), override | |
| 1095 | + | return classifyPermissionRequestTypes(ctx, requestKind, false, false, false), meta | |
| 1103 | 1096 | default: | |
| 1104 | 1097 | if requestPtr != 0 { | |
| 1105 | 1098 | typeName := permissionRequestTypeName(ctx, requestPtr) | |
| @@ -1111,7 +1104,7 @@ func (wv *WebView) determinePermissionTypes(ctx context.Context, requestPtr uint | |||
| 1111 | 1104 | } | |
| 1112 | 1105 | // Unknown permission type - could be clipboard, notifications, geolocation, etc. | |
| 1113 | 1106 | // For now, return empty to trigger denial. Future phases will add these types. | |
| 1114 | - | return nil, "" | |
| 1107 | + | return nil, nil | |
| 1115 | 1108 | } | |
| 1116 | 1109 | } | |
| 1117 | 1110 | ||
| @@ -11,16 +11,17 @@ import ( | |||||
| 11 | "time" | 11 | "time" | ||
| 12 | 12 | ||||
| 13 | "github.com/bnema/dumber/internal/application/port" | 13 | "github.com/bnema/dumber/internal/application/port" | ||
| 14 | + | "github.com/bnema/dumber/internal/domain/entity" | |||
| 14 | urlutil "github.com/bnema/dumber/internal/domain/url" | 15 | urlutil "github.com/bnema/dumber/internal/domain/url" | ||
| 15 | "github.com/bnema/dumber/internal/infrastructure/desktop" | 16 | "github.com/bnema/dumber/internal/infrastructure/desktop" | ||
| 16 | "github.com/bnema/dumber/internal/logging" | 17 | "github.com/bnema/dumber/internal/logging" | ||
| 17 | "github.com/bnema/puregotk-webkit/webkit" | 18 | "github.com/bnema/puregotk-webkit/webkit" | ||
| 18 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 19 | + | "github.com/bnema/puregotk/v4/gdk" |
| 19 | - | "github.com/jwijenbergh/puregotk/v4/gio" | 20 | + | "github.com/bnema/puregotk/v4/gio" |
| 20 | - | "github.com/jwijenbergh/puregotk/v4/glib" | 21 | + | "github.com/bnema/puregotk/v4/glib" |
| 21 | - | "github.com/jwijenbergh/puregotk/v4/gobject" | 22 | + | "github.com/bnema/puregotk/v4/gobject" |
| 22 | - | gtypes "github.com/jwijenbergh/puregotk/v4/gobject/types" | 23 | + | gtypes "github.com/bnema/puregotk/v4/gobject/types" |
| 23 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 24 | + | "github.com/bnema/puregotk/v4/gtk" |
| 24 | "github.com/rs/zerolog" | 25 | "github.com/rs/zerolog" | ||
| 25 | ) | 26 | ) | ||
| 26 | 27 | ||||
| @@ -162,7 +163,9 @@ type WebView struct { | |||||
| 162 | // PermissionRequest is called when a site requests permission (mic, camera, screen sharing). | 163 | // PermissionRequest is called when a site requests permission (mic, camera, screen sharing). | ||
| 163 | // Return true to indicate the request was handled. Call allow()/deny() to respond. | 164 | // Return true to indicate the request was handled. Call allow()/deny() to respond. | ||
| 164 | // The permission types are determined from the request object. | 165 | // The permission types are determined from the request object. | ||
| 165 | - | OnPermissionRequest func(origin string, permTypes []string, allow, deny func()) bool | 166 | + | // The metadata map carries permission-type-specific context; for website_data_access both |
| 167 | + | // entity.PermissionMetadataKeyRequestingDomain and entity.PermissionMetadataKeyCurrentDomain are populated. | |||
| 168 | + | OnPermissionRequest func(origin string, permTypes []string, metadata map[string]string, allow, deny func()) bool | |||
| 166 | 169 | ||||
| 167 | logger zerolog.Logger | 170 | logger zerolog.Logger | ||
| 168 | mu sync.RWMutex | 171 | mu sync.RWMutex | ||
| @@ -978,15 +981,17 @@ func (wv *WebView) connectWebProcessTerminatedSignal() { | |||||
| 978 | // connectPermissionRequestSignal sets up the permission-request signal handler. | 981 | // connectPermissionRequestSignal sets up the permission-request signal handler. | ||
| 979 | // This is emitted when a site calls getUserMedia() or getDisplayMedia(). | 982 | // This is emitted when a site calls getUserMedia() or getDisplayMedia(). | ||
| 980 | func (wv *WebView) connectPermissionRequestSignal() { | 983 | func (wv *WebView) connectPermissionRequestSignal() { | ||
| 981 | - | permissionCb := func(_ webkit.WebView, requestPtr uintptr) bool { | 984 | + | permissionCb := func(inner webkit.WebView, requestPtr uintptr) bool { |
| 982 | ctx := logging.WithContext(context.Background(), wv.logger) | 985 | ctx := logging.WithContext(context.Background(), wv.logger) | ||
| 983 | 986 | ||||
| 984 | if wv.OnPermissionRequest == nil { | 987 | if wv.OnPermissionRequest == nil { | ||
| 985 | return false // Not handled, WebKit will deny by default | 988 | return false // Not handled, WebKit will deny by default | ||
| 986 | } | 989 | } | ||
| 987 | 990 | ||||
| 988 | - | // Extract and normalize origin from current URI | 991 | + | // Use the live URI from the signal's WebView rather than the cached wv.URI(), |
| 989 | - | uri := wv.URI() | 992 | + | // so permission lookups use the current page origin even if navigation has |
| 993 | + | // occurred since the last load-changed signal. | |||
| 994 | + | uri := inner.GetUri() | |||
| 990 | if uri == "" { | 995 | if uri == "" { | ||
| 991 | wv.logger.Debug().Msg("permission request with empty origin, denying") | 996 | wv.logger.Debug().Msg("permission request with empty origin, denying") | ||
| 992 | return false | 997 | return false | ||
| @@ -998,14 +1003,11 @@ func (wv *WebView) connectPermissionRequestSignal() { | |||||
| 998 | } | 1003 | } | ||
| 999 | 1004 | ||||
| 1000 | // Determine permission types from the request | 1005 | // Determine permission types from the request | ||
| 1001 | - | permTypes, originOverride := wv.determinePermissionTypes(ctx, requestPtr) | 1006 | + | permTypes, metadata := wv.determinePermissionTypes(ctx, requestPtr) |
| 1002 | if len(permTypes) == 0 { | 1007 | if len(permTypes) == 0 { | ||
| 1003 | wv.logger.Warn().Msg("permission request with unknown type, denying") | 1008 | wv.logger.Warn().Msg("permission request with unknown type, denying") | ||
| 1004 | return false | 1009 | return false | ||
| 1005 | } | 1010 | } | ||
| 1006 | - | if originOverride != "" { | |||
| 1007 | - | origin = originOverride | |||
| 1008 | - | } | |||
| 1009 | 1011 | ||||
| 1010 | // Ref the request object to prevent use-after-free | 1012 | // Ref the request object to prevent use-after-free | ||
| 1011 | // The request may outlive the signal handler if we show a dialog | 1013 | // The request may outlive the signal handler if we show a dialog | ||
| @@ -1039,7 +1041,7 @@ func (wv *WebView) connectPermissionRequestSignal() { | |||||
| 1039 | } | 1041 | } | ||
| 1040 | 1042 | ||||
| 1041 | // Call the handler | 1043 | // Call the handler | ||
| 1042 | - | return wv.OnPermissionRequest(origin, permTypes, allow, deny) | 1044 | + | return wv.OnPermissionRequest(origin, permTypes, metadata, allow, deny) |
| 1043 | } | 1045 | } | ||
| 1044 | 1046 | ||||
| 1045 | sigID := wv.inner.ConnectPermissionRequest(&permissionCb) | 1047 | sigID := wv.inner.ConnectPermissionRequest(&permissionCb) | ||
| @@ -1051,13 +1053,13 @@ func (wv *WebView) connectPermissionRequestSignal() { | |||||
| 1051 | // We use GObject property accessors for audio/video request flags. Display detection | 1053 | // We use GObject property accessors for audio/video request flags. Display detection | ||
| 1052 | // uses the dedicated WebKit API because this WebKit build does not expose an | 1054 | // uses the dedicated WebKit API because this WebKit build does not expose an | ||
| 1053 | // "is-for-display-device" GObject property. | 1055 | // "is-for-display-device" GObject property. | ||
| 1054 | - | func (wv *WebView) determinePermissionTypes(ctx context.Context, requestPtr uintptr) (types []string, originOverride string) { | 1056 | + | func (wv *WebView) determinePermissionTypes(ctx context.Context, requestPtr uintptr) (types []string, metadata map[string]string) { |
| 1055 | requestKind := detectPermissionRequestKind(ctx, requestPtr) | 1057 | requestKind := detectPermissionRequestKind(ctx, requestPtr) | ||
| 1056 | switch requestKind { | 1058 | switch requestKind { | ||
| 1057 | case permissionRequestKindUserMedia: | 1059 | case permissionRequestKindUserMedia: | ||
| 1058 | userMediaReq := webkit.UserMediaPermissionRequestNewFromInternalPtr(requestPtr) | 1060 | userMediaReq := webkit.UserMediaPermissionRequestNewFromInternalPtr(requestPtr) | ||
| 1059 | if userMediaReq == nil { | 1061 | if userMediaReq == nil { | ||
| 1060 | - | return nil, "" | 1062 | + | return nil, nil |
| 1061 | } | 1063 | } | ||
| 1062 | 1064 | ||||
| 1063 | // Use GObject property accessors — more reliable than the C function wrappers | 1065 | // Use GObject property accessors — more reliable than the C function wrappers | ||
| @@ -1072,13 +1074,13 @@ func (wv *WebView) determinePermissionTypes(ctx context.Context, requestPtr uint | |||||
| 1072 | Bool("is_display", isDisplay). | 1074 | Bool("is_display", isDisplay). | ||
| 1073 | Msg("permission request type detection") | 1075 | Msg("permission request type detection") | ||
| 1074 | 1076 | ||||
| 1075 | - | return classifyPermissionRequestTypes(ctx, requestKind, isAudio, isVideo, isDisplay), "" | 1077 | + | return classifyPermissionRequestTypes(ctx, requestKind, isAudio, isVideo, isDisplay), nil |
| 1076 | case permissionRequestKindDeviceInfo: | 1078 | case permissionRequestKindDeviceInfo: | ||
| 1077 | - | return classifyPermissionRequestTypes(ctx, requestKind, false, false, false), "" | 1079 | + | return classifyPermissionRequestTypes(ctx, requestKind, false, false, false), nil |
| 1078 | case permissionRequestKindWebsiteDataAccess: | 1080 | case permissionRequestKindWebsiteDataAccess: | ||
| 1079 | wdaReq := webkit.WebsiteDataAccessPermissionRequestNewFromInternalPtr(requestPtr) | 1081 | wdaReq := webkit.WebsiteDataAccessPermissionRequestNewFromInternalPtr(requestPtr) | ||
| 1080 | if wdaReq == nil { | 1082 | if wdaReq == nil { | ||
| 1081 | - | return nil, "" | 1083 | + | return nil, nil |
| 1082 | } | 1084 | } | ||
| 1083 | currentDomain := wdaReq.GetCurrentDomain() | 1085 | currentDomain := wdaReq.GetCurrentDomain() | ||
| 1084 | requestingDomain := wdaReq.GetRequestingDomain() | 1086 | requestingDomain := wdaReq.GetRequestingDomain() | ||
| @@ -1086,20 +1088,11 @@ func (wv *WebView) determinePermissionTypes(ctx context.Context, requestPtr uint | |||||
| 1086 | Str("current_domain", currentDomain). | 1088 | Str("current_domain", currentDomain). | ||
| 1087 | Str("requesting_domain", requestingDomain). | 1089 | Str("requesting_domain", requestingDomain). | ||
| 1088 | Msg("website data access permission request") | 1090 | Msg("website data access permission request") | ||
| 1089 | - | override := "" | 1091 | + | meta := map[string]string{ |
| 1090 | - | if requestingDomain != "" { | 1092 | + | entity.PermissionMetadataKeyRequestingDomain: requestingDomain, |
| 1091 | - | candidate := "https://" + requestingDomain | 1093 | + | entity.PermissionMetadataKeyCurrentDomain: currentDomain, |
| 1092 | - | if normalized, err := urlutil.ExtractOrigin(candidate); err == nil { | |||
| 1093 | - | override = normalized | |||
| 1094 | - | } else { | |||
| 1095 | - | wv.logger.Warn(). | |||
| 1096 | - | Str("requesting_domain", requestingDomain). | |||
| 1097 | - | Err(err). | |||
| 1098 | - | Msg("website data access: failed to normalize requesting domain, using raw") | |||
| 1099 | - | override = candidate | |||
| 1100 | - | } | |||
| 1101 | } | 1094 | } | ||
| 1102 | - | return classifyPermissionRequestTypes(ctx, requestKind, false, false, false), override | 1095 | + | return classifyPermissionRequestTypes(ctx, requestKind, false, false, false), meta |
| 1103 | default: | 1096 | default: | ||
| 1104 | if requestPtr != 0 { | 1097 | if requestPtr != 0 { | ||
| 1105 | typeName := permissionRequestTypeName(ctx, requestPtr) | 1098 | typeName := permissionRequestTypeName(ctx, requestPtr) | ||
| @@ -1111,7 +1104,7 @@ func (wv *WebView) determinePermissionTypes(ctx context.Context, requestPtr uint | |||||
| 1111 | } | 1104 | } | ||
| 1112 | // Unknown permission type - could be clipboard, notifications, geolocation, etc. | 1105 | // Unknown permission type - could be clipboard, notifications, geolocation, etc. | ||
| 1113 | // For now, return empty to trigger denial. Future phases will add these types. | 1106 | // For now, return empty to trigger denial. Future phases will add these types. | ||
| 1114 | - | return nil, "" | 1107 | + | return nil, nil |
| 1115 | } | 1108 | } | ||
| 1116 | } | 1109 | } | ||
| 1117 | 1110 | ||||
M internal/logging/glib.go +1 -1
| @@ -4,7 +4,7 @@ import ( | |||
| 4 | 4 | "context" | |
| 5 | 5 | "sync" | |
| 6 | 6 | ||
| 7 | - | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 7 | + | "github.com/bnema/puregotk/v4/glib" | |
| 8 | 8 | "github.com/rs/zerolog" | |
| 9 | 9 | ) | |
| 10 | 10 | ||
| @@ -4,7 +4,7 @@ import ( | |||||
| 4 | "context" | 4 | "context" | ||
| 5 | "sync" | 5 | "sync" | ||
| 6 | 6 | ||||
| 7 | - | "github.com/jwijenbergh/puregotk/v4/glib" | 7 | + | "github.com/bnema/puregotk/v4/glib" |
| 8 | "github.com/rs/zerolog" | 8 | "github.com/rs/zerolog" | ||
| 9 | ) | 9 | ) | ||
| 10 | 10 | ||||
M internal/ui/adapter/favicon.go +2 -2
| @@ -8,8 +8,8 @@ import ( | |||
| 8 | 8 | "github.com/bnema/dumber/internal/application/port" | |
| 9 | 9 | domainurl "github.com/bnema/dumber/internal/domain/url" | |
| 10 | 10 | "github.com/bnema/dumber/internal/logging" | |
| 11 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 12 | - | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 11 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 12 | + | "github.com/bnema/puregotk/v4/glib" | |
| 13 | 13 | "github.com/rs/zerolog" | |
| 14 | 14 | ) | |
| 15 | 15 | ||
| @@ -8,8 +8,8 @@ import ( | |||||
| 8 | "github.com/bnema/dumber/internal/application/port" | 8 | "github.com/bnema/dumber/internal/application/port" | ||
| 9 | domainurl "github.com/bnema/dumber/internal/domain/url" | 9 | domainurl "github.com/bnema/dumber/internal/domain/url" | ||
| 10 | "github.com/bnema/dumber/internal/logging" | 10 | "github.com/bnema/dumber/internal/logging" | ||
| 11 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 11 | + | "github.com/bnema/puregotk/v4/gdk" |
| 12 | - | "github.com/jwijenbergh/puregotk/v4/glib" | 12 | + | "github.com/bnema/puregotk/v4/glib" |
| 13 | "github.com/rs/zerolog" | 13 | "github.com/rs/zerolog" | ||
| 14 | ) | 14 | ) | ||
| 15 | 15 | ||||
M internal/ui/app.go +5 -5
| @@ -27,11 +27,11 @@ import ( | |||
| 27 | 27 | "github.com/bnema/dumber/internal/ui/layout" | |
| 28 | 28 | "github.com/bnema/dumber/internal/ui/theme" | |
| 29 | 29 | "github.com/bnema/dumber/internal/ui/window" | |
| 30 | - | "github.com/jwijenbergh/puregotk/v4/adw" | |
| 31 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 32 | - | "github.com/jwijenbergh/puregotk/v4/gio" | |
| 33 | - | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 34 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 30 | + | "github.com/bnema/puregotk/v4/adw" | |
| 31 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 32 | + | "github.com/bnema/puregotk/v4/gio" | |
| 33 | + | "github.com/bnema/puregotk/v4/glib" | |
| 34 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 35 | 35 | ) | |
| 36 | 36 | ||
| 37 | 37 | const ( | |
| @@ -27,11 +27,11 @@ import ( | |||||
| 27 | "github.com/bnema/dumber/internal/ui/layout" | 27 | "github.com/bnema/dumber/internal/ui/layout" | ||
| 28 | "github.com/bnema/dumber/internal/ui/theme" | 28 | "github.com/bnema/dumber/internal/ui/theme" | ||
| 29 | "github.com/bnema/dumber/internal/ui/window" | 29 | "github.com/bnema/dumber/internal/ui/window" | ||
| 30 | - | "github.com/jwijenbergh/puregotk/v4/adw" | 30 | + | "github.com/bnema/puregotk/v4/adw" |
| 31 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 31 | + | "github.com/bnema/puregotk/v4/gdk" |
| 32 | - | "github.com/jwijenbergh/puregotk/v4/gio" | 32 | + | "github.com/bnema/puregotk/v4/gio" |
| 33 | - | "github.com/jwijenbergh/puregotk/v4/glib" | 33 | + | "github.com/bnema/puregotk/v4/glib" |
| 34 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 34 | + | "github.com/bnema/puregotk/v4/gtk" |
| 35 | ) | 35 | ) | ||
| 36 | 36 | ||||
| 37 | const ( | 37 | const ( | ||
M internal/ui/app_flags_test.go +1 -1
| @@ -3,7 +3,7 @@ package ui | |||
| 3 | 3 | import ( | |
| 4 | 4 | "testing" | |
| 5 | 5 | ||
| 6 | - | "github.com/jwijenbergh/puregotk/v4/gio" | |
| 6 | + | "github.com/bnema/puregotk/v4/gio" | |
| 7 | 7 | "github.com/stretchr/testify/assert" | |
| 8 | 8 | ) | |
| 9 | 9 | ||
| @@ -3,7 +3,7 @@ package ui | |||||
| 3 | import ( | 3 | import ( | ||
| 4 | "testing" | 4 | "testing" | ||
| 5 | 5 | ||||
| 6 | - | "github.com/jwijenbergh/puregotk/v4/gio" | 6 | + | "github.com/bnema/puregotk/v4/gio" |
| 7 | "github.com/stretchr/testify/assert" | 7 | "github.com/stretchr/testify/assert" | ||
| 8 | ) | 8 | ) | ||
| 9 | 9 | ||||
M internal/ui/component/accent_picker.go +2 -2
| @@ -5,8 +5,8 @@ import ( | |||
| 5 | 5 | ||
| 6 | 6 | "github.com/bnema/dumber/internal/application/port" | |
| 7 | 7 | "github.com/bnema/dumber/internal/ui/layout" | |
| 8 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 9 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 8 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 9 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 10 | 10 | ) | |
| 11 | 11 | ||
| 12 | 12 | // Accent picker layout constants. | |
| @@ -5,8 +5,8 @@ import ( | |||||
| 5 | 5 | ||||
| 6 | "github.com/bnema/dumber/internal/application/port" | 6 | "github.com/bnema/dumber/internal/application/port" | ||
| 7 | "github.com/bnema/dumber/internal/ui/layout" | 7 | "github.com/bnema/dumber/internal/ui/layout" | ||
| 8 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 8 | + | "github.com/bnema/puregotk/v4/gdk" |
| 9 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 9 | + | "github.com/bnema/puregotk/v4/gtk" |
| 10 | ) | 10 | ) | ||
| 11 | 11 | ||||
| 12 | // Accent picker layout constants. | 12 | // Accent picker layout constants. | ||
M internal/ui/component/find_bar.go +3 -3
| @@ -11,9 +11,9 @@ import ( | |||
| 11 | 11 | "github.com/bnema/dumber/internal/domain/entity" | |
| 12 | 12 | "github.com/bnema/dumber/internal/logging" | |
| 13 | 13 | "github.com/bnema/dumber/internal/ui/layout" | |
| 14 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 15 | - | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 16 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 14 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 15 | + | "github.com/bnema/puregotk/v4/glib" | |
| 16 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 17 | 17 | ) | |
| 18 | 18 | ||
| 19 | 19 | const ( | |
| @@ -11,9 +11,9 @@ import ( | |||||
| 11 | "github.com/bnema/dumber/internal/domain/entity" | 11 | "github.com/bnema/dumber/internal/domain/entity" | ||
| 12 | "github.com/bnema/dumber/internal/logging" | 12 | "github.com/bnema/dumber/internal/logging" | ||
| 13 | "github.com/bnema/dumber/internal/ui/layout" | 13 | "github.com/bnema/dumber/internal/ui/layout" | ||
| 14 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 14 | + | "github.com/bnema/puregotk/v4/gdk" |
| 15 | - | "github.com/jwijenbergh/puregotk/v4/glib" | 15 | + | "github.com/bnema/puregotk/v4/glib" |
| 16 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 16 | + | "github.com/bnema/puregotk/v4/gtk" |
| 17 | ) | 17 | ) | ||
| 18 | 18 | ||||
| 19 | const ( | 19 | const ( | ||
M internal/ui/component/link_status.go +2 -2
| @@ -5,8 +5,8 @@ import ( | |||
| 5 | 5 | "sync" | |
| 6 | 6 | ||
| 7 | 7 | "github.com/bnema/dumber/internal/ui/mainloop" | |
| 8 | - | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 9 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 8 | + | "github.com/bnema/puregotk/v4/glib" | |
| 9 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 10 | 10 | ||
| 11 | 11 | "github.com/bnema/dumber/internal/ui/layout" | |
| 12 | 12 | ) | |
| @@ -5,8 +5,8 @@ import ( | |||||
| 5 | "sync" | 5 | "sync" | ||
| 6 | 6 | ||||
| 7 | "github.com/bnema/dumber/internal/ui/mainloop" | 7 | "github.com/bnema/dumber/internal/ui/mainloop" | ||
| 8 | - | "github.com/jwijenbergh/puregotk/v4/glib" | 8 | + | "github.com/bnema/puregotk/v4/glib" |
| 9 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 9 | + | "github.com/bnema/puregotk/v4/gtk" |
| 10 | 10 | ||||
| 11 | "github.com/bnema/dumber/internal/ui/layout" | 11 | "github.com/bnema/dumber/internal/ui/layout" | ||
| 12 | ) | 12 | ) | ||
M internal/ui/component/loading_skeleton.go +1 -1
| @@ -4,7 +4,7 @@ import ( | |||
| 4 | 4 | "sync/atomic" | |
| 5 | 5 | ||
| 6 | 6 | "github.com/bnema/dumber/internal/ui/layout" | |
| 7 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 7 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 8 | 8 | ) | |
| 9 | 9 | ||
| 10 | 10 | // LoadingSkeleton displays a themed loading placeholder. | |
| @@ -4,7 +4,7 @@ import ( | |||||
| 4 | "sync/atomic" | 4 | "sync/atomic" | ||
| 5 | 5 | ||||
| 6 | "github.com/bnema/dumber/internal/ui/layout" | 6 | "github.com/bnema/dumber/internal/ui/layout" | ||
| 7 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 7 | + | "github.com/bnema/puregotk/v4/gtk" |
| 8 | ) | 8 | ) | ||
| 9 | 9 | ||||
| 10 | // LoadingSkeleton displays a themed loading placeholder. | 10 | // LoadingSkeleton displays a themed loading placeholder. | ||
M internal/ui/component/logo.go +2 -2
| @@ -5,8 +5,8 @@ import ( | |||
| 5 | 5 | "sync" | |
| 6 | 6 | ||
| 7 | 7 | "github.com/bnema/dumber/assets" | |
| 8 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 9 | - | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 8 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 9 | + | "github.com/bnema/puregotk/v4/glib" | |
| 10 | 10 | ) | |
| 11 | 11 | ||
| 12 | 12 | var ( | |
| @@ -5,8 +5,8 @@ import ( | |||||
| 5 | "sync" | 5 | "sync" | ||
| 6 | 6 | ||||
| 7 | "github.com/bnema/dumber/assets" | 7 | "github.com/bnema/dumber/assets" | ||
| 8 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 8 | + | "github.com/bnema/puregotk/v4/gdk" |
| 9 | - | "github.com/jwijenbergh/puregotk/v4/glib" | 9 | + | "github.com/bnema/puregotk/v4/glib" |
| 10 | ) | 10 | ) | ||
| 11 | 11 | ||||
| 12 | var ( | 12 | var ( | ||
M internal/ui/component/modal_sizing.go +1 -1
| @@ -2,7 +2,7 @@ package component | |||
| 2 | 2 | ||
| 3 | 3 | import ( | |
| 4 | 4 | "github.com/bnema/dumber/internal/ui/layout" | |
| 5 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 5 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 6 | 6 | ) | |
| 7 | 7 | ||
| 8 | 8 | // ModalSizeConfig holds configuration for modal sizing calculations. | |
| @@ -2,7 +2,7 @@ package component | |||||
| 2 | 2 | ||||
| 3 | import ( | 3 | import ( | ||
| 4 | "github.com/bnema/dumber/internal/ui/layout" | 4 | "github.com/bnema/dumber/internal/ui/layout" | ||
| 5 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 5 | + | "github.com/bnema/puregotk/v4/gtk" |
| 6 | ) | 6 | ) | ||
| 7 | 7 | ||||
| 8 | // ModalSizeConfig holds configuration for modal sizing calculations. | 8 | // ModalSizeConfig holds configuration for modal sizing calculations. | ||
M internal/ui/component/omnibox.go +4 -4
| @@ -18,10 +18,10 @@ import ( | |||
| 18 | 18 | "github.com/bnema/dumber/internal/ui/input" | |
| 19 | 19 | "github.com/bnema/dumber/internal/ui/layout" | |
| 20 | 20 | "github.com/bnema/dumber/internal/ui/mainloop" | |
| 21 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 22 | - | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 23 | - | "github.com/jwijenbergh/puregotk/v4/graphene" | |
| 24 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 21 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 22 | + | "github.com/bnema/puregotk/v4/glib" | |
| 23 | + | "github.com/bnema/puregotk/v4/graphene" | |
| 24 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 25 | 25 | ) | |
| 26 | 26 | ||
| 27 | 27 | const ( | |
| @@ -18,10 +18,10 @@ import ( | |||||
| 18 | "github.com/bnema/dumber/internal/ui/input" | 18 | "github.com/bnema/dumber/internal/ui/input" | ||
| 19 | "github.com/bnema/dumber/internal/ui/layout" | 19 | "github.com/bnema/dumber/internal/ui/layout" | ||
| 20 | "github.com/bnema/dumber/internal/ui/mainloop" | 20 | "github.com/bnema/dumber/internal/ui/mainloop" | ||
| 21 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 21 | + | "github.com/bnema/puregotk/v4/gdk" |
| 22 | - | "github.com/jwijenbergh/puregotk/v4/glib" | 22 | + | "github.com/bnema/puregotk/v4/glib" |
| 23 | - | "github.com/jwijenbergh/puregotk/v4/graphene" | 23 | + | "github.com/bnema/puregotk/v4/graphene" |
| 24 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 24 | + | "github.com/bnema/puregotk/v4/gtk" |
| 25 | ) | 25 | ) | ||
| 26 | 26 | ||||
| 27 | const ( | 27 | const ( | ||
M internal/ui/component/omnibox_navigation_state_test.go +1 -1
| @@ -3,7 +3,7 @@ package component | |||
| 3 | 3 | import ( | |
| 4 | 4 | "testing" | |
| 5 | 5 | ||
| 6 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 6 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 7 | 7 | ) | |
| 8 | 8 | ||
| 9 | 9 | func TestShouldPreferTypedURLNavigation(t *testing.T) { | |
| @@ -3,7 +3,7 @@ package component | |||||
| 3 | import ( | 3 | import ( | ||
| 4 | "testing" | 4 | "testing" | ||
| 5 | 5 | ||||
| 6 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 6 | + | "github.com/bnema/puregotk/v4/gdk" |
| 7 | ) | 7 | ) | ||
| 8 | 8 | ||||
| 9 | func TestShouldPreferTypedURLNavigation(t *testing.T) { | 9 | func TestShouldPreferTypedURLNavigation(t *testing.T) { | ||
M internal/ui/component/permission_popup.go +2 -2
| @@ -6,8 +6,8 @@ import ( | |||
| 6 | 6 | ||
| 7 | 7 | "github.com/bnema/dumber/internal/logging" | |
| 8 | 8 | "github.com/bnema/dumber/internal/ui/layout" | |
| 9 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 10 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 9 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 10 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 11 | 11 | ) | |
| 12 | 12 | ||
| 13 | 13 | // buttonSpacing is the spacing between buttons in the permission popup. | |
| @@ -6,8 +6,8 @@ import ( | |||||
| 6 | 6 | ||||
| 7 | "github.com/bnema/dumber/internal/logging" | 7 | "github.com/bnema/dumber/internal/logging" | ||
| 8 | "github.com/bnema/dumber/internal/ui/layout" | 8 | "github.com/bnema/dumber/internal/ui/layout" | ||
| 9 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 9 | + | "github.com/bnema/puregotk/v4/gdk" |
| 10 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 10 | + | "github.com/bnema/puregotk/v4/gtk" |
| 11 | ) | 11 | ) | ||
| 12 | 12 | ||||
| 13 | // buttonSpacing is the spacing between buttons in the permission popup. | 13 | // buttonSpacing is the spacing between buttons in the permission popup. | ||
M internal/ui/component/progress_bar.go +2 -2
| @@ -4,8 +4,8 @@ package component | |||
| 4 | 4 | import ( | |
| 5 | 5 | "sync" | |
| 6 | 6 | ||
| 7 | - | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 8 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 7 | + | "github.com/bnema/puregotk/v4/glib" | |
| 8 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 9 | 9 | ||
| 10 | 10 | "github.com/bnema/dumber/internal/ui/layout" | |
| 11 | 11 | ) | |
| @@ -4,8 +4,8 @@ package component | |||||
| 4 | import ( | 4 | import ( | ||
| 5 | "sync" | 5 | "sync" | ||
| 6 | 6 | ||||
| 7 | - | "github.com/jwijenbergh/puregotk/v4/glib" | 7 | + | "github.com/bnema/puregotk/v4/glib" |
| 8 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 8 | + | "github.com/bnema/puregotk/v4/gtk" |
| 9 | 9 | ||||
| 10 | "github.com/bnema/dumber/internal/ui/layout" | 10 | "github.com/bnema/dumber/internal/ui/layout" | ||
| 11 | ) | 11 | ) | ||
M internal/ui/component/session_manager.go +3 -3
| @@ -11,9 +11,9 @@ import ( | |||
| 11 | 11 | "github.com/bnema/dumber/internal/domain/entity" | |
| 12 | 12 | "github.com/bnema/dumber/internal/logging" | |
| 13 | 13 | "github.com/bnema/dumber/internal/ui/layout" | |
| 14 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 15 | - | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 16 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 14 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 15 | + | "github.com/bnema/puregotk/v4/glib" | |
| 16 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 17 | 17 | ) | |
| 18 | 18 | ||
| 19 | 19 | const ( | |
| @@ -11,9 +11,9 @@ import ( | |||||
| 11 | "github.com/bnema/dumber/internal/domain/entity" | 11 | "github.com/bnema/dumber/internal/domain/entity" | ||
| 12 | "github.com/bnema/dumber/internal/logging" | 12 | "github.com/bnema/dumber/internal/logging" | ||
| 13 | "github.com/bnema/dumber/internal/ui/layout" | 13 | "github.com/bnema/dumber/internal/ui/layout" | ||
| 14 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 14 | + | "github.com/bnema/puregotk/v4/gdk" |
| 15 | - | "github.com/jwijenbergh/puregotk/v4/glib" | 15 | + | "github.com/bnema/puregotk/v4/glib" |
| 16 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 16 | + | "github.com/bnema/puregotk/v4/gtk" |
| 17 | ) | 17 | ) | ||
| 18 | 18 | ||||
| 19 | const ( | 19 | const ( | ||
M internal/ui/component/tab_bar.go +1 -1
| @@ -4,7 +4,7 @@ import ( | |||
| 4 | 4 | "sync" | |
| 5 | 5 | ||
| 6 | 6 | "github.com/bnema/dumber/internal/domain/entity" | |
| 7 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 7 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 8 | 8 | ) | |
| 9 | 9 | ||
| 10 | 10 | // TabBar represents the horizontal tab bar widget. | |
| @@ -4,7 +4,7 @@ import ( | |||||
| 4 | "sync" | 4 | "sync" | ||
| 5 | 5 | ||||
| 6 | "github.com/bnema/dumber/internal/domain/entity" | 6 | "github.com/bnema/dumber/internal/domain/entity" | ||
| 7 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 7 | + | "github.com/bnema/puregotk/v4/gtk" |
| 8 | ) | 8 | ) | ||
| 9 | 9 | ||||
| 10 | // TabBar represents the horizontal tab bar widget. | 10 | // TabBar represents the horizontal tab bar widget. | ||
M internal/ui/component/tab_button.go +2 -2
| @@ -3,8 +3,8 @@ package component | |||
| 3 | 3 | ||
| 4 | 4 | import ( | |
| 5 | 5 | "github.com/bnema/dumber/internal/domain/entity" | |
| 6 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 7 | - | "github.com/jwijenbergh/puregotk/v4/pango" | |
| 6 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 7 | + | "github.com/bnema/puregotk/v4/pango" | |
| 8 | 8 | ) | |
| 9 | 9 | ||
| 10 | 10 | // TabButton represents a single tab button in the tab bar. | |
| @@ -3,8 +3,8 @@ package component | |||||
| 3 | 3 | ||||
| 4 | import ( | 4 | import ( | ||
| 5 | "github.com/bnema/dumber/internal/domain/entity" | 5 | "github.com/bnema/dumber/internal/domain/entity" | ||
| 6 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 6 | + | "github.com/bnema/puregotk/v4/gtk" |
| 7 | - | "github.com/jwijenbergh/puregotk/v4/pango" | 7 | + | "github.com/bnema/puregotk/v4/pango" |
| 8 | ) | 8 | ) | ||
| 9 | 9 | ||||
| 10 | // TabButton represents a single tab button in the tab bar. | 10 | // TabButton represents a single tab button in the tab bar. | ||
M internal/ui/component/tab_picker.go +3 -3
| @@ -6,9 +6,9 @@ import ( | |||
| 6 | 6 | ||
| 7 | 7 | "github.com/bnema/dumber/internal/domain/entity" | |
| 8 | 8 | "github.com/bnema/dumber/internal/ui/layout" | |
| 9 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 10 | - | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 11 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 9 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 10 | + | "github.com/bnema/puregotk/v4/glib" | |
| 11 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 12 | 12 | ) | |
| 13 | 13 | ||
| 14 | 14 | type TabPickerItem struct { | |
| @@ -6,9 +6,9 @@ import ( | |||||
| 6 | 6 | ||||
| 7 | "github.com/bnema/dumber/internal/domain/entity" | 7 | "github.com/bnema/dumber/internal/domain/entity" | ||
| 8 | "github.com/bnema/dumber/internal/ui/layout" | 8 | "github.com/bnema/dumber/internal/ui/layout" | ||
| 9 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 9 | + | "github.com/bnema/puregotk/v4/gdk" |
| 10 | - | "github.com/jwijenbergh/puregotk/v4/glib" | 10 | + | "github.com/bnema/puregotk/v4/glib" |
| 11 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 11 | + | "github.com/bnema/puregotk/v4/gtk" |
| 12 | ) | 12 | ) | ||
| 13 | 13 | ||||
| 14 | type TabPickerItem struct { | 14 | type TabPickerItem struct { | ||
M internal/ui/component/toaster.go +2 -2
| @@ -6,8 +6,8 @@ import ( | |||
| 6 | 6 | "fmt" | |
| 7 | 7 | "sync" | |
| 8 | 8 | ||
| 9 | - | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 10 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 9 | + | "github.com/bnema/puregotk/v4/glib" | |
| 10 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 11 | 11 | ||
| 12 | 12 | "github.com/bnema/dumber/internal/logging" | |
| 13 | 13 | "github.com/bnema/dumber/internal/ui/layout" | |
| @@ -6,8 +6,8 @@ import ( | |||||
| 6 | "fmt" | 6 | "fmt" | ||
| 7 | "sync" | 7 | "sync" | ||
| 8 | 8 | ||||
| 9 | - | "github.com/jwijenbergh/puregotk/v4/glib" | 9 | + | "github.com/bnema/puregotk/v4/glib" |
| 10 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 10 | + | "github.com/bnema/puregotk/v4/gtk" |
| 11 | 11 | ||||
| 12 | "github.com/bnema/dumber/internal/logging" | 12 | "github.com/bnema/dumber/internal/logging" | ||
| 13 | "github.com/bnema/dumber/internal/ui/layout" | 13 | "github.com/bnema/dumber/internal/ui/layout" | ||
M internal/ui/component/webrtc_permission_indicator.go +1 -1
| @@ -5,7 +5,7 @@ import ( | |||
| 5 | 5 | "sync" | |
| 6 | 6 | ||
| 7 | 7 | "github.com/bnema/dumber/internal/domain/entity" | |
| 8 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 8 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 9 | 9 | ) | |
| 10 | 10 | ||
| 11 | 11 | // revealerTransitionDuration is the animation duration in milliseconds | |
| @@ -5,7 +5,7 @@ import ( | |||||
| 5 | "sync" | 5 | "sync" | ||
| 6 | 6 | ||||
| 7 | "github.com/bnema/dumber/internal/domain/entity" | 7 | "github.com/bnema/dumber/internal/domain/entity" | ||
| 8 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 8 | + | "github.com/bnema/puregotk/v4/gtk" |
| 9 | ) | 9 | ) | ||
| 10 | 10 | ||||
| 11 | // revealerTransitionDuration is the animation duration in milliseconds | 11 | // revealerTransitionDuration is the animation duration in milliseconds | ||
M internal/ui/component/workspace_view.go +1 -1
| @@ -12,7 +12,7 @@ import ( | |||
| 12 | 12 | "github.com/bnema/dumber/internal/domain/entity" | |
| 13 | 13 | "github.com/bnema/dumber/internal/logging" | |
| 14 | 14 | "github.com/bnema/dumber/internal/ui/layout" | |
| 15 | - | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 15 | + | "github.com/bnema/puregotk/v4/glib" | |
| 16 | 16 | "github.com/rs/zerolog" | |
| 17 | 17 | ) | |
| 18 | 18 | ||
| @@ -12,7 +12,7 @@ import ( | |||||
| 12 | "github.com/bnema/dumber/internal/domain/entity" | 12 | "github.com/bnema/dumber/internal/domain/entity" | ||
| 13 | "github.com/bnema/dumber/internal/logging" | 13 | "github.com/bnema/dumber/internal/logging" | ||
| 14 | "github.com/bnema/dumber/internal/ui/layout" | 14 | "github.com/bnema/dumber/internal/ui/layout" | ||
| 15 | - | "github.com/jwijenbergh/puregotk/v4/glib" | 15 | + | "github.com/bnema/puregotk/v4/glib" |
| 16 | "github.com/rs/zerolog" | 16 | "github.com/rs/zerolog" | ||
| 17 | ) | 17 | ) | ||
| 18 | 18 | ||||
M internal/ui/component/workspace_view_test.go +1 -1
| @@ -4,7 +4,7 @@ import ( | |||
| 4 | 4 | "context" | |
| 5 | 5 | "testing" | |
| 6 | 6 | ||
| 7 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 7 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 8 | 8 | "github.com/stretchr/testify/assert" | |
| 9 | 9 | "github.com/stretchr/testify/mock" | |
| 10 | 10 | "github.com/stretchr/testify/require" | |
| @@ -4,7 +4,7 @@ import ( | |||||
| 4 | "context" | 4 | "context" | ||
| 5 | "testing" | 5 | "testing" | ||
| 6 | 6 | ||||
| 7 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 7 | + | "github.com/bnema/puregotk/v4/gtk" |
| 8 | "github.com/stretchr/testify/assert" | 8 | "github.com/stretchr/testify/assert" | ||
| 9 | "github.com/stretchr/testify/mock" | 9 | "github.com/stretchr/testify/mock" | ||
| 10 | "github.com/stretchr/testify/require" | 10 | "github.com/stretchr/testify/require" | ||
M internal/ui/coordinator/content/callbacks.go +5 -4
| @@ -9,7 +9,7 @@ import ( | |||
| 9 | 9 | "github.com/bnema/dumber/internal/application/usecase" | |
| 10 | 10 | "github.com/bnema/dumber/internal/domain/entity" | |
| 11 | 11 | "github.com/bnema/dumber/internal/logging" | |
| 12 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 12 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 13 | 13 | ) | |
| 14 | 14 | ||
| 15 | 15 | // internalSchemePath is the path used in dumb:// URIs (replaces webkit.HomePath). | |
| @@ -117,8 +117,8 @@ func (c *Coordinator) setupWebViewCallbacks(ctx context.Context, paneID entity.P | |||
| 117 | 117 | Msg("failed to load crash page after web process termination") | |
| 118 | 118 | } | |
| 119 | 119 | }, | |
| 120 | - | OnPermissionRequest: func(origin string, permTypes []string, allow, deny func()) bool { | |
| 121 | - | return c.handlePermissionRequest(ctx, origin, permTypes, allow, deny) | |
| 120 | + | OnPermissionRequest: func(origin string, permTypes []string, metadata map[string]string, allow, deny func()) bool { | |
| 121 | + | return c.handlePermissionRequest(ctx, origin, permTypes, metadata, allow, deny) | |
| 122 | 122 | }, | |
| 123 | 123 | } | |
| 124 | 124 | ||
| @@ -191,6 +191,7 @@ func (c *Coordinator) handlePermissionRequest( | |||
| 191 | 191 | ctx context.Context, | |
| 192 | 192 | origin string, | |
| 193 | 193 | permTypes []string, | |
| 194 | + | metadata map[string]string, | |
| 194 | 195 | allow, deny func(), | |
| 195 | 196 | ) bool { | |
| 196 | 197 | log := logging.FromContext(ctx) | |
| @@ -264,7 +265,7 @@ func (c *Coordinator) handlePermissionRequest( | |||
| 264 | 265 | Deny: wrappedDeny, | |
| 265 | 266 | } | |
| 266 | 267 | ||
| 267 | - | c.permissionUC.HandlePermissionRequest(ctx, origin, entityTypes, callback) | |
| 268 | + | c.permissionUC.HandlePermissionRequest(ctx, origin, entityTypes, entity.PermissionMetadata(metadata), callback) | |
| 268 | 269 | return true | |
| 269 | 270 | } | |
| 270 | 271 | ||
| @@ -9,7 +9,7 @@ import ( | |||||
| 9 | "github.com/bnema/dumber/internal/application/usecase" | 9 | "github.com/bnema/dumber/internal/application/usecase" | ||
| 10 | "github.com/bnema/dumber/internal/domain/entity" | 10 | "github.com/bnema/dumber/internal/domain/entity" | ||
| 11 | "github.com/bnema/dumber/internal/logging" | 11 | "github.com/bnema/dumber/internal/logging" | ||
| 12 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 12 | + | "github.com/bnema/puregotk/v4/gdk" |
| 13 | ) | 13 | ) | ||
| 14 | 14 | ||||
| 15 | // internalSchemePath is the path used in dumb:// URIs (replaces webkit.HomePath). | 15 | // internalSchemePath is the path used in dumb:// URIs (replaces webkit.HomePath). | ||
| @@ -117,8 +117,8 @@ func (c *Coordinator) setupWebViewCallbacks(ctx context.Context, paneID entity.P | |||||
| 117 | Msg("failed to load crash page after web process termination") | 117 | Msg("failed to load crash page after web process termination") | ||
| 118 | } | 118 | } | ||
| 119 | }, | 119 | }, | ||
| 120 | - | OnPermissionRequest: func(origin string, permTypes []string, allow, deny func()) bool { | 120 | + | OnPermissionRequest: func(origin string, permTypes []string, metadata map[string]string, allow, deny func()) bool { |
| 121 | - | return c.handlePermissionRequest(ctx, origin, permTypes, allow, deny) | 121 | + | return c.handlePermissionRequest(ctx, origin, permTypes, metadata, allow, deny) |
| 122 | }, | 122 | }, | ||
| 123 | } | 123 | } | ||
| 124 | 124 | ||||
| @@ -191,6 +191,7 @@ func (c *Coordinator) handlePermissionRequest( | |||||
| 191 | ctx context.Context, | 191 | ctx context.Context, | ||
| 192 | origin string, | 192 | origin string, | ||
| 193 | permTypes []string, | 193 | permTypes []string, | ||
| 194 | + | metadata map[string]string, | |||
| 194 | allow, deny func(), | 195 | allow, deny func(), | ||
| 195 | ) bool { | 196 | ) bool { | ||
| 196 | log := logging.FromContext(ctx) | 197 | log := logging.FromContext(ctx) | ||
| @@ -264,7 +265,7 @@ func (c *Coordinator) handlePermissionRequest( | |||||
| 264 | Deny: wrappedDeny, | 265 | Deny: wrappedDeny, | ||
| 265 | } | 266 | } | ||
| 266 | 267 | ||||
| 267 | - | c.permissionUC.HandlePermissionRequest(ctx, origin, entityTypes, callback) | 268 | + | c.permissionUC.HandlePermissionRequest(ctx, origin, entityTypes, entity.PermissionMetadata(metadata), callback) |
| 268 | return true | 269 | return true | ||
| 269 | } | 270 | } | ||
| 270 | 271 | ||||
M internal/ui/coordinator/content/lifecycle.go +1 -1
| @@ -10,7 +10,7 @@ import ( | |||
| 10 | 10 | "github.com/bnema/dumber/internal/ui/component" | |
| 11 | 11 | "github.com/bnema/dumber/internal/ui/input" | |
| 12 | 12 | "github.com/bnema/dumber/internal/ui/layout" | |
| 13 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 13 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 14 | 14 | ) | |
| 15 | 15 | ||
| 16 | 16 | // EnsureWebView acquires or reuses a WebView for the given pane. | |
| @@ -10,7 +10,7 @@ import ( | |||||
| 10 | "github.com/bnema/dumber/internal/ui/component" | 10 | "github.com/bnema/dumber/internal/ui/component" | ||
| 11 | "github.com/bnema/dumber/internal/ui/input" | 11 | "github.com/bnema/dumber/internal/ui/input" | ||
| 12 | "github.com/bnema/dumber/internal/ui/layout" | 12 | "github.com/bnema/dumber/internal/ui/layout" | ||
| 13 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 13 | + | "github.com/bnema/puregotk/v4/gtk" |
| 14 | ) | 14 | ) | ||
| 15 | 15 | ||||
| 16 | // EnsureWebView acquires or reuses a WebView for the given pane. | 16 | // EnsureWebView acquires or reuses a WebView for the given pane. | ||
M internal/ui/coordinator/content/navigation.go +1 -1
| @@ -9,7 +9,7 @@ import ( | |||
| 9 | 9 | "github.com/bnema/dumber/internal/domain/entity" | |
| 10 | 10 | urlutil "github.com/bnema/dumber/internal/domain/url" | |
| 11 | 11 | "github.com/bnema/dumber/internal/logging" | |
| 12 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 12 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 13 | 13 | ) | |
| 14 | 14 | ||
| 15 | 15 | // onLoadCommitted re-applies zoom when page content starts loading and records history. | |
| @@ -9,7 +9,7 @@ import ( | |||||
| 9 | "github.com/bnema/dumber/internal/domain/entity" | 9 | "github.com/bnema/dumber/internal/domain/entity" | ||
| 10 | urlutil "github.com/bnema/dumber/internal/domain/url" | 10 | urlutil "github.com/bnema/dumber/internal/domain/url" | ||
| 11 | "github.com/bnema/dumber/internal/logging" | 11 | "github.com/bnema/dumber/internal/logging" | ||
| 12 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 12 | + | "github.com/bnema/puregotk/v4/gtk" |
| 13 | ) | 13 | ) | ||
| 14 | 14 | ||||
| 15 | // onLoadCommitted re-applies zoom when page content starts loading and records history. | 15 | // onLoadCommitted re-applies zoom when page content starts loading and records history. | ||
M internal/ui/coordinator/content/oauth.go +1 -1
| @@ -10,7 +10,7 @@ import ( | |||
| 10 | 10 | "github.com/bnema/dumber/internal/application/port" | |
| 11 | 11 | "github.com/bnema/dumber/internal/domain/entity" | |
| 12 | 12 | "github.com/bnema/dumber/internal/logging" | |
| 13 | - | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 13 | + | "github.com/bnema/puregotk/v4/glib" | |
| 14 | 14 | ) | |
| 15 | 15 | ||
| 16 | 16 | // oauthFlowPatterns are URL patterns that indicate an OAuth flow is in progress. | |
| @@ -10,7 +10,7 @@ import ( | |||||
| 10 | "github.com/bnema/dumber/internal/application/port" | 10 | "github.com/bnema/dumber/internal/application/port" | ||
| 11 | "github.com/bnema/dumber/internal/domain/entity" | 11 | "github.com/bnema/dumber/internal/domain/entity" | ||
| 12 | "github.com/bnema/dumber/internal/logging" | 12 | "github.com/bnema/dumber/internal/logging" | ||
| 13 | - | "github.com/jwijenbergh/puregotk/v4/glib" | 13 | + | "github.com/bnema/puregotk/v4/glib" |
| 14 | ) | 14 | ) | ||
| 15 | 15 | ||||
| 16 | // oauthFlowPatterns are URL patterns that indicate an OAuth flow is in progress. | 16 | // oauthFlowPatterns are URL patterns that indicate an OAuth flow is in progress. | ||
M internal/ui/coordinator/content/title.go +2 -2
| @@ -9,8 +9,8 @@ import ( | |||
| 9 | 9 | "github.com/bnema/dumber/internal/logging" | |
| 10 | 10 | "github.com/bnema/dumber/internal/ui/adapter" | |
| 11 | 11 | "github.com/bnema/dumber/internal/ui/layout" | |
| 12 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 13 | - | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 12 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 13 | + | "github.com/bnema/puregotk/v4/glib" | |
| 14 | 14 | ) | |
| 15 | 15 | ||
| 16 | 16 | // GetTitle returns the current title for a pane. | |
| @@ -9,8 +9,8 @@ import ( | |||||
| 9 | "github.com/bnema/dumber/internal/logging" | 9 | "github.com/bnema/dumber/internal/logging" | ||
| 10 | "github.com/bnema/dumber/internal/ui/adapter" | 10 | "github.com/bnema/dumber/internal/ui/adapter" | ||
| 11 | "github.com/bnema/dumber/internal/ui/layout" | 11 | "github.com/bnema/dumber/internal/ui/layout" | ||
| 12 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 12 | + | "github.com/bnema/puregotk/v4/gdk" |
| 13 | - | "github.com/jwijenbergh/puregotk/v4/glib" | 13 | + | "github.com/bnema/puregotk/v4/glib" |
| 14 | ) | 14 | ) | ||
| 15 | 15 | ||||
| 16 | // GetTitle returns the current title for a pane. | 16 | // GetTitle returns the current title for a pane. | ||
M internal/ui/coordinator/update.go +1 -1
| @@ -5,7 +5,7 @@ import ( | |||
| 5 | 5 | "fmt" | |
| 6 | 6 | "sync" | |
| 7 | 7 | ||
| 8 | - | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 8 | + | "github.com/bnema/puregotk/v4/glib" | |
| 9 | 9 | ||
| 10 | 10 | "github.com/bnema/dumber/internal/application/usecase" | |
| 11 | 11 | "github.com/bnema/dumber/internal/domain/entity" | |
| @@ -5,7 +5,7 @@ import ( | |||||
| 5 | "fmt" | 5 | "fmt" | ||
| 6 | "sync" | 6 | "sync" | ||
| 7 | 7 | ||||
| 8 | - | "github.com/jwijenbergh/puregotk/v4/glib" | 8 | + | "github.com/bnema/puregotk/v4/glib" |
| 9 | 9 | ||||
| 10 | "github.com/bnema/dumber/internal/application/usecase" | 10 | "github.com/bnema/dumber/internal/application/usecase" | ||
| 11 | "github.com/bnema/dumber/internal/domain/entity" | 11 | "github.com/bnema/dumber/internal/domain/entity" | ||
M internal/ui/deps.go +1 -1
| @@ -11,7 +11,7 @@ import ( | |||
| 11 | 11 | "github.com/bnema/dumber/internal/infrastructure/config" | |
| 12 | 12 | "github.com/bnema/dumber/internal/ui/adapter" | |
| 13 | 13 | "github.com/bnema/dumber/internal/ui/theme" | |
| 14 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 14 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 15 | 15 | ) | |
| 16 | 16 | ||
| 17 | 17 | // Dependencies holds all injected dependencies for the UI layer. | |
| @@ -11,7 +11,7 @@ import ( | |||||
| 11 | "github.com/bnema/dumber/internal/infrastructure/config" | 11 | "github.com/bnema/dumber/internal/infrastructure/config" | ||
| 12 | "github.com/bnema/dumber/internal/ui/adapter" | 12 | "github.com/bnema/dumber/internal/ui/adapter" | ||
| 13 | "github.com/bnema/dumber/internal/ui/theme" | 13 | "github.com/bnema/dumber/internal/ui/theme" | ||
| 14 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 14 | + | "github.com/bnema/puregotk/v4/gtk" |
| 15 | ) | 15 | ) | ||
| 16 | 16 | ||||
| 17 | // Dependencies holds all injected dependencies for the UI layer. | 17 | // Dependencies holds all injected dependencies for the UI layer. | ||
M internal/ui/dialog/permission.go +13 -5
| @@ -21,6 +21,7 @@ type permissionDialogRequest struct { | |||
| 21 | 21 | ctx context.Context | |
| 22 | 22 | origin string | |
| 23 | 23 | permTypes []entity.PermissionType | |
| 24 | + | metadata entity.PermissionMetadata | |
| 24 | 25 | callback func(result port.PermissionDialogResult) | |
| 25 | 26 | } | |
| 26 | 27 | ||
| @@ -48,12 +49,14 @@ func (d *PermissionDialog) ShowPermissionDialog( | |||
| 48 | 49 | ctx context.Context, | |
| 49 | 50 | origin string, | |
| 50 | 51 | permTypes []entity.PermissionType, | |
| 52 | + | metadata entity.PermissionMetadata, | |
| 51 | 53 | callback func(result port.PermissionDialogResult), | |
| 52 | 54 | ) { | |
| 53 | 55 | req := permissionDialogRequest{ | |
| 54 | 56 | ctx: ctx, | |
| 55 | 57 | origin: origin, | |
| 56 | 58 | permTypes: permTypes, | |
| 59 | + | metadata: metadata, | |
| 57 | 60 | callback: callback, | |
| 58 | 61 | } | |
| 59 | 62 | ||
| @@ -94,7 +97,7 @@ func (d *PermissionDialog) showRequest(req permissionDialogRequest) { | |||
| 94 | 97 | ||
| 95 | 98 | // Build dialog text | |
| 96 | 99 | heading := d.buildHeading(permTypes) | |
| 97 | - | body := d.buildBody(origin, permTypes) | |
| 100 | + | body := d.buildBody(origin, permTypes, req.metadata) | |
| 98 | 101 | ||
| 99 | 102 | d.popup.Show(ctx, heading, body, func(allowed, persistent bool) { | |
| 100 | 103 | log.Debug(). | |
| @@ -198,7 +201,7 @@ func (d *PermissionDialog) buildHeading( | |||
| 198 | 201 | ||
| 199 | 202 | // buildBody creates the dialog body text. | |
| 200 | 203 | func (d *PermissionDialog) buildBody( | |
| 201 | - | origin string, permTypes []entity.PermissionType, | |
| 204 | + | origin string, permTypes []entity.PermissionType, metadata entity.PermissionMetadata, | |
| 202 | 205 | ) string { | |
| 203 | 206 | f := parsePermFlags(permTypes) | |
| 204 | 207 | var parts []string | |
| @@ -213,9 +216,14 @@ func (d *PermissionDialog) buildBody( | |||
| 213 | 216 | parts = append(parts, "share your screen") | |
| 214 | 217 | } | |
| 215 | 218 | if f.dataAccess { | |
| 216 | - | if len(parts) == 0 { | |
| 217 | - | parts = append(parts, | |
| 218 | - | "access its stored data while you browse this site") | |
| 219 | + | reqDomain := metadata[entity.PermissionMetadataKeyRequestingDomain] | |
| 220 | + | curDomain := metadata[entity.PermissionMetadataKeyCurrentDomain] | |
| 221 | + | if reqDomain != "" && curDomain != "" { | |
| 222 | + | parts = append(parts, fmt.Sprintf( | |
| 223 | + | "allow %s to access its data (including cookies) while you browse %s", | |
| 224 | + | reqDomain, curDomain)) | |
| 225 | + | } else if len(parts) == 0 { | |
| 226 | + | parts = append(parts, "access its stored data while you browse this site") | |
| 219 | 227 | } else { | |
| 220 | 228 | parts = append(parts, "access its stored data") | |
| 221 | 229 | } | |
| @@ -21,6 +21,7 @@ type permissionDialogRequest struct { | |||||
| 21 | ctx context.Context | 21 | ctx context.Context | ||
| 22 | origin string | 22 | origin string | ||
| 23 | permTypes []entity.PermissionType | 23 | permTypes []entity.PermissionType | ||
| 24 | + | metadata entity.PermissionMetadata | |||
| 24 | callback func(result port.PermissionDialogResult) | 25 | callback func(result port.PermissionDialogResult) | ||
| 25 | } | 26 | } | ||
| 26 | 27 | ||||
| @@ -48,12 +49,14 @@ func (d *PermissionDialog) ShowPermissionDialog( | |||||
| 48 | ctx context.Context, | 49 | ctx context.Context, | ||
| 49 | origin string, | 50 | origin string, | ||
| 50 | permTypes []entity.PermissionType, | 51 | permTypes []entity.PermissionType, | ||
| 52 | + | metadata entity.PermissionMetadata, | |||
| 51 | callback func(result port.PermissionDialogResult), | 53 | callback func(result port.PermissionDialogResult), | ||
| 52 | ) { | 54 | ) { | ||
| 53 | req := permissionDialogRequest{ | 55 | req := permissionDialogRequest{ | ||
| 54 | ctx: ctx, | 56 | ctx: ctx, | ||
| 55 | origin: origin, | 57 | origin: origin, | ||
| 56 | permTypes: permTypes, | 58 | permTypes: permTypes, | ||
| 59 | + | metadata: metadata, | |||
| 57 | callback: callback, | 60 | callback: callback, | ||
| 58 | } | 61 | } | ||
| 59 | 62 | ||||
| @@ -94,7 +97,7 @@ func (d *PermissionDialog) showRequest(req permissionDialogRequest) { | |||||
| 94 | 97 | ||||
| 95 | // Build dialog text | 98 | // Build dialog text | ||
| 96 | heading := d.buildHeading(permTypes) | 99 | heading := d.buildHeading(permTypes) | ||
| 97 | - | body := d.buildBody(origin, permTypes) | 100 | + | body := d.buildBody(origin, permTypes, req.metadata) |
| 98 | 101 | ||||
| 99 | d.popup.Show(ctx, heading, body, func(allowed, persistent bool) { | 102 | d.popup.Show(ctx, heading, body, func(allowed, persistent bool) { | ||
| 100 | log.Debug(). | 103 | log.Debug(). | ||
| @@ -198,7 +201,7 @@ func (d *PermissionDialog) buildHeading( | |||||
| 198 | 201 | ||||
| 199 | // buildBody creates the dialog body text. | 202 | // buildBody creates the dialog body text. | ||
| 200 | func (d *PermissionDialog) buildBody( | 203 | func (d *PermissionDialog) buildBody( | ||
| 201 | - | origin string, permTypes []entity.PermissionType, | 204 | + | origin string, permTypes []entity.PermissionType, metadata entity.PermissionMetadata, |
| 202 | ) string { | 205 | ) string { | ||
| 203 | f := parsePermFlags(permTypes) | 206 | f := parsePermFlags(permTypes) | ||
| 204 | var parts []string | 207 | var parts []string | ||
| @@ -213,9 +216,14 @@ func (d *PermissionDialog) buildBody( | |||||
| 213 | parts = append(parts, "share your screen") | 216 | parts = append(parts, "share your screen") | ||
| 214 | } | 217 | } | ||
| 215 | if f.dataAccess { | 218 | if f.dataAccess { | ||
| 216 | - | if len(parts) == 0 { | 219 | + | reqDomain := metadata[entity.PermissionMetadataKeyRequestingDomain] |
| 217 | - | parts = append(parts, | 220 | + | curDomain := metadata[entity.PermissionMetadataKeyCurrentDomain] |
| 218 | - | "access its stored data while you browse this site") | 221 | + | if reqDomain != "" && curDomain != "" { |
| 222 | + | parts = append(parts, fmt.Sprintf( | |||
| 223 | + | "allow %s to access its data (including cookies) while you browse %s", | |||
| 224 | + | reqDomain, curDomain)) | |||
| 225 | + | } else if len(parts) == 0 { | |||
| 226 | + | parts = append(parts, "access its stored data while you browse this site") | |||
| 219 | } else { | 227 | } else { | ||
| 220 | parts = append(parts, "access its stored data") | 228 | parts = append(parts, "access its stored data") | ||
| 221 | } | 229 | } | ||
M internal/ui/dialog/permission_test.go +14 -1
| @@ -51,6 +51,7 @@ func TestPermissionDialog_QueuesRequestsWhilePopupVisible(t *testing.T) { | |||
| 51 | 51 | context.Background(), | |
| 52 | 52 | "https://example.com", | |
| 53 | 53 | []entity.PermissionType{entity.PermissionTypeMicrophone}, | |
| 54 | + | nil, | |
| 54 | 55 | func(result port.PermissionDialogResult) { | |
| 55 | 56 | firstCalled = true | |
| 56 | 57 | firstResult = result | |
| @@ -63,6 +64,7 @@ func TestPermissionDialog_QueuesRequestsWhilePopupVisible(t *testing.T) { | |||
| 63 | 64 | context.Background(), | |
| 64 | 65 | "https://example.com", | |
| 65 | 66 | []entity.PermissionType{entity.PermissionTypeCamera}, | |
| 67 | + | nil, | |
| 66 | 68 | func(result port.PermissionDialogResult) { | |
| 67 | 69 | secondCalled = true | |
| 68 | 70 | secondResult = result | |
| @@ -98,6 +100,7 @@ func TestPermissionDialog_NoPopup_DeniesRequest(t *testing.T) { | |||
| 98 | 100 | context.Background(), | |
| 99 | 101 | "https://example.com", | |
| 100 | 102 | []entity.PermissionType{entity.PermissionTypeMicrophone}, | |
| 103 | + | nil, | |
| 101 | 104 | func(r port.PermissionDialogResult) { | |
| 102 | 105 | called = true | |
| 103 | 106 | result = r | |
| @@ -153,7 +156,17 @@ func TestPermissionDialog_BuildHeadingAndBody_DisplayCombinations(t *testing.T) | |||
| 153 | 156 | for _, tt := range tests { | |
| 154 | 157 | t.Run(tt.name, func(t *testing.T) { | |
| 155 | 158 | assert.Equal(t, tt.expectHeading, d.buildHeading(tt.permTypes)) | |
| 156 | - | assert.Equal(t, origin+" wants to "+tt.expectedAction+".", d.buildBody(origin, tt.permTypes)) | |
| 159 | + | assert.Equal(t, origin+" wants to "+tt.expectedAction+".", d.buildBody(origin, tt.permTypes, nil)) | |
| 157 | 160 | }) | |
| 158 | 161 | } | |
| 162 | + | ||
| 163 | + | // Test website_data_access with populated metadata (Epiphany-style rich message) | |
| 164 | + | t.Run("website data access with both domains", func(t *testing.T) { | |
| 165 | + | meta := entity.PermissionMetadata{ | |
| 166 | + | entity.PermissionMetadataKeyRequestingDomain: "accounts.google.com", | |
| 167 | + | entity.PermissionMetadataKeyCurrentDomain: "shop.example.com", | |
| 168 | + | } | |
| 169 | + | body := d.buildBody(origin, []entity.PermissionType{entity.PermissionTypeWebsiteDataAccess}, meta) | |
| 170 | + | assert.Equal(t, origin+" wants to allow accounts.google.com to access its data (including cookies) while you browse shop.example.com.", body) | |
| 171 | + | }) | |
| 159 | 172 | } | |
| @@ -51,6 +51,7 @@ func TestPermissionDialog_QueuesRequestsWhilePopupVisible(t *testing.T) { | |||||
| 51 | context.Background(), | 51 | context.Background(), | ||
| 52 | "https://example.com", | 52 | "https://example.com", | ||
| 53 | []entity.PermissionType{entity.PermissionTypeMicrophone}, | 53 | []entity.PermissionType{entity.PermissionTypeMicrophone}, | ||
| 54 | + | nil, | |||
| 54 | func(result port.PermissionDialogResult) { | 55 | func(result port.PermissionDialogResult) { | ||
| 55 | firstCalled = true | 56 | firstCalled = true | ||
| 56 | firstResult = result | 57 | firstResult = result | ||
| @@ -63,6 +64,7 @@ func TestPermissionDialog_QueuesRequestsWhilePopupVisible(t *testing.T) { | |||||
| 63 | context.Background(), | 64 | context.Background(), | ||
| 64 | "https://example.com", | 65 | "https://example.com", | ||
| 65 | []entity.PermissionType{entity.PermissionTypeCamera}, | 66 | []entity.PermissionType{entity.PermissionTypeCamera}, | ||
| 67 | + | nil, | |||
| 66 | func(result port.PermissionDialogResult) { | 68 | func(result port.PermissionDialogResult) { | ||
| 67 | secondCalled = true | 69 | secondCalled = true | ||
| 68 | secondResult = result | 70 | secondResult = result | ||
| @@ -98,6 +100,7 @@ func TestPermissionDialog_NoPopup_DeniesRequest(t *testing.T) { | |||||
| 98 | context.Background(), | 100 | context.Background(), | ||
| 99 | "https://example.com", | 101 | "https://example.com", | ||
| 100 | []entity.PermissionType{entity.PermissionTypeMicrophone}, | 102 | []entity.PermissionType{entity.PermissionTypeMicrophone}, | ||
| 103 | + | nil, | |||
| 101 | func(r port.PermissionDialogResult) { | 104 | func(r port.PermissionDialogResult) { | ||
| 102 | called = true | 105 | called = true | ||
| 103 | result = r | 106 | result = r | ||
| @@ -153,7 +156,17 @@ func TestPermissionDialog_BuildHeadingAndBody_DisplayCombinations(t *testing.T) | |||||
| 153 | for _, tt := range tests { | 156 | for _, tt := range tests { | ||
| 154 | t.Run(tt.name, func(t *testing.T) { | 157 | t.Run(tt.name, func(t *testing.T) { | ||
| 155 | assert.Equal(t, tt.expectHeading, d.buildHeading(tt.permTypes)) | 158 | assert.Equal(t, tt.expectHeading, d.buildHeading(tt.permTypes)) | ||
| 156 | - | assert.Equal(t, origin+" wants to "+tt.expectedAction+".", d.buildBody(origin, tt.permTypes)) | 159 | + | assert.Equal(t, origin+" wants to "+tt.expectedAction+".", d.buildBody(origin, tt.permTypes, nil)) |
| 157 | }) | 160 | }) | ||
| 158 | } | 161 | } | ||
| 162 | + | ||||
| 163 | + | // Test website_data_access with populated metadata (Epiphany-style rich message) | |||
| 164 | + | t.Run("website data access with both domains", func(t *testing.T) { | |||
| 165 | + | meta := entity.PermissionMetadata{ | |||
| 166 | + | entity.PermissionMetadataKeyRequestingDomain: "accounts.google.com", | |||
| 167 | + | entity.PermissionMetadataKeyCurrentDomain: "shop.example.com", | |||
| 168 | + | } | |||
| 169 | + | body := d.buildBody(origin, []entity.PermissionType{entity.PermissionTypeWebsiteDataAccess}, meta) | |||
| 170 | + | assert.Equal(t, origin+" wants to allow accounts.google.com to access its data (including cookies) while you browse shop.example.com.", body) | |||
| 171 | + | }) | |||
| 159 | } | 172 | } | ||
M internal/ui/dispatcher/keyboard.go +1 -1
| @@ -11,7 +11,7 @@ import ( | |||
| 11 | 11 | "github.com/bnema/dumber/internal/ui/component" | |
| 12 | 12 | "github.com/bnema/dumber/internal/ui/coordinator" | |
| 13 | 13 | "github.com/bnema/dumber/internal/ui/input" | |
| 14 | - | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 14 | + | "github.com/bnema/puregotk/v4/glib" | |
| 15 | 15 | ) | |
| 16 | 16 | ||
| 17 | 17 | // KeyboardDispatcher routes keyboard actions to appropriate coordinators. | |
| @@ -11,7 +11,7 @@ import ( | |||||
| 11 | "github.com/bnema/dumber/internal/ui/component" | 11 | "github.com/bnema/dumber/internal/ui/component" | ||
| 12 | "github.com/bnema/dumber/internal/ui/coordinator" | 12 | "github.com/bnema/dumber/internal/ui/coordinator" | ||
| 13 | "github.com/bnema/dumber/internal/ui/input" | 13 | "github.com/bnema/dumber/internal/ui/input" | ||
| 14 | - | "github.com/jwijenbergh/puregotk/v4/glib" | 14 | + | "github.com/bnema/puregotk/v4/glib" |
| 15 | ) | 15 | ) | ||
| 16 | 16 | ||||
| 17 | // KeyboardDispatcher routes keyboard actions to appropriate coordinators. | 17 | // KeyboardDispatcher routes keyboard actions to appropriate coordinators. | ||
M internal/ui/input/floating_shortcuts_test.go +1 -1
| @@ -5,7 +5,7 @@ import ( | |||
| 5 | 5 | "testing" | |
| 6 | 6 | ||
| 7 | 7 | "github.com/bnema/dumber/internal/domain/entity" | |
| 8 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 8 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 9 | 9 | "github.com/stretchr/testify/assert" | |
| 10 | 10 | "github.com/stretchr/testify/require" | |
| 11 | 11 | ) | |
| @@ -5,7 +5,7 @@ import ( | |||||
| 5 | "testing" | 5 | "testing" | ||
| 6 | 6 | ||||
| 7 | "github.com/bnema/dumber/internal/domain/entity" | 7 | "github.com/bnema/dumber/internal/domain/entity" | ||
| 8 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 8 | + | "github.com/bnema/puregotk/v4/gdk" |
| 9 | "github.com/stretchr/testify/assert" | 9 | "github.com/stretchr/testify/assert" | ||
| 10 | "github.com/stretchr/testify/require" | 10 | "github.com/stretchr/testify/require" | ||
| 11 | ) | 11 | ) | ||
M internal/ui/input/gesture.go +1 -1
| @@ -5,7 +5,7 @@ import ( | |||
| 5 | 5 | "sync" | |
| 6 | 6 | ||
| 7 | 7 | "github.com/bnema/dumber/internal/logging" | |
| 8 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 8 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 9 | 9 | ) | |
| 10 | 10 | ||
| 11 | 11 | // DirectNavigator allows direct back/forward navigation on a WebView. | |
| @@ -5,7 +5,7 @@ import ( | |||||
| 5 | "sync" | 5 | "sync" | ||
| 6 | 6 | ||||
| 7 | "github.com/bnema/dumber/internal/logging" | 7 | "github.com/bnema/dumber/internal/logging" | ||
| 8 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 8 | + | "github.com/bnema/puregotk/v4/gtk" |
| 9 | ) | 9 | ) | ||
| 10 | 10 | ||||
| 11 | // DirectNavigator allows direct back/forward navigation on a WebView. | 11 | // DirectNavigator allows direct back/forward navigation on a WebView. | ||
M internal/ui/input/global_shortcuts.go +3 -3
| @@ -8,9 +8,9 @@ import ( | |||
| 8 | 8 | ||
| 9 | 9 | "github.com/bnema/dumber/internal/domain/entity" | |
| 10 | 10 | "github.com/bnema/dumber/internal/logging" | |
| 11 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 12 | - | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 13 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 11 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 12 | + | "github.com/bnema/puregotk/v4/glib" | |
| 13 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 14 | 14 | ) | |
| 15 | 15 | ||
| 16 | 16 | // GlobalShortcutHandler manages keyboard shortcuts that must work globally, | |
| @@ -8,9 +8,9 @@ import ( | |||||
| 8 | 8 | ||||
| 9 | "github.com/bnema/dumber/internal/domain/entity" | 9 | "github.com/bnema/dumber/internal/domain/entity" | ||
| 10 | "github.com/bnema/dumber/internal/logging" | 10 | "github.com/bnema/dumber/internal/logging" | ||
| 11 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 11 | + | "github.com/bnema/puregotk/v4/gdk" |
| 12 | - | "github.com/jwijenbergh/puregotk/v4/glib" | 12 | + | "github.com/bnema/puregotk/v4/glib" |
| 13 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 13 | + | "github.com/bnema/puregotk/v4/gtk" |
| 14 | ) | 14 | ) | ||
| 15 | 15 | ||||
| 16 | // GlobalShortcutHandler manages keyboard shortcuts that must work globally, | 16 | // GlobalShortcutHandler manages keyboard shortcuts that must work globally, | ||
M internal/ui/input/hover.go +1 -1
| @@ -7,7 +7,7 @@ import ( | |||
| 7 | 7 | ||
| 8 | 8 | "github.com/bnema/dumber/internal/domain/entity" | |
| 9 | 9 | "github.com/bnema/dumber/internal/logging" | |
| 10 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 10 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 11 | 11 | ) | |
| 12 | 12 | ||
| 13 | 13 | const ( | |
| @@ -7,7 +7,7 @@ import ( | |||||
| 7 | 7 | ||||
| 8 | "github.com/bnema/dumber/internal/domain/entity" | 8 | "github.com/bnema/dumber/internal/domain/entity" | ||
| 9 | "github.com/bnema/dumber/internal/logging" | 9 | "github.com/bnema/dumber/internal/logging" | ||
| 10 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 10 | + | "github.com/bnema/puregotk/v4/gtk" |
| 11 | ) | 11 | ) | ||
| 12 | 12 | ||||
| 13 | const ( | 13 | const ( | ||
M internal/ui/input/keyboard.go +3 -3
| @@ -25,9 +25,9 @@ import ( | |||
| 25 | 25 | ||
| 26 | 26 | "github.com/bnema/dumber/internal/domain/entity" | |
| 27 | 27 | "github.com/bnema/dumber/internal/logging" | |
| 28 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 29 | - | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 30 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 28 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 29 | + | "github.com/bnema/puregotk/v4/glib" | |
| 30 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 31 | 31 | "github.com/rs/zerolog" | |
| 32 | 32 | ) | |
| 33 | 33 | ||
| @@ -25,9 +25,9 @@ import ( | |||||
| 25 | 25 | ||||
| 26 | "github.com/bnema/dumber/internal/domain/entity" | 26 | "github.com/bnema/dumber/internal/domain/entity" | ||
| 27 | "github.com/bnema/dumber/internal/logging" | 27 | "github.com/bnema/dumber/internal/logging" | ||
| 28 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 28 | + | "github.com/bnema/puregotk/v4/gdk" |
| 29 | - | "github.com/jwijenbergh/puregotk/v4/glib" | 29 | + | "github.com/bnema/puregotk/v4/glib" |
| 30 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 30 | + | "github.com/bnema/puregotk/v4/gtk" |
| 31 | "github.com/rs/zerolog" | 31 | "github.com/rs/zerolog" | ||
| 32 | ) | 32 | ) | ||
| 33 | 33 | ||||
M internal/ui/input/keyboard_test.go +1 -1
| @@ -5,7 +5,7 @@ import ( | |||
| 5 | 5 | "testing" | |
| 6 | 6 | ||
| 7 | 7 | "github.com/bnema/dumber/internal/domain/entity" | |
| 8 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 8 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 9 | 9 | "github.com/stretchr/testify/assert" | |
| 10 | 10 | ) | |
| 11 | 11 | ||
| @@ -5,7 +5,7 @@ import ( | |||||
| 5 | "testing" | 5 | "testing" | ||
| 6 | 6 | ||||
| 7 | "github.com/bnema/dumber/internal/domain/entity" | 7 | "github.com/bnema/dumber/internal/domain/entity" | ||
| 8 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 8 | + | "github.com/bnema/puregotk/v4/gdk" |
| 9 | "github.com/stretchr/testify/assert" | 9 | "github.com/stretchr/testify/assert" | ||
| 10 | ) | 10 | ) | ||
| 11 | 11 | ||||
M internal/ui/input/shortcuts.go +1 -1
| @@ -8,7 +8,7 @@ import ( | |||
| 8 | 8 | ||
| 9 | 9 | "github.com/bnema/dumber/internal/domain/entity" | |
| 10 | 10 | "github.com/bnema/dumber/internal/logging" | |
| 11 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 11 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 12 | 12 | ) | |
| 13 | 13 | ||
| 14 | 14 | // Modifier represents keyboard modifier flags. | |
| @@ -8,7 +8,7 @@ import ( | |||||
| 8 | 8 | ||||
| 9 | "github.com/bnema/dumber/internal/domain/entity" | 9 | "github.com/bnema/dumber/internal/domain/entity" | ||
| 10 | "github.com/bnema/dumber/internal/logging" | 10 | "github.com/bnema/dumber/internal/logging" | ||
| 11 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 11 | + | "github.com/bnema/puregotk/v4/gdk" |
| 12 | ) | 12 | ) | ||
| 13 | 13 | ||||
| 14 | // Modifier represents keyboard modifier flags. | 14 | // Modifier represents keyboard modifier flags. | ||
M internal/ui/input/shortcuts_test.go +1 -1
| @@ -3,7 +3,7 @@ package input | |||
| 3 | 3 | import ( | |
| 4 | 4 | "testing" | |
| 5 | 5 | ||
| 6 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 6 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 7 | 7 | ) | |
| 8 | 8 | ||
| 9 | 9 | func TestParseKeyString_SingleKeys(t *testing.T) { | |
| @@ -3,7 +3,7 @@ package input | |||||
| 3 | import ( | 3 | import ( | ||
| 4 | "testing" | 4 | "testing" | ||
| 5 | 5 | ||||
| 6 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 6 | + | "github.com/bnema/puregotk/v4/gdk" |
| 7 | ) | 7 | ) | ||
| 8 | 8 | ||||
| 9 | func TestParseKeyString_SingleKeys(t *testing.T) { | 9 | func TestParseKeyString_SingleKeys(t *testing.T) { | ||
M internal/ui/layout/gtk_widgets.go +5 -5
| @@ -1,11 +1,11 @@ | |||
| 1 | 1 | package layout | |
| 2 | 2 | ||
| 3 | 3 | import ( | |
| 4 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 5 | - | "github.com/jwijenbergh/puregotk/v4/gobject" | |
| 6 | - | "github.com/jwijenbergh/puregotk/v4/graphene" | |
| 7 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 8 | - | "github.com/jwijenbergh/puregotk/v4/pango" | |
| 4 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 5 | + | "github.com/bnema/puregotk/v4/gobject" | |
| 6 | + | "github.com/bnema/puregotk/v4/graphene" | |
| 7 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 8 | + | "github.com/bnema/puregotk/v4/pango" | |
| 9 | 9 | ) | |
| 10 | 10 | ||
| 11 | 11 | // Ensure implementations satisfy interfaces at compile time. | |
| @@ -1,11 +1,11 @@ | |||||
| 1 | package layout | 1 | package layout | ||
| 2 | 2 | ||||
| 3 | import ( | 3 | import ( | ||
| 4 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 4 | + | "github.com/bnema/puregotk/v4/gdk" |
| 5 | - | "github.com/jwijenbergh/puregotk/v4/gobject" | 5 | + | "github.com/bnema/puregotk/v4/gobject" |
| 6 | - | "github.com/jwijenbergh/puregotk/v4/graphene" | 6 | + | "github.com/bnema/puregotk/v4/graphene" |
| 7 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 7 | + | "github.com/bnema/puregotk/v4/gtk" |
| 8 | - | "github.com/jwijenbergh/puregotk/v4/pango" | 8 | + | "github.com/bnema/puregotk/v4/pango" |
| 9 | ) | 9 | ) | ||
| 10 | 10 | ||||
| 11 | // Ensure implementations satisfy interfaces at compile time. | 11 | // Ensure implementations satisfy interfaces at compile time. | ||
M internal/ui/layout/mocks/mocks.go +1 -1
| @@ -7,7 +7,7 @@ package mocks | |||
| 7 | 7 | import ( | |
| 8 | 8 | "github.com/bnema/dumber/internal/domain/entity" | |
| 9 | 9 | "github.com/bnema/dumber/internal/ui/layout" | |
| 10 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 10 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 11 | 11 | mock "github.com/stretchr/testify/mock" | |
| 12 | 12 | ) | |
| 13 | 13 | ||
| @@ -7,7 +7,7 @@ package mocks | |||||
| 7 | import ( | 7 | import ( | ||
| 8 | "github.com/bnema/dumber/internal/domain/entity" | 8 | "github.com/bnema/dumber/internal/domain/entity" | ||
| 9 | "github.com/bnema/dumber/internal/ui/layout" | 9 | "github.com/bnema/dumber/internal/ui/layout" | ||
| 10 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 10 | + | "github.com/bnema/puregotk/v4/gtk" |
| 11 | mock "github.com/stretchr/testify/mock" | 11 | mock "github.com/stretchr/testify/mock" | ||
| 12 | ) | 12 | ) | ||
| 13 | 13 | ||||
M internal/ui/layout/split.go +1 -1
| @@ -6,7 +6,7 @@ import ( | |||
| 6 | 6 | "time" | |
| 7 | 7 | ||
| 8 | 8 | "github.com/bnema/dumber/internal/logging" | |
| 9 | - | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 9 | + | "github.com/bnema/puregotk/v4/glib" | |
| 10 | 10 | "github.com/rs/zerolog" | |
| 11 | 11 | ) | |
| 12 | 12 | ||
| @@ -6,7 +6,7 @@ import ( | |||||
| 6 | "time" | 6 | "time" | ||
| 7 | 7 | ||||
| 8 | "github.com/bnema/dumber/internal/logging" | 8 | "github.com/bnema/dumber/internal/logging" | ||
| 9 | - | "github.com/jwijenbergh/puregotk/v4/glib" | 9 | + | "github.com/bnema/puregotk/v4/glib" |
| 10 | "github.com/rs/zerolog" | 10 | "github.com/rs/zerolog" | ||
| 11 | ) | 11 | ) | ||
| 12 | 12 | ||||
M internal/ui/layout/stacked.go +2 -2
| @@ -6,8 +6,8 @@ import ( | |||
| 6 | 6 | "sync" | |
| 7 | 7 | ||
| 8 | 8 | "github.com/bnema/dumber/internal/logging" | |
| 9 | - | "github.com/jwijenbergh/puregotk/v4/gobject" | |
| 10 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 9 | + | "github.com/bnema/puregotk/v4/gobject" | |
| 10 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 11 | 11 | ) | |
| 12 | 12 | ||
| 13 | 13 | // ErrStackEmpty is returned when operating on an empty stack. | |
| @@ -6,8 +6,8 @@ import ( | |||||
| 6 | "sync" | 6 | "sync" | ||
| 7 | 7 | ||||
| 8 | "github.com/bnema/dumber/internal/logging" | 8 | "github.com/bnema/dumber/internal/logging" | ||
| 9 | - | "github.com/jwijenbergh/puregotk/v4/gobject" | 9 | + | "github.com/bnema/puregotk/v4/gobject" |
| 10 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 10 | + | "github.com/bnema/puregotk/v4/gtk" |
| 11 | ) | 11 | ) | ||
| 12 | 12 | ||||
| 13 | // ErrStackEmpty is returned when operating on an empty stack. | 13 | // ErrStackEmpty is returned when operating on an empty stack. | ||
M internal/ui/layout/widgets.go +1 -1
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | package layout | |
| 4 | 4 | ||
| 5 | 5 | import ( | |
| 6 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 6 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 7 | 7 | ) | |
| 8 | 8 | ||
| 9 | 9 | // Orientation represents the orientation for layout widgets. | |
| @@ -3,7 +3,7 @@ | |||||
| 3 | package layout | 3 | package layout | ||
| 4 | 4 | ||||
| 5 | import ( | 5 | import ( | ||
| 6 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 6 | + | "github.com/bnema/puregotk/v4/gtk" |
| 7 | ) | 7 | ) | ||
| 8 | 8 | ||||
| 9 | // Orientation represents the orientation for layout widgets. | 9 | // Orientation represents the orientation for layout widgets. | ||
M internal/ui/theme/manager.go +2 -2
| @@ -7,8 +7,8 @@ import ( | |||
| 7 | 7 | "github.com/bnema/dumber/internal/application/port" | |
| 8 | 8 | "github.com/bnema/dumber/internal/domain/entity" | |
| 9 | 9 | "github.com/bnema/dumber/internal/logging" | |
| 10 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | |
| 11 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 10 | + | "github.com/bnema/puregotk/v4/gdk" | |
| 11 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 12 | 12 | ) | |
| 13 | 13 | ||
| 14 | 14 | // Manager handles theme state and CSS application. | |
| @@ -7,8 +7,8 @@ import ( | |||||
| 7 | "github.com/bnema/dumber/internal/application/port" | 7 | "github.com/bnema/dumber/internal/application/port" | ||
| 8 | "github.com/bnema/dumber/internal/domain/entity" | 8 | "github.com/bnema/dumber/internal/domain/entity" | ||
| 9 | "github.com/bnema/dumber/internal/logging" | 9 | "github.com/bnema/dumber/internal/logging" | ||
| 10 | - | "github.com/jwijenbergh/puregotk/v4/gdk" | 10 | + | "github.com/bnema/puregotk/v4/gdk" |
| 11 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 11 | + | "github.com/bnema/puregotk/v4/gtk" |
| 12 | ) | 12 | ) | ||
| 13 | 13 | ||||
| 14 | // Manager handles theme state and CSS application. | 14 | // Manager handles theme state and CSS application. | ||
M internal/ui/window/main_window.go +1 -1
| @@ -6,7 +6,7 @@ import ( | |||
| 6 | 6 | ||
| 7 | 7 | "github.com/bnema/dumber/internal/logging" | |
| 8 | 8 | "github.com/bnema/dumber/internal/ui/component" | |
| 9 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | |
| 9 | + | "github.com/bnema/puregotk/v4/gtk" | |
| 10 | 10 | "github.com/rs/zerolog" | |
| 11 | 11 | ) | |
| 12 | 12 | ||
| @@ -6,7 +6,7 @@ import ( | |||||
| 6 | 6 | ||||
| 7 | "github.com/bnema/dumber/internal/logging" | 7 | "github.com/bnema/dumber/internal/logging" | ||
| 8 | "github.com/bnema/dumber/internal/ui/component" | 8 | "github.com/bnema/dumber/internal/ui/component" | ||
| 9 | - | "github.com/jwijenbergh/puregotk/v4/gtk" | 9 | + | "github.com/bnema/puregotk/v4/gtk" |
| 10 | "github.com/rs/zerolog" | 10 | "github.com/rs/zerolog" | ||
| 11 | ) | 11 | ) | ||
| 12 | 12 | ||||