Hide navigations aborted due to downloading from ntp
If a navigation was started by an HTMLAnchorElement with a download
attribute (<a download>), the navigation will end up being aborted,
and turned into a download, so leaving the URL around for the user to
edit is not useful.
BUG=808966
[email protected],[email protected]
Change-Id: Idcfa5c952cba7933fdf62e75a67ec4a2e2087695
Reviewed-on: https://chromium-review.googlesource.com/908451
Reviewed-by: Camille Lamy <[email protected]>
Reviewed-by: Charlie Reis <[email protected]>
Commit-Queue: Jochen Eisinger <[email protected]>
Cr-Commit-Position: refs/heads/master@{#541471}
diff --git a/chrome/browser/download/download_ui_controller.cc b/chrome/browser/download/download_ui_controller.cc
index 15279d7..28d98a2 100644
--- a/chrome/browser/download/download_ui_controller.cc
+++ b/chrome/browser/download/download_ui_controller.cc
@@ -143,7 +143,8 @@
content::WebContents* web_contents =
content::DownloadItemUtils::GetWebContents(item);
if (web_contents && (item->IsSavePackageDownload() ||
- (web_contents->GetURL() != item->GetOriginalUrl() &&
+ (!web_contents->GetURL().is_empty() &&
+ web_contents->GetURL() != item->GetOriginalUrl() &&
web_contents->GetURL() != item->GetURL()))) {
auto* security_state_tab_helper =
SecurityStateTabHelper::FromWebContents(web_contents);
diff --git a/chrome/browser/ui/search/local_ntp_browsertest.cc b/chrome/browser/ui/search/local_ntp_browsertest.cc
index 10796e8e..9eaa382 100644
--- a/chrome/browser/ui/search/local_ntp_browsertest.cc
+++ b/chrome/browser/ui/search/local_ntp_browsertest.cc
@@ -297,8 +297,9 @@
ui_test_utils::NavigateToURL(browser(), download_url);
download_observer.WaitForFinished();
- // This should have changed the visible URL, but not the last committed one.
- ASSERT_EQ(download_url, active_tab->GetVisibleURL());
+ // This should neither have changed the visible URL, nor the last committed
+ // one.
+ ASSERT_EQ(GURL(chrome::kChromeUINewTabURL), active_tab->GetVisibleURL());
ASSERT_EQ(GURL(chrome::kChromeUINewTabURL),
active_tab->GetLastCommittedURL());
diff --git a/content/browser/frame_host/frame_tree_node.cc b/content/browser/frame_host/frame_tree_node.cc
index 5de5bfb..f33998c 100644
--- a/content/browser/frame_host/frame_tree_node.cc
+++ b/content/browser/frame_host/frame_tree_node.cc
@@ -603,7 +603,8 @@
expected_pending_nav_entry_id =
navigation_request_->navigation_handle()->pending_nav_entry_id();
}
- navigator_->DiscardPendingEntryIfNeeded(expected_pending_nav_entry_id);
+ navigator_->DiscardPendingEntryIfNeeded(expected_pending_nav_entry_id,
+ false /* is_download */);
}
ResetNavigationRequest(false, true);
}
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
index 0cb359a..7add424f 100644
--- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -8024,4 +8024,22 @@
EXPECT_TRUE(capturer.is_same_document());
}
+IN_PROC_BROWSER_TEST_F(ContentBrowserTest, HideDownloadFromUnmodifiedNewTab) {
+ GURL url("data:application/octet-stream,");
+
+ const NavigationControllerImpl& controller =
+ static_cast<const NavigationControllerImpl&>(
+ shell()->web_contents()->GetController());
+
+ OpenURLParams params(url, Referrer(), WindowOpenDisposition::CURRENT_TAB,
+ ui::PAGE_TRANSITION_LINK, true);
+ params.suggested_filename = std::string("foo");
+
+ shell()->web_contents()->OpenURL(params);
+ WaitForLoadStop(shell()->web_contents());
+
+ EXPECT_FALSE(controller.GetPendingEntry());
+ EXPECT_FALSE(controller.GetVisibleEntry());
+}
+
} // namespace content
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index 2b5446b5..25c58f38 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -995,11 +995,15 @@
if (navigation_handle_.get())
navigation_handle_->set_net_error_code(static_cast<net::Error>(net_error));
- int expected_pending_entry_id =
- navigation_handle_.get() ? navigation_handle_->pending_nav_entry_id()
- : nav_entry_id_;
+ int expected_pending_entry_id = nav_entry_id_;
+ bool is_download = false;
+ if (navigation_handle_.get()) {
+ expected_pending_entry_id = navigation_handle_->pending_nav_entry_id();
+ is_download = navigation_handle_->IsDownload();
+ }
+
frame_tree_node_->navigator()->DiscardPendingEntryIfNeeded(
- expected_pending_entry_id);
+ expected_pending_entry_id, is_download);
// If the request was canceled by the user do not show an error page.
if (net_error == net::ERR_ABORTED) {
diff --git a/content/browser/frame_host/navigator.h b/content/browser/frame_host/navigator.h
index 771a0b9..e93b664 100644
--- a/content/browser/frame_host/navigator.h
+++ b/content/browser/frame_host/navigator.h
@@ -199,7 +199,8 @@
// With sufficiently bad interleaving of IPCs, this may no longer be the
// pending NavigationEntry, in which case the pending NavigationEntry will not
// be discarded.
- virtual void DiscardPendingEntryIfNeeded(int expected_pending_entry_id) {}
+ virtual void DiscardPendingEntryIfNeeded(int expected_pending_entry_id,
+ bool is_download) {}
protected:
friend class base::RefCounted<Navigator>;
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc
index f48d0f2..194b79b 100644
--- a/content/browser/frame_host/navigator_impl.cc
+++ b/content/browser/frame_host/navigator_impl.cc
@@ -237,11 +237,13 @@
}
// Discard the pending navigation entry if needed.
- int expected_pending_entry_id =
- render_frame_host->GetNavigationHandle()
- ? render_frame_host->GetNavigationHandle()->pending_nav_entry_id()
- : 0;
- DiscardPendingEntryIfNeeded(expected_pending_entry_id);
+ int expected_pending_entry_id = 0;
+ if (render_frame_host->GetNavigationHandle()) {
+ expected_pending_entry_id =
+ render_frame_host->GetNavigationHandle()->pending_nav_entry_id();
+ DCHECK(!render_frame_host->GetNavigationHandle()->IsDownload());
+ }
+ DiscardPendingEntryIfNeeded(expected_pending_entry_id, false);
}
void NavigatorImpl::DidFailLoadWithError(
@@ -982,14 +984,15 @@
}
}
-void NavigatorImpl::DiscardPendingEntryIfNeeded(int expected_pending_entry_id) {
+void NavigatorImpl::DiscardPendingEntryIfNeeded(int expected_pending_entry_id,
+ bool is_download) {
// Racy conditions can cause a fail message to arrive after its corresponding
// pending entry has been replaced by another navigation. If
// |DiscardPendingEntry| is called in this case, then the completely valid
// entry for the new navigation would be discarded. See crbug.com/513742. To
// catch this case, the current pending entry is compared against the current
// navigation handle's entry id, which should correspond to the failed load.
- NavigationEntry* pending_entry = controller_->GetPendingEntry();
+ NavigationEntryImpl* pending_entry = controller_->GetPendingEntry();
bool pending_matches_fail_msg =
pending_entry &&
expected_pending_entry_id == pending_entry->GetUniqueID();
@@ -1010,9 +1013,13 @@
// allow the view to clear the pending entry and typed URL if the user
// requests (e.g., hitting Escape with focus in the address bar).
//
+ // Note that the pending entry does not need to be preserved for downloads,
+ // since the user is unlikely to try again.
+ //
// Note: don't touch the transient entry, since an interstitial may exist.
- bool should_preserve_entry = controller_->IsUnmodifiedBlankTab() ||
- delegate_->ShouldPreserveAbortedURLs();
+ bool should_preserve_entry = (controller_->IsUnmodifiedBlankTab() ||
+ delegate_->ShouldPreserveAbortedURLs()) &&
+ !is_download;
if (pending_entry != controller_->GetVisibleEntry() ||
!should_preserve_entry) {
controller_->DiscardPendingEntry(true);
diff --git a/content/browser/frame_host/navigator_impl.h b/content/browser/frame_host/navigator_impl.h
index a1bedd3..07a1a12 100644
--- a/content/browser/frame_host/navigator_impl.h
+++ b/content/browser/frame_host/navigator_impl.h
@@ -106,7 +106,8 @@
const base::TimeTicks& renderer_before_unload_end_time) override;
void CancelNavigation(FrameTreeNode* frame_tree_node,
bool inform_renderer) override;
- void DiscardPendingEntryIfNeeded(int expected_pending_entry_id) override;
+ void DiscardPendingEntryIfNeeded(int expected_pending_entry_id,
+ bool is_download) override;
private:
// Holds data used to track browser side navigation metrics.
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
index 283d3ba..7ee614e7 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -508,9 +508,12 @@
// already updated its state properly, and doesn't need to be notified.
if (speculative_render_frame_host_->GetNavigationHandle() &&
request.from_begin_navigation()) {
+ DCHECK(!speculative_render_frame_host_->GetNavigationHandle()
+ ->IsDownload());
frame_tree_node_->navigator()->DiscardPendingEntryIfNeeded(
speculative_render_frame_host_->GetNavigationHandle()
- ->pending_nav_entry_id());
+ ->pending_nav_entry_id(),
+ false /* is_download */);
}
DiscardUnusedFrame(UnsetSpeculativeRenderFrameHost());
}
@@ -547,9 +550,12 @@
if (speculative_render_frame_host_ &&
speculative_render_frame_host_->GetNavigationHandle() &&
request.from_begin_navigation()) {
+ DCHECK(!speculative_render_frame_host_->GetNavigationHandle()
+ ->IsDownload());
frame_tree_node_->navigator()->DiscardPendingEntryIfNeeded(
speculative_render_frame_host_->GetNavigationHandle()
- ->pending_nav_entry_id());
+ ->pending_nav_entry_id(),
+ false /* is_download */);
}
// If a previous speculative RenderFrameHost didn't exist or if its
diff --git a/content/shell/browser/shell.cc b/content/shell/browser/shell.cc
index 20c1331..ef47bd27 100644
--- a/content/shell/browser/shell.cc
+++ b/content/shell/browser/shell.cc
@@ -392,6 +392,7 @@
load_url_params.is_renderer_initiated = params.is_renderer_initiated;
load_url_params.should_replace_current_entry =
params.should_replace_current_entry;
+ load_url_params.suggested_filename = params.suggested_filename;
if (params.uses_post) {
load_url_params.load_type = NavigationController::LOAD_TYPE_HTTP_POST;