Closed Bug 1658877 Opened 1 year ago Closed 1 year ago

<a download> does not download the file when a Content-Disposition inline header is returned

Categories

(Core :: Networking: HTTP, defect, P2)

79 Branch
defect

Tracking

()

RESOLVED FIXED
82 Branch
Tracking Status
firefox82 --- fixed

People

(Reporter: s.tenbrinke2, Assigned: kershaw)

References

Details

(Keywords: dev-doc-complete, Whiteboard: [necko-triaged])

Attachments

(2 files)

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0

Steps to reproduce:

  • Make a web server return a file with a Content-Disposition: inline;filename="image.jpg" header.
  • Use <a href="URL_TO_FILE_HERE" download="image.jpg">
  • Click on the link

Important:
For download to work, the web server and HTML should be running on the same domain.

Actual results:

The browser opens the file in the browser. (It does not download the file)

Expected results:

It should download the file, or show a download pop-up.

Both Chrome and Chromium Edge DO show me a pop-up or save the file.

I understand that Content-Disposition: inline means that the web server implies that the file should be rendered on/as the page. But <a download> implies that the client wishes to download the file.

I believe that the client is the one who should have higher priority, and thus it should download the file. A website dictates the experience for the user, not the web server. So if a front-end decides that a file should be downloaded, it should.

Attached file SafariDownload.zip

I made this little project to test what the behaviour is on safari, but this project also works fine to demonstrate the issue on firefox.

To run:

  • have dotnet 3.1 installed

  • run dotnet run in the deep folder where csproj is located

  • go to https://localhost:5001/index.html

  • click on the Open file in Browser link -> File should be opened in browser.

  • click on the Download file link -> File should be downloaded.

In firefox, the 2nd link doesn't download the file. On chrome and edge, it does.

Please note that the file we are downloading is actually a fake file. it is not a real png.

Component: Untriaged → DOM: Core & HTML
Product: Firefox → Core

Thanks for your report. It seems it's by design if Content-Disposition: inline, Firefox prefers the header while Chrome prefers download[1]. Redirect this bug to Networking to get further determination.

[1] https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a

Component: DOM: Core & HTML → DOM: Networking

Hi, thanks for your response.

I can't believe I did not read that part; I must have read that page sooo many times.

Anyway, I'd love to discuss what happens next. It is (probably) a breaking change, but I believe that the behavior of basically every other big browser is correct, compared to what Firefox does :).

Component: DOM: Networking → File Handling
Product: Core → Firefox

Um, why did this get moved to File Handling without comment? The code for <a download> is part of Gecko, so if it doesn't work as desired, this is not the right place.

I'm also confused because comment #2 suggests this should be resolved "WFM" based on a statement of fact about behaviour taken from MDN, when really it sounds like Safari and Chrome and us do different things, so if we're not wrong then they are, or the spec is unclear. A casual look at the spec ( https://html.spec.whatwg.org/multipage/links.html#as-a-download ) suggests we're wrong ("it should provide the user with a way to save the resource for later use, if a resource is successfully obtained"). Anne, thoughts on this one?

As far as I can tell, docshell saves the filename / "this is a download" info onto the channel at https://searchfox.org/mozilla-central/rev/6cc48251bb97600fdf11a5b4c5f621bfc8606d55/docshell/base/nsDocShell.cpp#9305-9321 , or perhaps an equivalent thing in parent-process-document-channel, and maybe then it gets overwritten by the headers from the request, or something? That sounds to me like it'd be a networking bug... The URILoader code just asks the channel for the content disposition info later. If the download attribute is meant to trump that, the channel code should be ensuring that...

Component: File Handling → DOM: Networking
Flags: needinfo?(kershaw)
Flags: needinfo?(annevk)
Product: Firefox → Core

(In reply to :Gijs (he/him) from comment #4)

Um, why did this get moved to File Handling without comment? The code for <a download> is part of Gecko, so if it doesn't work as desired, this is not the right place.

Sorry, I thought this kind of issue belongs to File Handling. I'll wait for Anne's info and decide the next step.

Flags: needinfo?(kershaw)

We had some discussion around this 8 years ago when the feature was implemented: bug 676619 comment 118. At that point in time basically no spec existed.

With a better spec now available, would it be a good idea to do some research if this would be a huge breaking change? If the spec indicates that firefox does it wrong, I feel like it would be the right thing to do? :)

As far as I can tell Gijs is correct. (Please don't use MDN as a reference for what to implement, it's not authoritative.) For same-origin resources the download attribute should win and that it doesn't is the result of how it appears to be implemented (using an internal Content-Disposition header that gets overridden).

Flags: needinfo?(annevk)
Assignee: nobody → kershaw
Severity: -- → S3
Component: DOM: Networking → Networking: HTTP
Priority: -- → P2
Whiteboard: [necko-triaged]
See Also: → 1660636

I see a discussion in the phabricator link about the following situation:

Content-Disposition: inline; filename="test.pdf"

and

<a download="othername.pdf">

Apparently safari would use the othername.pdf, while chrome and edge use test.pdf from the header.

Perhaps the bug Tom links is related to my point, I am not very sure.

My point is that I think that safari does it right, and firefox should follow safari's behavior.

Chrome, Safari and Edge all respect the browser's preference when <a download> is used; If the server says that it should be shown in the browser, it will be downloaded instead.

So why do Chrome and Edge choose the client's side for the download, but the server's side for the file name that will be used? It makes no sense to me.

Safari's behaviour is a lot better, in my opinion. if <a download="test.pdf"> is used, it will be downloaded and it will be downloaded with the the client's desired filename.

Pushed by kjang@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/3737bbc9e671
Don't overwrite mContentDispositionHint if it's DISPOSITION_ATTACHMENT r=valentin,Gijs
Status: UNCONFIRMED → RESOLVED
Closed: 1 year ago
Resolution: --- → FIXED
Target Milestone: --- → 82 Branch

(In reply to Anne (:annevk) from comment #8)

As far as I can tell Gijs is correct. (Please don't use MDN as a reference for what to implement, it's not authoritative.) For same-origin resources the download attribute should win and that it doesn't is the result of how it appears to be implemented (using an internal Content-Disposition header that gets overridden).

If MDN is wrong, please fix it or set keyword.

Keywords: dev-doc-needed

(In reply to j.j. from comment #13)

(In reply to Anne (:annevk) from comment #8)

As far as I can tell Gijs is correct. (Please don't use MDN as a reference for what to implement, it's not authoritative.) For same-origin resources the download attribute should win and that it doesn't is the result of how it appears to be implemented (using an internal Content-Disposition header that gets overridden).

If MDN is wrong, please fix it or set keyword.

MDN isn't wrong, it's more that it describes current behaviour (warts and all, just look at some of the stuff it used to have about IE if that's your jam), and shouldn't be used to determine whether Gecko's current behaviour is correct per the specification / web-compatible.

I added more info about the header/attribute behaviour to MDN. It may take a few minutes to update.

MDN now mentions this

If the header specifies a filename, it takes priority over the attribute.

Can anyone explain to me why this is done? I questioned this decision in a previous comment. If the spec specifies this, can anyone tell me why this is a better idea than letting the client decide? Why does the spec say this :)?

The server is more authoritative and sites shouldn't be able to spoof it.

(In reply to :Gijs (he/him) from comment #14)

If MDN is wrong, please fix it or set keyword.

MDN isn't wrong, it's more that it describes current behaviour (warts and all, just look at some of the stuff it used to have about IE if that's your jam), and shouldn't be used to determine whether Gecko's current behaviour is correct per the specification / web-compatible.

I added more info about the header/attribute behaviour to MDN.

Thanks!
With "wrong" I meant MDN didn't state reality before (Chromium vs. Firefox vs. spec) and especially after this bugfix.
That said, these days MDN actually describes specced behaviour and even has links to bug reports if browsers don't follow. There is signifiant input from Google/Chromium folks.

I took the result of this thread to mean that from build 82:

  • if download is specified in HTML the file will be downloaded, even if the content-disposition header specifies inline, and irrespective of the value of the filename in the attribute or the header.
  • if both the content disposition header and download specify a filename, then the filename that is used will be the one in the header (because that is more authoritative).

Is that correct? that is not quite what the note on https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#Attributes says. But I want to confirm ^^^ before modifying.

that is not quite what the note on https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#Attributes says. But I want to confirm ^^^ before modifying.

Specifically, it says

If the header specifies a disposition of inline but no filename, Chrome, and Firefox 82 and later, prioritize the attribute and treat it as a download.

The implication might be that if the header specifies a disposition of inline and also a filename then perhaps it does something different. Probably "but not filename" is redundant.

:annevk, can you help Hamish out with his questions about the documentation? Thanks ;-)

Flags: needinfo?(annevk)

(In reply to Hamish Willee from comment #19)

I took the result of this thread to mean that from build 82:

  • if download is specified in HTML the file will be downloaded, even if the content-disposition header specifies inline, and irrespective of the value of the filename in the attribute or the header.

This is correct when this is a same-origin download.
For cross-origin case, I think we only download the file when the header specifies the attachment disposition type, but I didn't verify this.

  • if both the content disposition header and download specify a filename, then the filename that is used will be the one in the header (because that is more authoritative).

Correct.

The MDN documentation is correct (including noting the difference between same-origin and cross-origin). Gijs already updated it as per comment 15 and did a great job.

I suspect there might be an issue that dev-doc-complete did not propagate to the spreadsheet that Hamish is presumably looking at?

Flags: needinfo?(annevk) → needinfo?(cmills)

Thanks very much :annevk, :kershaw.

Yes Gijs did a great job in the note - without which I would have been stumped. I have done a minor update to make it a little more readable (to me) and to remove the unnecessary "but no filename" bit in "If the header specifies a disposition of inline but no filename,"

I also added a simpler note in Content-Disposition > As a response header for the main body.

Flags: needinfo?(cmills)

Hey guys!

What is your policy on mentioning bug fixes in release notes?

Not to sound petty, but I was pretty proud of finding this bug and getting it fixed for everyone! I expected to find it in the release notes somewhere but I can't find it :)

https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/82#HTTP(In reply to s.tenbrinke2 from comment #25)

Hey guys!

What is your policy on mentioning bug fixes in release notes?

Not to sound petty, but I was pretty proud of finding this bug and getting it fixed for everyone! I expected to find it in the release notes somewhere but I can't find it :)

It's me me me with you :-). Joking, you should be pleased.

The policy is that all fixes go into the release notes, which is why you will find a note for this, with linked bug, where you would expect: Releases/82#HTTP. Perhaps you were looking in the wrong release?

This issue is still present on 87.0a1 when redirection is involved. Suppose there is an <a download> to link to api/data endpoint that immediately redirects to api/data?token=xxx which then returns Content-Disposition: inline, Chromium/Safari will proceed to download the content (intended behavior) while Firefox tries to play the content inline.

Flags: needinfo?(jstutte)

Jesse, could you file a new bug on that?

(In reply to Anne (:annevk) from comment #28)

Jesse, could you file a new bug on that?

^

Flags: needinfo?(jstutte) → needinfo?(jc)

(In reply to Anne (:annevk) from comment #28)

Jesse, could you file a new bug on that?

(In reply to Jens Stutte [:jstutte] from comment #29)

(In reply to Anne (:annevk) from comment #28)

Jesse, could you file a new bug on that?

^

https://bugzilla.mozilla.org/show_bug.cgi?id=1689018

Thanks.

Flags: needinfo?(jc)
Blocks: 1689018

Thank you! 😊

You need to log in before you can comment on or make changes to this bug.