Index: content/browser/frame_host/navigator_impl.cc |
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc |
index 4483572739ddffb3fde5d0c77e3c3c055bdd2cec..6ab8be5baeb5dfc592f8e68ebb45d7bec4f1ef90 100644 |
--- a/content/browser/frame_host/navigator_impl.cc |
+++ b/content/browser/frame_host/navigator_impl.cc |
@@ -46,6 +46,7 @@ |
#include "content/public/common/content_constants.h" |
#include "content/public/common/resource_response.h" |
#include "net/base/net_errors.h" |
+#include "net/base/url_util.h" |
#include "url/gurl.h" |
namespace content { |
@@ -53,9 +54,13 @@ namespace content { |
namespace { |
FrameMsg_Navigate_Type::Value GetNavigationType( |
- BrowserContext* browser_context, |
+ const GURL& old_url, |
+ const GURL& new_url, |
+ ReloadType reload_type, |
const NavigationEntryImpl& entry, |
- ReloadType reload_type) { |
+ const FrameNavigationEntry& frame_entry, |
+ bool is_same_document_history_load) { |
+ // Reload navigations |
switch (reload_type) { |
case ReloadType::NORMAL: |
return FrameMsg_Navigate_Type::RELOAD; |
@@ -73,10 +78,36 @@ FrameMsg_Navigate_Type::Value GetNavigationType( |
if (entry.restore_type() == RestoreType::LAST_SESSION_EXITED_CLEANLY) { |
if (entry.GetHasPostData()) |
return FrameMsg_Navigate_Type::RESTORE_WITH_POST; |
- return FrameMsg_Navigate_Type::RESTORE; |
+ else |
+ return FrameMsg_Navigate_Type::RESTORE; |
+ } |
+ |
+ // History navigations. |
+ if (frame_entry.page_state().IsValid()) { |
+ if (is_same_document_history_load) |
+ return FrameMsg_Navigate_Type::HISTORY_SAME_DOCUMENT; |
+ else |
+ return FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT; |
} |
+ DCHECK(!is_same_document_history_load); |
- return FrameMsg_Navigate_Type::NORMAL; |
+ // A same-document fragment-navigation happens when the only part of the url |
+ // that is modified is after the '#' character. |
+ // |
+ // Be careful not to consider history navigations. For instance, if the |
+ // history is: 'A#bar' -> 'B' -> 'A#foo'. Then an history navigation from |
+ // 'A#foo' to 'A#bar' is not a same-document navigation, but a |
+ // different-document one! The two FrameNavigationEntry doesn't share the same |
+ // document_sequence_number. |
+ // |
+ // When modifying this condition, please take a look at: |
+ // FrameLoader::shouldPerformFragmentNavigation. |
+ if (net::IsFragmentAddedOrUpdated(old_url, new_url) && |
+ frame_entry.method() == "GET") { |
+ return FrameMsg_Navigate_Type::SAME_DOCUMENT; |
+ } else { |
+ return FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT; |
+ } |
} |
} // namespace |
@@ -415,15 +446,20 @@ bool NavigatorImpl::NavigateToEntry( |
navigation_start, dest_url, entry.restore_type())); |
// Create the navigation parameters. |
FrameMsg_Navigate_Type::Value navigation_type = GetNavigationType( |
- controller_->GetBrowserContext(), entry, reload_type); |
+ frame_tree_node->current_url(), // old_url |
+ dest_url, // new_url |
+ reload_type, // reload_type |
+ entry, // entry |
+ frame_entry, // frame_entry |
+ is_same_document_history_load); // is_same_document_history_load |
+ |
dest_render_frame_host->Navigate( |
entry.ConstructCommonNavigationParams( |
frame_entry, post_body, dest_url, dest_referrer, navigation_type, |
previews_state, navigation_start), |
entry.ConstructStartNavigationParams(), |
entry.ConstructRequestNavigationParams( |
- frame_entry, is_same_document_history_load, |
- is_history_navigation_in_new_child, |
+ frame_entry, is_history_navigation_in_new_child, |
entry.GetSubframeUniqueNames(frame_tree_node), |
frame_tree_node->has_committed_real_load(), |
controller_->GetPendingEntryIndex() == -1, |
@@ -1132,8 +1168,13 @@ void NavigatorImpl::RequestNavigation(FrameTreeNode* frame_tree_node, |
bool should_dispatch_beforeunload = |
!is_same_document_history_load && |
frame_tree_node->current_frame_host()->ShouldDispatchBeforeUnload(); |
- FrameMsg_Navigate_Type::Value navigation_type = |
- GetNavigationType(controller_->GetBrowserContext(), entry, reload_type); |
+ FrameMsg_Navigate_Type::Value navigation_type = GetNavigationType( |
+ frame_tree_node->current_url(), // old_url |
+ dest_url, // new_url |
+ reload_type, // reload_type |
+ entry, // entry |
+ frame_entry, // frame_entry |
+ is_same_document_history_load); // is_same_document_history_load |
std::unique_ptr<NavigationRequest> scoped_request = |
NavigationRequest::CreateBrowserInitiated( |
frame_tree_node, dest_url, dest_referrer, frame_entry, entry, |