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/trace_event.h" | 9 #include "base/debug/trace_event.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 for (size_t i = 0; i < entries->size(); ++i) { | 97 for (size_t i = 0; i < entries->size(); ++i) { |
98 // Use a transition type of reload so that we don't incorrectly increase | 98 // Use a transition type of reload so that we don't incorrectly increase |
99 // the typed count. | 99 // the typed count. |
100 (*entries)[i]->SetTransitionType(PAGE_TRANSITION_RELOAD); | 100 (*entries)[i]->SetTransitionType(PAGE_TRANSITION_RELOAD); |
101 (*entries)[i]->set_restore_type(ControllerRestoreTypeToEntryType(type)); | 101 (*entries)[i]->set_restore_type(ControllerRestoreTypeToEntryType(type)); |
102 // NOTE(darin): This code is only needed for backwards compat. | 102 // NOTE(darin): This code is only needed for backwards compat. |
103 SetPageStateIfEmpty((*entries)[i].get()); | 103 SetPageStateIfEmpty((*entries)[i].get()); |
104 } | 104 } |
105 } | 105 } |
106 | 106 |
107 // See NavigationController::IsURLInPageNavigation for how this works and why. | 107 // There are two general cases where a navigation is in page: |
| 108 // 1. A fragment navigation, in which the url is kept the same except for the |
| 109 // reference fragment. |
| 110 // 2. A history API navigation (pushState and replaceState). This case is |
| 111 // always in-page, but the urls are not guaranteed to match excluding the |
| 112 // fragment. The relevant spec allows pushState/replaceState to any URL on |
| 113 // the same origin. |
| 114 // However, due to reloads, even identical urls are *not* guaranteed to be |
| 115 // in-page navigations, we have to trust the renderer almost entirely. |
| 116 // The one thing we do know is that cross-origin navigations will *never* be |
| 117 // in-page. Therefore, trust the renderer if the URLs are on the same origin, |
| 118 // and assume the renderer is malicious if a cross-origin navigation claims to |
| 119 // be in-page. |
108 bool AreURLsInPageNavigation(const GURL& existing_url, | 120 bool AreURLsInPageNavigation(const GURL& existing_url, |
109 const GURL& new_url, | 121 const GURL& new_url, |
110 bool renderer_says_in_page, | 122 bool renderer_says_in_page, |
111 NavigationType navigation_type) { | 123 RenderFrameHost* rfh) { |
112 if (existing_url.GetOrigin() == new_url.GetOrigin()) | 124 WebPreferences prefs = rfh->GetRenderViewHost()->GetWebkitPreferences(); |
113 return renderer_says_in_page; | 125 bool is_same_origin = existing_url.is_empty() || |
114 | 126 existing_url.GetOrigin() == new_url.GetOrigin() || |
115 if (!new_url.has_ref()) { | 127 !prefs.web_security_enabled; |
116 // When going back from the ref URL to the non ref one the navigation type | 128 if (!is_same_origin && renderer_says_in_page) |
117 // is IN_PAGE. | 129 rfh->GetProcess()->ReceivedBadMessage(); |
118 return navigation_type == NAVIGATION_TYPE_IN_PAGE; | 130 return is_same_origin && renderer_says_in_page; |
119 } | |
120 | |
121 url::Replacements<char> replacements; | |
122 replacements.ClearRef(); | |
123 return existing_url.ReplaceComponents(replacements) == | |
124 new_url.ReplaceComponents(replacements); | |
125 } | 131 } |
126 | 132 |
127 // Determines whether or not we should be carrying over a user agent override | 133 // Determines whether or not we should be carrying over a user agent override |
128 // between two NavigationEntries. | 134 // between two NavigationEntries. |
129 bool ShouldKeepOverride(const NavigationEntry* last_entry) { | 135 bool ShouldKeepOverride(const NavigationEntry* last_entry) { |
130 return last_entry && last_entry->GetIsOverridingUserAgent(); | 136 return last_entry && last_entry->GetIsOverridingUserAgent(); |
131 } | 137 } |
132 | 138 |
133 } // namespace | 139 } // namespace |
134 | 140 |
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
759 // effect of removing forward browsing history, if such existed. | 765 // effect of removing forward browsing history, if such existed. |
760 // Or if we are doing a cross-site redirect navigation, | 766 // Or if we are doing a cross-site redirect navigation, |
761 // we will do a similar thing. | 767 // we will do a similar thing. |
762 details->did_replace_entry = | 768 details->did_replace_entry = |
763 pending_entry_ && pending_entry_->should_replace_entry(); | 769 pending_entry_ && pending_entry_->should_replace_entry(); |
764 | 770 |
765 // Do navigation-type specific actions. These will make and commit an entry. | 771 // Do navigation-type specific actions. These will make and commit an entry. |
766 details->type = ClassifyNavigation(rfh, params); | 772 details->type = ClassifyNavigation(rfh, params); |
767 | 773 |
768 // is_in_page must be computed before the entry gets committed. | 774 // is_in_page must be computed before the entry gets committed. |
769 details->is_in_page = IsURLInPageNavigation( | 775 details->is_in_page = AreURLsInPageNavigation(rfh->GetLastCommittedURL(), |
770 params.url, params.was_within_same_page, details->type); | 776 params.url, params.was_within_same_page, rfh); |
771 | 777 |
772 switch (details->type) { | 778 switch (details->type) { |
773 case NAVIGATION_TYPE_NEW_PAGE: | 779 case NAVIGATION_TYPE_NEW_PAGE: |
774 RendererDidNavigateToNewPage(rfh, params, details->did_replace_entry); | 780 RendererDidNavigateToNewPage(rfh, params, details->did_replace_entry); |
775 break; | 781 break; |
776 case NAVIGATION_TYPE_EXISTING_PAGE: | 782 case NAVIGATION_TYPE_EXISTING_PAGE: |
777 RendererDidNavigateToExistingPage(rfh, params); | 783 RendererDidNavigateToExistingPage(rfh, params); |
778 break; | 784 break; |
779 case NAVIGATION_TYPE_SAME_PAGE: | 785 case NAVIGATION_TYPE_SAME_PAGE: |
780 RendererDidNavigateToSamePage(rfh, params); | 786 RendererDidNavigateToSamePage(rfh, params); |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
979 // the pending entry and go back to where we were (the "existing entry"). | 985 // the pending entry and go back to where we were (the "existing entry"). |
980 return NAVIGATION_TYPE_SAME_PAGE; | 986 return NAVIGATION_TYPE_SAME_PAGE; |
981 } | 987 } |
982 | 988 |
983 // Any toplevel navigations with the same base (minus the reference fragment) | 989 // Any toplevel navigations with the same base (minus the reference fragment) |
984 // are in-page navigations. We weeded out subframe navigations above. Most of | 990 // are in-page navigations. We weeded out subframe navigations above. Most of |
985 // the time this doesn't matter since WebKit doesn't tell us about subframe | 991 // the time this doesn't matter since WebKit doesn't tell us about subframe |
986 // navigations that don't actually navigate, but it can happen when there is | 992 // navigations that don't actually navigate, but it can happen when there is |
987 // an encoding override (it always sends a navigation request). | 993 // an encoding override (it always sends a navigation request). |
988 if (AreURLsInPageNavigation(existing_entry->GetURL(), params.url, | 994 if (AreURLsInPageNavigation(existing_entry->GetURL(), params.url, |
989 params.was_within_same_page, | 995 params.was_within_same_page, rfh)) { |
990 NAVIGATION_TYPE_UNKNOWN)) { | |
991 return NAVIGATION_TYPE_IN_PAGE; | 996 return NAVIGATION_TYPE_IN_PAGE; |
992 } | 997 } |
993 | 998 |
994 // Since we weeded out "new" navigations above, we know this is an existing | 999 // Since we weeded out "new" navigations above, we know this is an existing |
995 // (back/forward) navigation. | 1000 // (back/forward) navigation. |
996 return NAVIGATION_TYPE_EXISTING_PAGE; | 1001 return NAVIGATION_TYPE_EXISTING_PAGE; |
997 } | 1002 } |
998 | 1003 |
999 void NavigationControllerImpl::RendererDidNavigateToNewPage( | 1004 void NavigationControllerImpl::RendererDidNavigateToNewPage( |
1000 RenderFrameHost* rfh, | 1005 RenderFrameHost* rfh, |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1246 const NavigationEntries::const_iterator i(std::find( | 1251 const NavigationEntries::const_iterator i(std::find( |
1247 entries_.begin(), | 1252 entries_.begin(), |
1248 entries_.end(), | 1253 entries_.end(), |
1249 entry)); | 1254 entry)); |
1250 return (i == entries_.end()) ? -1 : static_cast<int>(i - entries_.begin()); | 1255 return (i == entries_.end()) ? -1 : static_cast<int>(i - entries_.begin()); |
1251 } | 1256 } |
1252 | 1257 |
1253 bool NavigationControllerImpl::IsURLInPageNavigation( | 1258 bool NavigationControllerImpl::IsURLInPageNavigation( |
1254 const GURL& url, | 1259 const GURL& url, |
1255 bool renderer_says_in_page, | 1260 bool renderer_says_in_page, |
1256 NavigationType navigation_type) const { | 1261 RenderFrameHost* rfh) const { |
1257 NavigationEntry* last_committed = GetLastCommittedEntry(); | 1262 NavigationEntry* last_committed = GetLastCommittedEntry(); |
1258 return last_committed && AreURLsInPageNavigation( | 1263 return last_committed && AreURLsInPageNavigation( |
1259 last_committed->GetURL(), url, renderer_says_in_page, navigation_type); | 1264 last_committed->GetURL(), url, renderer_says_in_page, rfh); |
1260 } | 1265 } |
1261 | 1266 |
1262 void NavigationControllerImpl::CopyStateFrom( | 1267 void NavigationControllerImpl::CopyStateFrom( |
1263 const NavigationController& temp) { | 1268 const NavigationController& temp) { |
1264 const NavigationControllerImpl& source = | 1269 const NavigationControllerImpl& source = |
1265 static_cast<const NavigationControllerImpl&>(temp); | 1270 static_cast<const NavigationControllerImpl&>(temp); |
1266 // Verify that we look new. | 1271 // Verify that we look new. |
1267 DCHECK(GetEntryCount() == 0 && !GetPendingEntry()); | 1272 DCHECK(GetEntryCount() == 0 && !GetPendingEntry()); |
1268 | 1273 |
1269 if (source.GetEntryCount() == 0) | 1274 if (source.GetEntryCount() == 0) |
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1770 } | 1775 } |
1771 } | 1776 } |
1772 } | 1777 } |
1773 | 1778 |
1774 void NavigationControllerImpl::SetGetTimestampCallbackForTest( | 1779 void NavigationControllerImpl::SetGetTimestampCallbackForTest( |
1775 const base::Callback<base::Time()>& get_timestamp_callback) { | 1780 const base::Callback<base::Time()>& get_timestamp_callback) { |
1776 get_timestamp_callback_ = get_timestamp_callback; | 1781 get_timestamp_callback_ = get_timestamp_callback; |
1777 } | 1782 } |
1778 | 1783 |
1779 } // namespace content | 1784 } // namespace content |
OLD | NEW |