Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(161)

Side by Side Diff: content/browser/frame_host/navigation_controller_impl.cc

Issue 1002803002: Classify navigations without page id in parallel to the existing classifier. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: greeeeeeen Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/frame_host/navigation_controller_impl.h" 5 #include "content/browser/frame_host/navigation_controller_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
(...skipping 794 matching lines...) Expand 10 before | Expand all | Expand 10 after
805 // when we got the notice of the load failure. If so, look at the copy of the 805 // when we got the notice of the load failure. If so, look at the copy of the
806 // pending parameters that were saved. 806 // pending parameters that were saved.
807 if (params.url_is_unreachable && failed_pending_entry_id_ != 0) { 807 if (params.url_is_unreachable && failed_pending_entry_id_ != 0) {
808 details->did_replace_entry = failed_pending_entry_should_replace_; 808 details->did_replace_entry = failed_pending_entry_should_replace_;
809 } else { 809 } else {
810 details->did_replace_entry = pending_entry_ && 810 details->did_replace_entry = pending_entry_ &&
811 pending_entry_->should_replace_entry(); 811 pending_entry_->should_replace_entry();
812 } 812 }
813 813
814 // Do navigation-type specific actions. These will make and commit an entry. 814 // Do navigation-type specific actions. These will make and commit an entry.
815 details->type = ClassifyNavigation(rfh, params); 815 details->type = ClassifyNavigation(rfh, params);
clamy 2015/04/10 12:05:44 With PlzNavigate enabled, ClassifyNavigation fails
Avi (use Gerrit) 2015/04/13 22:42:48 My current plan is to commit this with the DCHECK
clamy 2015/04/14 15:44:47 Acknowledged.
816 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
817 switches::kSitePerProcess)) {
818 // For site-per-process, both ClassifyNavigation methods get it wrong (see
819 // http://crbug.com/464014) so don't worry about a mismatch if that's the
820 // case.
821 DCHECK_EQ(details->type, ClassifyNavigationWithoutPageID(rfh, params));
822 }
816 823
817 // is_in_page must be computed before the entry gets committed. 824 // is_in_page must be computed before the entry gets committed.
818 details->is_in_page = AreURLsInPageNavigation(rfh->GetLastCommittedURL(), 825 details->is_in_page = AreURLsInPageNavigation(rfh->GetLastCommittedURL(),
819 params.url, params.was_within_same_page, rfh); 826 params.url, params.was_within_same_page, rfh);
820 827
821 switch (details->type) { 828 switch (details->type) {
822 case NAVIGATION_TYPE_NEW_PAGE: 829 case NAVIGATION_TYPE_NEW_PAGE:
823 RendererDidNavigateToNewPage(rfh, params, details->did_replace_entry); 830 RendererDidNavigateToNewPage(rfh, params, details->did_replace_entry);
824 break; 831 break;
825 case NAVIGATION_TYPE_EXISTING_PAGE: 832 case NAVIGATION_TYPE_EXISTING_PAGE:
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
905 details->http_status_code = params.http_status_code; 912 details->http_status_code = params.http_status_code;
906 NotifyNavigationEntryCommitted(details); 913 NotifyNavigationEntryCommitted(details);
907 914
908 return true; 915 return true;
909 } 916 }
910 917
911 NavigationType NavigationControllerImpl::ClassifyNavigation( 918 NavigationType NavigationControllerImpl::ClassifyNavigation(
912 RenderFrameHostImpl* rfh, 919 RenderFrameHostImpl* rfh,
913 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) const { 920 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) const {
914 if (params.page_id == -1) { 921 if (params.page_id == -1) {
915 // TODO(nasko, creis): An out-of-process child frame has no way of 922 // TODO(nasko, creis): An out-of-process child frame has no way of knowing
916 // knowing the page_id of its parent, so it is passing back -1. The 923 // the page_id of its parent, so it is passing back -1. The semantics here
917 // semantics here should be re-evaluated during session history refactor 924 // should be re-evaluated during session history refactor (see
918 // (see http://crbug.com/236848). For now, we assume this means the 925 // http://crbug.com/236848 and in particular http://crbug.com/464014). For
919 // child frame loaded and proceed. Note that this may do the wrong thing 926 // now, we assume this means the child frame loaded and proceed. Note that
920 // for cross-process AUTO_SUBFRAME navigations. 927 // this may do the wrong thing for cross-process AUTO_SUBFRAME navigations.
921 if (rfh->IsCrossProcessSubframe()) 928 if (rfh->IsCrossProcessSubframe())
922 return NAVIGATION_TYPE_NEW_SUBFRAME; 929 return NAVIGATION_TYPE_NEW_SUBFRAME;
923 930
924 // The renderer generates the page IDs, and so if it gives us the invalid 931 // The renderer generates the page IDs, and so if it gives us the invalid
925 // page ID (-1) we know it didn't actually navigate. This happens in a few 932 // page ID (-1) we know it didn't actually navigate. This happens in a few
926 // cases: 933 // cases:
927 // 934 //
928 // - If a page makes a popup navigated to about blank, and then writes 935 // - If a page makes a popup navigated to about blank, and then writes
929 // stuff like a subframe navigated to a real page. We'll get the commit 936 // stuff like a subframe navigated to a real page. We'll get the commit
930 // for the subframe, but there won't be any commit for the outer page. 937 // for the subframe, but there won't be any commit for the outer page.
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1018 DCHECK(GetLastCommittedEntry()); 1025 DCHECK(GetLastCommittedEntry());
1019 return NAVIGATION_TYPE_AUTO_SUBFRAME; 1026 return NAVIGATION_TYPE_AUTO_SUBFRAME;
1020 } 1027 }
1021 1028
1022 // Anything below here we know is a main frame navigation. 1029 // Anything below here we know is a main frame navigation.
1023 if (pending_entry_ && 1030 if (pending_entry_ &&
1024 !pending_entry_->is_renderer_initiated() && 1031 !pending_entry_->is_renderer_initiated() &&
1025 existing_entry != pending_entry_ && 1032 existing_entry != pending_entry_ &&
1026 pending_entry_->GetPageID() == -1 && 1033 pending_entry_->GetPageID() == -1 &&
1027 existing_entry == GetLastCommittedEntry()) { 1034 existing_entry == GetLastCommittedEntry()) {
1028 // In this case, we have a pending entry for a URL but WebCore didn't do a 1035 const std::vector<GURL>& existing_redirect_chain =
1029 // new navigation. This happens when you press enter in the URL bar to 1036 existing_entry->GetRedirectChain();
1030 // reload. We will create a pending entry, but WebKit will convert it to 1037
1031 // a reload since it's the same page and not create a new entry for it 1038 if (existing_entry->GetURL() == pending_entry_->GetURL() ||
1032 // (the user doesn't want to have a new back/forward entry when they do 1039 (existing_redirect_chain.size() &&
1033 // this). If this matches the last committed entry, we want to just ignore 1040 existing_redirect_chain[0] == pending_entry_->GetURL()) ||
1034 // the pending entry and go back to where we were (the "existing entry"). 1041 existing_entry->GetURL() == pending_entry_->GetVirtualURL()) {
Charlie Reis 2015/04/10 23:54:21 We probably shouldn't be changing ClassifyNavigati
Avi (use Gerrit) 2015/04/13 22:42:48 https://codereview.chromium.org/1082083002 It sho
1035 return NAVIGATION_TYPE_SAME_PAGE; 1042 // In this case, we have a pending entry for a URL but WebCore didn't do a
1043 // new navigation. This happens when you press enter in the URL bar to
1044 // reload. We will create a pending entry, but WebKit will convert it to
1045 // a reload since it's the same page and not create a new entry for it
1046 // (the user doesn't want to have a new back/forward entry when they do
1047 // this). If this matches the last committed entry, we want to just ignore
1048 // the pending entry and go back to where we were (the "existing entry").
1049 return NAVIGATION_TYPE_SAME_PAGE;
1050 }
1036 } 1051 }
1037 1052
1038 // Any toplevel navigations with the same base (minus the reference fragment) 1053 // Any toplevel navigations with the same base (minus the reference fragment)
1039 // are in-page navigations. We weeded out subframe navigations above. Most of 1054 // are in-page navigations. We weeded out subframe navigations above. Most of
1040 // the time this doesn't matter since WebKit doesn't tell us about subframe 1055 // the time this doesn't matter since WebKit doesn't tell us about subframe
1041 // navigations that don't actually navigate, but it can happen when there is 1056 // navigations that don't actually navigate, but it can happen when there is
1042 // an encoding override (it always sends a navigation request). 1057 // an encoding override (it always sends a navigation request).
1043 if (AreURLsInPageNavigation(existing_entry->GetURL(), params.url, 1058 if (AreURLsInPageNavigation(existing_entry->GetURL(), params.url,
1044 params.was_within_same_page, rfh)) { 1059 params.was_within_same_page, rfh)) {
1045 return NAVIGATION_TYPE_IN_PAGE; 1060 return NAVIGATION_TYPE_IN_PAGE;
1046 } 1061 }
1047 1062
1048 // Since we weeded out "new" navigations above, we know this is an existing 1063 // Since we weeded out "new" navigations above, we know this is an existing
1049 // (back/forward) navigation. 1064 // (back/forward) navigation.
1050 return NAVIGATION_TYPE_EXISTING_PAGE; 1065 return NAVIGATION_TYPE_EXISTING_PAGE;
1051 } 1066 }
1052 1067
1068 NavigationType NavigationControllerImpl::ClassifyNavigationWithoutPageID(
1069 RenderFrameHostImpl* rfh,
1070 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) const {
1071 if (params.did_create_new_entry) {
1072 // A new entry. We may or may not have a pending entry for the page, and
1073 // this may or may not be the main frame.
1074 if (ui::PageTransitionIsMainFrame(params.transition)) {
1075 // TODO(avi): I want to use |if (!rfh->GetParent())| here but lots of unit
1076 // tests fake auto subframe commits by sending the main frame a
1077 // PAGE_TRANSITION_AUTO_SUBFRAME transition. Fix those, and adjust here.
Charlie Reis 2015/04/10 23:54:20 I like this plan.
Avi (use Gerrit) 2015/04/13 22:42:48 Acknowledged. PageTransitionIsMainFrame is used i
1078 return NAVIGATION_TYPE_NEW_PAGE;
1079 }
1080
1081 // When this is a new subframe navigation, we should have a committed page
1082 // in which it's a subframe. This may not be the case when an iframe is
1083 // navigated on a popup navigated to about:blank (the iframe would be
1084 // written into the popup by script on the main page). For these cases,
1085 // there isn't any navigation stuff we can do, so just ignore it.
1086 if (!GetLastCommittedEntry())
1087 return NAVIGATION_TYPE_NAV_IGNORE;
1088
1089 // Valid subframe navigation.
1090 return NAVIGATION_TYPE_NEW_SUBFRAME;
1091 }
1092
1093 // We only clear the session history when navigating to a new page.
1094 DCHECK(!params.history_list_was_cleared);
1095
1096 if (!ui::PageTransitionIsMainFrame(params.transition)) {
1097 // All manual subframes would be did_create_new_entry and handled above, so
1098 // we know this is auto.
1099 if (GetLastCommittedEntry()) {
1100 return NAVIGATION_TYPE_AUTO_SUBFRAME;
1101 } else {
1102 // We ignore subframes created in non-committed pages; we'd appreciate if
1103 // people stopped doing that.
1104 return NAVIGATION_TYPE_NAV_IGNORE;
1105 }
1106 }
1107
1108 if (params.nav_entry_id == 0) {
Charlie Reis 2015/04/10 23:54:20 Can you add a comment saying what nav_entry_id ==
Avi (use Gerrit) 2015/04/13 22:42:48 Done.
1109 // Just like above in the did_create_new_entry case, it's possible to
1110 // scribble onto an uncommitted page. Again, there isn't any navigation
1111 // stuff that we can do, so ignore it here as well.
1112 if (!GetLastCommittedEntry())
1113 return NAVIGATION_TYPE_NAV_IGNORE;
1114
1115 // This is a renderer-initiated navigation, but didn't create a new page.
1116 if (params.was_within_same_page) {
1117 // This is history.replaceState(), which is renderer-initiated yet within
1118 // the same page.
1119 return NAVIGATION_TYPE_IN_PAGE;
1120 } else {
1121 // This is history.reload() and client-side redirection.
1122 return NAVIGATION_TYPE_EXISTING_PAGE;
1123 }
1124 }
1125
1126 if (pending_entry_ && pending_entry_index_ == -1 &&
1127 pending_entry_->GetUniqueID() == params.nav_entry_id) {
1128 // In this case, we have a pending entry for a load of a new URL but Blink
1129 // didn't do a new navigation (params.did_create_new_entry). This happens
1130 // when you press enter in the URL bar to reload. We will create a pending
1131 // entry, but Blink will convert it to a reload since it's the same page and
1132 // not create a new entry for it (the user doesn't want to have a new
1133 // back/forward entry when they do this). Therefore we want to just ignore
1134 // the pending entry and go back to where we were (the "existing entry").
1135 return NAVIGATION_TYPE_SAME_PAGE;
1136 }
1137
1138 if (params.url_is_unreachable && failed_pending_entry_id_ != 0 &&
1139 params.nav_entry_id == failed_pending_entry_id_) {
1140 // If the renderer was going to a new pending entry that got cleared because
1141 // of an error, this is the case of the user trying to retry a failed load
1142 // by pressing return.
1143 return NAVIGATION_TYPE_EXISTING_PAGE;
1144 }
1145
1146 // Now we know that the notification is for an existing page. Find that entry.
1147 int existing_entry_index = GetEntryIndexWithUniqueID(params.nav_entry_id);
1148 if (existing_entry_index == -1) {
1149 // The page was not found. It could have been pruned because of the limit on
1150 // back/forward entries (not likely since we'll usually tell it to navigate
1151 // to such entries). It could also mean that the renderer is smoking crack.
1152 // TODO(avi): Crash the renderer like we do in the old ClassifyNavigation?
1153 NOTREACHED() << "Could not find nav entry with id " << params.nav_entry_id;
1154 return NAVIGATION_TYPE_NAV_IGNORE;
1155 }
1156
1157 // Any top-level navigations with the same base (minus the reference fragment)
1158 // are in-page navigations. (We weeded out subframe navigations above.) Most
1159 // of the time this doesn't matter since Blink doesn't tell us about subframe
1160 // navigations that don't actually navigate, but it can happen when there is
1161 // an encoding override (it always sends a navigation request).
1162 NavigationEntryImpl* existing_entry = entries_[existing_entry_index].get();
1163 if (AreURLsInPageNavigation(existing_entry->GetURL(), params.url,
1164 params.was_within_same_page, rfh)) {
1165 return NAVIGATION_TYPE_IN_PAGE;
1166 }
1167
1168 // Since we weeded out "new" navigations above, we know this is an existing
1169 // (back/forward) navigation.
1170 return NAVIGATION_TYPE_EXISTING_PAGE;
1171 }
1172
1053 void NavigationControllerImpl::RendererDidNavigateToNewPage( 1173 void NavigationControllerImpl::RendererDidNavigateToNewPage(
1054 RenderFrameHostImpl* rfh, 1174 RenderFrameHostImpl* rfh,
1055 const FrameHostMsg_DidCommitProvisionalLoad_Params& params, 1175 const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
1056 bool replace_entry) { 1176 bool replace_entry) {
1057 NavigationEntryImpl* new_entry; 1177 NavigationEntryImpl* new_entry;
1058 bool update_virtual_url; 1178 bool update_virtual_url;
1059 // Only make a copy of the pending entry if it is appropriate for the new page 1179 // Only make a copy of the pending entry if it is appropriate for the new page
1060 // that was just loaded. We verify this at a coarse grain by checking that 1180 // that was just loaded. We verify this at a coarse grain by checking that
1061 // the SiteInstance hasn't been assigned to something else. 1181 // the SiteInstance hasn't been assigned to something else.
1062 if (pending_entry_ && 1182 if (pending_entry_ &&
(...skipping 741 matching lines...) Expand 10 before | Expand all | Expand 10 after
1804 int NavigationControllerImpl::GetEntryIndexWithPageID( 1924 int NavigationControllerImpl::GetEntryIndexWithPageID(
1805 SiteInstance* instance, int32 page_id) const { 1925 SiteInstance* instance, int32 page_id) const {
1806 for (int i = static_cast<int>(entries_.size()) - 1; i >= 0; --i) { 1926 for (int i = static_cast<int>(entries_.size()) - 1; i >= 0; --i) {
1807 if ((entries_[i]->site_instance() == instance) && 1927 if ((entries_[i]->site_instance() == instance) &&
1808 (entries_[i]->GetPageID() == page_id)) 1928 (entries_[i]->GetPageID() == page_id))
1809 return i; 1929 return i;
1810 } 1930 }
1811 return -1; 1931 return -1;
1812 } 1932 }
1813 1933
1934 int NavigationControllerImpl::GetEntryIndexWithUniqueID(
1935 int nav_entry_id) const {
1936 for (int i = static_cast<int>(entries_.size()) - 1; i >= 0; --i) {
1937 if (entries_[i]->GetUniqueID() == nav_entry_id)
1938 return i;
1939 }
1940 return -1;
1941 }
1942
1814 NavigationEntryImpl* NavigationControllerImpl::GetTransientEntry() const { 1943 NavigationEntryImpl* NavigationControllerImpl::GetTransientEntry() const {
1815 if (transient_entry_index_ == -1) 1944 if (transient_entry_index_ == -1)
1816 return NULL; 1945 return NULL;
1817 return entries_[transient_entry_index_].get(); 1946 return entries_[transient_entry_index_].get();
1818 } 1947 }
1819 1948
1820 void NavigationControllerImpl::SetTransientEntry(NavigationEntry* entry) { 1949 void NavigationControllerImpl::SetTransientEntry(NavigationEntry* entry) {
1821 // Discard any current transient entry, we can only have one at a time. 1950 // Discard any current transient entry, we can only have one at a time.
1822 int index = 0; 1951 int index = 0;
1823 if (last_committed_entry_index_ != -1) 1952 if (last_committed_entry_index_ != -1)
(...skipping 23 matching lines...) Expand all
1847 } 1976 }
1848 } 1977 }
1849 } 1978 }
1850 1979
1851 void NavigationControllerImpl::SetGetTimestampCallbackForTest( 1980 void NavigationControllerImpl::SetGetTimestampCallbackForTest(
1852 const base::Callback<base::Time()>& get_timestamp_callback) { 1981 const base::Callback<base::Time()>& get_timestamp_callback) {
1853 get_timestamp_callback_ = get_timestamp_callback; 1982 get_timestamp_callback_ = get_timestamp_callback;
1854 } 1983 }
1855 1984
1856 } // namespace content 1985 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698