Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specify cancelling a file upload from a file input #6376

Closed
adroitwhiz opened this issue Feb 11, 2021 · 20 comments · Fixed by #6735
Closed

Specify cancelling a file upload from a file input #6376

adroitwhiz opened this issue Feb 11, 2021 · 20 comments · Fixed by #6735
Labels
interop Implementations are not interoperable with each other needs tests Moving the issue forward requires someone to write tests topic: forms

Comments

@adroitwhiz
Copy link
Contributor

When you activate a file input, most (all?) browsers open a file chooser dialog of some sort that allows you to choose a file, or cancel the operation.

However, the specification appears to completely ignore the latter option:

Run these steps in parallel:

  1. Optionally, wait until any prior execution of this algorithm has terminated.

  2. Display a prompt to the user requesting that the user specify some files. If the multiple attribute is not set, there must be no more than one file selected; otherwise, any number may be selected. Files can be from the filesystem or created on the fly, e.g., a picture taken from a camera connected to the user's device.

  3. Wait for the user to have made their selection.

  4. Update the file selection for the input element.

(Side note: "Run these steps in parallel... Wait" is a bit of a contradiction, no?)

Anyway, the language there seems to assume that the user will have made a selection, which may not be the case if the "cancel" button is pressed.

There seems to be at least one difference between browsers as a result of this--in Firefox and WebKit (via the Midori browser), cancelling a file select dialog will retain the previous state of the input and not emit any events, whereas in Chromium, it will change the state of the input to "no files selected" and emit a change event. These were the results on Linux--they may be different on other platforms.

As a result of this, there is currently no cross-browser way to tell if a user has clicked "Cancel" on a file upload dialog. Such a feature would be useful, for instance, if you want to put an "upload file" option in a menu that closes after you upload a file or cancel the dialog.

It would be useful to clarify the intended behavior here. If the intended behavior when canceling/closing the file selection dialog is to empty the file selection and count that as a change, then Firefox and WebKit should change. If the intended behavior is to retain the previous input and not emit a change event, then perhaps a cancel event could be added so that file dialogs opened via JavaScript would always resolve rather than leaving the caller hanging, so to speak?

@annevk
Copy link
Member

annevk commented Feb 11, 2021

In parallel effectively creates a new thread. Waiting there is fine. (At least in spec language.)

I think per the current language Firefox and Safari ought to change as canceling is making a selection, essentially.

cc @whatwg/forms

@annevk annevk added interop Implementations are not interoperable with each other needs tests Moving the issue forward requires someone to write tests topic: forms labels Feb 11, 2021
@zcorpan
Copy link
Member

zcorpan commented Feb 11, 2021

I disagree that canceling is making a selection. I would expect the file picker to retain the previously selected files. But I haven't done a usability study.

Is Chrome's behavior deliberate?

@annevk
Copy link
Member

annevk commented Feb 11, 2021

Ah, I misread, I would not expect the selection to change either in that case, but I could still see it being considered a selection.

@domenic
Copy link
Member

domenic commented Feb 26, 2021

Note the new File System Access API has well-specified behavior for this case

If the user dismissed the prompt without making a selection, reject p with an AbortError [sic] and abort.

Also web developers are apparently using fun hacks to try to detect this.

So I think we should specify this in more detail. However, given the different API surface without a clear error delivery channel, I'm not sure which behavior we should pick. /cc @mkruisselbrink, especially since Chrome is the odd one out.

@mkruisselbrink
Copy link
Contributor

https://crbug.com/1100116 was a request for an explicit cancel event of some sorts for input type=file. Not sure if that would be weird or not. I would tend to agree that cancelling not changing the selection seems more intuitive. Not sure if there is any historical reason for Chrome's current behavior.

@adroitwhiz
Copy link
Contributor Author

From the last couple of mentions of this issue, people still seem to be running into this--I'm not sure who else to solicit opinions from to obtain some consensus and move this forward.

I don't have any opinion on whether canceling should be considered making a selection, but if it is decided that it doesn't count, then I definitely think that a cancel event should be added soon after (or along with) the relevant spec change, just so that web developers have some way of telling that it occurred.

@tomayac Since you ran into this a couple times, do you have an opinion on this?

@domenic domenic added the agenda+ To be discussed at a triage meeting label Apr 5, 2021
@domenic
Copy link
Member

domenic commented Apr 5, 2021

I've added agenda+ to this issue as it seems like the folks who have been attending the triage meetings (#6551) might be able to help with it. /cc @smaug---- @mfreed7 in case they want to read up in advance.

@tomayac
Copy link

tomayac commented Apr 6, 2021

@tomayac Since you ran into this a couple times, do you have an opinion on this?

FWIW, we have undone our previous hack due to incompatibility issues with Firefox (it worked in WebKit/Chromium-based browsers). We now approximate the behavior we would get from a proper cancelation event or an AbortError, which seems to work well enough as a workaround, but would definitely appreciate a clean way to handle this situation.

@annevk
Copy link
Member

annevk commented May 7, 2021

Coming back to this after the triage meeting. Even if canceling would clear an existing selection and fire the change event, that wouldn't help when there is no existing selection. As is the case when you wrap <input type=file>.click() in a function. So it seems that even though that behavior difference exists when there is an existing selection, you need something like a cancel (or abort?) signal either way.

It does seem somewhat reasonable to offer such a signal, though the signal should not be used when canceling alters the selection, as can be the case in Chrome today.

I wonder if we offer this signal, if we should restrict it to first parties (same origin with top-level origin) as a first step toward making this dialog harder to use from a third party context.

Aside: usability of this control leaves a lot to be desired. In Firefox/Safari you cannot clear your selection. In Chrome you can only clear it through clicking "Choose File" first.

@tomayac
Copy link

tomayac commented May 7, 2021

Somewhat related: I realized that Safari makes <a download> cancelable, whereas all other browsers immediately perform the download. Whatever mechanism we come up with for the present issue should probably also work for <a download>.

Screen Shot 2021-05-07 at 15 24 07

@domenic
Copy link
Member

domenic commented May 7, 2021

though the signal should not be used when canceling alters the selection, as can be the case in Chrome today.

Why?

Whatever mechanism we come up with for the present issue should probably also work for <a download>.

That seems like pretty dangerous scope creep to me, which is likely to derail this idea :(.

@annevk
Copy link
Member

annevk commented May 7, 2021

@domenic would you expect both abort and a change event in some order? What if a browser offered a "clear selection" button? It seems to me that if pressing cancel actually changes the selection it's not an abort, but a change.

@adroitwhiz
Copy link
Contributor Author

Getting the notification reminded me to ask this:

I wonder if we offer this signal, if we should restrict it to first parties (same origin with top-level origin) as a first step toward making this dialog harder to use from a third party context.

What's the rationale behind making the dialog harder to use from a third party context?

Also, was a decision reached as to whether cancelling should clear the selection or not, or if it's fine with that being browser-specific?

@annevk
Copy link
Member

annevk commented May 7, 2021

What's the rationale behind making the dialog harder to use from a third party context?

We don't want third parties to be able to show dialogs generally (it might be okay if the first party grants it that ability through Permissions Policy).

No decisions were reached (we don't make decisions during meetings).

@domenic
Copy link
Member

domenic commented May 7, 2021

@domenic would you expect both abort and a change event in some order?

Yeah, that's what I would expect.

What if a browser offered a "clear selection" button?

That would be only a change event. Effectively, Chrome's UX combines both of those into the cancel button.

It seems to me that if pressing cancel actually changes the selection it's not an abort, but a change.

It's both, IMO.

@adroitwhiz
Copy link
Contributor Author

We don't want third parties to be able to show dialogs generally (it might be okay if the first party grants it that ability through a Permissions Policy).

In that case, I don't think making the API surface less ergonomic in third-party contexts would help matters. I doubt the types of people who want to do malicious/shady things by opening dialogs would be deterred by bad ergonomics, but legitimate developers would definitely suffer.

@annevk
Copy link
Member

annevk commented May 7, 2021

If we offer Permissions Policy legitimate developers would end up adopting that and then we could block it for the other cases.

@adroitwhiz
Copy link
Contributor Author

I agree that Permissions Policy would be the way to go--I'm saying that making the cancel/abort event only usable from first-party contexts reduces ergonomics without providing any increase in security. I'm completely fine with blocking the ability to open dialogs in the first place.

@adroitwhiz
Copy link
Contributor Author

It's both, IMO.

To me, at least, abort would indicate a lack of change--e.g. the user was going to change their selection but instead chose not to, and thus abort and change seem mutually exclusive to me.

@domenic
Copy link
Member

domenic commented Jun 3, 2021

I've put up a pull request at #6735; thoughts appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
interop Implementations are not interoperable with each other needs tests Moving the issue forward requires someone to write tests topic: forms
Development

Successfully merging a pull request may close this issue.

6 participants