android.webkit.DownloadListener's onDownloadStart is not called for downloads requested using HTTP POST requests on KK and LL
Reported by
ssivakum...@gmail.com,
Apr 13 2016
|
||
Issue descriptionExample URL: http://awposttester.appspot.com/form/post/direct Steps to reproduce the problem: 1. Create an application with a WebView and register a DownloadListener to it. (See attached application code or use the generated APK in the zip file). 2. Try to download a file from any site that is designed to accept POST requests. Example : http://awposttester.appspot.com/form/post/direct 3. In the example site listed above, clicking on the "Submit" button sends a POST request to the site and results in a download. The download works fine on any other browser, but not on an Android WebView since onDownloadStart is not triggered. NOTE: Downloads are triggered for GET requests. Example : http://awposttester.appspot.com/form/get/direct What is the expected behavior? onDownloadStart should be called for HTTP POST requests as well. What went wrong? The onDownloadStart callback is not triggered and downloads fail. Did this work before? Yes Issue not observed on Jellybean, which is based on WebKit. But fails in KK and above which are based on Chromium. Chrome version: 33+ Channel: stable OS Version: KitKat+ Flash Version: This issue can be seen on all WebView based browsers on the Play Store. Example : Javelin Browser. This is a duplicate of the bug raised in Android on 17-Mar-2015, but no progress has been made on that. I thought it would be more appropriate to raise it here. Issue link - https://code.google.com/p/android/issues/detail?id=160664
,
Apr 13 2016
This isn't just a bug, this is a fundamental thing that will require design and API changes probably, and will need input from the WebView team. The issue is that the POST will alrady have been sent to the server before receiving the response headers that let us know it's a download, and so at that point it's *not safe* to go call onDownloadStart to tell the embedding app that a download was requested, because the app cannot simply redo the POST in case that changes server state a second time. Chrome on Android has a similar dilemma: for GETs, downloads are restarted using the platform download manager, but for POSTs, Chrome has to complete the download using its own network stack (since the platform doesn't support POST downloads, and it couldn't safely do it anyway). To allow POST downloads to work we'd need to have an entirely new API where WebView can actually feed the embedding app the actual bytes of the download, and allow the download to continue using the chromium network stack, or something else I haven't thought of.
,
Apr 13 2016
ALso, did this really work in jellybean? The platform download manager doesn't support POST, so forwarding requests to it won't work, and if the old webview implementation was canceling POST downloads and reporting them to this API, then that's really bad and can potentially result in unwanted server-side side effects...
,
Apr 13 2016
wontfix for now. another explanation of the same thing in https://bugs.chromium.org/p/chromium/issues/detail?id=480986#c14
,
Apr 13 2016
Ah, thanks Bo. That's a better explanation, and yes, there is no way this could have worked in pre-K either, the API simply doesn't make it possible.
,
Apr 13 2016
Hi All, I do understand the problems with repeating the POST request again after the onDownloadStart has been called. But in most cases, the server would just take in a few POST request parameters and respond with the file content. So repeating the request would most likely work. To support this scenario, is it possible to provide an API like onDownloadStart that also provides the POST content so that the embedding app can repeat the request? The API can be documented with a note/warning/caveat stating that this behavior does not adhere to the HTTP spec. This way, the embedding app takes the risk of re-posting the request. I think this relatively simpler fix would handle a lot of cases. Thoughts?
,
Apr 13 2016
That's totally not ok. What if the post request was to send 100 bucks to someone. If you repeat it, suddenly user is sending 200 bucks. (Good servers should catch that as a user mistake, but still not ok for client to do it behind user's back) The correct solution is something like torne mentioned above: > To allow POST downloads to work we'd need to have an entirely new API where WebView can actually feed the embedding app the actual bytes of the download, and allow the download to continue using the chromium network stack, or something else I haven't thought of.
,
Apr 14 2016
well for scenarios where the developer owns both the server and the app, I can see that you can make it work, for example what is told in #6, so it is not totally broken. It is the general scenario that is not achievable. I can however see that most developers shooting themselves in the foot by that.
,
Apr 14 2016
Even if we *did* provide an API that allowed the embedding app to repeat the request, the new API would only be added to the next releases of Android. We can't add APIs in WebView updates. So, this wouldn't actually solve anything for apps running on current OS versions. As I said, there is a way we could solve this with a new API, but it would require the download to complete using the existing request in the Chromium net stack. We may well add this in future, but it hasn't been sufficiently high priority for us to spend our developer resources on yet. :/ Just saying the embedding app takes the risk isn't acceptable - we know from past experience that if we give apps a very easy way to do something wrong and no way to make sure they're doing the right thing, then they will just do it wrong and it will have a negative impact on users. An app that's trying to make a POST download work on a site that the app developer controls might well do the right thing, but your original post was about "WebView based browsers", i.e. general web browsers that are used for arbitrary third party web pages, and it's never going to be okay for a general web browser to assume that just repeating a POST is acceptable.
,
Apr 14 2016
From comment #3 - ALso, did this really work in jellybean? I was wrong in reporting that it works on JellyBean. It does not work. But there is a difference in behavior when compared with KitKat+. In JellyBean, the onDownloadStart callback is triggered. But since the POST content is not known, the download client will hit the received URL as a GET request and download whatever response (most likely the same page) the server sends.
,
Apr 14 2016
OK, so that's probably worse than not calling it at all - I'd consider the current behaviour an improvement. :) |
||
►
Sign in to add a comment |
||
Comment 1 by b...@chromium.org
, Apr 13 2016Components: Mobile>WebView