Getting file from file chooser after extension popup closed

In the previous version of Firefox, it was possible to get and react at a ‘change’ event of a input field of the type ‘file’ from within a popup page, after the file chooser was open and a file was selected.

Since the update of Firefox, this seems to be not possible anymore.
Did anything related to this change?

This kind of functionality is used in one add-on, here:
FlagCookies.js - importing settings file

I don’t see the code for getting the file name in there (not a single name property is being accessed).
In my code the name is accessed through e.target.files[0].name and it still works even in current Nightly 65. Maybe issue with onchange / change handler?

The reason this is happening is that the panel closes on blur – and opening any kind of (non-HTML) dialog takes the focus. This behavior is … unfortunate, but there is no way to prevent it (as an extension developer).

Anyway, after the panel closes and emits its unload event, no other events or timers related to that window will fire.

What could work is to have the background page “own” the input element. Maybe the event will then sill fire even if the panel is gone. But I don’t think that the file picker can be opened while the input element is owned by the background page. So what you might want to try is to transfer the ownership of the element to the background page after the picker is opened.

That could look something like this:

const input = document.querySelector('input[type=file]');

const background = await browser.runtime.getBackgroundPage();
if (!background) { console.warn(`This doesn't work in private windows ...`); return; }

window.onunload = () => {
    background.document.adoptNode(input); // this may or may not help, but if it doesn't, I don't think there is a solution at all ...
};

input.onchange = () => {
    background.doSomethingWith(input.files);
};

Just be aware that your window is still dead, so doSomethingWith should probably be a function from a background script, to avoid weird things.

@juraj.masiar
Thank you for your answer. But there is no need to retrieve the file name as jsZip is can use the file object (blob) directly instead. But as you pointed out, there’s a issue with the change event/handler.

@NilkasG
Indeed that is the case as you describe, I added a fix on Github, which makes use of getBackgroundPage() and document.adoptNode().

This works very well, the only downside to your solution, getBackgroundPage() does not work in ‘Private Windows’.

Also, there was no direct need to make use of the unload event and the import function had to be added directly to the background script.

I committed the changes here:
File input change on Github

Thank you very much help!

Interesting, and good to know that this works.

So to summarize what you are doing /what’s happening (in that order):

  • define the change event handler in a background script
  • the panel opens and has the file input in its DOM
  • input element be adopted by the background page, set the change event handler
  • the node is still in the panels DOM and will be clicked by the user
  • the panel closes but the event is still fired (in the background page)

Is that right? Please do correct me if I’m wrong!

@NilkasG
The steps are right.

For it to work, the function to be called has to be placed in the background script, otherwise, after the blur of the popup page, the function is removed prior and marked as “dead object”, even when anonymous - which is not accessible anymore then.

Just to mention, the trigger for the “background page handling” is called by click on the input. Not on unload, as the input node is not accessible for transfer to the background page at this point.

So yes, it is like you say.

Ah, yes. It might be important to call adoptNode after the click that opens the popup, because I think that it removes the node from its original DOM.
And also that the “entire” event listener must be a background script function, to avoid that [dead object] business.

Thanks for your feedback!

I tried your extension at Firefox 108, set dark mode theme and exported settings, then set it back to light mode and imported the exported settings. Sadly, it did not turn to dark mode theme. Try to adapt your code snippet to my extension to fit Firefox, yet failed.

Hello, the problem seems to be much bigger now. The current solution does, as you explain, not work anymore. And I do not know how to fix this issue at this moment.
The exported settings themself are fine.

From what I understand the flow is as following:

  1. Open the addon from the icon
  2. Open “settings” page
    3a) Click on “Import settings” - this click will also “close” the browser overlay because of the file chooser opening up.
    3b) No import is done, after the file is choosen, as the overlay is closed as this point, so it seems.

This also affects other browsers. Not only Firefox.

Ironically, the normal way to listen to the change event does work in chrome, https://github.com/BoostPic/BoostPic/blob/fe278339a4a9b94cd39bd2d9272f19d376159a30/BoostPic_Chrome/ts/main.ts#L297.

I am wondering whether there is a programmatical way to control ui.popup.disable_autohide from the extension in firefox, https://extensionworkshop.com/documentation/develop/debugging/#debugging-popups

I made a quick, and, somehow, dirty, fix. I use “browser.windows.create” to open a new window in the browser once the “import settings” button is hit.

Inside this window is the file chooser and the “overwrite settings” confirm button. There, the user can freely select a file and import the settings.

I am aware, that this is not pretty but I do not see another way of keeping the addon popup open once the file chooser is shown.

2 Likes