detached 2b3891d

feat(permission): wire WebsiteDataAccessPermissionRequest through WebKit layer

commit
2b3891ddef341def12196aaf0890a9b7fffcae14
author
brice · · 2026-03-17 19:13 UTC
committer
brice · · 2026-03-17 19:16 UTC
parent
fcdcea4
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
2 files · +63 -6
M internal/infrastructure/webkit/webview.go +58 -6
@@ -998,11 +998,14 @@ func (wv *WebView) connectPermissionRequestSignal() {
998998 }
999999
10001000 // Determine permission types from the request
1001- permTypes := wv.determinePermissionTypes(ctx, requestPtr)
1001+ permTypes, originOverride := wv.determinePermissionTypes(ctx, requestPtr)
10021002 if len(permTypes) == 0 {
10031003 wv.logger.Warn().Msg("permission request with unknown type, denying")
10041004 return false
10051005 }
1006+ if originOverride != "" {
1007+ origin = originOverride
1008+ }
10061009
10071010 // Ref the request object to prevent use-after-free
10081011 // The request may outlive the signal handler if we show a dialog
@@ -1048,13 +1051,13 @@ func (wv *WebView) connectPermissionRequestSignal() {
10481051 // We use GObject property accessors for audio/video request flags. Display detection
10491052 // uses the dedicated WebKit API because this WebKit build does not expose an
10501053 // "is-for-display-device" GObject property.
1051-func (wv *WebView) determinePermissionTypes(ctx context.Context, requestPtr uintptr) []string {
1054+func (wv *WebView) determinePermissionTypes(ctx context.Context, requestPtr uintptr) (types []string, originOverride string) {
10521055 requestKind := detectPermissionRequestKind(ctx, requestPtr)
10531056 switch requestKind {
10541057 case permissionRequestKindUserMedia:
10551058 userMediaReq := webkit.UserMediaPermissionRequestNewFromInternalPtr(requestPtr)
10561059 if userMediaReq == nil {
1057- return nil
1060+ return nil, ""
10581061 }
10591062
10601063 // Use GObject property accessors — more reliable than the C function wrappers
@@ -1069,9 +1072,34 @@ func (wv *WebView) determinePermissionTypes(ctx context.Context, requestPtr uint
10691072 Bool("is_display", isDisplay).
10701073 Msg("permission request type detection")
10711074
1072- return classifyPermissionRequestTypes(ctx, requestKind, isAudio, isVideo, isDisplay)
1075+ return classifyPermissionRequestTypes(ctx, requestKind, isAudio, isVideo, isDisplay), ""
10731076 case permissionRequestKindDeviceInfo:
1074- return classifyPermissionRequestTypes(ctx, requestKind, false, false, false)
1077+ return classifyPermissionRequestTypes(ctx, requestKind, false, false, false), ""
1078+ case permissionRequestKindWebsiteDataAccess:
1079+ wdaReq := webkit.WebsiteDataAccessPermissionRequestNewFromInternalPtr(requestPtr)
1080+ if wdaReq == nil {
1081+ return nil, ""
1082+ }
1083+ currentDomain := wdaReq.GetCurrentDomain()
1084+ requestingDomain := wdaReq.GetRequestingDomain()
1085+ wv.logger.Debug().
1086+ Str("current_domain", currentDomain).
1087+ Str("requesting_domain", requestingDomain).
1088+ 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+ }
1101+ }
1102+ return classifyPermissionRequestTypes(ctx, requestKind, false, false, false), override
10751103 default:
10761104 if requestPtr != 0 {
10771105 typeName := permissionRequestTypeName(ctx, requestPtr)
@@ -1083,7 +1111,7 @@ func (wv *WebView) determinePermissionTypes(ctx context.Context, requestPtr uint
10831111 }
10841112 // Unknown permission type - could be clipboard, notifications, geolocation, etc.
10851113 // For now, return empty to trigger denial. Future phases will add these types.
1086- return nil
1114+ return nil, ""
10871115 }
10881116 }
10891117
@@ -1093,6 +1121,7 @@ const (
10931121 permissionRequestKindUnknown permissionRequestKind = iota
10941122 permissionRequestKindUserMedia
10951123 permissionRequestKindDeviceInfo
1124+ permissionRequestKindWebsiteDataAccess
10961125 )
10971126
10981127 func detectPermissionRequestKind(ctx context.Context, requestPtr uintptr) permissionRequestKind {
@@ -1106,6 +1135,11 @@ func detectPermissionRequestKind(ctx context.Context, requestPtr uintptr) permis
11061135 return permissionRequestKindDeviceInfo
11071136 }
11081137 }
1138+ if gtype, ok := safeGLibType(ctx, webkit.WebsiteDataAccessPermissionRequestGLibType); ok {
1139+ if isPermissionRequestType(ctx, requestPtr, gtype) {
1140+ return permissionRequestKindWebsiteDataAccess
1141+ }
1142+ }
11091143 return permissionRequestKindUnknown
11101144 }
11111145
@@ -1140,6 +1174,8 @@ func classifyPermissionRequestTypes(
11401174 return classifyUserMediaPermissionTypes(ctx, isAudio, isVideo, isDisplay)
11411175 case permissionRequestKindDeviceInfo:
11421176 return []string{"device_info"}
1177+ case permissionRequestKindWebsiteDataAccess:
1178+ return []string{"website_data_access"}
11431179 default:
11441180 return nil
11451181 }
@@ -1190,6 +1226,14 @@ func (wv *WebView) allowPermissionRequest(requestPtr uintptr) {
11901226 return
11911227 }
11921228
1229+ // Try WebsiteDataAccessPermissionRequest
1230+ wdaReq := webkit.WebsiteDataAccessPermissionRequestNewFromInternalPtr(requestPtr)
1231+ if wdaReq != nil {
1232+ wdaReq.Allow()
1233+ wv.logger.Debug().Msg("website data access permission request allowed")
1234+ return
1235+ }
1236+
11931237 wv.logger.Warn().Uint64("request_ptr", uint64(requestPtr)).Msg("permission request: unknown type, cannot allow")
11941238 }
11951239
@@ -1211,6 +1255,14 @@ func (wv *WebView) denyPermissionRequest(requestPtr uintptr) {
12111255 return
12121256 }
12131257
1258+ // Try WebsiteDataAccessPermissionRequest
1259+ wdaReq := webkit.WebsiteDataAccessPermissionRequestNewFromInternalPtr(requestPtr)
1260+ if wdaReq != nil {
1261+ wdaReq.Deny()
1262+ wv.logger.Debug().Msg("website data access permission request denied")
1263+ return
1264+ }
1265+
12141266 wv.logger.Warn().Uint64("request_ptr", uint64(requestPtr)).Msg("permission request: unknown type, cannot deny")
12151267 }
12161268
@@ -998,11 +998,14 @@ func (wv *WebView) connectPermissionRequestSignal() {
998 }998 }
999 999
1000 // Determine permission types from the request1000 // Determine permission types from the request
1001- permTypes := wv.determinePermissionTypes(ctx, requestPtr)1001+ permTypes, originOverride := wv.determinePermissionTypes(ctx, requestPtr)
1002 if len(permTypes) == 0 {1002 if len(permTypes) == 0 {
1003 wv.logger.Warn().Msg("permission request with unknown type, denying")1003 wv.logger.Warn().Msg("permission request with unknown type, denying")
1004 return false1004 return false
1005 }1005 }
1006+ if originOverride != "" {
1007+ origin = originOverride
1008+ }
1006 1009
1007 // Ref the request object to prevent use-after-free1010 // Ref the request object to prevent use-after-free
1008 // The request may outlive the signal handler if we show a dialog1011 // The request may outlive the signal handler if we show a dialog
@@ -1048,13 +1051,13 @@ func (wv *WebView) connectPermissionRequestSignal() {
1048 // We use GObject property accessors for audio/video request flags. Display detection1051 // We use GObject property accessors for audio/video request flags. Display detection
1049 // uses the dedicated WebKit API because this WebKit build does not expose an1052 // uses the dedicated WebKit API because this WebKit build does not expose an
1050 // "is-for-display-device" GObject property.1053 // "is-for-display-device" GObject property.
1051-func (wv *WebView) determinePermissionTypes(ctx context.Context, requestPtr uintptr) []string {1054+func (wv *WebView) determinePermissionTypes(ctx context.Context, requestPtr uintptr) (types []string, originOverride string) {
1052 requestKind := detectPermissionRequestKind(ctx, requestPtr)1055 requestKind := detectPermissionRequestKind(ctx, requestPtr)
1053 switch requestKind {1056 switch requestKind {
1054 case permissionRequestKindUserMedia:1057 case permissionRequestKindUserMedia:
1055 userMediaReq := webkit.UserMediaPermissionRequestNewFromInternalPtr(requestPtr)1058 userMediaReq := webkit.UserMediaPermissionRequestNewFromInternalPtr(requestPtr)
1056 if userMediaReq == nil {1059 if userMediaReq == nil {
1057- return nil1060+ return nil, ""
1058 }1061 }
1059 1062
1060 // Use GObject property accessors — more reliable than the C function wrappers1063 // Use GObject property accessors — more reliable than the C function wrappers
@@ -1069,9 +1072,34 @@ func (wv *WebView) determinePermissionTypes(ctx context.Context, requestPtr uint
1069 Bool("is_display", isDisplay).1072 Bool("is_display", isDisplay).
1070 Msg("permission request type detection")1073 Msg("permission request type detection")
1071 1074
1072- return classifyPermissionRequestTypes(ctx, requestKind, isAudio, isVideo, isDisplay)1075+ return classifyPermissionRequestTypes(ctx, requestKind, isAudio, isVideo, isDisplay), ""
1073 case permissionRequestKindDeviceInfo:1076 case permissionRequestKindDeviceInfo:
1074- return classifyPermissionRequestTypes(ctx, requestKind, false, false, false)1077+ return classifyPermissionRequestTypes(ctx, requestKind, false, false, false), ""
1078+ case permissionRequestKindWebsiteDataAccess:
1079+ wdaReq := webkit.WebsiteDataAccessPermissionRequestNewFromInternalPtr(requestPtr)
1080+ if wdaReq == nil {
1081+ return nil, ""
1082+ }
1083+ currentDomain := wdaReq.GetCurrentDomain()
1084+ requestingDomain := wdaReq.GetRequestingDomain()
1085+ wv.logger.Debug().
1086+ Str("current_domain", currentDomain).
1087+ Str("requesting_domain", requestingDomain).
1088+ 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+ }
1101+ }
1102+ return classifyPermissionRequestTypes(ctx, requestKind, false, false, false), override
1075 default:1103 default:
1076 if requestPtr != 0 {1104 if requestPtr != 0 {
1077 typeName := permissionRequestTypeName(ctx, requestPtr)1105 typeName := permissionRequestTypeName(ctx, requestPtr)
@@ -1083,7 +1111,7 @@ func (wv *WebView) determinePermissionTypes(ctx context.Context, requestPtr uint
1083 }1111 }
1084 // Unknown permission type - could be clipboard, notifications, geolocation, etc.1112 // Unknown permission type - could be clipboard, notifications, geolocation, etc.
1085 // For now, return empty to trigger denial. Future phases will add these types.1113 // For now, return empty to trigger denial. Future phases will add these types.
1086- return nil1114+ return nil, ""
1087 }1115 }
1088 }1116 }
1089 1117
@@ -1093,6 +1121,7 @@ const (
1093 permissionRequestKindUnknown permissionRequestKind = iota1121 permissionRequestKindUnknown permissionRequestKind = iota
1094 permissionRequestKindUserMedia1122 permissionRequestKindUserMedia
1095 permissionRequestKindDeviceInfo1123 permissionRequestKindDeviceInfo
1124+ permissionRequestKindWebsiteDataAccess
1096 )1125 )
1097 1126
1098 func detectPermissionRequestKind(ctx context.Context, requestPtr uintptr) permissionRequestKind {1127 func detectPermissionRequestKind(ctx context.Context, requestPtr uintptr) permissionRequestKind {
@@ -1106,6 +1135,11 @@ func detectPermissionRequestKind(ctx context.Context, requestPtr uintptr) permis
1106 return permissionRequestKindDeviceInfo1135 return permissionRequestKindDeviceInfo
1107 }1136 }
1108 }1137 }
1138+ if gtype, ok := safeGLibType(ctx, webkit.WebsiteDataAccessPermissionRequestGLibType); ok {
1139+ if isPermissionRequestType(ctx, requestPtr, gtype) {
1140+ return permissionRequestKindWebsiteDataAccess
1141+ }
1142+ }
1109 return permissionRequestKindUnknown1143 return permissionRequestKindUnknown
1110 }1144 }
1111 1145
@@ -1140,6 +1174,8 @@ func classifyPermissionRequestTypes(
1140 return classifyUserMediaPermissionTypes(ctx, isAudio, isVideo, isDisplay)1174 return classifyUserMediaPermissionTypes(ctx, isAudio, isVideo, isDisplay)
1141 case permissionRequestKindDeviceInfo:1175 case permissionRequestKindDeviceInfo:
1142 return []string{"device_info"}1176 return []string{"device_info"}
1177+ case permissionRequestKindWebsiteDataAccess:
1178+ return []string{"website_data_access"}
1143 default:1179 default:
1144 return nil1180 return nil
1145 }1181 }
@@ -1190,6 +1226,14 @@ func (wv *WebView) allowPermissionRequest(requestPtr uintptr) {
1190 return1226 return
1191 }1227 }
1192 1228
1229+ // Try WebsiteDataAccessPermissionRequest
1230+ wdaReq := webkit.WebsiteDataAccessPermissionRequestNewFromInternalPtr(requestPtr)
1231+ if wdaReq != nil {
1232+ wdaReq.Allow()
1233+ wv.logger.Debug().Msg("website data access permission request allowed")
1234+ return
1235+ }
1236+
1193 wv.logger.Warn().Uint64("request_ptr", uint64(requestPtr)).Msg("permission request: unknown type, cannot allow")1237 wv.logger.Warn().Uint64("request_ptr", uint64(requestPtr)).Msg("permission request: unknown type, cannot allow")
1194 }1238 }
1195 1239
@@ -1211,6 +1255,14 @@ func (wv *WebView) denyPermissionRequest(requestPtr uintptr) {
1211 return1255 return
1212 }1256 }
1213 1257
1258+ // Try WebsiteDataAccessPermissionRequest
1259+ wdaReq := webkit.WebsiteDataAccessPermissionRequestNewFromInternalPtr(requestPtr)
1260+ if wdaReq != nil {
1261+ wdaReq.Deny()
1262+ wv.logger.Debug().Msg("website data access permission request denied")
1263+ return
1264+ }
1265+
1214 wv.logger.Warn().Uint64("request_ptr", uint64(requestPtr)).Msg("permission request: unknown type, cannot deny")1266 wv.logger.Warn().Uint64("request_ptr", uint64(requestPtr)).Msg("permission request: unknown type, cannot deny")
1215 }1267 }
1216 1268
M internal/infrastructure/webkit/webview_permission_types_test.go +5 -0
@@ -87,6 +87,11 @@ func TestClassifyPermissionRequestTypes(t *testing.T) {
8787 kind: permissionRequestKindUnknown,
8888 expected: nil,
8989 },
90+ {
91+ name: "website data access request",
92+ kind: permissionRequestKindWebsiteDataAccess,
93+ expected: []string{"website_data_access"},
94+ },
9095 }
9196
9297 for _, tt := range tests {
@@ -87,6 +87,11 @@ func TestClassifyPermissionRequestTypes(t *testing.T) {
87 kind: permissionRequestKindUnknown,87 kind: permissionRequestKindUnknown,
88 expected: nil,88 expected: nil,
89 },89 },
90+ {
91+ name: "website data access request",
92+ kind: permissionRequestKindWebsiteDataAccess,
93+ expected: []string{"website_data_access"},
94+ },
90 }95 }
91 96
92 for _, tt := range tests {97 for _, tt := range tests {

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close