Created attachment 8808261 [details] Network tab showing 2 xhr POSTs having no status, 0 B, 0 ms following POST of "report?output=xl" document download. 8 rows above see same xhr POSTs with appropriate status and responses. User Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36 Steps to reproduce: While several active XHR requests are awaiting their responses, POST a form to a web service that responds with plain text containing the following headers: Response.AddHeader("Content-Description", "File Transfer") Response.AddHeader("Content-Disposition", "attachment; filename=" & str1 & ".xls") Response.AddHeader("Content-Transfer-Encoding", "binary") Response.AddHeader("Content-Type", "text/html") Actual results: One or more of the active XHR requests receive no response nor status return, or receive a truncated response (resulting in a JSON Parse.error), depending on the actual timing of when the web service downloading file contents sends its response. The file download does complete successfully and the downloaded file's contents are correct. Expected results: The active XHR requests should receive their expected JSON responses without being truncated or completely eliminated, just as they do if the concurrent form POST to download a text file isn't requested by the end user. Please note that the expected results do occur properly when testing the same steps in both Google Chrome and MS Edge.
Keywords: dataloss, reproducible
OS: Unspecified → Windows 10
Hardware: Unspecified → x86_64
Could you provide a simplified testcase to reproduce the issue, please.
Component: Untriaged → Networking
Keywords: dataloss, reproducible → testcase-wanted
Product: Firefox → Core
Thanks, I'll check your email, and test to see if there is a possible regression in Firefox. If a Mozilla dev asks for credentials, I'll forward it to him too.
(In reply to Loic from comment #3) > Thanks, I'll check your email, and test to see if there is a possible > regression in Firefox. If a Mozilla dev asks for credentials, I'll forward > it to him too. Have you been successful using the login credentials I supplied to trigger the truncated/suppressed xhr response problem when simultaneously posting a form to download a plain text file with header "Content-Disposition", "attachment; filename=xxx"?
I tested the testcase your provided by email, I'm able to reproduce the issue, with e10s on/off. I check if it was a recent regression, that's not the case, Firefox 38 has the same behavior too. Patrick, is there someone with time who can test and start to debug the testcase? The testcase is simple, only a few clicks on the page with the Netmonitor open (persistant lohs checked).
Flags: needinfo?(efriedm) → needinfo?(mcmanus)
Keywords: testcase-wanted → testcase
loic can you generate an http_log from nspr? (on nightly/devchannel you can do it dynamically from about:networking) I suspect something is cancelling the whole load group - probably the download manager - and necko is just responding to it. in which case the toolkit/dlmgr is the component to look at - but we can tell from the log if there is a cancel()
Created attachment 8814290 [details] log.txt-main.6276 2 XHR requests received no response in the log (I verified in the Netmonitor) just before downloading the Excel file.
While the "no response" situation is typical, I would like you to note that, depending on the actual timing of the Excel download request, occasionally a pending XHR request will start to receive its (JSON) response, but that response is then truncated by the Excel download request. This typically results in an invalid JSON parse exception being thrown, and is how we noticed the problem. Perhaps that will help shed some light on the cause of the problem?
Kershaw will take a look at this problem. Could Eric or Loic forward him the simplified test case to reproduce it? Thanks.
Assignee: nobody → kechang
I am happy to send Kershaw the simplified test case documentation but I'll need his email address.
(In reply to Shian-Yow Wu [:swu] from comment #9) > Kershaw will take a look at this problem. Could Eric or Loic forward him > the simplified test case to reproduce it? Thanks. I sent him the testcase by email.
(In reply to Loic from comment #11) > (In reply to Shian-Yow Wu [:swu] from comment #9) > > Kershaw will take a look at this problem. Could Eric or Loic forward him > > the simplified test case to reproduce it? Thanks. > > I sent him the testcase by email. Thanks. I am bale to reproduce this bug. As Patrick said in comment #6, the whole load group is canceled. The call stack  shows that it is canceled by |nsDocShell::InternalLoad| . However, I have no idea about the reason behind this. Perhaps bz knows a thing or two?  http://searchfox.org/mozilla-central/rev/d98418da69edeb1f2f8e6f3840157fae1512f89b/docshell/base/nsDocShell.cpp#10592  call stack frame #0: 0x00000001031f0efd XUL`mozilla::net::nsHttpChannel::Cancel(this=0x000000011b887000, status=2152398850) + 157 at nsHttpChannel.cpp:5574 [opt] frame #1: 0x00000001032019ad XUL`non-virtual thunk to mozilla::net::nsHttpChannel::Cancel(this=<unavailable>, status=<unavailable>) + 13 at nsHttpChannel.cpp:5565 [opt] frame #2: 0x0000000102ebadf1 XUL`mozilla::net::nsLoadGroup::Cancel(this=<unavailable>, status=<unavailable>) + 705 at nsLoadGroup.cpp:273 [opt] frame #3: 0x0000000103a1722f XUL`nsDocLoader::Stop(this=<unavailable>) + 351 at nsDocLoader.cpp:243 [opt] frame #4: 0x00000001062f934f XUL`nsDocShell::Stop(unsigned int) [inlined] nsDocShell::Stop(this=<unavailable>) + 543 at nsDocShell.h:189 [opt] frame #5: 0x00000001062f9347 XUL`nsDocShell::Stop(this=0x0000000121b58000, aStopFlags=1) + 535 at nsDocShell.cpp:5525 [opt] frame #6: 0x000000010630b5b3 XUL`nsDocShell::InternalLoad(this=<unavailable>, aURI=<unavailable>, aOriginalURI=0x0000000000000000, aLoadReplace=<unavailable>, aReferrer=<unavailable>, aReferrerPolicy=1, aTriggeringPrincipal=<unavailable>, aPrincipalToInherit=<unavailable>, aFlags=6, aWindowTarget=<unavailable>, aTypeHint=<unavailable>, aFileName=0x000000010930c050, aPostData=0x0000000000000004, aHeadersData=<unavailable>, aLoadType=<unavailable>, aSHEntry=<unavailable>, aFirstParty=<unavailable>, aSrcdoc=<unavailable>, aSourceDocShell=<unavailable>, aBaseURI=<unavailable>, aDocShell=<unavailable>, aRequest=<unavailable>) + 13395 at nsDocShell.cpp:10599 [opt] frame #7: 0x000000010633c961 XUL`nsDocShell::OnLinkClickSync(this=<unavailable>, aContent=<unavailable>, aURI=<unavailable>, aTargetSpec=<unavailable>, aFileName=0x000000010930c050, aPostDataStream=0x000000011b6ffb30, aHeadersDataStream=<unavailable>, aDocShell=<unavailable>, aRequest=<unavailable>) + 2769 at nsDocShell.cpp:14022 [opt] frame #8: 0x000000010500f79e XUL`mozilla::dom::HTMLFormElement::SubmitSubmission(this=0x0000000127411000, aFormSubmission=<unavailable>) + 1294 at HTMLFormElement.cpp:829 [opt] frame #9: 0x000000010500f016 XUL`mozilla::dom::HTMLFormElement::DoSubmit(this=0x0000000127411000, aEvent=<unavailable>) + 454 at HTMLFormElement.cpp:686 [opt] frame #10: 0x000000010500de3a XUL`mozilla::dom::HTMLFormElement::Submit(mozilla::ErrorResult&) [inlined] mozilla::dom::HTMLFormElement::DoSubmitOrReset(this=0x0000000127411000, aEvent=<unavailable>, aMessage=eFormSubmit) + 90 at HTMLFormElement.cpp:606 [opt] frame #11: 0x000000010500dde0 XUL`mozilla::dom::HTMLFormElement::Submit(this=0x0000000127411000, aRv=0x00007fff5fbfb8f8) + 48 at HTMLFormElement.cpp:262 [opt] frame #12: 0x0000000104bdf6fd XUL`mozilla::dom::HTMLFormElementBinding::submit(cx=0x0000000110719000, obj=<unavailable>, self=<unavailable>, args=0x00007fff5fbfb958) + 61 at HTMLFormElementBinding.cpp:661 [opt]
It's very long-standing behavior: all outstanding requests are canceled when a navigation _starts_ (which is before we know whether it will complete), because canceling them after you actually unload the page is not web-compatible, and you _do_ generally want to cancel stuff when you navigate. This behavior has been in place for at least 15 years, I believe. Note that this behavior is also quite clearly specified in the HTML spec, for what it's worth, though there has been some discussion about trying to change that (e.g. by doing the canceling right before firing unload, and not canceling the actual load for the navigation or something). If the spec gets changed, and there is some indication that the changed spec is web-compatible (e.g. if someone else ships it without the world blowing up in their face), we can talk about changing our behavior. I think this is all discussed at length in other bugs, for what it's worth.
Whiteboard: [necko-active] → [necko-active] DUPEME
I think we can close this bug since this seems to be an expected behavior according to comment#13. What do you think, Eric?
I can understand why navigation AWAY from a page that issued AJAX calls would cancel those calls, since the page that issued them has been/will be unloaded. However, in my considered opinion, Content-disposition: attachment is NOT navigation because it doesn't unload the current page; quite the contrary, it's a download of data while REMAINING on the current page. It should not result in canceling of pending AJAX calls since the page that issued them remains the current page. This is conceptually no different than an AJAX request that supplies additional information to be displayed on the current page, which is also clearly not navigation. How else would a persistent page download a file if not by submitting a form that returns the file contents using Content-disposition: attachment? I should reiterate that Mozilla's behavior in canceling these AJAX calls also truncates responses that have already begun to be received. This truncation of a JSON response results in a JSON parse error exception. That's clearly a serious bug. In thorough testing, neither Google Chrome nor MS Edge exhibit this same behavior problem. Both of them properly treat Content-disposition: attachment as NOT being page navigation, because it doesn't unload the current page.
> However, in my considered opinion, Content-disposition: attachment is NOT navigation Per spec it is navigation until you get the response; then the navigation is aborted. > This is conceptually no different than an AJAX request It's conceptually different because the AJAX request cannot possibly navigate, whereas a form submit _can_ and you don't know whether it _will_ until you get the server response. Again, if you think the spec here should change, this discussion should go into a spec issue. Maybe you'll have some luck getting the Google and Microsoft folks to talk to you and describe what they're actually doing. I haven't had such luck. In the meantime, as I said above we are doing exactly what the spec says to do.
Eric, I'm glad the hidden iframe thing worked well for you. > How should this discussion morph into a spec issue? Probably by filing an issue at https://github.com/whatwg/html/issues if there isn't one already. At first glance, https://github.com/whatwg/html/issues/1382 might be more or less about the same thing, maybe.
Boris, i think issue 1382 seems spot on, and I've added my 2 cents comment to it. I don't believe the iFrame workaround should be necessary to avoid this issue, but it clearly works for us. Thanks very much for your help!
I think we can close this bug now. Thanks for bz's detailed explanation.
Status: ASSIGNED → RESOLVED
Last Resolved: 2 years ago
Resolution: --- → INVALID
You need to log in before you can comment on or make changes to this bug.