Merge remote-tracking branch 'origin/main'
This commit is contained in:
@@ -67,12 +67,27 @@ enum PermissionManager {
|
|||||||
results[cap] = ScreenRecordingProbe.isAuthorized()
|
results[cap] = ScreenRecordingProbe.isAuthorized()
|
||||||
|
|
||||||
case .microphone:
|
case .microphone:
|
||||||
let granted = AVCaptureDevice.authorizationStatus(for: .audio) == .authorized
|
let status = AVCaptureDevice.authorizationStatus(for: .audio)
|
||||||
if interactive, !granted {
|
switch status {
|
||||||
let ok = await AVCaptureDevice.requestAccess(for: .audio)
|
case .authorized:
|
||||||
results[cap] = ok
|
results[cap] = true
|
||||||
} else {
|
|
||||||
results[cap] = granted
|
case .notDetermined:
|
||||||
|
if interactive {
|
||||||
|
let ok = await AVCaptureDevice.requestAccess(for: .audio)
|
||||||
|
results[cap] = ok
|
||||||
|
} else {
|
||||||
|
results[cap] = false
|
||||||
|
}
|
||||||
|
|
||||||
|
case .denied, .restricted:
|
||||||
|
results[cap] = false
|
||||||
|
if interactive {
|
||||||
|
MicrophonePermissionHelper.openSettings()
|
||||||
|
}
|
||||||
|
|
||||||
|
@unknown default:
|
||||||
|
results[cap] = false
|
||||||
}
|
}
|
||||||
|
|
||||||
case .speechRecognition:
|
case .speechRecognition:
|
||||||
@@ -150,6 +165,21 @@ enum NotificationPermissionHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum MicrophonePermissionHelper {
|
||||||
|
static func openSettings() {
|
||||||
|
let candidates = [
|
||||||
|
"x-apple.systempreferences:com.apple.preference.security?Privacy_Microphone",
|
||||||
|
"x-apple.systempreferences:com.apple.preference.security",
|
||||||
|
]
|
||||||
|
|
||||||
|
for candidate in candidates {
|
||||||
|
if let url = URL(string: candidate), NSWorkspace.shared.open(url) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum AppleScriptPermission {
|
enum AppleScriptPermission {
|
||||||
private static let logger = Logger(subsystem: "com.steipete.clawdis", category: "AppleScriptPermission")
|
private static let logger = Logger(subsystem: "com.steipete.clawdis", category: "AppleScriptPermission")
|
||||||
|
|
||||||
|
|||||||
@@ -388,11 +388,19 @@ final class WebChatWindowController: NSWindowController, WKNavigationDelegate, N
|
|||||||
}
|
}
|
||||||
|
|
||||||
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
|
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
|
||||||
|
if Self.shouldIgnoreNavigationError(error) {
|
||||||
|
webChatLogger.debug("webchat navigation cancelled (provisional)")
|
||||||
|
return
|
||||||
|
}
|
||||||
webChatLogger.error("webchat navigation failed (provisional): \(error.localizedDescription, privacy: .public)")
|
webChatLogger.error("webchat navigation failed (provisional): \(error.localizedDescription, privacy: .public)")
|
||||||
self.showError(error.localizedDescription)
|
self.showError(error.localizedDescription)
|
||||||
}
|
}
|
||||||
|
|
||||||
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
|
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
|
||||||
|
if Self.shouldIgnoreNavigationError(error) {
|
||||||
|
webChatLogger.debug("webchat navigation cancelled")
|
||||||
|
return
|
||||||
|
}
|
||||||
webChatLogger.error("webchat navigation failed: \(error.localizedDescription, privacy: .public)")
|
webChatLogger.error("webchat navigation failed: \(error.localizedDescription, privacy: .public)")
|
||||||
self.showError(error.localizedDescription)
|
self.showError(error.localizedDescription)
|
||||||
}
|
}
|
||||||
@@ -483,6 +491,11 @@ final class WebChatWindowController: NSWindowController, WKNavigationDelegate, N
|
|||||||
if let url = Bundle.module.url(forResource: "WebChat", withExtension: nil) { return url }
|
if let url = Bundle.module.url(forResource: "WebChat", withExtension: nil) { return url }
|
||||||
throw NSError(domain: "WebChat", code: 10, userInfo: [NSLocalizedDescriptionKey: "WebChat assets missing"])
|
throw NSError(domain: "WebChat", code: 10, userInfo: [NSLocalizedDescriptionKey: "WebChat assets missing"])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static func shouldIgnoreNavigationError(_ error: Error) -> Bool {
|
||||||
|
let ns = error as NSError
|
||||||
|
return ns.domain == NSURLErrorDomain && ns.code == NSURLErrorCancelled
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension WebChatWindowController {
|
extension WebChatWindowController {
|
||||||
|
|||||||
@@ -51,10 +51,6 @@ cat > "$ENT_TMP_BASE" <<'PLIST'
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.security.hardened-runtime</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.cs.allow-jit</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.automation.apple-events</key>
|
<key>com.apple.security.automation.apple-events</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>com.apple.security.device.audio-input</key>
|
<key>com.apple.security.device.audio-input</key>
|
||||||
@@ -68,10 +64,6 @@ cat > "$ENT_TMP_APP_BASE" <<'PLIST'
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.security.hardened-runtime</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.cs.allow-jit</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.automation.apple-events</key>
|
<key>com.apple.security.automation.apple-events</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>com.apple.security.device.audio-input</key>
|
<key>com.apple.security.device.audio-input</key>
|
||||||
@@ -87,10 +79,6 @@ cat > "$ENT_TMP_APP" <<'PLIST'
|
|||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.developer.usernotifications.time-sensitive</key>
|
<key>com.apple.developer.usernotifications.time-sensitive</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>com.apple.security.hardened-runtime</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.cs.allow-jit</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.automation.apple-events</key>
|
<key>com.apple.security.automation.apple-events</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>com.apple.security.device.audio-input</key>
|
<key>com.apple.security.device.audio-input</key>
|
||||||
@@ -99,17 +87,14 @@ cat > "$ENT_TMP_APP" <<'PLIST'
|
|||||||
</plist>
|
</plist>
|
||||||
PLIST
|
PLIST
|
||||||
|
|
||||||
# The time-sensitive entitlement is restricted and needs to be present in a
|
# The time-sensitive entitlement is restricted and requires explicit enablement
|
||||||
# matching provisioning profile when using Apple Development signing.
|
# (and typically a matching provisioning profile). It is *not* safe to enable
|
||||||
# Avoid breaking local debug builds by only enabling it when forced, or when
|
# unconditionally for local debug packaging since AMFI will refuse to launch.
|
||||||
# using distribution-style identities.
|
|
||||||
APP_ENTITLEMENTS="$ENT_TMP_APP_BASE"
|
APP_ENTITLEMENTS="$ENT_TMP_APP_BASE"
|
||||||
if [[ "${ENABLE_TIME_SENSITIVE_NOTIFICATIONS:-}" == "1" ]]; then
|
if [[ "${ENABLE_TIME_SENSITIVE_NOTIFICATIONS:-}" == "1" ]]; then
|
||||||
APP_ENTITLEMENTS="$ENT_TMP_APP"
|
APP_ENTITLEMENTS="$ENT_TMP_APP"
|
||||||
elif [[ "$IDENTITY" == *"Developer ID Application"* ]] || [[ "$IDENTITY" == *"Apple Distribution"* ]]; then
|
|
||||||
APP_ENTITLEMENTS="$ENT_TMP_APP"
|
|
||||||
else
|
else
|
||||||
echo "Note: Time Sensitive Notifications entitlement disabled for this signing identity."
|
echo "Note: Time Sensitive Notifications entitlement disabled."
|
||||||
echo " To force it: ENABLE_TIME_SENSITIVE_NOTIFICATIONS=1 scripts/codesign-mac-app.sh <app>"
|
echo " To force it: ENABLE_TIME_SENSITIVE_NOTIFICATIONS=1 scripts/codesign-mac-app.sh <app>"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -86,7 +86,16 @@ choose_app_bundle() {
|
|||||||
choose_app_bundle
|
choose_app_bundle
|
||||||
|
|
||||||
# 4) Launch the installed app in the foreground so the menu bar extra appears.
|
# 4) Launch the installed app in the foreground so the menu bar extra appears.
|
||||||
run_step "launch app" open "${APP_BUNDLE}"
|
# LaunchServices can inherit a huge environment from this shell (secrets, prompt vars, etc.).
|
||||||
|
# That can cause launchd spawn failures and is undesirable for a GUI app anyway.
|
||||||
|
run_step "launch app" env -i \
|
||||||
|
HOME="${HOME}" \
|
||||||
|
USER="${USER:-$(id -un)}" \
|
||||||
|
LOGNAME="${LOGNAME:-$(id -un)}" \
|
||||||
|
TMPDIR="${TMPDIR:-/tmp}" \
|
||||||
|
PATH="/usr/bin:/bin:/usr/sbin:/sbin" \
|
||||||
|
LANG="${LANG:-en_US.UTF-8}" \
|
||||||
|
/usr/bin/open "${APP_BUNDLE}"
|
||||||
|
|
||||||
# 5) Verify the app is alive.
|
# 5) Verify the app is alive.
|
||||||
sleep 1.5
|
sleep 1.5
|
||||||
|
|||||||
Reference in New Issue
Block a user