PDA

View Full Version : Sandboxing...




ArtOfWarfare
Feb 9, 2012, 05:46 PM
How can I make my app sandbox compliant? The list of things it does that I'm not sure whether are okay or not are...

- It calls IOReg and collects information on various devices (name, battery percent, whether it's charging, etc.,)
- It makes an NSStatusItem.
- It stores a bunch of data into NSUserDefaults
- It modifies whether it is a launch item or not. The code it uses to do this is below:

- (NSArray *)loginItems
{
CFArrayRef snapshotRef = LSSharedFileListCopySnapshot(loginItemsListRef, NULL);
return (__bridge NSArray *)snapshotRef;
}

// Return a CFRetained item for the app's bundle, if there is one.
- (LSSharedFileListItemRef)mainBundleLoginItemCopy
{
NSArray *loginItems = [self loginItems];
NSURL *bundleURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];

for (id item in loginItems) {
LSSharedFileListItemRef itemRef = (__bridge LSSharedFileListItemRef)item;
CFURLRef itemURLRef;

if (LSSharedFileListItemResolve(itemRef, 0, &itemURLRef, NULL) == noErr) {
// Again, use toll-free bridging.
NSURL *itemURL = (__bridge NSURL *)itemURLRef;
if ([itemURL isEqual:bundleURL])
{
return (__bridge LSSharedFileListItemRef)item;
}
}
}

return NULL;
}

- (BOOL)launchOnLogin
{
if (!loginItemsListRef)
return NO;

LSSharedFileListItemRef itemRef = [self mainBundleLoginItemCopy];
if (!itemRef)
return NO;

CFRelease(itemRef);
return YES;
}

- (void)setLaunchOnLogin:(BOOL)value
{
if (!loginItemsListRef)
return;

if (!value) {
[self removeMainBundleFromLoginItems];
} else {
[self addMainBundleToLoginItems];
}
}

- (void)addMainBundleToLoginItems
{
// We use the URL to the app itself (i.e. the main bundle).
NSURL *bundleURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];

NSDictionary *properties;
properties = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:@"com.apple.loginitem.HideOnLaunch"];

LSSharedFileListItemRef itemRef;
itemRef = LSSharedFileListInsertItemURL(loginItemsListRef,
kLSSharedFileListItemLast,
NULL,
NULL,
(__bridge CFURLRef)bundleURL,
(__bridge CFDictionaryRef)properties,
NULL);
if (itemRef) {
CFRelease(itemRef);
}
}

- (void)removeMainBundleFromLoginItems
{
// Try to get the item corresponding to the main bundle URL.
LSSharedFileListItemRef itemRef = [self mainBundleLoginItemCopy];
if (!itemRef)
return;

LSSharedFileListItemRemove(loginItemsListRef, itemRef);

CFRelease(itemRef);
}

I guess I should have a more clear question: What, if anything, do I need to do to make my app sandbox compliant? Are there any entitlements I need to give it? Do I need to use different APIs? Is there any part that simply can't be done with sandboxing? (I fear that I may just have to give Battery Status a final update next week and then lie low and wait for Apple to remove it for not being sandbox compliant.)



kainjow
Feb 9, 2012, 09:18 PM
Did you read Apple's extensive documentation?
https://developer.apple.com/devcenter/mac/app-sandbox/


- It calls IOReg and collects information on various devices (name, battery percent, whether it's charging, etc.,)
- It makes an NSStatusItem.
- It stores a bunch of data into NSUserDefaults
These are fine.

- It modifies whether it is a launch item or not. The code it uses to do this is below:
This won't work. You will just have to make the user do this manually.

If you have a helper app you want to launch at login, use SMLoginItemSetEnabled().

ArtOfWarfare
Feb 9, 2012, 10:13 PM
This won't work. You will just have to make the user do this manually.

Darn. Users specifically cite the ease of accessing the option as something they like in reviews of the app. Oh well, I guess if I want to update the app after March 1st it'll have to have the option replaced with a note explaining that only system preferences is non-hackable enough to be allowed to have such an ability to change which apps are allowed to launch at log-in. And provide instructions with how to add (or remove) it as a launch item, of course.