To implement the
AX API accessibility checking (and resolve the
1st issue):
Additionally to
AXAPIEnabled(), you should also check
AXIsProcessTrusted(),
That is, if your source code used to look like this:
if (!AXAPIEnabled())// global option disabled?
{
// offer opening the Universal Access preference pane
int ret = NSRunAlertPanel (@"Accessibility API",
@"This feature requires that the Accessibility API be enabled.\nWould you like me to launch System Preferences so that you can turn on \"Enable access for assistive devices\"?",
@"OK", @"Cancel",nil);
if (ret == NSAlertDefaultReturn)
[[NSWorkspace sharedWorkspace] openFile:
@"/System/Library/PreferencePanes/UniversalAccessPref.prefPane"];
}
To implement
Trust.app support, the above source code should look like this:
if (
!AXAPIEnabled()// global option disabled
&& // and
!AXIsProcessTrusted()// process is not trusted
)
{
// offer opening the Universal Access preference pane
int ret = NSRunAlertPanel (@"Accessibility API",
@"This feature requires that the Accessibility API be enabled...",
@"OK", @"Cancel",nil);
if (ret == NSAlertDefaultReturn)
[[NSWorkspace sharedWorkspace] openFile:
@"/System/Library/PreferencePanes/UniversalAccessPref.prefPane"];
}
This means that trusted processes automatically gain access to the
AX API, even if the global accessibility option is disabled.
We also offer using our single function
TrustIsEnabled() instead of relying on returned values of functions
AXAPIEnabled and
AXIsProcessTrusted (source code files are available below.)
if (!TrustIsEnabled())// no trust?
{
// offer opening the Universal Access preference pane
int ret = NSRunAlertPanel (@"Accessibility API",
@"This feature requires that the Accessibility API be enabled...",
@"OK", @"Cancel",nil);
if (ret == NSAlertDefaultReturn)
[[NSWorkspace sharedWorkspace] openFile:
@"/System/Library/PreferencePanes/UniversalAccessPref.prefPane"];
}
To resolve
the second issue (security in 10.5), you have to mark your bundle containing internal frameworks (which are linked using @executable_path and usually added during an additional Copy Files phase) as 'Weak'; (Xcode / Project Tree / Targets / Our Target Name / Link Binary With Libraries - the Role column for internal frameworks: Change the value from Required to Weak), and preload those frameworks in the
main() function (usually in the main.m file) before giving control to the
NSApplicationMain function.
External frameworks available from
/System/Library/Frameworks,
/Library/Frameworks, etc., won't require any changes.
The code of your
main() function could look like this:
int main(int argc, char *argv[])
{
NSAutoreleasePool * arp = [NSAutoreleasePool new];
NSString * selfPath = [NSString stringWithUTF8String:argv[0]];
NSString * frameworks =
[[[selfPath stringByDeletingLastPathComponent]
stringByDeletingLastPathComponent]
stringByAppendingPathComponent:@"Frameworks"];
[[NSBundle bundleWithPath:
[frameworks stringByAppendingPathComponent:
@"Growl.framework"]] load];
[[NSBundle bundleWithPath:
[frameworks stringByAppendingPathComponent:
@"Submarine.framework"]] load];
[arp drain];
return NSApplicationMain(argc, (const char **) argv);
}
For convenience, we offer loading frameworks using the
TrustLoadFramework function. In such case your code would look like this:
int main(int argc, char *argv[])
{
TrustLoadFramework(@"Growl.framework");
TrustLoadFramework(@"Submarine.framework");
return NSApplicationMain(argc, (const char **) argv);
}
There's an issue regarding automatic software updates:
The problem is that the
AX API trust system is pretty "apprehensive", and in case of an executable file modification, it stops trusting it.
However, you can easily override this behavior by calling the
TrustUpdate() function in the beginning of the
main() function:
int main(int argc, char *argv[])
{
TrustUpdate();
TrustLoadFramework(@"Growl.framework");
TrustLoadFramework(@"Submarine.framework");
TrustLoadFrameworkFromFolder(@"MyPrivate.framework",
@"MyPrivateFrameworks");
if (TrustIsEnabled())
NSLog(@"I'm trusted Application!");
return NSApplicationMain(argc, (const char **) argv);
}
TrustUpdate performs a check, then it securely asks the Trust module to raise your trust level, and restarts the application, if the operation was successful.