Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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); |
| 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 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1050 if (AreURLsInPageNavigation(existing_entry->GetURL(), params.url, | 1057 if (AreURLsInPageNavigation(existing_entry->GetURL(), params.url, |
| 1051 params.was_within_same_page, rfh)) { | 1058 params.was_within_same_page, rfh)) { |
| 1052 return NAVIGATION_TYPE_IN_PAGE; | 1059 return NAVIGATION_TYPE_IN_PAGE; |
| 1053 } | 1060 } |
| 1054 | 1061 |
| 1055 // Since we weeded out "new" navigations above, we know this is an existing | 1062 // Since we weeded out "new" navigations above, we know this is an existing |
| 1056 // (back/forward) navigation. | 1063 // (back/forward) navigation. |
| 1057 return NAVIGATION_TYPE_EXISTING_PAGE; | 1064 return NAVIGATION_TYPE_EXISTING_PAGE; |
| 1058 } | 1065 } |
| 1059 | 1066 |
| 1067 NavigationType NavigationControllerImpl::ClassifyNavigationWithoutPageID( | |
| 1068 RenderFrameHostImpl* rfh, | |
| 1069 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) const { | |
| 1070 if (params.did_create_new_entry) { | |
| 1071 // A new entry. We may or may not have a pending entry for the page, and | |
| 1072 // this may or may not be the main frame. | |
| 1073 if (ui::PageTransitionIsMainFrame(params.transition)) { | |
| 1074 // TODO(avi): I want to use |if (!rfh->GetParent())| here but lots of unit | |
| 1075 // tests fake auto subframe commits by sending the main frame a | |
| 1076 // PAGE_TRANSITION_AUTO_SUBFRAME transition. Fix those, and adjust here. | |
| 1077 return NAVIGATION_TYPE_NEW_PAGE; | |
| 1078 } | |
| 1079 | |
| 1080 // When this is a new subframe navigation, we should have a committed page | |
| 1081 // in which it's a subframe. This may not be the case when an iframe is | |
| 1082 // navigated on a popup navigated to about:blank (the iframe would be | |
| 1083 // written into the popup by script on the main page). For these cases, | |
| 1084 // there isn't any navigation stuff we can do, so just ignore it. | |
| 1085 if (!GetLastCommittedEntry()) | |
| 1086 return NAVIGATION_TYPE_NAV_IGNORE; | |
| 1087 | |
| 1088 // Valid subframe navigation. | |
| 1089 return NAVIGATION_TYPE_NEW_SUBFRAME; | |
| 1090 } | |
| 1091 | |
| 1092 // We only clear the session history when navigating to a new page. | |
| 1093 DCHECK(!params.history_list_was_cleared); | |
| 1094 | |
| 1095 if (!ui::PageTransitionIsMainFrame(params.transition)) { | |
| 1096 // All manual subframes would be did_create_new_entry and handled above, so | |
| 1097 // we know this is auto. | |
| 1098 if (GetLastCommittedEntry()) { | |
| 1099 return NAVIGATION_TYPE_AUTO_SUBFRAME; | |
| 1100 } else { | |
| 1101 // We ignore subframes created in non-committed pages; we'd appreciate if | |
| 1102 // people stopped doing that. | |
| 1103 return NAVIGATION_TYPE_NAV_IGNORE; | |
| 1104 } | |
| 1105 } | |
| 1106 | |
| 1107 if (params.nav_entry_id == 0) { | |
| 1108 // This is a renderer-initiated navigation (nav_entry_id == 0), but didn't | |
| 1109 // create a new page. | |
| 1110 | |
| 1111 // Just like above in the did_create_new_entry case, it's possible to | |
| 1112 // scribble onto an uncommitted page. Again, there isn't any navigation | |
| 1113 // stuff that we can do, so ignore it here as well. | |
| 1114 if (!GetLastCommittedEntry()) | |
| 1115 return NAVIGATION_TYPE_NAV_IGNORE; | |
| 1116 | |
| 1117 if (params.was_within_same_page) { | |
| 1118 // This is history.replaceState(), which is renderer-initiated yet within | |
| 1119 // the same page. | |
| 1120 return NAVIGATION_TYPE_IN_PAGE; | |
| 1121 } else { | |
| 1122 // This is history.reload() and client-side redirection. | |
|
Charlie Reis
2015/04/22 05:27:25
nit: and client-side redirection -> or a client re
Avi (use Gerrit)
2015/04/22 18:31:50
Done.
| |
| 1123 return NAVIGATION_TYPE_EXISTING_PAGE; | |
| 1124 } | |
| 1125 } | |
| 1126 | |
| 1127 if (pending_entry_ && pending_entry_index_ == -1 && | |
| 1128 pending_entry_->GetUniqueID() == params.nav_entry_id) { | |
|
Charlie Reis
2015/04/22 05:27:24
Just to make sure I understand... If it looks like
Avi (use Gerrit)
2015/04/22 18:31:50
Exactly.
| |
| 1129 // In this case, we have a pending entry for a load of a new URL but Blink | |
| 1130 // didn't do a new navigation (params.did_create_new_entry). This happens | |
| 1131 // when you press enter in the URL bar to reload. We will create a pending | |
| 1132 // entry, but Blink will convert it to a reload since it's the same page and | |
| 1133 // not create a new entry for it (the user doesn't want to have a new | |
| 1134 // back/forward entry when they do this). Therefore we want to just ignore | |
| 1135 // the pending entry and go back to where we were (the "existing entry"). | |
| 1136 return NAVIGATION_TYPE_SAME_PAGE; | |
| 1137 } | |
| 1138 | |
| 1139 if (params.url_is_unreachable && failed_pending_entry_id_ != 0 && | |
| 1140 params.nav_entry_id == failed_pending_entry_id_) { | |
| 1141 // If the renderer was going to a new pending entry that got cleared because | |
| 1142 // of an error, this is the case of the user trying to retry a failed load | |
| 1143 // by pressing return. | |
| 1144 return NAVIGATION_TYPE_EXISTING_PAGE; | |
| 1145 } | |
| 1146 | |
| 1147 // Now we know that the notification is for an existing page. Find that entry. | |
| 1148 int existing_entry_index = GetEntryIndexWithUniqueID(params.nav_entry_id); | |
| 1149 if (existing_entry_index == -1) { | |
| 1150 // The page was not found. It could have been pruned because of the limit on | |
| 1151 // back/forward entries (not likely since we'll usually tell it to navigate | |
| 1152 // to such entries). It could also mean that the renderer is smoking crack. | |
| 1153 // TODO(avi): Crash the renderer like we do in the old ClassifyNavigation? | |
| 1154 NOTREACHED() << "Could not find nav entry with id " << params.nav_entry_id; | |
| 1155 return NAVIGATION_TYPE_NAV_IGNORE; | |
| 1156 } | |
| 1157 | |
| 1158 // Any top-level navigations with the same base (minus the reference fragment) | |
| 1159 // are in-page navigations. (We weeded out subframe navigations above.) Most | |
| 1160 // of the time this doesn't matter since Blink doesn't tell us about subframe | |
| 1161 // navigations that don't actually navigate, but it can happen when there is | |
| 1162 // an encoding override (it always sends a navigation request). | |
| 1163 NavigationEntryImpl* existing_entry = entries_[existing_entry_index].get(); | |
| 1164 if (AreURLsInPageNavigation(existing_entry->GetURL(), params.url, | |
| 1165 params.was_within_same_page, rfh)) { | |
| 1166 return NAVIGATION_TYPE_IN_PAGE; | |
| 1167 } | |
| 1168 | |
| 1169 // Since we weeded out "new" navigations above, we know this is an existing | |
| 1170 // (back/forward) navigation. | |
| 1171 return NAVIGATION_TYPE_EXISTING_PAGE; | |
| 1172 } | |
| 1173 | |
| 1060 void NavigationControllerImpl::RendererDidNavigateToNewPage( | 1174 void NavigationControllerImpl::RendererDidNavigateToNewPage( |
| 1061 RenderFrameHostImpl* rfh, | 1175 RenderFrameHostImpl* rfh, |
| 1062 const FrameHostMsg_DidCommitProvisionalLoad_Params& params, | 1176 const FrameHostMsg_DidCommitProvisionalLoad_Params& params, |
| 1063 bool replace_entry) { | 1177 bool replace_entry) { |
| 1064 NavigationEntryImpl* new_entry; | 1178 NavigationEntryImpl* new_entry; |
| 1065 bool update_virtual_url; | 1179 bool update_virtual_url; |
| 1066 // Only make a copy of the pending entry if it is appropriate for the new page | 1180 // Only make a copy of the pending entry if it is appropriate for the new page |
| 1067 // that was just loaded. We verify this at a coarse grain by checking that | 1181 // that was just loaded. We verify this at a coarse grain by checking that |
| 1068 // the SiteInstance hasn't been assigned to something else. | 1182 // the SiteInstance hasn't been assigned to something else. |
| 1069 if (pending_entry_ && | 1183 if (pending_entry_ && |
| (...skipping 741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1811 int NavigationControllerImpl::GetEntryIndexWithPageID( | 1925 int NavigationControllerImpl::GetEntryIndexWithPageID( |
| 1812 SiteInstance* instance, int32 page_id) const { | 1926 SiteInstance* instance, int32 page_id) const { |
| 1813 for (int i = static_cast<int>(entries_.size()) - 1; i >= 0; --i) { | 1927 for (int i = static_cast<int>(entries_.size()) - 1; i >= 0; --i) { |
| 1814 if ((entries_[i]->site_instance() == instance) && | 1928 if ((entries_[i]->site_instance() == instance) && |
| 1815 (entries_[i]->GetPageID() == page_id)) | 1929 (entries_[i]->GetPageID() == page_id)) |
| 1816 return i; | 1930 return i; |
| 1817 } | 1931 } |
| 1818 return -1; | 1932 return -1; |
| 1819 } | 1933 } |
| 1820 | 1934 |
| 1935 int NavigationControllerImpl::GetEntryIndexWithUniqueID( | |
| 1936 int nav_entry_id) const { | |
| 1937 for (int i = static_cast<int>(entries_.size()) - 1; i >= 0; --i) { | |
| 1938 if (entries_[i]->GetUniqueID() == nav_entry_id) | |
| 1939 return i; | |
| 1940 } | |
| 1941 return -1; | |
| 1942 } | |
| 1943 | |
| 1821 NavigationEntryImpl* NavigationControllerImpl::GetTransientEntry() const { | 1944 NavigationEntryImpl* NavigationControllerImpl::GetTransientEntry() const { |
| 1822 if (transient_entry_index_ == -1) | 1945 if (transient_entry_index_ == -1) |
| 1823 return NULL; | 1946 return NULL; |
| 1824 return entries_[transient_entry_index_].get(); | 1947 return entries_[transient_entry_index_].get(); |
| 1825 } | 1948 } |
| 1826 | 1949 |
| 1827 void NavigationControllerImpl::SetTransientEntry(NavigationEntry* entry) { | 1950 void NavigationControllerImpl::SetTransientEntry(NavigationEntry* entry) { |
| 1828 // Discard any current transient entry, we can only have one at a time. | 1951 // Discard any current transient entry, we can only have one at a time. |
| 1829 int index = 0; | 1952 int index = 0; |
| 1830 if (last_committed_entry_index_ != -1) | 1953 if (last_committed_entry_index_ != -1) |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 1854 } | 1977 } |
| 1855 } | 1978 } |
| 1856 } | 1979 } |
| 1857 | 1980 |
| 1858 void NavigationControllerImpl::SetGetTimestampCallbackForTest( | 1981 void NavigationControllerImpl::SetGetTimestampCallbackForTest( |
| 1859 const base::Callback<base::Time()>& get_timestamp_callback) { | 1982 const base::Callback<base::Time()>& get_timestamp_callback) { |
| 1860 get_timestamp_callback_ = get_timestamp_callback; | 1983 get_timestamp_callback_ = get_timestamp_callback; |
| 1861 } | 1984 } |
| 1862 | 1985 |
| 1863 } // namespace content | 1986 } // namespace content |
| OLD | NEW |