Post

Replies

Boosts

Views

Activity

Public API to silently query "Remote Desktop" TCC authorization status (without triggering a system prompt)
Product area macOS / Privacy & Security / ScreenCaptureKit / Core Graphics Environment macOS 27 Beta 4 (build: fill in your exact build number, e.g. 27A5xxx) Xcode 26.5 / SDK 260500 (adjust to match what you actually built with) App holds the com.apple.developer.persistent-content-capture entitlement (approved via Apple's request form), targeting macOS 14.4+ Summary Our app is a remote-support/remote-control tool (screen viewing + control), comparable to VNC-style products. On macOS 27, we've found that System Settings > Privacy & Security now shows a "Remote Desktop" entry that is distinct from "Screen & System Audio Recording" — granting one does not affect the other. We need a way to check, at any time, whether our app currently has "Remote Desktop" authorization, without causing the system to show a permission-request alert as a side effect. We have not found a documented, public API that does this. What we've tried CGPreflightScreenCaptureAccess() Confirmed via a controlled test on-device: granting only "Remote Desktop" leaves this API returning false; granting only "Screen & System Audio Recording" makes it return true. So this API appears to reflect kTCCServiceScreenCapture only, and does not reflect the "Remote Desktop" permission at all. ScreenCaptureKit (SCShareableContent, e.g. via a refreshAvailableContentWithCompletionHandler:-style call) This call does appear to interact with the "Remote Desktop" permission — but calling it triggers a real system consent alert every time we call it, even when we only intend to read the current status, not request it. This makes it unusable for passive/background status polling (e.g. to decide what to show in our own onboarding UI without surprising the user with an OS-level prompt). We are intentionally not reading /Library/Application Support/com.apple.TCC/TCC.db directly — we understand this is a private, undocumented database and want a supported API instead. Sample code illustrating both attempts // Attempt 1: CGPreflightScreenCaptureAccess — does not reflect Remote Desktop grant BOOL preflightResult = CGPreflightScreenCaptureAccess(); // preflightResult stays NO even after the user grants "Remote Desktop" in // System Settings > Privacy & Security > Remote Desktop. // It correctly flips to YES only when "Screen & System Audio Recording" is granted. // Attempt 2: ScreenCaptureKit-based check — reflects it, but prompts every time SCShareableContent... // (via our wrapper) refreshAvailableContentWithCompletionHandler: // This call appears to influence/query the Remote Desktop TCC entry, but the OS // shows a permission alert as a side effect of the call itself, even when we only // want to read the current authorization state. Question Is there a public, documented API equivalent to CGPreflightScreenCaptureAccess() — i.e., a read-only, non-prompting status check — for the new "Remote Desktop" privacy category introduced around macOS 26/27? Is com.apple.developer.persistent-content-capture actually the entitlement that governs this new "Remote Desktop" category, or is it unrelated? Apple's own documentation describes this entitlement purely in terms of "persistent access to screen capture" for VNC apps, with no mention of a distinct "Remote Desktop" permission surface — we'd like to confirm whether that description is still accurate on macOS 26/27, or whether the underlying TCC service (kTCCServiceRemoteDesktop, which we found via TCC.db schema inspection only, not public docs) has been intentionally split out. If no such API exists yet, is this planned, and is there a recommended interim approach for apps that need to know this state before deciding whether to show their own onboarding/permission UI?
2
0
307
1d
macOS 15.2, strange runtime error on NSDictionary extension method
We are developing remote desktop app on macOS and recently got user's report about unexpected app crash on macOS 15.2 beta. On macOS 15.2, there's strange app crash on NSDictionary extension method. We have narrowed down the steps and create the sample code to duplicate this issue. Create a cocoa app project in objective-c Try to access [NSNull null] value in NSDictionary Use specific method name for NSDictionary extension - (long long)longLongValueForKey:(NSString*)key withDefault:(long long)defaultValue; The console output for the example app is like below, the method pointer seems to be wrong when trying to get value with longLongValueForKey:withDefault: method to a [NSNull null] object. ********* longLongValueForKey: a: 0 ********* longLongValueForKey: b: 100 ********* longLongValueForKey: c: 0 ********* longLongValueForKey:withDefault: a: -1 ********* longLongValueForKey:withDefault: b: 100 ********* exception: -[NSNull longLongValue]: unrecognized selector sent to instance 0x7ff8528d9760 ********* longLongValueForKey:withDefault1: a: -1 ********* longLongValueForKey:withDefault1: b: 100 ********* longLongValueForKey:withDefault1: c: -1 Please create an objective-c app project and add below code to reproduce this issue. // // AppDelegate.m // DictionaryTest // // Created by splashtop on 2024/11/13. // #import "AppDelegate.h" #define IsNullObject(id) ((!id) || [id isKindOfClass:[NSNull class]]) @interface NSDictionary (extension) (long long)longLongValueForKey:(NSString*)key; (long long)longLongValueForKey:(NSString*)key withDefault:(long long)defaultValue; (long long)longLongValueForKey:(NSString*)key withDefault1:(long long)defaultValue; @end @interface AppDelegate () @property (strong) IBOutlet NSWindow *window; @end @implementation AppDelegate (void)applicationDidFinishLaunching:(NSNotification *)aNotification { // Insert code here to initialize your application NSDictionary* dict = @{ @"b" : @(100), @"c" : [NSNull null], }; @try { long long a = [dict longLongValueForKey:@"a"]; NSLog(@"********* longLongValueForKey: a: %lld", a); long long b = [dict longLongValueForKey:@"b"]; NSLog(@"********* longLongValueForKey: b: %lld", b); long long c = [dict longLongValueForKey:@"c"]; NSLog(@"********* longLongValueForKey: c: %lld", c); } @catch(NSException* e) { NSLog(@"********* exception: %@", e); } @try { long long a = [dict longLongValueForKey:@"a" withDefault:-1]; NSLog(@"********* longLongValueForKey:withDefault: a: %lld", a); long long b = [dict longLongValueForKey:@"b" withDefault:-1]; NSLog(@"********* longLongValueForKey:withDefault: b: %lld", b); long long c = [dict longLongValueForKey:@"c" withDefault:-1]; NSLog(@"********* longLongValueForKey:withDefault: c: %lld", c); } @catch(NSException* e) { NSLog(@"********* exception: %@", e); } @try { long long a = [dict longLongValueForKey:@"a" withDefault1:-1]; NSLog(@"********* longLongValueForKey:withDefault1: a: %lld", a); long long b = [dict longLongValueForKey:@"b" withDefault1:-1]; NSLog(@"********* longLongValueForKey:withDefault1: b: %lld", b); long long c = [dict longLongValueForKey:@"c" withDefault1:-1]; NSLog(@"********* longLongValueForKey:withDefault1: c: %lld", c); } @catch(NSException* e) { NSLog(@"********* exception: %@", e); } } @end @implementation NSDictionary (extension) (long long)longLongValueForKey:(NSString*)key { long long defaultValue = 0; id value = [self objectForKey:key]; if (IsNullObject(value) || value == [NSNull null]) { return defaultValue; } if ([value isKindOfClass:[NSNumber class]] || [value isKindOfClass:[NSString class]]) { return [value longLongValue]; } return defaultValue; } (long long)longLongValueForKey:(NSString*)key withDefault:(long long)defaultValue { id value = [self objectForKey:key]; if (IsNullObject(value) || value == [NSNull null]) { return defaultValue; } if ([value isKindOfClass:[NSNumber class]] || [value isKindOfClass:[NSString class]]) { return [value longLongValue]; } return defaultValue; } (long long)longLongValueForKey:(NSString*)key withDefault1:(long long)defaultValue { id value = [self objectForKey:key]; if (IsNullObject(value) || value == [NSNull null]) { return defaultValue; } if ([value isKindOfClass:[NSNumber class]] || [value isKindOfClass:[NSString class]]) { return [value longLongValue]; } return defaultValue; } @end
1
0
529
Nov ’24
Public API to silently query "Remote Desktop" TCC authorization status (without triggering a system prompt)
Product area macOS / Privacy & Security / ScreenCaptureKit / Core Graphics Environment macOS 27 Beta 4 (build: fill in your exact build number, e.g. 27A5xxx) Xcode 26.5 / SDK 260500 (adjust to match what you actually built with) App holds the com.apple.developer.persistent-content-capture entitlement (approved via Apple's request form), targeting macOS 14.4+ Summary Our app is a remote-support/remote-control tool (screen viewing + control), comparable to VNC-style products. On macOS 27, we've found that System Settings > Privacy & Security now shows a "Remote Desktop" entry that is distinct from "Screen & System Audio Recording" — granting one does not affect the other. We need a way to check, at any time, whether our app currently has "Remote Desktop" authorization, without causing the system to show a permission-request alert as a side effect. We have not found a documented, public API that does this. What we've tried CGPreflightScreenCaptureAccess() Confirmed via a controlled test on-device: granting only "Remote Desktop" leaves this API returning false; granting only "Screen & System Audio Recording" makes it return true. So this API appears to reflect kTCCServiceScreenCapture only, and does not reflect the "Remote Desktop" permission at all. ScreenCaptureKit (SCShareableContent, e.g. via a refreshAvailableContentWithCompletionHandler:-style call) This call does appear to interact with the "Remote Desktop" permission — but calling it triggers a real system consent alert every time we call it, even when we only intend to read the current status, not request it. This makes it unusable for passive/background status polling (e.g. to decide what to show in our own onboarding UI without surprising the user with an OS-level prompt). We are intentionally not reading /Library/Application Support/com.apple.TCC/TCC.db directly — we understand this is a private, undocumented database and want a supported API instead. Sample code illustrating both attempts // Attempt 1: CGPreflightScreenCaptureAccess — does not reflect Remote Desktop grant BOOL preflightResult = CGPreflightScreenCaptureAccess(); // preflightResult stays NO even after the user grants "Remote Desktop" in // System Settings > Privacy & Security > Remote Desktop. // It correctly flips to YES only when "Screen & System Audio Recording" is granted. // Attempt 2: ScreenCaptureKit-based check — reflects it, but prompts every time SCShareableContent... // (via our wrapper) refreshAvailableContentWithCompletionHandler: // This call appears to influence/query the Remote Desktop TCC entry, but the OS // shows a permission alert as a side effect of the call itself, even when we only // want to read the current authorization state. Question Is there a public, documented API equivalent to CGPreflightScreenCaptureAccess() — i.e., a read-only, non-prompting status check — for the new "Remote Desktop" privacy category introduced around macOS 26/27? Is com.apple.developer.persistent-content-capture actually the entitlement that governs this new "Remote Desktop" category, or is it unrelated? Apple's own documentation describes this entitlement purely in terms of "persistent access to screen capture" for VNC apps, with no mention of a distinct "Remote Desktop" permission surface — we'd like to confirm whether that description is still accurate on macOS 26/27, or whether the underlying TCC service (kTCCServiceRemoteDesktop, which we found via TCC.db schema inspection only, not public docs) has been intentionally split out. If no such API exists yet, is this planned, and is there a recommended interim approach for apps that need to know this state before deciding whether to show their own onboarding/permission UI?
Replies
2
Boosts
0
Views
307
Activity
1d
macOS 15.2, strange runtime error on NSDictionary extension method
We are developing remote desktop app on macOS and recently got user's report about unexpected app crash on macOS 15.2 beta. On macOS 15.2, there's strange app crash on NSDictionary extension method. We have narrowed down the steps and create the sample code to duplicate this issue. Create a cocoa app project in objective-c Try to access [NSNull null] value in NSDictionary Use specific method name for NSDictionary extension - (long long)longLongValueForKey:(NSString*)key withDefault:(long long)defaultValue; The console output for the example app is like below, the method pointer seems to be wrong when trying to get value with longLongValueForKey:withDefault: method to a [NSNull null] object. ********* longLongValueForKey: a: 0 ********* longLongValueForKey: b: 100 ********* longLongValueForKey: c: 0 ********* longLongValueForKey:withDefault: a: -1 ********* longLongValueForKey:withDefault: b: 100 ********* exception: -[NSNull longLongValue]: unrecognized selector sent to instance 0x7ff8528d9760 ********* longLongValueForKey:withDefault1: a: -1 ********* longLongValueForKey:withDefault1: b: 100 ********* longLongValueForKey:withDefault1: c: -1 Please create an objective-c app project and add below code to reproduce this issue. // // AppDelegate.m // DictionaryTest // // Created by splashtop on 2024/11/13. // #import "AppDelegate.h" #define IsNullObject(id) ((!id) || [id isKindOfClass:[NSNull class]]) @interface NSDictionary (extension) (long long)longLongValueForKey:(NSString*)key; (long long)longLongValueForKey:(NSString*)key withDefault:(long long)defaultValue; (long long)longLongValueForKey:(NSString*)key withDefault1:(long long)defaultValue; @end @interface AppDelegate () @property (strong) IBOutlet NSWindow *window; @end @implementation AppDelegate (void)applicationDidFinishLaunching:(NSNotification *)aNotification { // Insert code here to initialize your application NSDictionary* dict = @{ @"b" : @(100), @"c" : [NSNull null], }; @try { long long a = [dict longLongValueForKey:@"a"]; NSLog(@"********* longLongValueForKey: a: %lld", a); long long b = [dict longLongValueForKey:@"b"]; NSLog(@"********* longLongValueForKey: b: %lld", b); long long c = [dict longLongValueForKey:@"c"]; NSLog(@"********* longLongValueForKey: c: %lld", c); } @catch(NSException* e) { NSLog(@"********* exception: %@", e); } @try { long long a = [dict longLongValueForKey:@"a" withDefault:-1]; NSLog(@"********* longLongValueForKey:withDefault: a: %lld", a); long long b = [dict longLongValueForKey:@"b" withDefault:-1]; NSLog(@"********* longLongValueForKey:withDefault: b: %lld", b); long long c = [dict longLongValueForKey:@"c" withDefault:-1]; NSLog(@"********* longLongValueForKey:withDefault: c: %lld", c); } @catch(NSException* e) { NSLog(@"********* exception: %@", e); } @try { long long a = [dict longLongValueForKey:@"a" withDefault1:-1]; NSLog(@"********* longLongValueForKey:withDefault1: a: %lld", a); long long b = [dict longLongValueForKey:@"b" withDefault1:-1]; NSLog(@"********* longLongValueForKey:withDefault1: b: %lld", b); long long c = [dict longLongValueForKey:@"c" withDefault1:-1]; NSLog(@"********* longLongValueForKey:withDefault1: c: %lld", c); } @catch(NSException* e) { NSLog(@"********* exception: %@", e); } } @end @implementation NSDictionary (extension) (long long)longLongValueForKey:(NSString*)key { long long defaultValue = 0; id value = [self objectForKey:key]; if (IsNullObject(value) || value == [NSNull null]) { return defaultValue; } if ([value isKindOfClass:[NSNumber class]] || [value isKindOfClass:[NSString class]]) { return [value longLongValue]; } return defaultValue; } (long long)longLongValueForKey:(NSString*)key withDefault:(long long)defaultValue { id value = [self objectForKey:key]; if (IsNullObject(value) || value == [NSNull null]) { return defaultValue; } if ([value isKindOfClass:[NSNumber class]] || [value isKindOfClass:[NSString class]]) { return [value longLongValue]; } return defaultValue; } (long long)longLongValueForKey:(NSString*)key withDefault1:(long long)defaultValue { id value = [self objectForKey:key]; if (IsNullObject(value) || value == [NSNull null]) { return defaultValue; } if ([value isKindOfClass:[NSNumber class]] || [value isKindOfClass:[NSString class]]) { return [value longLongValue]; } return defaultValue; } @end
Replies
1
Boosts
0
Views
529
Activity
Nov ’24