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 bool is_same_origin = existing_url.is_empty() || |
Nate Chapin
2014/06/06 22:45:23
Declaring a navigation from an empty url same-orig
nasko
2014/06/09 18:49:43
Isn't the initial empty document with "about:blank
Nate Chapin
2014/06/09 18:53:49
It is (most of the time, there's a special case in
nasko
2014/06/09 18:59:24
Ok, though I think we would have to start reportin
Nate Chapin
2014/06/09 19:02:54
Huh, interesting. I would have thought that the in
nasko
2014/06/09 20:41:28
When I discussed this with Charlie, we found that
| |
113 return renderer_says_in_page; | 125 existing_url.GetOrigin() == new_url.GetOrigin(); |
114 | 126 if (!is_same_origin && renderer_says_in_page) |
115 if (!new_url.has_ref()) { | 127 rfh->GetProcess()->ReceivedBadMessage(); |
116 // When going back from the ref URL to the non ref one the navigation type | 128 return is_same_origin && renderer_says_in_page; |
117 // is IN_PAGE. | |
118 return navigation_type == NAVIGATION_TYPE_IN_PAGE; | |
119 } | |
120 | |
121 url::Replacements<char> replacements; | |
122 replacements.ClearRef(); | |
123 return existing_url.ReplaceComponents(replacements) == | |
124 new_url.ReplaceComponents(replacements); | |
125 } | 129 } |
126 | 130 |
127 // Determines whether or not we should be carrying over a user agent override | 131 // Determines whether or not we should be carrying over a user agent override |
128 // between two NavigationEntries. | 132 // between two NavigationEntries. |
129 bool ShouldKeepOverride(const NavigationEntry* last_entry) { | 133 bool ShouldKeepOverride(const NavigationEntry* last_entry) { |
130 return last_entry && last_entry->GetIsOverridingUserAgent(); | 134 return last_entry && last_entry->GetIsOverridingUserAgent(); |
131 } | 135 } |
132 | 136 |
133 } // namespace | 137 } // namespace |
134 | 138 |
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
759 // effect of removing forward browsing history, if such existed. | 763 // effect of removing forward browsing history, if such existed. |
760 // Or if we are doing a cross-site redirect navigation, | 764 // Or if we are doing a cross-site redirect navigation, |
761 // we will do a similar thing. | 765 // we will do a similar thing. |
762 details->did_replace_entry = | 766 details->did_replace_entry = |
763 pending_entry_ && pending_entry_->should_replace_entry(); | 767 pending_entry_ && pending_entry_->should_replace_entry(); |
764 | 768 |
765 // Do navigation-type specific actions. These will make and commit an entry. | 769 // Do navigation-type specific actions. These will make and commit an entry. |
766 details->type = ClassifyNavigation(rfh, params); | 770 details->type = ClassifyNavigation(rfh, params); |
767 | 771 |
768 // is_in_page must be computed before the entry gets committed. | 772 // is_in_page must be computed before the entry gets committed. |
769 details->is_in_page = IsURLInPageNavigation( | 773 details->is_in_page = AreURLsInPageNavigation(rfh->GetLastCommittedURL(), |
Nate Chapin
2014/06/06 22:45:23
Unlike other uses of the in-page logic, this calls
nasko
2014/06/09 18:49:43
GetLastCommittedURL on RFH worries me a bit. It co
Nate Chapin
2014/06/09 18:53:49
Fair enough. Is there an alternate way to get the
nasko
2014/06/09 18:59:24
It is already there: https://code.google.com/p/chr
Nate Chapin
2014/06/09 19:02:54
I see the URL being navigated to, the base url, an
nasko
2014/06/09 20:41:28
Duh, I misread what you meant. You are correct. Lo
| |
770 params.url, params.was_within_same_page, details->type); | 774 params.url, params.was_within_same_page, rfh); |
771 | 775 |
772 switch (details->type) { | 776 switch (details->type) { |
773 case NAVIGATION_TYPE_NEW_PAGE: | 777 case NAVIGATION_TYPE_NEW_PAGE: |
774 RendererDidNavigateToNewPage(rfh, params, details->did_replace_entry); | 778 RendererDidNavigateToNewPage(rfh, params, details->did_replace_entry); |
775 break; | 779 break; |
776 case NAVIGATION_TYPE_EXISTING_PAGE: | 780 case NAVIGATION_TYPE_EXISTING_PAGE: |
777 RendererDidNavigateToExistingPage(rfh, params); | 781 RendererDidNavigateToExistingPage(rfh, params); |
778 break; | 782 break; |
779 case NAVIGATION_TYPE_SAME_PAGE: | 783 case NAVIGATION_TYPE_SAME_PAGE: |
780 RendererDidNavigateToSamePage(rfh, params); | 784 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"). | 983 // the pending entry and go back to where we were (the "existing entry"). |
980 return NAVIGATION_TYPE_SAME_PAGE; | 984 return NAVIGATION_TYPE_SAME_PAGE; |
981 } | 985 } |
982 | 986 |
983 // Any toplevel navigations with the same base (minus the reference fragment) | 987 // Any toplevel navigations with the same base (minus the reference fragment) |
984 // are in-page navigations. We weeded out subframe navigations above. Most of | 988 // 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 | 989 // 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 | 990 // navigations that don't actually navigate, but it can happen when there is |
987 // an encoding override (it always sends a navigation request). | 991 // an encoding override (it always sends a navigation request). |
988 if (AreURLsInPageNavigation(existing_entry->GetURL(), params.url, | 992 if (AreURLsInPageNavigation(existing_entry->GetURL(), params.url, |
989 params.was_within_same_page, | 993 params.was_within_same_page, rfh)) { |
990 NAVIGATION_TYPE_UNKNOWN)) { | |
991 return NAVIGATION_TYPE_IN_PAGE; | 994 return NAVIGATION_TYPE_IN_PAGE; |
992 } | 995 } |
993 | 996 |
994 // Since we weeded out "new" navigations above, we know this is an existing | 997 // Since we weeded out "new" navigations above, we know this is an existing |
995 // (back/forward) navigation. | 998 // (back/forward) navigation. |
996 return NAVIGATION_TYPE_EXISTING_PAGE; | 999 return NAVIGATION_TYPE_EXISTING_PAGE; |
997 } | 1000 } |
998 | 1001 |
999 void NavigationControllerImpl::RendererDidNavigateToNewPage( | 1002 void NavigationControllerImpl::RendererDidNavigateToNewPage( |
1000 RenderFrameHost* rfh, | 1003 RenderFrameHost* rfh, |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1246 const NavigationEntries::const_iterator i(std::find( | 1249 const NavigationEntries::const_iterator i(std::find( |
1247 entries_.begin(), | 1250 entries_.begin(), |
1248 entries_.end(), | 1251 entries_.end(), |
1249 entry)); | 1252 entry)); |
1250 return (i == entries_.end()) ? -1 : static_cast<int>(i - entries_.begin()); | 1253 return (i == entries_.end()) ? -1 : static_cast<int>(i - entries_.begin()); |
1251 } | 1254 } |
1252 | 1255 |
1253 bool NavigationControllerImpl::IsURLInPageNavigation( | 1256 bool NavigationControllerImpl::IsURLInPageNavigation( |
1254 const GURL& url, | 1257 const GURL& url, |
1255 bool renderer_says_in_page, | 1258 bool renderer_says_in_page, |
1256 NavigationType navigation_type) const { | 1259 RenderFrameHost* rfh) const { |
1257 NavigationEntry* last_committed = GetLastCommittedEntry(); | 1260 NavigationEntry* last_committed = GetLastCommittedEntry(); |
1258 return last_committed && AreURLsInPageNavigation( | 1261 return last_committed && AreURLsInPageNavigation( |
1259 last_committed->GetURL(), url, renderer_says_in_page, navigation_type); | 1262 last_committed->GetURL(), url, renderer_says_in_page, rfh); |
1260 } | 1263 } |
1261 | 1264 |
1262 void NavigationControllerImpl::CopyStateFrom( | 1265 void NavigationControllerImpl::CopyStateFrom( |
1263 const NavigationController& temp) { | 1266 const NavigationController& temp) { |
1264 const NavigationControllerImpl& source = | 1267 const NavigationControllerImpl& source = |
1265 static_cast<const NavigationControllerImpl&>(temp); | 1268 static_cast<const NavigationControllerImpl&>(temp); |
1266 // Verify that we look new. | 1269 // Verify that we look new. |
1267 DCHECK(GetEntryCount() == 0 && !GetPendingEntry()); | 1270 DCHECK(GetEntryCount() == 0 && !GetPendingEntry()); |
1268 | 1271 |
1269 if (source.GetEntryCount() == 0) | 1272 if (source.GetEntryCount() == 0) |
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1770 } | 1773 } |
1771 } | 1774 } |
1772 } | 1775 } |
1773 | 1776 |
1774 void NavigationControllerImpl::SetGetTimestampCallbackForTest( | 1777 void NavigationControllerImpl::SetGetTimestampCallbackForTest( |
1775 const base::Callback<base::Time()>& get_timestamp_callback) { | 1778 const base::Callback<base::Time()>& get_timestamp_callback) { |
1776 get_timestamp_callback_ = get_timestamp_callback; | 1779 get_timestamp_callback_ = get_timestamp_callback; |
1777 } | 1780 } |
1778 | 1781 |
1779 } // namespace content | 1782 } // namespace content |
OLD | NEW |