Is there a way to prevent file deletion in deleteItem callback in macOS FileProviderExtension?

176 views Asked by At

In macOS FileProviderExtension, when user deletes an item in Finder, a deleteItem callback is invoked. And here I don't mean trashing the item but really deleting it.

Now let's consider following scenario:

  1. User selects an item (file or folder) in Finder
  2. User on keyboard presses Cmd+Backspace to Delete the item
  3. Item disappears in Finder
  4. A deleteItem(identifier:version:options:request:completionHandler) is invoked
  5. In deleteItem we try to delete the item on the server
  6. Server responds with 403 Forbidden
  7. Now we would like to return the deleted item so that it reappears in the Finder because it couldn't be deleted on the server (since ie the user doesn't have the permission to delete the relevant file)

Is there a way we can achieve this rollback of deleted item so that it reappears in the Finder after unsuccessful deletion on the server?

I know that we can control whether Finder should allow item deletion by setting allowsDeleting capability in FileProviderItem's capabilities.

However, for whatever reason, it could be that on item-delete attempt, server responds with error indicating that the user does NOT have the permission to delete the file.

So as a result, the file (or folder) should reappear in the Finder instead of disappearing (forever).

Now, in deleteItem callback an error can be returned but the file remains deleted. Is there a way to return an error such that file would be returned back?

For example, invoking a completion handler like

completionHandler(NSFileProviderError(.deletionRejected))

might hint a Finder that it should restore the deleted item, however that doesn't happen.

1

There are 1 answers

0
mixtly87 On

One option is to define NSFileProviderUserInteractions section in Info.plist file like:

<key>NSFileProviderUserInteractions</key>
<array>
  <string></string>
  <dict>
    <key>ActivationRule</key>
    <string>action == "Delete"</string>
    <key>SubInteractions</key>
    <array>
      <dict>
        <key>ActivationRule</key>
        <string>sourceItemsCount == 1</string>
        <key>Alert</key>
        <dict>
          <key>LocalizedRecoveryOptions</key>
          <dict>
            <key>Cancel</key>
            <string>I understand</string>
          </dict>
          <key>LocalizedSubTitle</key>
          <string>Item cannot be deleted.</string>
          <key>LocalizedTitle</key>
          <string>Cannot delete item.</string>
          <key>RecoveryOptions</key>
          <dict>
            <key>Continue</key>
            <false/>
          </dict>
        </dict>
      </dict>
    </array>
  </dict>
</array>

This will prevent file deletion with proper Finder error dialog explaining the situation.

Activation rule:

<key>ActivationRule</key>
<string>action == "Delete"</string>

is used by FileProviderExtension to figure out for which item it should prevent the deletion.

For more details, look at Apple WWDC FruitBasket example. That predicate can be more complicated and it is querying the userInfo dictionary from the NSFileProviderItem class.