Sandboxing done right - looking for knowledge people to discuss this.

While this isn’t specifically related to Xojo, it affects the previous RS as well, I’m looking to open a discussion with the most knowledgeable users and I think this is where I will find them.

In summary: I’ve been using Security Scoped Bookmarks to hold references for recent items and for open files, while these work they’ve lead to many issues. In comparison, had I built an app using the “Document based app” template in Xcode and Obj-C, I wouldn’t be facing the problems that I am. Apple’s NSDocument based app, automagically retains access for open documents and recent documents. Meaning the developer doesn’t even have to go through the hassle of doing anything special, it just works.

I’ve spoken to Apple engineers, I’ve built a doc based app in Obj-C and been researching every little fricking detail I can in order to understand the hidden magic that Apple uses for it’s NSDocument based apps. I’ve narrowed it down to one key object, and several processes.

NSDocumentController is the key object here from what I can understand.
NSDocumentController contains functions for storing and retrieving a recent items list and any file added to that list, has it’s access automagically retained.

NSDocumentController is also the key object when used with Lion’s WindowRestoration classes and it’s this functionality that holds on to the access of open documents.

For recent items, I was able to implement and it works beautifully. For Lion’s WindowRestoration - I keep hitting brick wall after brick wall. Documentation on how to accomplish this correctly is scarce and it seems some functionality cannot be accomplished with declares.

I believe that this issue is very important to Xojo as means that a Xojo app cannot operate as well as a Obj-C app in a Sandboxed environment.

From what I’ve been able to find it seems, that the first part is getting the OS to correctly encode certain properties of the window. Mainly it needs to encode the representedURL. It’s not difficult to specify the representedURL, but it doesn’t get encoded. So far I’ve found at least 3 things that I believe need to be set on a Window to trigger the encoding correctly.

#1 setRestorable must be True - which is a simple declare.
#2 You must set a restorable class - which is another simple declare.
#3 You must give the window a unique ID before any views are created in the window. The issue is ‘identifier’ is a variable of the window, with no getter or setter, so I’ve not been able to do this via a declare. It looks like I will have to jump in a create a plugin.

I haven’t gotten much further than that, I’ve tried creating a NSDocument and associating the two (which works, but doesn’t help). I’ve tried allocating a NSWindowController, (which works but doesn’t help).

All this is just to get the OS to encode the URL.

Even if the URL is correctly encoded, I’m not sure that a Xojo app will automagically have access to the URL, until it has been decoded correctly.

Decoding the restorable state, is a whole 'nother bag of snakes. It seems the way to do within Xojo is to add an event to the NSApplication

  • (BOOL)restoreWindowWithIdentifier:(NSString *)identifier state:(NSCoder *)state completionHandler:(void (^)(NSWindow *, NSError *))completionHandler NS_AVAILABLE_MAC(10_7);

Again it can’t be done via a declare.

And even then, I’m not sure that this will help much as then your app must take over decode the data. So I’m hoping that simply by being able to correctly encode the window information (capturing the URL) this will solve the problem for Xojo users. If not then…

Thoughts anyone?

I just want to add, that I know this seems like a bit of a rant, it probably is. But I’m mad at Apple also for making it difficult for developers who don’t use Xcode/Obj-C to get at required functionality.

I agree, making a RB (Xojo) compiled app Sandboxed is a real PITA. Especially when you are dealing with files. So I feel the pain but sadly cannot help you Sam … everything I know about sandboxing, I learned from you (thank you for making AppWrapper which is by far the best tool).

On a side note:
I also want to add the Shell class does not work within a Sandboxed app. Fingers crossed if Xojo can do this in the near future.

I believe they do this on purpose. It is in their best interest to make Xcode the best dev tool for making Mac & iOS apps. From their perspective they can simply say, “Use our tools. We know they work.”

I’m still working on getting more stuff to the plugins for this. I hope we get it done soon.

Thanks Christian for helping out with this - it really is very important that we get this right, I’m really getting fed up with having my app broken because of the stupid SSBs!

[quote=8277:@Christophe De Vocht]I agree, making a RB (Xojo) compiled app Sandboxed is a real PITA. Especially when you are dealing with files. So I feel the pain but sadly cannot help you Sam … everything I know about sandboxing, I learned from you (thank you for making AppWrapper which is by far the best tool).

On a side note:
I also want to add the Shell class does not work within a Sandboxed app. Fingers crossed if Xojo can do this in the near future.[/quote]
You are helping by simple being involved in this conversation, the more people involved, hopefully the more that Xojo will take an interest and implement some behind the scene stuff so Sandboxing no longer becomes such a PITA for Xojo developers.

I’ve added a feature request for NSTask support as later this year I will need it form one of my apps. Sign on. <https://xojo.com/issue/26605>

Yes, I now mostly use NSTask (with MBS plugins) and it works fine. But it should be doable with the default Shell class imo

Hmmm… Feedback Case #26605 isn’t reviewed yet… bummer. But I did put in my top cases. :slight_smile:

Well, the important thing is to have a way doing it. For the restore state, it would help if Apple could tell us what is required. It is so easy to implement 99% and forget one required call.

Okay so with Christian’s help I finally got somewhere, I can now get to correctly create the encoding data, holding on to a file reference. I have to make NSDocument, attach the file to the document, then create a window controller, attach it to the window, then attach the NSDocument to the window controller…

The trouble is that the ‘Restore’ data gets wiped out when the application quits… On to investigating that one…

Even more progress - turns out that the Xojo quit mechanism was doing something that flushes the data. instead using [NSApplication terminate:self] Preserved the data and then we’re able to watch Christian’s debug plugin register and fire the restoration methods.

I understood directly running shell commands wasn’t accessible to any sandboxed app, regardless of development tools. Is it possible with Xcode/ObjC?

IT WORKS!!! Simply by being able to get the OS to store the reference to the file, access is automatically retained through restarts of the application…

Still having some trouble in quitting the application (seems like NSApplication.terminate doesn’t work from a Sandboxed app).

By this is superb progress… I can see SSBs circling the toilet right now!

Good job, Sam! Sounds like you have some writing to do in your future.

Yes it works with Xcode, RB and Xojo. But you have to use NSTask for doing this. It has some limits though.

Alright folks - I’ve wrapped up the code into a demo application, which you can download and try out here.
betterSandboxSolutionDemo.zip

No security-scoped bodgemarks were used for this solution!

I’m working on the documentation of how to use this, but there is a lot of information in my head right now that I need to sort out before I can even begin to explain to other developers how to use it.

The key thing is that in order to utilize this code so that your app works, just like other apps on Lion, you must alter the design of your application otherwise this code is wasted (i.e. the file accesses isn’t retained by the OS), or it will lead to data loss and user frustration.

You need to regularly Auto Save your documents and provide a way for the user to ‘revert to last saved’ or retain an undo stack.

I’m calling this “Better Sandbox Solution” as it’s better than lacing everything with Security-Scoped Bodgemarks, but it’s far from the “Best” Sandbox solution. With my currently level of understanding the best way to implement Sandboxing and file access retention is to use NSDocuments, this is not currently possible with declares and I’m hoping that Christian will be able to implement this in the very near future.

I have created a feedback case for getting Xojo to create a Document based model, and utilize NSDocument on OS X.
<https://xojo.com/issue/26685>

Okay - so I’m still working on getting this right.

I had created my app Document based framework, which included it’s own restoration infrastructure. While it works, I’ve found that Lion’s Window Restoration interferes with my own restoration and screws up my window order and writes a bunch of messages to the console while it’s doing it. Bah! Why is this so fricking difficult?

So last night, I bit the bullet and tackled an NSApplicationDelegate in an attempt to get at the event “restoreWindowWithIdentifier:state:completionHandler:” so I could override Lion’s system (and potentially utilize it for my own purposes). While I failed miserably, I was able to get application state restoring working correctly…

hmmm… So what I’ve now discovered is that if you jam a NSURL into the app restore mechanism, access is retained. It seems that I was tackling the most difficult way of doing this and getting my fingers burnt while doing it.