feat(captureallow): allow xdg-desktop-portal-gnome instead of the wlr portal
- commit
- a5764bdc8540ac73589a21d8649ca9055415f2d4
- author
- brice · · 2026-10-14 20:37 UTC
- committer
- brice · · 2026-10-14 21:39 UTC
- parent
- c050b9a
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
6 files · +14 -12
M examples/capture-allow +4 -4
| @@ -5,8 +5,8 @@ | |||
| 5 | 5 | # | |
| 6 | 6 | # /usr/bin/grim | |
| 7 | 7 | # /usr/bin/nefercap | |
| 8 | - | # /usr/lib/xdg-desktop-portal-wlr | |
| 9 | - | # /usr/libexec/xdg-desktop-portal-wlr | |
| 8 | + | # /usr/lib/xdg-desktop-portal-gnome | |
| 9 | + | # /usr/libexec/xdg-desktop-portal-gnome | |
| 10 | 10 | # | |
| 11 | 11 | # To allow a tool installed elsewhere, copy this file to | |
| 12 | 12 | # /etc/neferwl/capture-allow as root and add its path. The file REPLACES the | |
| @@ -27,5 +27,5 @@ | |||
| 27 | 27 | # would then be allowed to capture. | |
| 28 | 28 | /usr/bin/grim | |
| 29 | 29 | /usr/bin/nefercap | |
| 30 | - | /usr/lib/xdg-desktop-portal-wlr | |
| 31 | - | /usr/libexec/xdg-desktop-portal-wlr | |
| 30 | + | /usr/lib/xdg-desktop-portal-gnome | |
| 31 | + | /usr/libexec/xdg-desktop-portal-gnome | |
| @@ -5,8 +5,8 @@ | |||||
| 5 | # | 5 | # | ||
| 6 | # /usr/bin/grim | 6 | # /usr/bin/grim | ||
| 7 | # /usr/bin/nefercap | 7 | # /usr/bin/nefercap | ||
| 8 | - | # /usr/lib/xdg-desktop-portal-wlr | 8 | + | # /usr/lib/xdg-desktop-portal-gnome |
| 9 | - | # /usr/libexec/xdg-desktop-portal-wlr | 9 | + | # /usr/libexec/xdg-desktop-portal-gnome |
| 10 | # | 10 | # | ||
| 11 | # To allow a tool installed elsewhere, copy this file to | 11 | # To allow a tool installed elsewhere, copy this file to | ||
| 12 | # /etc/neferwl/capture-allow as root and add its path. The file REPLACES the | 12 | # /etc/neferwl/capture-allow as root and add its path. The file REPLACES the | ||
| @@ -27,5 +27,5 @@ | |||||
| 27 | # would then be allowed to capture. | 27 | # would then be allowed to capture. | ||
| 28 | /usr/bin/grim | 28 | /usr/bin/grim | ||
| 29 | /usr/bin/nefercap | 29 | /usr/bin/nefercap | ||
| 30 | - | /usr/lib/xdg-desktop-portal-wlr | 30 | + | /usr/lib/xdg-desktop-portal-gnome |
| 31 | - | /usr/libexec/xdg-desktop-portal-wlr | 31 | + | /usr/libexec/xdg-desktop-portal-gnome |
M internal/adapters/captureallow/policy.go +2 -2
| @@ -45,8 +45,8 @@ func Builtin() *Policy { | |||
| 45 | 45 | builtin := [...]string{ | |
| 46 | 46 | "/usr/bin/grim", | |
| 47 | 47 | "/usr/bin/nefercap", | |
| 48 | - | "/usr/lib/xdg-desktop-portal-wlr", | |
| 49 | - | "/usr/libexec/xdg-desktop-portal-wlr", | |
| 48 | + | "/usr/lib/xdg-desktop-portal-gnome", | |
| 49 | + | "/usr/libexec/xdg-desktop-portal-gnome", | |
| 50 | 50 | } | |
| 51 | 51 | p := &Policy{mode: ModeList, exes: make(map[string]struct{}, len(builtin))} | |
| 52 | 52 | for _, e := range builtin { | |
| @@ -45,8 +45,8 @@ func Builtin() *Policy { | |||||
| 45 | builtin := [...]string{ | 45 | builtin := [...]string{ | ||
| 46 | "/usr/bin/grim", | 46 | "/usr/bin/grim", | ||
| 47 | "/usr/bin/nefercap", | 47 | "/usr/bin/nefercap", | ||
| 48 | - | "/usr/lib/xdg-desktop-portal-wlr", | 48 | + | "/usr/lib/xdg-desktop-portal-gnome", |
| 49 | - | "/usr/libexec/xdg-desktop-portal-wlr", | 49 | + | "/usr/libexec/xdg-desktop-portal-gnome", |
| 50 | } | 50 | } | ||
| 51 | p := &Policy{mode: ModeList, exes: make(map[string]struct{}, len(builtin))} | 51 | p := &Policy{mode: ModeList, exes: make(map[string]struct{}, len(builtin))} | ||
| 52 | for _, e := range builtin { | 52 | for _, e := range builtin { | ||
M internal/adapters/captureallow/policy_test.go +3 -3
| @@ -16,8 +16,8 @@ func TestParse(t *testing.T) { | |||
| 16 | 16 | errLine int | |
| 17 | 17 | wantFail bool | |
| 18 | 18 | }{ | |
| 19 | - | {name: "paths comments blanks", in: "# header\n\n/usr/bin/grim\n /usr/lib/xdg-desktop-portal-wlr \n\t# indented comment\n/opt/a#b\n", | |
| 20 | - | mode: ModeList, allowed: []string{"/usr/bin/grim", "/usr/lib/xdg-desktop-portal-wlr", "/opt/a#b"}, refused: []string{"/usr/bin/grim2", "/usr/bin", "grim", ""}}, | |
| 19 | + | {name: "paths comments blanks", in: "# header\n\n/usr/bin/grim\n /usr/lib/xdg-desktop-portal-gnome \n\t# indented comment\n/opt/a#b\n", | |
| 20 | + | mode: ModeList, allowed: []string{"/usr/bin/grim", "/usr/lib/xdg-desktop-portal-gnome", "/opt/a#b"}, refused: []string{"/usr/bin/grim2", "/usr/bin", "grim", ""}}, | |
| 21 | 21 | {name: "cleaned", in: "/usr//bin/../bin/grim\n", mode: ModeList, allowed: []string{"/usr/bin/grim"}}, | |
| 22 | 22 | {name: "no trailing newline", in: "/a/b", mode: ModeList, allowed: []string{"/a/b"}}, | |
| 23 | 23 | {name: "empty file allows nothing", in: "", mode: ModeList, refused: []string{"/usr/bin/grim"}}, | |
| @@ -75,7 +75,7 @@ func TestParseTooLarge(t *testing.T) { | |||
| 75 | 75 | ||
| 76 | 76 | func TestBuiltin(t *testing.T) { | |
| 77 | 77 | p := Builtin() | |
| 78 | - | want := []string{"/usr/bin/grim", "/usr/bin/nefercap", "/usr/lib/xdg-desktop-portal-wlr", "/usr/libexec/xdg-desktop-portal-wlr"} | |
| 78 | + | want := []string{"/usr/bin/grim", "/usr/bin/nefercap", "/usr/lib/xdg-desktop-portal-gnome", "/usr/libexec/xdg-desktop-portal-gnome"} | |
| 79 | 79 | if p.Mode() != ModeList || p.Len() != len(want) { | |
| 80 | 80 | t.Fatalf("mode %v, len %d", p.Mode(), p.Len()) | |
| 81 | 81 | } | |
| @@ -16,8 +16,8 @@ func TestParse(t *testing.T) { | |||||
| 16 | errLine int | 16 | errLine int | ||
| 17 | wantFail bool | 17 | wantFail bool | ||
| 18 | }{ | 18 | }{ | ||
| 19 | - | {name: "paths comments blanks", in: "# header\n\n/usr/bin/grim\n /usr/lib/xdg-desktop-portal-wlr \n\t# indented comment\n/opt/a#b\n", | 19 | + | {name: "paths comments blanks", in: "# header\n\n/usr/bin/grim\n /usr/lib/xdg-desktop-portal-gnome \n\t# indented comment\n/opt/a#b\n", |
| 20 | - | mode: ModeList, allowed: []string{"/usr/bin/grim", "/usr/lib/xdg-desktop-portal-wlr", "/opt/a#b"}, refused: []string{"/usr/bin/grim2", "/usr/bin", "grim", ""}}, | 20 | + | mode: ModeList, allowed: []string{"/usr/bin/grim", "/usr/lib/xdg-desktop-portal-gnome", "/opt/a#b"}, refused: []string{"/usr/bin/grim2", "/usr/bin", "grim", ""}}, |
| 21 | {name: "cleaned", in: "/usr//bin/../bin/grim\n", mode: ModeList, allowed: []string{"/usr/bin/grim"}}, | 21 | {name: "cleaned", in: "/usr//bin/../bin/grim\n", mode: ModeList, allowed: []string{"/usr/bin/grim"}}, | ||
| 22 | {name: "no trailing newline", in: "/a/b", mode: ModeList, allowed: []string{"/a/b"}}, | 22 | {name: "no trailing newline", in: "/a/b", mode: ModeList, allowed: []string{"/a/b"}}, | ||
| 23 | {name: "empty file allows nothing", in: "", mode: ModeList, refused: []string{"/usr/bin/grim"}}, | 23 | {name: "empty file allows nothing", in: "", mode: ModeList, refused: []string{"/usr/bin/grim"}}, | ||
| @@ -75,7 +75,7 @@ func TestParseTooLarge(t *testing.T) { | |||||
| 75 | 75 | ||||
| 76 | func TestBuiltin(t *testing.T) { | 76 | func TestBuiltin(t *testing.T) { | ||
| 77 | p := Builtin() | 77 | p := Builtin() | ||
| 78 | - | want := []string{"/usr/bin/grim", "/usr/bin/nefercap", "/usr/lib/xdg-desktop-portal-wlr", "/usr/libexec/xdg-desktop-portal-wlr"} | 78 | + | want := []string{"/usr/bin/grim", "/usr/bin/nefercap", "/usr/lib/xdg-desktop-portal-gnome", "/usr/libexec/xdg-desktop-portal-gnome"} |
| 79 | if p.Mode() != ModeList || p.Len() != len(want) { | 79 | if p.Mode() != ModeList || p.Len() != len(want) { | ||
| 80 | t.Fatalf("mode %v, len %d", p.Mode(), p.Len()) | 80 | t.Fatalf("mode %v, len %d", p.Mode(), p.Len()) | ||
| 81 | } | 81 | } | ||
M internal/adapters/wayland/captureauth.go +3 -1
| @@ -14,7 +14,9 @@ import ( | |||
| 14 | 14 | // capture sessions and frames, whatever their source (output, output region | |
| 15 | 15 | // or workspace), and the attach of a layer surface to a capture exclusion. A | |
| 16 | 16 | // refused client gets the failure its protocol defines (failed, or stopped | |
| 17 | - | // for a session) and nothing is captured or flashed. In order: | |
| 17 | + | // for a session) and nothing is captured or flashed. The same executable | |
| 18 | + | // allowlist also gates the D-Bus screencast callers (adapters/screencast). In | |
| 19 | + | // order: | |
| 18 | 20 | // | |
| 19 | 21 | // 1. While the session is protected (ext-session-lock) no client may | |
| 20 | 22 | // capture, so nothing of the locked session reaches a buffer. | |
| @@ -14,7 +14,9 @@ import ( | |||||
| 14 | // capture sessions and frames, whatever their source (output, output region | 14 | // capture sessions and frames, whatever their source (output, output region | ||
| 15 | // or workspace), and the attach of a layer surface to a capture exclusion. A | 15 | // or workspace), and the attach of a layer surface to a capture exclusion. A | ||
| 16 | // refused client gets the failure its protocol defines (failed, or stopped | 16 | // refused client gets the failure its protocol defines (failed, or stopped | ||
| 17 | - | // for a session) and nothing is captured or flashed. In order: | 17 | + | // for a session) and nothing is captured or flashed. The same executable |
| 18 | + | // allowlist also gates the D-Bus screencast callers (adapters/screencast). In | |||
| 19 | + | // order: | |||
| 18 | // | 20 | // | ||
| 19 | // 1. While the session is protected (ext-session-lock) no client may | 21 | // 1. While the session is protected (ext-session-lock) no client may | ||
| 20 | // capture, so nothing of the locked session reaches a buffer. | 22 | // capture, so nothing of the locked session reaches a buffer. | ||
M internal/adapters/wayland/extforeigntoplevel.go +1 -1
| @@ -10,7 +10,7 @@ import ( | |||
| 10 | 10 | ) | |
| 11 | 11 | ||
| 12 | 12 | // ext-foreign-toplevel-list lists mapped toplevels, read-only: title, app_id | |
| 13 | - | // and a stable identifier. xdg-desktop-portal-wlr lists the windows it can | |
| 13 | + | // and a stable identifier. Screen-sharing portals list the windows they can | |
| 14 | 14 | // share with it, and ext_foreign_toplevel_image_capture_source_manager_v1 | |
| 15 | 15 | // takes its handles (window capture, imagecopy.go). It follows the same | |
| 16 | 16 | // window state and session-protection rules as wlr-foreign-toplevel. | |
| @@ -10,7 +10,7 @@ import ( | |||||
| 10 | ) | 10 | ) | ||
| 11 | 11 | ||||
| 12 | // ext-foreign-toplevel-list lists mapped toplevels, read-only: title, app_id | 12 | // ext-foreign-toplevel-list lists mapped toplevels, read-only: title, app_id | ||
| 13 | - | // and a stable identifier. xdg-desktop-portal-wlr lists the windows it can | 13 | + | // and a stable identifier. Screen-sharing portals list the windows they can |
| 14 | // share with it, and ext_foreign_toplevel_image_capture_source_manager_v1 | 14 | // share with it, and ext_foreign_toplevel_image_capture_source_manager_v1 | ||
| 15 | // takes its handles (window capture, imagecopy.go). It follows the same | 15 | // takes its handles (window capture, imagecopy.go). It follows the same | ||
| 16 | // window state and session-protection rules as wlr-foreign-toplevel. | 16 | // window state and session-protection rules as wlr-foreign-toplevel. | ||
M internal/adapters/wayland/imagecopy.go +1 -1
| @@ -587,7 +587,7 @@ type captureExtFrame struct { | |||
| 587 | 587 | // A frame whose target is briefly unavailable (not active yet, rendered off | |
| 588 | 588 | // screen by another session, its indicator or exclusion not on screen yet, | |
| 589 | 589 | // a renderer slot busy) is tried again rather than failed: failed(unknown) | |
| 590 | - | // ends the whole screencast in clients such as xdg-desktop-portal-wlr. Only | |
| 590 | + | // ends the whole screencast in screen-sharing clients. Only | |
| 591 | 591 | // a stopped session, a refused client or a wrong buffer fail at once. | |
| 592 | 592 | const ( | |
| 593 | 593 | captureRetryEvery = 16 * time.Millisecond | |
| @@ -587,7 +587,7 @@ type captureExtFrame struct { | |||||
| 587 | // A frame whose target is briefly unavailable (not active yet, rendered off | 587 | // A frame whose target is briefly unavailable (not active yet, rendered off | ||
| 588 | // screen by another session, its indicator or exclusion not on screen yet, | 588 | // screen by another session, its indicator or exclusion not on screen yet, | ||
| 589 | // a renderer slot busy) is tried again rather than failed: failed(unknown) | 589 | // a renderer slot busy) is tried again rather than failed: failed(unknown) | ||
| 590 | - | // ends the whole screencast in clients such as xdg-desktop-portal-wlr. Only | 590 | + | // ends the whole screencast in screen-sharing clients. Only |
| 591 | // a stopped session, a refused client or a wrong buffer fail at once. | 591 | // a stopped session, a refused client or a wrong buffer fail at once. | ||
| 592 | const ( | 592 | const ( | ||
| 593 | captureRetryEvery = 16 * time.Millisecond | 593 | captureRetryEvery = 16 * time.Millisecond | ||