parent
0a490b0e03
commit
80baae355a
5 changed files with 50 additions and 3 deletions
|
|
@ -28,6 +28,8 @@
|
|||
<string></string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>A program running within cmux would like to use your microphone.</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>A program running within cmux would like to use your camera.</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
<key>NSServices</key>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,23 @@
|
|||
"sourceLanguage": "en",
|
||||
"version": "1.0",
|
||||
"strings": {
|
||||
"NSCameraUsageDescription": {
|
||||
"extractionState": "manual",
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "A program running within cmux would like to use your camera."
|
||||
}
|
||||
},
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "cmux 内で実行中のプログラムがカメラの使用を求めています。"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"NSMicrophoneUsageDescription": {
|
||||
"extractionState": "manual",
|
||||
"localizations": {
|
||||
|
|
|
|||
|
|
@ -1533,6 +1533,7 @@ final class BrowserPanel: Panel, ObservableObject {
|
|||
private static func makeWebView() -> CmuxWebView {
|
||||
let config = WKWebViewConfiguration()
|
||||
config.processPool = BrowserPanel.sharedProcessPool
|
||||
config.mediaTypesRequiringUserActionForPlayback = []
|
||||
// Ensure browser cookies/storage persist across navigations and launches.
|
||||
// This reduces repeated consent/bot-challenge flows on sites like Google.
|
||||
config.websiteDataStore = .default()
|
||||
|
|
@ -3652,6 +3653,16 @@ private class BrowserUIDelegate: NSObject, WKUIDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
func webView(
|
||||
_ webView: WKWebView,
|
||||
requestMediaCapturePermissionFor origin: WKSecurityOrigin,
|
||||
initiatedByFrame frame: WKFrameInfo,
|
||||
type: WKMediaCaptureType,
|
||||
decisionHandler: @escaping (WKPermissionDecision) -> Void
|
||||
) {
|
||||
decisionHandler(.prompt)
|
||||
}
|
||||
|
||||
func webView(
|
||||
_ webView: WKWebView,
|
||||
runJavaScriptAlertPanelWithMessage message: String,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
<true/>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.device.camera</key>
|
||||
<true/>
|
||||
<key>com.apple.security.device.audio-input</key>
|
||||
<true/>
|
||||
<key>com.apple.security.automation.apple-events</key>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Regression test: cmux advertises and allows microphone access."""
|
||||
"""Regression test: cmux advertises media-capture access metadata."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
|
|
@ -36,6 +36,7 @@ def main() -> int:
|
|||
entitlements = load_plist(repo_root / "cmux.entitlements", failures)
|
||||
|
||||
mic_usage = info.get("NSMicrophoneUsageDescription")
|
||||
camera_usage = info.get("NSCameraUsageDescription")
|
||||
if not isinstance(mic_usage, str) or not mic_usage.strip():
|
||||
failures.append(
|
||||
"Resources/Info.plist must define a non-empty NSMicrophoneUsageDescription"
|
||||
|
|
@ -50,13 +51,27 @@ def main() -> int:
|
|||
"cmux.entitlements must set com.apple.security.device.audio-input to true"
|
||||
)
|
||||
|
||||
if not isinstance(camera_usage, str) or not camera_usage.strip():
|
||||
failures.append(
|
||||
"Resources/Info.plist must define a non-empty NSCameraUsageDescription"
|
||||
)
|
||||
elif camera_usage.strip() != "A program running within cmux would like to use your camera.":
|
||||
failures.append(
|
||||
"Resources/Info.plist NSCameraUsageDescription should match the Ghostty-style wording"
|
||||
)
|
||||
|
||||
if entitlements.get("com.apple.security.device.camera") is not True:
|
||||
failures.append(
|
||||
"cmux.entitlements must set com.apple.security.device.camera to true"
|
||||
)
|
||||
|
||||
if failures:
|
||||
print("FAIL: microphone access metadata regression(s) detected")
|
||||
print("FAIL: media-capture metadata regression(s) detected")
|
||||
for failure in failures:
|
||||
print(f"- {failure}")
|
||||
return 1
|
||||
|
||||
print("PASS: microphone usage description and entitlement are present")
|
||||
print("PASS: microphone/camera usage descriptions and entitlements are present")
|
||||
return 0
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue