New issue
Advanced search Search tips

Issue 603014 link

Starred by 3 users

Issue metadata

Status: WontFix
Owner: ----
Closed: Apr 2016
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Android
Pri: 2
Type: Bug



Sign in to add a comment

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 description

Example 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
 
DownloadableWebView.zip
2.5 MB Download
DownloadableWebView.apk
770 KB Download

Comment 1 by b...@chromium.org, Apr 13 2016

Cc: asanka@chromium.org
Components: Mobile>WebView
Asanka: you did some work with downloads, could you please take a look at this?

Comment 2 by torne@chromium.org, 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.

Comment 3 by torne@chromium.org, 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...

Comment 4 by boliu@chromium.org, Apr 13 2016

Status: WontFix (was: Unconfirmed)
wontfix for now. another explanation of the same thing in https://bugs.chromium.org/p/chromium/issues/detail?id=480986#c14

Comment 5 by torne@chromium.org, 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.
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?

Comment 7 by boliu@chromium.org, 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.

Comment 8 by sgu...@chromium.org, 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. 

Comment 9 by torne@chromium.org, 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.

Comment 10 Deleted

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. 

Comment 12 by torne@chromium.org, 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