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/debug/crash_logging.h" | |
10 #include "base/logging.h" | 9 #include "base/logging.h" |
11 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
12 #include "base/strings/string_number_conversions.h" // Temporary | 11 #include "base/strings/string_number_conversions.h" // Temporary |
13 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
14 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
15 #include "base/time/time.h" | 14 #include "base/time/time.h" |
16 #include "base/trace_event/trace_event.h" | 15 #include "base/trace_event/trace_event.h" |
17 #include "build/build_config.h" | 16 #include "build/build_config.h" |
18 #include "cc/base/switches.h" | 17 #include "cc/base/switches.h" |
19 #include "components/mime_util/mime_util.h" | 18 #include "components/mime_util/mime_util.h" |
(...skipping 766 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
786 if (params.url_is_unreachable && failed_pending_entry_id_ != 0) { | 785 if (params.url_is_unreachable && failed_pending_entry_id_ != 0) { |
787 details->did_replace_entry = failed_pending_entry_should_replace_; | 786 details->did_replace_entry = failed_pending_entry_should_replace_; |
788 } else { | 787 } else { |
789 details->did_replace_entry = pending_entry_ && | 788 details->did_replace_entry = pending_entry_ && |
790 pending_entry_->should_replace_entry(); | 789 pending_entry_->should_replace_entry(); |
791 } | 790 } |
792 | 791 |
793 // Do navigation-type specific actions. These will make and commit an entry. | 792 // Do navigation-type specific actions. These will make and commit an entry. |
794 details->type = ClassifyNavigation(rfh, params); | 793 details->type = ClassifyNavigation(rfh, params); |
795 NavigationType new_type = ClassifyNavigationWithoutPageID(rfh, params); | 794 NavigationType new_type = ClassifyNavigationWithoutPageID(rfh, params); |
796 if (details->type == NAVIGATION_TYPE_NAV_IGNORE && | |
797 new_type == NAVIGATION_TYPE_NAV_IGNORE) { | |
798 base::debug::SetCrashKeyValue("369661-doubleignore", | |
799 rfh->CommitCountString()); | |
800 } | |
801 bool ignore_mismatch = false; | 795 bool ignore_mismatch = false; |
802 // There are disagreements on some Android bots over SAME_PAGE between the two | 796 // There are disagreements on some Android bots over SAME_PAGE between the two |
803 // classifiers so ignore disagreements if that's the case. | 797 // classifiers so ignore disagreements if that's the case. |
804 ignore_mismatch |= details->type == NAVIGATION_TYPE_EXISTING_PAGE && | 798 ignore_mismatch |= details->type == NAVIGATION_TYPE_EXISTING_PAGE && |
805 new_type == NAVIGATION_TYPE_SAME_PAGE; | 799 new_type == NAVIGATION_TYPE_SAME_PAGE; |
806 ignore_mismatch |= details->type == NAVIGATION_TYPE_SAME_PAGE && | 800 ignore_mismatch |= details->type == NAVIGATION_TYPE_SAME_PAGE && |
807 new_type == NAVIGATION_TYPE_EXISTING_PAGE; | 801 new_type == NAVIGATION_TYPE_EXISTING_PAGE; |
808 // There are mismatches in the field where the new classifier thinks it's | 802 // There are mismatches in the field where the new classifier thinks it's |
809 // AUTO_SUBFRAME and the old classifier somehow thinks it's NEW or IGNORE. For | 803 // AUTO_SUBFRAME and the old classifier somehow thinks it's NEW or IGNORE. For |
810 // IGNORE we know of at least one repro (https://crbug.com/492875), and for | 804 // IGNORE we know of at least one repro (https://crbug.com/492875), and for |
811 // NEW it's not entirely clear what's going on, but we're pretty sure the new | 805 // NEW it's not entirely clear what's going on, but we're pretty sure the new |
812 // classifier is correct for both cases, so we're letting these mismatches go. | 806 // classifier is correct for both cases, so we're letting these mismatches go. |
813 ignore_mismatch |= details->type == NAVIGATION_TYPE_NEW_SUBFRAME && | 807 ignore_mismatch |= details->type == NAVIGATION_TYPE_NEW_SUBFRAME && |
814 new_type == NAVIGATION_TYPE_AUTO_SUBFRAME; | 808 new_type == NAVIGATION_TYPE_AUTO_SUBFRAME; |
815 ignore_mismatch |= details->type == NAVIGATION_TYPE_NAV_IGNORE && | 809 ignore_mismatch |= details->type == NAVIGATION_TYPE_NAV_IGNORE && |
816 new_type == NAVIGATION_TYPE_AUTO_SUBFRAME; | 810 new_type == NAVIGATION_TYPE_AUTO_SUBFRAME; |
817 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 811 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
818 switches::kSitePerProcess)) { | 812 switches::kSitePerProcess)) { |
819 // We know that the old classifier is wrong for OOPIFs, so use the new one | 813 // We know that the old classifier is wrong for OOPIFs, so use the new one |
820 // in --site-per-process mode. | 814 // in --site-per-process mode. |
821 details->type = new_type; | 815 details->type = new_type; |
822 ignore_mismatch = true; | 816 ignore_mismatch = true; |
823 } | 817 } |
824 if (!ignore_mismatch) { | 818 if (!ignore_mismatch) { |
825 base::debug::SetCrashKeyValue("369661-oldtype", | 819 DCHECK_EQ(details->type, new_type); |
826 base::IntToString(details->type)); | |
827 base::debug::SetCrashKeyValue("369661-newtype", | |
828 base::IntToString(new_type)); | |
829 base::debug::SetCrashKeyValue("369661-navurl", params.url.spec()); | |
830 base::debug::SetCrashKeyValue("369661-naventryid", | |
831 base::IntToString(params.nav_entry_id)); | |
832 base::debug::SetCrashKeyValue("369661-didcreatenew", | |
833 params.did_create_new_entry ? "yes" : "no"); | |
834 base::debug::SetCrashKeyValue("369661-pageid", | |
835 base::IntToString(params.page_id)); | |
836 base::debug::SetCrashKeyValue( | |
837 "369661-maxpageid", | |
838 base::IntToString(delegate_->GetMaxPageIDForSiteInstance( | |
839 rfh->GetSiteInstance()))); | |
840 CHECK_EQ(details->type, new_type); | |
841 } | 820 } |
842 | 821 |
843 // is_in_page must be computed before the entry gets committed. | 822 // is_in_page must be computed before the entry gets committed. |
844 details->is_in_page = IsURLInPageNavigation( | 823 details->is_in_page = IsURLInPageNavigation( |
845 params.url, params.was_within_same_page, rfh); | 824 params.url, params.was_within_same_page, rfh); |
846 | 825 |
847 switch (details->type) { | 826 switch (details->type) { |
848 case NAVIGATION_TYPE_NEW_PAGE: | 827 case NAVIGATION_TYPE_NEW_PAGE: |
849 RendererDidNavigateToNewPage(rfh, params, details->did_replace_entry); | 828 RendererDidNavigateToNewPage(rfh, params, details->did_replace_entry); |
850 break; | 829 break; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
950 // - We were also getting these for failed loads (for example, bug 21849). | 929 // - We were also getting these for failed loads (for example, bug 21849). |
951 // The guess is that we get a "load commit" for the alternate error page, | 930 // The guess is that we get a "load commit" for the alternate error page, |
952 // but that doesn't affect the page ID, so we get the "old" one, which | 931 // but that doesn't affect the page ID, so we get the "old" one, which |
953 // could be invalid. This can also happen for a cross-site transition | 932 // could be invalid. This can also happen for a cross-site transition |
954 // that causes us to swap processes. Then the error page load will be in | 933 // that causes us to swap processes. Then the error page load will be in |
955 // a new process with no page IDs ever assigned (and hence a -1 value), | 934 // a new process with no page IDs ever assigned (and hence a -1 value), |
956 // yet the navigation controller still might have previous pages in its | 935 // yet the navigation controller still might have previous pages in its |
957 // list. | 936 // list. |
958 // | 937 // |
959 // In these cases, there's nothing we can do with them, so ignore. | 938 // In these cases, there's nothing we can do with them, so ignore. |
960 base::debug::SetCrashKeyValue("369661-oldignore", | |
961 rfh->CommitCountString() + | |
962 " no page id"); | |
963 return NAVIGATION_TYPE_NAV_IGNORE; | 939 return NAVIGATION_TYPE_NAV_IGNORE; |
964 } | 940 } |
965 | 941 |
966 if (params.page_id > delegate_->GetMaxPageIDForSiteInstance( | 942 if (params.page_id > delegate_->GetMaxPageIDForSiteInstance( |
967 rfh->GetSiteInstance())) { | 943 rfh->GetSiteInstance())) { |
968 // Greater page IDs than we've ever seen before are new pages. We may or may | 944 // Greater page IDs than we've ever seen before are new pages. We may or may |
969 // not have a pending entry for the page, and this may or may not be the | 945 // not have a pending entry for the page, and this may or may not be the |
970 // main frame. | 946 // main frame. |
971 if (!rfh->GetParent()) | 947 if (!rfh->GetParent()) |
972 return NAVIGATION_TYPE_NEW_PAGE; | 948 return NAVIGATION_TYPE_NEW_PAGE; |
973 | 949 |
974 // When this is a new subframe navigation, we should have a committed page | 950 // When this is a new subframe navigation, we should have a committed page |
975 // for which it's a suframe in. This may not be the case when an iframe is | 951 // for which it's a suframe in. This may not be the case when an iframe is |
976 // navigated on a popup navigated to about:blank (the iframe would be | 952 // navigated on a popup navigated to about:blank (the iframe would be |
977 // written into the popup by script on the main page). For these cases, | 953 // written into the popup by script on the main page). For these cases, |
978 // there isn't any navigation stuff we can do, so just ignore it. | 954 // there isn't any navigation stuff we can do, so just ignore it. |
979 if (!GetLastCommittedEntry()) { | 955 if (!GetLastCommittedEntry()) |
980 base::debug::SetCrashKeyValue("369661-oldignore", | |
981 rfh->CommitCountString() + | |
982 " new subframe no last committed"); | |
983 return NAVIGATION_TYPE_NAV_IGNORE; | 956 return NAVIGATION_TYPE_NAV_IGNORE; |
984 } | |
985 | 957 |
986 // Valid subframe navigation. | 958 // Valid subframe navigation. |
987 return NAVIGATION_TYPE_NEW_SUBFRAME; | 959 return NAVIGATION_TYPE_NEW_SUBFRAME; |
988 } | 960 } |
989 | 961 |
990 // We only clear the session history when navigating to a new page. | 962 // We only clear the session history when navigating to a new page. |
991 DCHECK(!params.history_list_was_cleared); | 963 DCHECK(!params.history_list_was_cleared); |
992 | 964 |
993 // Now we know that the notification is for an existing page. Find that entry. | 965 // Now we know that the notification is for an existing page. Find that entry. |
994 int existing_entry_index = GetEntryIndexWithPageID( | 966 int existing_entry_index = GetEntryIndexWithPageID( |
(...skipping 30 matching lines...) Expand all Loading... |
1025 if (entries_[i]->site_instance()) | 997 if (entries_[i]->site_instance()) |
1026 temp.append(base::IntToString(entries_[i]->site_instance()->GetId())); | 998 temp.append(base::IntToString(entries_[i]->site_instance()->GetId())); |
1027 else | 999 else |
1028 temp.append("N"); | 1000 temp.append("N"); |
1029 if (entries_[i]->site_instance() != rfh->GetSiteInstance()) | 1001 if (entries_[i]->site_instance() != rfh->GetSiteInstance()) |
1030 temp.append("x"); | 1002 temp.append("x"); |
1031 temp.append(","); | 1003 temp.append(","); |
1032 } | 1004 } |
1033 GURL url(temp); | 1005 GURL url(temp); |
1034 rfh->render_view_host()->Send(new ViewMsg_TempCrashWithData(url)); | 1006 rfh->render_view_host()->Send(new ViewMsg_TempCrashWithData(url)); |
1035 base::debug::SetCrashKeyValue("369661-oldignore", | |
1036 rfh->CommitCountString() + | |
1037 " renderer smoking crack"); | |
1038 return NAVIGATION_TYPE_NAV_IGNORE; | 1007 return NAVIGATION_TYPE_NAV_IGNORE; |
1039 } | 1008 } |
1040 NavigationEntryImpl* existing_entry = entries_[existing_entry_index].get(); | 1009 NavigationEntryImpl* existing_entry = entries_[existing_entry_index].get(); |
1041 | 1010 |
1042 if (rfh->GetParent()) { | 1011 if (rfh->GetParent()) { |
1043 // All manual subframes would get new IDs and were handled above, so we | 1012 // All manual subframes would get new IDs and were handled above, so we |
1044 // know this is auto. Since the current page was found in the navigation | 1013 // know this is auto. Since the current page was found in the navigation |
1045 // entry list, we're guaranteed to have a last committed entry. | 1014 // entry list, we're guaranteed to have a last committed entry. |
1046 DCHECK(GetLastCommittedEntry()); | 1015 DCHECK(GetLastCommittedEntry()); |
1047 return NAVIGATION_TYPE_AUTO_SUBFRAME; | 1016 return NAVIGATION_TYPE_AUTO_SUBFRAME; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1100 // this may or may not be the main frame. | 1069 // this may or may not be the main frame. |
1101 if (!rfh->GetParent()) { | 1070 if (!rfh->GetParent()) { |
1102 return NAVIGATION_TYPE_NEW_PAGE; | 1071 return NAVIGATION_TYPE_NEW_PAGE; |
1103 } | 1072 } |
1104 | 1073 |
1105 // When this is a new subframe navigation, we should have a committed page | 1074 // When this is a new subframe navigation, we should have a committed page |
1106 // in which it's a subframe. This may not be the case when an iframe is | 1075 // in which it's a subframe. This may not be the case when an iframe is |
1107 // navigated on a popup navigated to about:blank (the iframe would be | 1076 // navigated on a popup navigated to about:blank (the iframe would be |
1108 // written into the popup by script on the main page). For these cases, | 1077 // written into the popup by script on the main page). For these cases, |
1109 // there isn't any navigation stuff we can do, so just ignore it. | 1078 // there isn't any navigation stuff we can do, so just ignore it. |
1110 if (!GetLastCommittedEntry()) { | 1079 if (!GetLastCommittedEntry()) |
1111 base::debug::SetCrashKeyValue("369661-newignore", | |
1112 rfh->CommitCountString() + | |
1113 " new subframe no last committed"); | |
1114 return NAVIGATION_TYPE_NAV_IGNORE; | 1080 return NAVIGATION_TYPE_NAV_IGNORE; |
1115 } | |
1116 | 1081 |
1117 // Valid subframe navigation. | 1082 // Valid subframe navigation. |
1118 return NAVIGATION_TYPE_NEW_SUBFRAME; | 1083 return NAVIGATION_TYPE_NEW_SUBFRAME; |
1119 } | 1084 } |
1120 | 1085 |
1121 // We only clear the session history when navigating to a new page. | 1086 // We only clear the session history when navigating to a new page. |
1122 DCHECK(!params.history_list_was_cleared); | 1087 DCHECK(!params.history_list_was_cleared); |
1123 | 1088 |
1124 if (rfh->GetParent()) { | 1089 if (rfh->GetParent()) { |
1125 // All manual subframes would be did_create_new_entry and handled above, so | 1090 // All manual subframes would be did_create_new_entry and handled above, so |
1126 // we know this is auto. | 1091 // we know this is auto. |
1127 if (GetLastCommittedEntry()) { | 1092 if (GetLastCommittedEntry()) { |
1128 return NAVIGATION_TYPE_AUTO_SUBFRAME; | 1093 return NAVIGATION_TYPE_AUTO_SUBFRAME; |
1129 } else { | 1094 } else { |
1130 // We ignore subframes created in non-committed pages; we'd appreciate if | 1095 // We ignore subframes created in non-committed pages; we'd appreciate if |
1131 // people stopped doing that. | 1096 // people stopped doing that. |
1132 base::debug::SetCrashKeyValue("369661-newignore", | |
1133 rfh->CommitCountString() + | |
1134 " auto subframe no last committed"); | |
1135 return NAVIGATION_TYPE_NAV_IGNORE; | 1097 return NAVIGATION_TYPE_NAV_IGNORE; |
1136 } | 1098 } |
1137 } | 1099 } |
1138 | 1100 |
1139 if (params.nav_entry_id == 0) { | 1101 if (params.nav_entry_id == 0) { |
1140 // This is a renderer-initiated navigation (nav_entry_id == 0), but didn't | 1102 // This is a renderer-initiated navigation (nav_entry_id == 0), but didn't |
1141 // create a new page. | 1103 // create a new page. |
1142 | 1104 |
1143 // Just like above in the did_create_new_entry case, it's possible to | 1105 // Just like above in the did_create_new_entry case, it's possible to |
1144 // scribble onto an uncommitted page. Again, there isn't any navigation | 1106 // scribble onto an uncommitted page. Again, there isn't any navigation |
1145 // stuff that we can do, so ignore it here as well. | 1107 // stuff that we can do, so ignore it here as well. |
1146 NavigationEntry* last_committed = GetLastCommittedEntry(); | 1108 NavigationEntry* last_committed = GetLastCommittedEntry(); |
1147 if (!last_committed) { | 1109 if (!last_committed) |
1148 base::debug::SetCrashKeyValue("369661-newignore", | |
1149 rfh->CommitCountString() + | |
1150 " renderer-initiated no last committed"); | |
1151 return NAVIGATION_TYPE_NAV_IGNORE; | 1110 return NAVIGATION_TYPE_NAV_IGNORE; |
1152 } | |
1153 | 1111 |
1154 if (IsURLInPageNavigation(params.url, params.was_within_same_page, rfh)) { | 1112 if (IsURLInPageNavigation(params.url, params.was_within_same_page, rfh)) { |
1155 // This is history.replaceState(), which is renderer-initiated yet within | 1113 // This is history.replaceState(), which is renderer-initiated yet within |
1156 // the same page. | 1114 // the same page. |
1157 return NAVIGATION_TYPE_IN_PAGE; | 1115 return NAVIGATION_TYPE_IN_PAGE; |
1158 } else { | 1116 } else { |
1159 // This is history.reload() or a client-side redirect. | 1117 // This is history.reload() or a client-side redirect. |
1160 return NAVIGATION_TYPE_EXISTING_PAGE; | 1118 return NAVIGATION_TYPE_EXISTING_PAGE; |
1161 } | 1119 } |
1162 } | 1120 } |
(...skipping 27 matching lines...) Expand all Loading... |
1190 } | 1148 } |
1191 | 1149 |
1192 // Now we know that the notification is for an existing page. Find that entry. | 1150 // Now we know that the notification is for an existing page. Find that entry. |
1193 int existing_entry_index = GetEntryIndexWithUniqueID(params.nav_entry_id); | 1151 int existing_entry_index = GetEntryIndexWithUniqueID(params.nav_entry_id); |
1194 if (existing_entry_index == -1) { | 1152 if (existing_entry_index == -1) { |
1195 // The page was not found. It could have been pruned because of the limit on | 1153 // The page was not found. It could have been pruned because of the limit on |
1196 // back/forward entries (not likely since we'll usually tell it to navigate | 1154 // back/forward entries (not likely since we'll usually tell it to navigate |
1197 // to such entries). It could also mean that the renderer is smoking crack. | 1155 // to such entries). It could also mean that the renderer is smoking crack. |
1198 // TODO(avi): Crash the renderer like we do in the old ClassifyNavigation? | 1156 // TODO(avi): Crash the renderer like we do in the old ClassifyNavigation? |
1199 NOTREACHED() << "Could not find nav entry with id " << params.nav_entry_id; | 1157 NOTREACHED() << "Could not find nav entry with id " << params.nav_entry_id; |
1200 base::debug::SetCrashKeyValue("369661-newignore", | |
1201 rfh->CommitCountString() + | |
1202 " renderer smoking crack"); | |
1203 return NAVIGATION_TYPE_NAV_IGNORE; | 1158 return NAVIGATION_TYPE_NAV_IGNORE; |
1204 } | 1159 } |
1205 | 1160 |
1206 // Any top-level navigations with the same base (minus the reference fragment) | 1161 // Any top-level navigations with the same base (minus the reference fragment) |
1207 // are in-page navigations. (We weeded out subframe navigations above.) Most | 1162 // are in-page navigations. (We weeded out subframe navigations above.) Most |
1208 // of the time this doesn't matter since Blink doesn't tell us about subframe | 1163 // of the time this doesn't matter since Blink doesn't tell us about subframe |
1209 // navigations that don't actually navigate, but it can happen when there is | 1164 // navigations that don't actually navigate, but it can happen when there is |
1210 // an encoding override (it always sends a navigation request). | 1165 // an encoding override (it always sends a navigation request). |
1211 if (IsURLInPageNavigation(params.url, params.was_within_same_page, rfh)) | 1166 if (IsURLInPageNavigation(params.url, params.was_within_same_page, rfh)) |
1212 return NAVIGATION_TYPE_IN_PAGE; | 1167 return NAVIGATION_TYPE_IN_PAGE; |
(...skipping 868 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2081 } | 2036 } |
2082 } | 2037 } |
2083 } | 2038 } |
2084 | 2039 |
2085 void NavigationControllerImpl::SetGetTimestampCallbackForTest( | 2040 void NavigationControllerImpl::SetGetTimestampCallbackForTest( |
2086 const base::Callback<base::Time()>& get_timestamp_callback) { | 2041 const base::Callback<base::Time()>& get_timestamp_callback) { |
2087 get_timestamp_callback_ = get_timestamp_callback; | 2042 get_timestamp_callback_ = get_timestamp_callback; |
2088 } | 2043 } |
2089 | 2044 |
2090 } // namespace content | 2045 } // namespace content |
OLD | NEW |