Andrew Madsen Andrew Madsen - 4 months ago 22
Objective-C Question

AppleScripting sandboxed app from another sandboxed app using ScriptingBridge

I'm trying to script a sandboxed app (which I wrote) from another sandboxed app using ScriptingBridge. I have access groups set up in the target app's sdef, and entitlements configured in the scripting app's sandbox entitlements. However, when I try to send Apple Events to the target (using ScriptingBridge), I see

warning: failed to get scripting definition from ~/<snip>/MyApp.app; it may not be scriptable.
logged in the console (the path to the target app is correct).

I've been able to reproduce the problem with a lightly modified version of the Sketch sample code app and a very simple test app that uses scripting bridge. I added
<access-group identifier="com.apple.CocoaExamples.Sketch.Draw" access="rw"/>
to many elements in Sketch.sdef, as well as turned on sandboxing for Sketch.

Then, in my test app, I turned on sandboxing with the following entitlements:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.scripting-targets</key>
<dict>
<key>com.apple.CocoaExamples.Sketch</key>
<array>
<string>com.apple.CocoaExamples.Sketch.Draw</string>
</array>
</dict>
</dict>
</plist>


The app does the following:

#import "ViewController.h"
#import "Sketch.h"

@implementation ViewController
- (IBAction)draw:(id)sender {
SketchApplication *sketch = [SBApplication applicationWithBundleIdentifier:@"com.apple.CocoaExamples.Sketch"];
if (![sketch isKindOfClass:[NSClassFromString(@"SketchApplication") class]]) {
NSLog(@"Unable to get SketchApplication for Sketch");
}
}
@end


Upon the call to
-applicationWithBundleIdentifier:
, the "warning: failed to get scripting definition" message is logged, and the object returned is an instance of
SBApplication
rather than a
SketchApplication
.

If I turn off sandboxing in the test app, the error is not logged, and
-applicationWithBundleIdentifier:
returns a
SketchApplication
as expected. The same is true if I add the
com.apple.security.temporary-exception.apple-events
entitlement, though I believe this is unlikely to pass app store review.

Am I missing something beyond defining access groups in the target's sdef and adding the
com.apple.security.scripting-targets
entitlement? Does this work for anyone?

I've uploaded the test app and my modified Sketch projects here: https://www.dropbox.com/s/cdml9n5npu8o2m3/SandboxScriptTest.zip?dl=0

Answer

I filed a tech support incident with Apple about this, and they confirmed that it is a bug. The only workaround they suggested is to hold onto the (valid) instance of SketchApplication returned by the first call to -applicationWithBundleIdentifier: when Sketch is running for later use. This is not really a viable workaround at all in my particular case since the target app is very likely to already be running before the scripting app is launched.

The other option is to use the com.apple.security.temporary-exception.apple-events sandbox entitlement. I'll do that for now, and hope that I can justify its use for app store review.

I've filed a radar for this: rdar://27625862.