URL.Bookmark Class (bookmarks)

An instance of the URL.Bookmark class records the permission to access a given URL and will restore that permission, as well as a possibly renamed file, at a later point.

Because of security features in iOS/iPadOS/macOS the user must actively approve the use of files and folders located outside of the current applicationā€™s sandbox security zone.

To eliminate the need for the plug-in user to locate and select a specified location or file used by the plug-in, every time the plug-in is run, you can store an approved reference to the user-selected location in the system Keychain. This reference is called a “bookmark.” Stored bookmarks can be retrieved and used without further user interaction.

The storing of bookmarks in the system Keychain is accomplished through the use of the Credentials class.

Credentials Instance Functions

On macOS, bookmarks can be located in the Keychain Access application by filtering using the credential service title:

(⬇ see below ) The bookmark credential in the Keychain Access application (macOS):


(⬇ see below ) Info for the bookmark. NOTE: the value of the password is the bookmark:


URL.Bookmark Class Functions

URL.Bookmark Instance Functions

URL.Access Class

An instance of the URL.Access class holds the temporary access given by the URL.Bookmark.access() function. These should not be stored longer than needed.

Example Plug-In

Here is an example plug-in that demonstrates how to store and retrieve instances of the URL.Bookmark class:

(⬇ see below ) To remove the stored bookmark, hold down the Control key when selecting the plug-in from the Automation menu:

Bookmark Example: Open Chosen/Stored Directory

/*{ "type": "action", "targets": ["omnigraffle","omnifocus","omniplan","omnioutliner"], "author": "Otto Automator", "identifier": "com.omni-automation.all.bookmark-example", "version": "1.0", "description": "This plug-in uses the URL.Bookmark class to create and retrieve stored bookmark.", "label": "Bookmark Example", "shortLabel": "Bookmark Example", "paletteLabel": "Bookmark", "image": "gearshape.fill" }*/ (() => { let credentials = new Credentials() let serviceTitle = "source-folder" const action = new PlugIn.Action((selection, sender) => { (async () => { // TO REMOVE BOOKMARK HOLD DOWN CONTROL KEY WHEN SELECTING PLUG-IN if (app.controlKeyDown){ let alertMessage = "Remove the stored bookmark?" let alert = new Alert("Confirmation Required", alertMessage) alert.addOption("Remove") alert.addOption("Cancel") alert.show(buttonIndex => { if (buttonIndex === 0){credentials.remove(serviceTitle)} }) } else { // RETRIEVE BOOKMARK let bookmark = credentials.readBookmark(serviceTitle) // IF NO BOOKMARK, ASK FOR FOLDER if(!bookmark){ let picker = new FilePicker() picker.folders = true picker.multiple = false let chosenDirectoryURLs = await picker.show() bookmark = URL.Bookmark.fromURL(chosenDirectoryURLs[0]) credentials.writeBookmark(serviceTitle, bookmark) bookmark = credentials.readBookmark(serviceTitle) } // RETRIEVE ACCESS TOKEN AND PERFORM ACTION WITH FOLDER let token = await bookmark.access() let url = token.url url.open() } })().catch(err => console.error(err.message)) }); action.validate = (selection, sender) => { // validation code return true }; return action; })();