objective-c NSDocumentController RecentDocuments Sandbox (странная) проблема

Я использую objective-c, Xcode 11, macOS, а не iOS, изолированное приложение.

Мне нужно вручную обновить меню последних документов. Я храню URL-адреса в закладках, чтобы получить к ним доступ в песочнице.

Что странно, так это то, что код A работает, а B - нет. У кого-нибудь есть объяснение этому?

// Code A
NSURL* bookmarkURL = (some valid URL from bookmark);
[bookmarkURL startAccessingSecurityScopedResource]; <- returns TRUE
[[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:bookmarkURL];
//[bookmarkURL stopAccessingSecurityScopedResource]; <-- Without closing access it works

// Code B
NSURL* bookmarkURL = (some valid URL from bookmark);
[bookmarkURL startAccessingSecurityScopedResource]; <- returns TRUE
[[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:bookmarkURL];
[bookmarkURL stopAccessingSecurityScopedResource];

B не работает (с закрытием безопасного доступа)! Неправильно не закрывать безопасный доступ. Для случая B выдается следующая ошибка

Insert failed for list identifier com.apple.LSSharedFileList.ApplicationRecentDocuments Error: Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted" (Restricted by sandbox) UserInfo={NSDebugDescription=Restricted by sandbox}

Без запуска доступа безопасности выдается такая же ошибка (очевидно).

1 ответ

Похоже, что приложение должно сохранять разрешение в области безопасности до тех пор, пока документ находится в списке последних (управляемых вручную).

В моем случае ошибка заключалась в том, что

  • пункт меню «Очистить меню» в меню «Файл» / «Открыть недавние» остался серым
  • недавний список не сохранялся при запуске приложения
  • недавний список не появился на доке.
  • Я получил ошибки в Console.app, говорящие

    Не удалось вставить идентификатор списка com.apple.LSSharedFileList.ApplicationRecentDocuments Ошибка: Ошибка Domain=NSPOSIXErrorDomain Code=1 «Операция не разрешена» (Доступ к списку запрещен) UserInfo={NSDebugDescription=Доступ к списку запрещен}

Похоже, что внутренне список последних документов управляется отдельным потоком, который, в свою очередь, взаимодействует с системным процессом.sharedfilelistd. Если яstopAccessingSecurityScopedResource, я могу наблюдатьsandboxdнарушение в Console.app со следующим стеком вызовов (сокращенно):

      Sandbox: MyApp(24093) deny(1) file-read-data /path/to/recent/document

Thread 1 (id: 364320):
0   libsystem_kernel.dylib          0x00007ff81b2265b2 mach_msg2_trap + 10
1   libsystem_kernel.dylib          0x00007ff81b22d5e4 mach_msg_overwrite + 692
2   libsystem_kernel.dylib          0x00007ff81b22689a mach_msg + 19
3   libdispatch.dylib               0x00007ff81b0dce6f _dispatch_mach_send_and_wait_for_reply + 518
4   libdispatch.dylib               0x00007ff81b0dd273 dispatch_mach_send_with_result_and_wait_for_reply + 50
5   libxpc.dylib                    0x00007ff81afacb97 xpc_connection_send_message_with_reply_sync + 238
6   Foundation                      0x00007ff81c18b423 __NSXPCCONNECTION_IS_WAITING_FOR_A_SYNCHRONOUS_REPLY__ + 9
7   Foundation                      0x00007ff81c1893c1 -[NSXPCConnection _sendInvocation:orArguments:count:methodSignature:selector:withProxy:] + 3215
8   Foundation                      0x00007ff81c188723 -[NSXPCConnection _sendInvocation:withProxy:] + 91
9   CoreFoundation                  0x00007ff81b3234c6 ___forwarding___ + 671
10  CoreFoundation                  0x00007ff81b323198 _CF_forwarding_prep_0 + 120
11  SharedFileList                  0x00007ff823244145 __44-[SFLGenericList _insertItem:atIndex:error:]_block_invoke + 695
12  libsystem_trace.dylib           0x00007ff81afeaa0e _os_activity_initiate_impl + 51
13  SharedFileList                  0x00007ff823243ddc -[SFLGenericList _insertItem:atIndex:error:] + 301
14  SharedFileList                  0x00007ff823243ba5 __46-[SFLGenericList _insertItem:afterItem:error:]_block_invoke + 378
15  libsystem_trace.dylib           0x00007ff81afeaa0e _os_activity_initiate_impl + 51
16  SharedFileList                  0x00007ff823243961 -[SFLGenericList _insertItem:afterItem:error:] + 316
17  SharedFileList                  0x00007ff8232433b2 -[SFLGenericList insertItem:afterItem:error:] + 100
18  SharedFileList                  0x00007ff82323c085 +[SFLList(LSSharedFileListSupport) itemByInsertingAfterItem:name:URL:propertiesToSet:propertiesToClear:list:] + 1370
19  SharedFileList                  0x00007ff82323f3f7 LSSharedFileListInsertItemURL + 183
20  AppKit                          0x00007ff81e80868f -[_NSRecentItemsMenuController _notePendingRecentDocumentURLsForKey:documentsSnapshot:] + 677
21  Foundation                      0x00007ff81c1ada71 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 7
22  Foundation                      0x00007ff81c1ad969 -[NSBlockOperation main] + 98
23  Foundation                      0x00007ff81c1ad902 __NSOPERATION_IS_INVOKING_MAIN__ + 17
24  Foundation                      0x00007ff81c1acc02 -[NSOperation start] + 782
25  Foundation                      0x00007ff81c1ac8e8 __NSOPERATIONQUEUE_IS_STARTING_AN_OPERATION__ + 17
26  Foundation                      0x00007ff81c1ac7b6 __NSOQSchedule_f + 182
27  libdispatch.dylib               0x00007ff81b0d1771 _dispatch_block_async_invoke2 + 83
...

Это показывает, что системой запущен поток, выполняющий некоторую асинхронно отправленную операцию, называемую[_NSRecentItemsMenuController _notePendingRecentDocumentURLs...], который, в свою очередь, отправляет вызовы XPC к SFL (общему списку файлов), что каким-то образом приводит к попытке прочитать указанный документ, который блокируется App Sandbox.

Таким образом, мы можем заключить, что после вызоваnoteNewRecentDocumentURL, приложение по-прежнему должно сохранять разрешение на доступ к файлу, поскольку фактическое управление последним списком происходит асинхронно в другом потоке, и этот поток должен иметь возможность проверять существование файла или читать его по какой-либо другой причине.

Я переписал свое приложение так, чтобы оно удерживало ресурсы области безопасности, пока связанные файлы находятся в списке последних, и прекращало доступ к ним, когда они удаляются из списка. Интернет-мудрость подсказывает, что доступно несколько тысяч таких ресурсов, см. Каковы текущие ограничения ресурсов ядра для закладок с областью безопасности?. Поскольку мой недавний список никогда не вырастет до такого размера, мое приложение никогда не исчерпает ресурсы ядра.

См. также https://developer.apple.com/forums/thread/710278 .

Другие вопросы по тегам