summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/chromeos/imageburner/burn_manager.cc1
-rw-r--r--chrome/browser/download/download_browsertest.cc58
-rw-r--r--chrome/browser/extensions/webstore_installer.cc2
-rw-r--r--chrome/browser/tab_contents/render_view_context_menu.cc48
-rw-r--r--chrome/test/data/downloads/form_page_to_post.html17
-rw-r--r--content/browser/download/download_manager_impl.cc20
-rw-r--r--content/browser/download/download_manager_impl.h1
-rw-r--r--content/browser/download/drag_download_file.cc1
-rw-r--r--content/browser/renderer_host/resource_dispatcher_host.cc9
-rw-r--r--content/browser/tab_contents/tab_contents.cc48
-rw-r--r--content/browser/tab_contents/tab_contents.h3
-rw-r--r--content/public/browser/download_manager.h6
-rw-r--r--content/test/mock_download_manager.h3
13 files changed, 177 insertions, 40 deletions
diff --git a/chrome/browser/chromeos/imageburner/burn_manager.cc b/chrome/browser/chromeos/imageburner/burn_manager.cc
index 502b588..ffb35eb 100644
--- a/chrome/browser/chromeos/imageburner/burn_manager.cc
+++ b/chrome/browser/chromeos/imageburner/burn_manager.cc
@@ -432,6 +432,7 @@ void Downloader::OnFileStreamCreated(const GURL& url,
web_contents->GetURL(),
web_contents->GetEncoding(),
false,
+ -1,
save_info,
web_contents);
} else {
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc
index 1cf1b05..f2ac365 100644
--- a/chrome/browser/download/download_browsertest.cc
+++ b/chrome/browser/download/download_browsertest.cc
@@ -44,9 +44,11 @@
#include "content/browser/download/download_persistent_store_info.h"
#include "content/browser/net/url_request_mock_http_job.h"
#include "content/browser/net/url_request_slow_download_job.h"
+#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/renderer_host/resource_dispatcher_host.h"
#include "content/public/browser/download_item.h"
#include "content/public/browser/download_manager.h"
+#include "content/public/browser/notification_source.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/page_transition_types.h"
#include "net/base/net_util.h"
@@ -1701,7 +1703,7 @@ IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadUrl) {
DownloadSaveInfo save_info;
save_info.prompt_for_save_location = true;
DownloadManagerForBrowser(browser())->DownloadUrl(
- url, GURL(""), "", false, save_info, web_contents);
+ url, GURL(""), "", false, -1, save_info, web_contents);
observer->WaitForFinished();
EXPECT_TRUE(observer->select_file_dialog_seen());
@@ -1728,7 +1730,7 @@ IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadUrlToPath) {
DownloadTestObserver* observer(CreateWaiter(browser(), 1));
DownloadManagerForBrowser(browser())->DownloadUrl(
- url, GURL(""), "", false, save_info, web_contents);
+ url, GURL(""), "", false, -1, save_info, web_contents);
observer->WaitForFinished();
// Check state.
@@ -1774,3 +1776,55 @@ IN_PROC_BROWSER_TEST_F(DownloadTest, SavePageNonHTMLViaGet) {
ASSERT_EQ(1u, download_items.size());
ASSERT_EQ(url, download_items[0]->GetOriginalUrl());
}
+
+IN_PROC_BROWSER_TEST_F(DownloadTest, SavePageNonHTMLViaPost) {
+ // Do initial setup.
+ ASSERT_TRUE(InitialSetup(false));
+ ASSERT_TRUE(test_server()->Start());
+ NullSelectFile(browser());
+ std::vector<DownloadItem*> download_items;
+ GetDownloads(browser(), &download_items);
+ ASSERT_TRUE(download_items.empty());
+
+ // Navigate to a form page.
+ GURL form_url = test_server()->GetURL(
+ "files/downloads/form_page_to_post.html");
+ ASSERT_TRUE(form_url.is_valid());
+ ui_test_utils::NavigateToURL(browser(), form_url);
+
+ // Submit the form. This will send a POST reqeuest, and the response is a
+ // JPEG image. The resource also has Cache-Control: no-cache set,
+ // which normally requires revalidation each time.
+ GURL jpeg_url = test_server()->GetURL("files/post/downloads/image.jpg");
+ ASSERT_TRUE(jpeg_url.is_valid());
+ WebContents* web_contents = browser()->GetSelectedWebContents();
+ ASSERT_TRUE(web_contents != NULL);
+ ui_test_utils::WindowedNotificationObserver observer(
+ content::NOTIFICATION_NAV_ENTRY_COMMITTED,
+ content::Source<content::NavigationController>(
+ &web_contents->GetController()));
+ RenderViewHost* render_view_host = web_contents->GetRenderViewHost();
+ ASSERT_TRUE(render_view_host != NULL);
+ render_view_host->ExecuteJavascriptInWebFrame(
+ string16(), ASCIIToUTF16("SubmitForm()"));
+ observer.Wait();
+ EXPECT_EQ(jpeg_url, web_contents->GetURL());
+
+ // Stop the test server, and then try to save the page. If cache validation
+ // is not bypassed then this will fail since the server is no longer
+ // reachable. This will also fail if it tries to be retrieved via "GET"
+ // rather than "POST".
+ ASSERT_TRUE(test_server()->Stop());
+ scoped_ptr<DownloadTestObserver> waiter(
+ new DownloadTestObserver(
+ DownloadManagerForBrowser(browser()), 1, DownloadItem::COMPLETE,
+ false, DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL));
+ browser()->SavePage();
+ waiter->WaitForFinished();
+
+ // Validate that the correct file was downloaded.
+ GetDownloads(browser(), &download_items);
+ EXPECT_TRUE(waiter->select_file_dialog_seen());
+ ASSERT_EQ(1u, download_items.size());
+ ASSERT_EQ(jpeg_url, download_items[0]->GetOriginalUrl());
+}
diff --git a/chrome/browser/extensions/webstore_installer.cc b/chrome/browser/extensions/webstore_installer.cc
index cb9a9b03..57f1493 100644
--- a/chrome/browser/extensions/webstore_installer.cc
+++ b/chrome/browser/extensions/webstore_installer.cc
@@ -215,7 +215,7 @@ void WebstoreInstaller::StartDownload(FilePath file) {
download_util::INITIATED_BY_WEBSTORE_INSTALLER_COUNT);
profile_->GetDownloadManager()->DownloadUrl(
download_url_, referrer, "",
- false, save_info, controller_->GetWebContents());
+ false, -1, save_info, controller_->GetWebContents());
}
void WebstoreInstaller::ReportFailure(const std::string& error) {
diff --git a/chrome/browser/tab_contents/render_view_context_menu.cc b/chrome/browser/tab_contents/render_view_context_menu.cc
index e24f65e..af82831 100644
--- a/chrome/browser/tab_contents/render_view_context_menu.cc
+++ b/chrome/browser/tab_contents/render_view_context_menu.cc
@@ -1484,27 +1484,51 @@ void RenderViewContextMenu::ExecuteCommand(int id, int event_flags) {
content::PAGE_TRANSITION_LINK);
break;
- case IDC_CONTENT_CONTEXT_SAVEAVAS:
- case IDC_CONTENT_CONTEXT_SAVEIMAGEAS:
case IDC_CONTENT_CONTEXT_SAVELINKAS: {
download_util::RecordDownloadCount(
download_util::INITIATED_BY_CONTEXT_MENU_COUNT);
const GURL& referrer =
params_.frame_url.is_empty() ? params_.page_url : params_.frame_url;
- const GURL& url =
- (id == IDC_CONTENT_CONTEXT_SAVELINKAS ? params_.link_url :
- params_.src_url);
+ const GURL& url = params_.link_url;
+ DownloadSaveInfo save_info;
+ save_info.prompt_for_save_location = true;
DownloadManager* dlm =
DownloadServiceFactory::GetForProfile(profile_)->GetDownloadManager();
- // For images and AV "Save As" context menu commands, save the cached
- // data even if it is no longer valid. This helps ensure that the content
- // that is visible on the page is what is saved. For links, this behavior
- // is not desired since the content being linked to is not visible.
- bool prefer_cache = (id != IDC_CONTENT_CONTEXT_SAVELINKAS);
+ dlm->DownloadUrl(url,
+ referrer,
+ params_.frame_charset,
+ false, // Don't prefer_cache
+ -1, // No POST id
+ save_info,
+ source_web_contents_);
+ break;
+ }
+
+ case IDC_CONTENT_CONTEXT_SAVEAVAS:
+ case IDC_CONTENT_CONTEXT_SAVEIMAGEAS: {
+ download_util::RecordDownloadCount(
+ download_util::INITIATED_BY_CONTEXT_MENU_COUNT);
+ const GURL& referrer =
+ params_.frame_url.is_empty() ? params_.page_url : params_.frame_url;
+ const GURL& url = params_.src_url;
DownloadSaveInfo save_info;
save_info.prompt_for_save_location = true;
- dlm->DownloadUrl(url, referrer, params_.frame_charset,
- prefer_cache, save_info, source_web_contents_);
+ int64 post_id = -1;
+ if (url == source_web_contents_->GetURL()) {
+ const NavigationEntry* entry =
+ source_web_contents_->GetController().GetActiveEntry();
+ if (entry)
+ post_id = entry->GetPostID();
+ }
+ DownloadManager* dlm =
+ DownloadServiceFactory::GetForProfile(profile_)->GetDownloadManager();
+ dlm->DownloadUrl(url,
+ referrer,
+ "",
+ true, // prefer_cache
+ post_id,
+ save_info,
+ source_web_contents_);
break;
}
diff --git a/chrome/test/data/downloads/form_page_to_post.html b/chrome/test/data/downloads/form_page_to_post.html
new file mode 100644
index 0000000..8202505
--- /dev/null
+++ b/chrome/test/data/downloads/form_page_to_post.html
@@ -0,0 +1,17 @@
+<html>
+<head>
+ <title>Page with POST form</title>
+
+<script>
+ function SubmitForm() {
+ document.forms['doit'].submit();
+ }
+</script>
+
+</head>
+<body>
+ <form id="doit" action="/files/post/downloads/image.jpg" method="post">
+ <input type="Submit" value="Do It"/>
+ </form>
+</body>
+</html>
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 @@ namespace {
// 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 @@ void BeginDownload(const URLParams& url_params,
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 @@ void DownloadManagerImpl::DownloadUrl(
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 @@ void DownloadManagerImpl::DownloadUrl(
BrowserThread::IO, FROM_HERE,
base::Bind(
&BeginDownload,
- URLParams(url, referrer),
+ URLParams(url, referrer, post_id),
prefer_cache,
save_info,
resource_dispatcher_host,
diff --git a/content/browser/download/download_manager_impl.h b/content/browser/download/download_manager_impl.h
index 7fda51b..ce28cc8 100644
--- a/content/browser/download/download_manager_impl.h
+++ b/content/browser/download/download_manager_impl.h
@@ -59,6 +59,7 @@ class CONTENT_EXPORT DownloadManagerImpl
const GURL& referrer,
const std::string& referrer_encoding,
bool prefer_cache,
+ int64 post_id,
const DownloadSaveInfo& save_info,
content::WebContents* web_contents) OVERRIDE;
virtual void AddObserver(Observer* observer) OVERRIDE;
diff --git a/content/browser/download/drag_download_file.cc b/content/browser/download/drag_download_file.cc
index 81f9d12..cecb9be 100644
--- a/content/browser/download/drag_download_file.cc
+++ b/content/browser/download/drag_download_file.cc
@@ -137,6 +137,7 @@ void DragDownloadFile::InitiateDownload() {
referrer_,
referrer_encoding_,
false,
+ -1,
save_info,
web_contents_);
download_stats::RecordDownloadCount(
diff --git a/content/browser/renderer_host/resource_dispatcher_host.cc b/content/browser/renderer_host/resource_dispatcher_host.cc
index d915806..1d8c8df 100644
--- a/content/browser/renderer_host/resource_dispatcher_host.cc
+++ b/content/browser/renderer_host/resource_dispatcher_host.cc
@@ -894,7 +894,14 @@ net::Error ResourceDispatcherHost::BeginDownload(
request->set_context(request_context);
int extra_load_flags = net::LOAD_IS_DOWNLOAD;
if (prefer_cache) {
- extra_load_flags |= net::LOAD_PREFERRING_CACHE;
+ // If there is upload data attached, only retrieve from cache because there
+ // is no current mechanism to prompt the user for their consent for a
+ // re-post. For GETs, try to retrieve data from the cache and skip
+ // validating the entry if present.
+ if (request->get_upload() != NULL)
+ extra_load_flags |= net::LOAD_ONLY_FROM_CACHE;
+ else
+ extra_load_flags |= net::LOAD_PREFERRING_CACHE;
} else {
extra_load_flags |= net::LOAD_DISABLE_CACHE;
}
diff --git a/content/browser/tab_contents/tab_contents.cc b/content/browser/tab_contents/tab_contents.cc
index 1fc4bfa..fa0e657 100644
--- a/content/browser/tab_contents/tab_contents.cc
+++ b/content/browser/tab_contents/tab_contents.cc
@@ -934,21 +934,10 @@ bool TabContents::IsSavable() {
void TabContents::OnSavePage() {
// If we can not save the page, try to download it.
if (!IsSavable()) {
- DownloadManager* dlm = GetBrowserContext()->GetDownloadManager();
- const GURL& current_page_url = GetURL();
- if (dlm && current_page_url.is_valid()) {
- DownloadSaveInfo save_info;
- save_info.prompt_for_save_location = true;
- dlm->DownloadUrl(current_page_url,
- GURL(),
- "",
- true, // prefer_cache
- save_info,
- this);
- download_stats::RecordDownloadCount(
- download_stats::INITIATED_BY_SAVE_PACKAGE_FAILURE_COUNT);
- return;
- }
+ SaveURL(GetURL(), GURL());
+ download_stats::RecordDownloadCount(
+ download_stats::INITIATED_BY_SAVE_PACKAGE_FAILURE_COUNT);
+ return;
}
Stop();
@@ -1425,10 +1414,7 @@ void TabContents::OnUpdateZoomLimits(int minimum_percent,
}
void TabContents::OnSaveURL(const GURL& url) {
- DownloadManager* dlm = GetBrowserContext()->GetDownloadManager();
- DownloadSaveInfo save_info;
- save_info.prompt_for_save_location = true;
- dlm->DownloadUrl(url, GetURL(), "", true, save_info, this);
+ SaveURL(url, GetURL());
}
void TabContents::OnEnumerateDirectory(int request_id,
@@ -2288,6 +2274,30 @@ void TabContents::SetEncoding(const std::string& encoding) {
GetCanonicalEncodingNameByAliasName(encoding);
}
+void TabContents::SaveURL(const GURL& url, const GURL& referrer) {
+ DownloadManager* dlm = GetBrowserContext()->GetDownloadManager();
+ if (!dlm)
+ return;
+ int64 post_id = -1;
+ // Check if the URL to save matches the URL of the page itself. One
+ // circumstance where this may not happen is when a Pepper plugin initiates
+ // a save.
+ if (url == GetURL()) {
+ const NavigationEntry* entry = controller_.GetActiveEntry();
+ if (entry)
+ post_id = entry->GetPostID();
+ }
+ DownloadSaveInfo save_info;
+ save_info.prompt_for_save_location = true;
+ dlm->DownloadUrl(url,
+ referrer,
+ "",
+ true, // prefer_cache
+ post_id,
+ save_info,
+ this);
+}
+
void TabContents::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) {
RenderWidgetHostView* rwh_view = GetView()->CreateViewForWidget(rvh);
// Can be NULL during tests.
diff --git a/content/browser/tab_contents/tab_contents.h b/content/browser/tab_contents/tab_contents.h
index 2ec9aba..db170eb 100644
--- a/content/browser/tab_contents/tab_contents.h
+++ b/content/browser/tab_contents/tab_contents.h
@@ -496,6 +496,9 @@ class CONTENT_EXPORT TabContents
void SetEncoding(const std::string& encoding);
+ // Save a URL to the local filesystem.
+ void SaveURL(const GURL& url, const GURL& referrer);
+
// Stores random bits of data for others to associate with this object.
// WARNING: this needs to be deleted after NavigationController.
base::PropertyBag property_bag_;
diff --git a/content/public/browser/download_manager.h b/content/public/browser/download_manager.h
index b91f517..52a5437 100644
--- a/content/public/browser/download_manager.h
+++ b/content/public/browser/download_manager.h
@@ -167,7 +167,10 @@ class CONTENT_EXPORT DownloadManager
// Downloads the content at |url|. |referrer| and |referrer_encoding| are the
// referrer for the download, and may be empty. If |prefer_cache| is true,
// then if the response to |url| is in the HTTP cache it will be used without
- // revalidation. |save_info| specifies where the downloaded file should be
+ // revalidation. If |post_id| is non-negative, then it identifies the post
+ // transaction used to originally retrieve the |url| resource - it also
+ // requires |prefer_cache| to be |true| since re-post'ing is not done.
+ // |save_info| specifies where the downloaded file should be
// saved, and whether the user should be prompted about the download.
// |web_contents| is the web page that the download is done in context of,
// and must be non-NULL.
@@ -175,6 +178,7 @@ class CONTENT_EXPORT DownloadManager
const GURL& referrer,
const std::string& referrer_encoding,
bool prefer_cache,
+ int64 post_id,
const DownloadSaveInfo& save_info,
content::WebContents* web_contents) = 0;
diff --git a/content/test/mock_download_manager.h b/content/test/mock_download_manager.h
index 280bc8aa..be946b5 100644
--- a/content/test/mock_download_manager.h
+++ b/content/test/mock_download_manager.h
@@ -51,10 +51,11 @@ class MockDownloadManager : public content::DownloadManager {
base::Time remove_end));
MOCK_METHOD1(RemoveDownloads, int(base::Time remove_begin));
MOCK_METHOD0(RemoveAllDownloads, int());
- MOCK_METHOD6(DownloadUrl, void(const GURL& url,
+ MOCK_METHOD7(DownloadUrl, void(const GURL& url,
const GURL& referrer,
const std::string& referrer_encoding,
bool prefer_cache,
+ int64 post_id,
const DownloadSaveInfo& save_info,
content::WebContents* web_contents));
MOCK_METHOD1(AddObserver, void(Observer* observer));