This issue occurs in the latest version of Electron, but not in Chromium outside of Electron.
The following example code uses the Filesystem API's showDirectoryPicker method to open a directory-picker when a user clicks a button:
async function handleClick() {
try {
dirHandle = await window.showDirectoryPicker({startIn: "downloads"});
} catch (error) {
console.log(error);
}
}
However the following circumstances lead to the directory-picker being permanently broken:
Downloads
already, so doesn't think they need to create/choose a subdirectoryOpen
without making an explicit choicedirHandle
is null.showDirectoryPicker()
throws an AbortError
of NotAllowedError: Failed to execute 'showDirectoryPicker' on 'Window': File picker already active.
Any subsequent clicks to open the directory-picker fail with this same NotAllowedError: Failed to execute 'showDirectoryPicker' on 'Window': File picker already active.
error.
So my question is: How can I deactivate, reset, close, delete, resolve, etc., the File Picker, so that it can be opened a second time. I can't make the dirHandle
null since it's already null. Likewise, the Promise returned by showDirectoryPicker()
is already resolved.
Any solution would be very welcome. There has to be some obvious way to resolve this, because otherwise it would be a massive bug in the Filesystem API.
Alternatively, is there any way to make showDirectoryPicker() just actually pick that starting directory (Downloads
in this case)?
This only appears to be happening in Electron. In normal Chromium, this issue cannot occur because instead of giving the user an Open
option, it gives them a Select
option, and won't allow them not to select a directory.
This turned out to be an Electron-specific Issue. Luckily, one of the Electron engineers has pushed a fix that allows you to catch if a user tries to select a protected System directory. Better yet, the Electron implementation now lets the developer choose to offer the user the option to override the restriction and specify one of these directories, such as Desktop
, Documents
, Downloads
, etc.
The fix is documented in the Electron Documentation.
In short, you just need to make sure to include dialog
and session
from electron
at the top of main.js
:
const { app, dialog, BrowserWindow, session } = require('electron')
and then add code like the following into your createWindow()
function:
session.defaultSession.on('file-system-access-restricted', async (e, details, callback) => {
const { origin, path } = details
const { response } = await dialog.showMessageBox({
message: `Are you sure you want ${origin} to open restricted path ${path}?`,
title: 'File System Access Restricted',
buttons: ['Choose a different folder', 'Allow', 'Cancel'],
cancelId: 2
})
if (response === 0) {
callback('tryAgain')
} else if (response === 1) {
callback('allow')
} else {
callback('deny')
}
})
This will prompt the user with a dialog box if they try and pick a protected directory, and give them the option to "Choose a different folder", "Allow" using that directory, or "Cancel". Even if they click "Cancel", they'll still be able to use the directory-picker again, unlike before.