"Save As" for content retrieved via POST works in most circumstances.

If the content is in the HTTP cache, this will work in the following cases:
  - "Save Page As" from the wrench menu for non-HTML pages.
  - Context-menu save image as, or save audio/video plugin as.
  - ViewHostMsg_SaveURLAs IPC's.
  
This will work for back/forward navigations to an item which was POST'ed, as well as for tabs restored via the TabRestoreService.

It does not work for tabs restored via the SessionService, such as after Chrome crashes or for users who have the "Reopen the Pages that were Open Last" option set.

This CL currently depends on http://codereview.chromium.org/9317009/
 
BUG=55551
TEST=DownloadTest.SavePageNonHTMLViaPost


Review URL: http://codereview.chromium.org/9314037

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@120494 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index aee4d14..ae29289 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -34,6 +34,7 @@
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents_delegate.h"
+#include "net/base/upload_data.h"
 
 // TODO(benjhayden): Change this to DCHECK when we have more debugging
 // information from the next dev cycle, before the next stable/beta branch is
@@ -54,10 +55,11 @@
 
 // Param structs exist because base::Bind can only handle 6 args.
 struct URLParams {
-  URLParams(const GURL& url, const GURL& referrer)
-    : url_(url), referrer_(referrer) {}
+  URLParams(const GURL& url, const GURL& referrer, int64 post_id)
+    : url_(url), referrer_(referrer), post_id_(post_id) {}
   GURL url_;
   GURL referrer_;
+  int64 post_id_;
 };
 
 struct RenderParams {
@@ -76,6 +78,17 @@
   scoped_ptr<net::URLRequest> request(
       new net::URLRequest(url_params.url_, resource_dispatcher_host));
   request->set_referrer(url_params.referrer_.spec());
+  if (url_params.post_id_ >= 0) {
+    // The POST in this case does not have an actual body, and only works
+    // when retrieving data from cache. This is done because we don't want
+    // to do a re-POST without user consent, and currently don't have a good
+    // plan on how to display the UI for that.
+    DCHECK(prefer_cache);
+    request->set_method("POST");
+    scoped_refptr<net::UploadData> upload_data = new net::UploadData();
+    upload_data->set_identifier(url_params.post_id_);
+    request->set_upload(upload_data);
+  }
   resource_dispatcher_host->BeginDownload(
       request.Pass(), prefer_cache, save_info,
       DownloadResourceHandler::OnStartedCallback(),
@@ -814,6 +827,7 @@
     const GURL& referrer,
     const std::string& referrer_charset,
     bool prefer_cache,
+    int64 post_id,
     const DownloadSaveInfo& save_info,
     WebContents* web_contents) {
   ResourceDispatcherHost* resource_dispatcher_host =
@@ -826,7 +840,7 @@
       BrowserThread::IO, FROM_HERE,
       base::Bind(
           &BeginDownload,
-          URLParams(url, referrer),
+          URLParams(url, referrer, post_id),
           prefer_cache,
           save_info,
           resource_dispatcher_host,