If the renderer drops a navigation, make sure the spinner doesn't spin endlessly.
BUG=431853
TEST=none
Review URL: https://codereview.chromium.org/790843002
Cr-Commit-Position: refs/heads/master@{#307567}
diff --git a/content/browser/frame_host/render_frame_host_delegate.h b/content/browser/frame_host/render_frame_host_delegate.h
index 6c22d94..57b2ad42 100644
--- a/content/browser/frame_host/render_frame_host_delegate.h
+++ b/content/browser/frame_host/render_frame_host_delegate.h
@@ -57,13 +57,17 @@
// Informs the delegate whenever a RenderFrameHost is deleted.
virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) {}
- // The top-level RenderFrame began loading a new page. This corresponds to
+ // The specified RenderFrame began loading a new page. This corresponds to
// Blink's notion of the throbber starting.
// |to_different_document| will be true unless the load is a fragment
// navigation, or triggered by history.pushState/replaceState.
virtual void DidStartLoading(RenderFrameHost* render_frame_host,
bool to_different_document) {}
+ // The specified RenderFrame stopped loading a page. This corresponds to
+ // Blink's notion of the throbber stopping.
+ virtual void DidStopLoading(RenderFrameHost* render_frame_host) {}
+
// The RenderFrameHost has been swapped out.
virtual void SwappedOut(RenderFrameHost* render_frame_host) {}
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 72d5324..13bb3160 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -303,6 +303,7 @@
OnDidFailLoadWithError)
IPC_MESSAGE_HANDLER_GENERIC(FrameHostMsg_DidCommitProvisionalLoad,
OnDidCommitProvisionalLoad(msg))
+ IPC_MESSAGE_HANDLER(FrameHostMsg_DidDropNavigation, OnDidDropNavigation)
IPC_MESSAGE_HANDLER(FrameHostMsg_OpenURL, OnOpenURL)
IPC_MESSAGE_HANDLER(FrameHostMsg_DocumentOnLoadCompleted,
OnDocumentOnLoadCompleted)
@@ -703,6 +704,14 @@
frame_tree_node()->navigator()->DidNavigate(this, validated_params);
}
+void RenderFrameHostImpl::OnDidDropNavigation() {
+ // At the end of Navigate(), the delegate's DidStartLoading is called to force
+ // the spinner to start, even if the renderer didn't yet begin the load. If it
+ // turns out that the renderer dropped the navigation, we need to turn off the
+ // spinner.
+ delegate_->DidStopLoading(this);
+}
+
RenderWidgetHostImpl* RenderFrameHostImpl::GetRenderWidgetHost() {
return static_cast<RenderWidgetHostImpl*>(render_view_host_);
}
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 052da3b..3769ce20 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -421,6 +421,7 @@
int error_code,
const base::string16& error_description);
void OnDidCommitProvisionalLoad(const IPC::Message& msg);
+ void OnDidDropNavigation();
void OnBeforeUnloadACK(
bool proceed,
const base::TimeTicks& renderer_before_unload_start_time,
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 8e1c657..a747fe8 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -352,6 +352,7 @@
void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
void DidStartLoading(RenderFrameHost* render_frame_host,
bool to_different_document) override;
+ void DidStopLoading(RenderFrameHost* render_frame_host) override;
void SwappedOut(RenderFrameHost* render_frame_host) override;
void DidDeferAfterResponseStarted(
const TransitionLayerData& transition_data) override;
@@ -883,9 +884,6 @@
// Calculates the progress of the current load and notifies the delegate.
void SendLoadProgressChanged();
- // Called once when the last frame on the page has stopped loading.
- void DidStopLoading(RenderFrameHost* render_frame_host);
-
// Misc non-view stuff -------------------------------------------------------
// Helper functions for sending notifications.
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index 0b8b72b7..af8289f 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -578,6 +578,9 @@
int /* error_code */,
base::string16 /* error_description */)
+// Sent when the renderer decides to ignore a navigation.
+IPC_MESSAGE_ROUTED0(FrameHostMsg_DidDropNavigation)
+
// Sent when the renderer starts loading the page. |to_different_document| will
// be true unless the load is a fragment navigation, or triggered by
// history.pushState/replaceState.
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 28ff2b4..f16b132 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -956,6 +956,7 @@
params.common_params.url, params.common_params.navigation_type,
params.commit_params.page_state, true, params.pending_history_list_offset,
params.page_id, &is_reload, &cache_policy)) {
+ Send(new FrameHostMsg_DidDropNavigation(routing_id_));
return;
}
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 0e7a0c2..c4665ff 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -864,6 +864,13 @@
EXPECT_EQ(2, view()->history_list_length_);
EXPECT_EQ(1, view()->history_list_offset_);
EXPECT_EQ(3, view()->history_page_ids_[1]);
+
+ // Check for a valid DidDropNavigation message.
+ ProcessPendingMessages();
+ const IPC::Message* msg = render_thread_->sink().GetUniqueMessageMatching(
+ FrameHostMsg_DidDropNavigation::ID);
+ ASSERT_TRUE(msg);
+ render_thread_->sink().ClearMessages();
}
// Test that we do not ignore navigations after the entry limit is reached,