gkngkc / UnityStandaloneFileBrowser

A native file browser for unity standalone platforms
MIT License
2.01k stars 317 forks source link

SaveFilePanel crashes the plugin in a Mac App Store build #52

Closed CanisLupus closed 5 years ago

CanisLupus commented 5 years ago

Sorry to bother you again, Gökhan.

The following code crashes the plugin on a macOS build for the Mac App Store (i.e. built with Mac App Store Validation enabled in Unity, then codesigned and packaged, then installed from the package):

Debug.Log("before StandaloneFileBrowser.SaveFilePanel");
string path = SFB.StandaloneFileBrowser.SaveFilePanel("Export", "", "something", "pdf");
Debug.Log("path: " + path);

The crash results in the following in Unity's Player.log file:

before StandaloneFileBrowser.SaveFilePanel

(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)

2018-11-15 15:22:36.282 Our Application[17987:3915399] init
2018-11-15 15:22:36.390 Our Application[17987:3915399] *** Assertion failure in -[NSVBSavePanel viewWillInvalidate:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/AppKit/AppKit-1671/Nav.subproj/OpenAndSavePanelRemote/NSVBOpenAndSavePanels.m:374
2018-11-15 15:22:36.391 Our Application[17987:3915399] -[NSVBSavePanel init] caught non-fatal NSObjectNotAvailableException 'service com.apple.appkit.xpc.openAndSavePanelService failed to init an instance of NSSavePanelService on behalf of <NSRemoteView: 0x600003308460> due to {
    callStackSymbols = (
    0   CoreFoundation                      0x00007fff4663943d __exceptionPreprocess + 256
    1   libobjc.A.dylib                     0x00007fff72546720 objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff4663926f +[NSException raise:format:] + 201
    3   com.apple.appkit.xpc.openAndSavePanelService 0x000000010258b204 com.apple.appkit.xpc.openAndSavePanelService + 8708
    4   AppKit                              0x00007fff43c5d10b -[NSViewController _loadViewIfRequired] + 75
    5   AppKit                              0x00007fff43c5d076 -[NSViewController view] + 30
    6   ViewBridge                          0x00007fff6f644ac3 -[NSViewServiceMarshal _bootstrap:replyData:] + 2899
    7   ViewBridge                          0x00007fff6f646047 -[NSViewServiceMarshal bootstrap:withReply:] + 167
    8   CoreFoundation                      0x00007fff4658ef8c __invoking___ + 140
    9   CoreFoundation                      0x00007fff4658ee5f -[NSInvocation invoke] + 311
    10  CoreFoundation                      0x00007fff465f053d -[NSInvocation invokeWithTarget:] + 56
    11  ViewBridge                          0x00007fff6f68baaf -[NSVB_ViewServiceImplicitAnimationDecodingProxy forwardInvocation:] + 85
    12  CoreFoundation                      0x00007fff465d880e ___forwarding___ + 780
    13  CoreFoundation                      0x00007fff465d8478 _CF_forwarding_prep_0 + 120
    14  CoreFoundation                      0x00007fff4658ef8c __invoking___ + 140
    15  CoreFoundation                      0x00007fff4658ee5f -[NSInvocation invoke] + 311
    16  CoreFoundation                      0x00007fff465f053d -[NSInvocation invokeWithTarget:] + 56
    17  ViewBridge                          0x00007fff6f653973 -[NSVB_QueueingProxy forwardInvocation:] + 324
    18  CoreFoundation                      0x00007fff465d880e ___forwarding___ + 780
    19  CoreFoundation                      0x00007fff465d8478 _CF_forwarding_prep_0 + 120
    20  CoreFoundation                      0x00007fff4658ef8c __invoking___ + 140
    21  CoreFoundation                      0x00007fff4658ee5f -[NSInvocation invoke] + 311
    22  CoreFoundation                      0x00007fff465f053d -[NSInvocation invokeWithTarget:] + 56
    23  CoreFoundation                      0x00007fff465d880e ___forwarding___ + 780
    24  CoreFoundation                      0x00007fff465d8478 _CF_forwarding_prep_0 + 120
    25  CoreFoundation                      0x00007fff4658ef8c __invoking___ + 140
    26  CoreFoundation                      0x00007fff4658ee5f -[NSInvocation invoke] + 311
    27  ViewBridge                          0x00007fff6f6206cd __deferNSXPCInvocationOntoMainThread_block_invoke + 237
    28  ViewBridge                          0x00007fff6f615af3 __wrapBlockWithVoucher_block_invoke + 37
    29  ViewBridge                          0x00007fff6f6158a4 __deferBlockOntoMainThread_block_invoke_2 + 553
    30  CoreFoundation                      0x00007fff465bcca7 __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
    31  CoreFoundation                      0x00007fff4657fced __CFRunLoopDoBlocks + 395
    32  CoreFoundation                      0x00007fff4657fa49 __CFRunLoopRun + 2834
    33  CoreFoundation                      0x00007fff4657ece4 CFRunLoopRunSpecific + 463
    34  HIToolbox                           0x00007fff45818895 RunCurrentEventLoopInMode + 293
    35  HIToolbox                           0x00007fff458185cb ReceiveNextEventCommon + 618
    36  HIToolbox                           0x00007fff45818348 _BlockUntilNextEventMatchingListInModeWithFilter + 64
    37  AppKit                              0x00007fff43ad595b _DPSNextEvent + 997
    38  AppKit                              0x00007fff43ad46fa -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1362
    39  ViewBridge                          0x00007fff6f61e226 -[NSViewServiceApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 92
    40  AppKit                              0x00007fff43ace75d -[NSApplication run] + 699
    41  AppKit                              0x00007fff43abde97 NSApplicationMain + 780
    42  libxpc.dylib                        0x00007fff7384af1f _xpc_objc_main + 612
    43  libxpc.dylib                        0x00007fff7384a9e5 _xpc_copy_xpcservice_dictionary + 0
    44  ViewBridge                          0x00007fff6f60fa76 xpc_connection_handler + 0
    45  ViewBridge                          0x00007fff6f618a03 NSViewServiceApplicationMain + 2877
    46  com.apple.appkit.xpc.openAndSavePanelService 0x00000001025904ea main + 208
    47  libdyld.dylib                       0x00007fff73614085 start + 1
);
    name = NSInternalInconsistencyException;
    reason = "+[NSOpenAndSavePanelService loadViewToService:isOpenPanel:appCentric:] : failed entitlements check";
    userInfo = "<null>";
}' with backtrace (
    0   CoreFoundation                      0x00007fff4663943d __exceptionPreprocess + 256
    1   libobjc.A.dylib                     0x00007fff72546720 objc_exception_throw + 48
    2   ViewBridge                          0x00007fff6f671b00 -[NSRemoteView _advanceToConfigPhaseLegacy] + 1593
    3   ViewBridge                          0x00007fff6f672845 -[NSRemoteView _viewServiceMarshalProxy:withDetailedErrorHandler:] + 217
    4   ViewBridge                          0x00007fff6f672c1a -[NSRemoteView _viewServiceMarshalProxy:withErrorHandler:] + 73
    5   ViewBridge                          0x00007fff6f6613c0 -[NSRemoteView _bridge] + 393
    6   ViewBridge                          0x00007fff6f661211 -[NSRemoteView bridge] + 30
    7   AppKit                              0x00007fff43e2c5fa -[NSVBSavePanel init] + 290
    8   AppKit                              0x00007fff43e2c119 +[NSSavePanel _crunchyRawUnbonedPanel] + 75
    9   StandaloneFileBrowser               0x000000010e3429f8 -[StandaloneFileBrowser createSavePanel:directory:defaultName:filters:] + 167
    10  StandaloneFileBrowser               0x000000010e342848 -[StandaloneFileBrowser dialogSaveFilePanel:directory:defaultName:filters:] + 19
    11  StandaloneFileBrowser               0x000000010e341ed9 DialogSaveFilePanel + 224
    12  ???                                 0x0000000110e56063 0x0 + 4578435171
)
path: 

The crucial part seems to be "service com.apple.appkit.xpc.openAndSavePanelService failed to init an instance of NSSavePanelService".

The error affects only the plugin (the app itself does not crash), which returns an empty path without opening the save file dialog at all. This does not happen on a standalone macOS build from Unity (i.e. not prepared for the store), which is very strange. StandaloneFileBrowser.OpenFilePanel seems to work regardless of SaveFilePanel not working. Could this be a permissions issue that doesn't happen for non-store builds?

It happens on both a recent iMac with Mojave (the error above is from that) and a very old MacBook Pro from 2010 with High Sierra 10.13.6. We are using the current unitypackage from your repository's "Package" folder.

Any ideas? :)

Cheers! Daniel Lobo

gkngkc commented 5 years ago

I'm not sure but it's probably because of apple's app sandbox. I think you have to specify file-access permissions in the entitlement key. Documentation is here.

CanisLupus commented 5 years ago

You were spot-on, thank you very much. :)

Turns out that OpenFilePanel was working because we already had the com.apple.security.files.user-selected.read-only permission, since by following Unity's instructions we copied the entitlements file created by Xcode for a default project.

Adding com.apple.security.files.user-selected.read-write worked perfectly.

For reference, if anyone stumbles upon this thread, the correct entitlements file for us was:

<?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.files.user-selected.read-only</key>
    <true/>
    <key>com.apple.security.files.user-selected.read-write</key>
    <true/>
</dict>
</plist>

Thanks again! Your help is much appreciated. ;) Daniel