| 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 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 bool NavigationControllerImpl::IsInitialNavigation() const { | 414 bool NavigationControllerImpl::IsInitialNavigation() const { |
| 415 return is_initial_navigation_; | 415 return is_initial_navigation_; |
| 416 } | 416 } |
| 417 | 417 |
| 418 NavigationEntryImpl* NavigationControllerImpl::GetEntryWithPageID( | 418 NavigationEntryImpl* NavigationControllerImpl::GetEntryWithPageID( |
| 419 SiteInstance* instance, int32 page_id) const { | 419 SiteInstance* instance, int32 page_id) const { |
| 420 int index = GetEntryIndexWithPageID(instance, page_id); | 420 int index = GetEntryIndexWithPageID(instance, page_id); |
| 421 return (index != -1) ? entries_[index].get() : NULL; | 421 return (index != -1) ? entries_[index].get() : NULL; |
| 422 } | 422 } |
| 423 | 423 |
| 424 bool NavigationControllerImpl::HasCommittedRealLoad( | |
| 425 FrameTreeNode* frame_tree_node) const { | |
| 426 NavigationEntryImpl* last_committed = GetLastCommittedEntry(); | |
| 427 return last_committed && last_committed->HasFrameEntry(frame_tree_node); | |
| 428 } | |
| 429 | |
| 430 void NavigationControllerImpl::LoadEntry(NavigationEntryImpl* entry) { | 424 void NavigationControllerImpl::LoadEntry(NavigationEntryImpl* entry) { |
| 431 // When navigating to a new page, we don't know for sure if we will actually | 425 // When navigating to a new page, we don't know for sure if we will actually |
| 432 // end up leaving the current page. The new page load could for example | 426 // end up leaving the current page. The new page load could for example |
| 433 // result in a download or a 'no content' response (e.g., a mailto: URL). | 427 // result in a download or a 'no content' response (e.g., a mailto: URL). |
| 434 SetPendingEntry(entry); | 428 SetPendingEntry(entry); |
| 435 NavigateToPendingEntry(NO_RELOAD); | 429 NavigateToPendingEntry(NO_RELOAD); |
| 436 } | 430 } |
| 437 | 431 |
| 438 void NavigationControllerImpl::SetPendingEntry(NavigationEntryImpl* entry) { | 432 void NavigationControllerImpl::SetPendingEntry(NavigationEntryImpl* entry) { |
| 439 DiscardNonCommittedEntriesInternal(); | 433 DiscardNonCommittedEntriesInternal(); |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 832 NavigationType new_type = ClassifyNavigationWithoutPageID(rfh, params); | 826 NavigationType new_type = ClassifyNavigationWithoutPageID(rfh, params); |
| 833 bool ignore_mismatch = false; | 827 bool ignore_mismatch = false; |
| 834 // There are disagreements on some Android bots over SAME_PAGE between the two | 828 // There are disagreements on some Android bots over SAME_PAGE between the two |
| 835 // classifiers so ignore disagreements if that's the case. | 829 // classifiers so ignore disagreements if that's the case. |
| 836 ignore_mismatch |= details->type == NAVIGATION_TYPE_EXISTING_PAGE && | 830 ignore_mismatch |= details->type == NAVIGATION_TYPE_EXISTING_PAGE && |
| 837 new_type == NAVIGATION_TYPE_SAME_PAGE; | 831 new_type == NAVIGATION_TYPE_SAME_PAGE; |
| 838 ignore_mismatch |= details->type == NAVIGATION_TYPE_SAME_PAGE && | 832 ignore_mismatch |= details->type == NAVIGATION_TYPE_SAME_PAGE && |
| 839 new_type == NAVIGATION_TYPE_EXISTING_PAGE; | 833 new_type == NAVIGATION_TYPE_EXISTING_PAGE; |
| 840 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 834 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 841 switches::kSitePerProcess)) { | 835 switches::kSitePerProcess)) { |
| 842 // We know that the old classifier is wrong for OOPIFs, so use the new one | 836 // In site-per-process mode, the new classifier sometimes correctly |
| 843 // in --site-per-process mode. | 837 // classifies things as auto-subframe where the old classifier incorrectly |
| 844 details->type = new_type; | 838 // ignored them or called them NEW_SUBFRAME. |
| 845 ignore_mismatch = true; | 839 ignore_mismatch |= details->type == NAVIGATION_TYPE_NAV_IGNORE && |
| 840 new_type == NAVIGATION_TYPE_AUTO_SUBFRAME; |
| 841 ignore_mismatch |= details->type == NAVIGATION_TYPE_NEW_SUBFRAME && |
| 842 new_type == NAVIGATION_TYPE_AUTO_SUBFRAME; |
| 846 } | 843 } |
| 847 if (!ignore_mismatch) { | 844 if (!ignore_mismatch) { |
| 848 DCHECK_EQ(details->type, new_type); | 845 DCHECK_EQ(details->type, new_type); |
| 849 } | 846 } |
| 850 #endif // DCHECK_IS_ON() | 847 #endif // DCHECK_IS_ON() |
| 851 | 848 |
| 852 // is_in_page must be computed before the entry gets committed. | 849 // is_in_page must be computed before the entry gets committed. |
| 853 details->is_in_page = AreURLsInPageNavigation(rfh->GetLastCommittedURL(), | 850 details->is_in_page = AreURLsInPageNavigation(rfh->GetLastCommittedURL(), |
| 854 params.url, params.was_within_same_page, rfh); | 851 params.url, params.was_within_same_page, rfh); |
| 855 | 852 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 939 details->serialized_security_info = params.security_info; | 936 details->serialized_security_info = params.security_info; |
| 940 details->http_status_code = params.http_status_code; | 937 details->http_status_code = params.http_status_code; |
| 941 NotifyNavigationEntryCommitted(details); | 938 NotifyNavigationEntryCommitted(details); |
| 942 | 939 |
| 943 return true; | 940 return true; |
| 944 } | 941 } |
| 945 | 942 |
| 946 NavigationType NavigationControllerImpl::ClassifyNavigation( | 943 NavigationType NavigationControllerImpl::ClassifyNavigation( |
| 947 RenderFrameHostImpl* rfh, | 944 RenderFrameHostImpl* rfh, |
| 948 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) const { | 945 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) const { |
| 946 // Hack; remove once http://crbug.com/464014 is fixed. |
| 947 if (rfh->IsCrossProcessSubframe()) |
| 948 return NAVIGATION_TYPE_NEW_SUBFRAME; |
| 949 |
| 949 if (params.page_id == -1) { | 950 if (params.page_id == -1) { |
| 950 // The renderer generates the page IDs, and so if it gives us the invalid | 951 // The renderer generates the page IDs, and so if it gives us the invalid |
| 951 // page ID (-1) we know it didn't actually navigate. This happens in a few | 952 // page ID (-1) we know it didn't actually navigate. This happens in a few |
| 952 // cases: | 953 // cases: |
| 953 // | 954 // |
| 954 // - If a page makes a popup navigated to about blank, and then writes | 955 // - If a page makes a popup navigated to about blank, and then writes |
| 955 // stuff like a subframe navigated to a real page. We'll get the commit | 956 // stuff like a subframe navigated to a real page. We'll get the commit |
| 956 // for the subframe, but there won't be any commit for the outer page. | 957 // for the subframe, but there won't be any commit for the outer page. |
| 957 // | 958 // |
| 958 // - We were also getting these for failed loads (for example, bug 21849). | 959 // - We were also getting these for failed loads (for example, bug 21849). |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1088 } | 1089 } |
| 1089 | 1090 |
| 1090 // Since we weeded out "new" navigations above, we know this is an existing | 1091 // Since we weeded out "new" navigations above, we know this is an existing |
| 1091 // (back/forward) navigation. | 1092 // (back/forward) navigation. |
| 1092 return NAVIGATION_TYPE_EXISTING_PAGE; | 1093 return NAVIGATION_TYPE_EXISTING_PAGE; |
| 1093 } | 1094 } |
| 1094 | 1095 |
| 1095 NavigationType NavigationControllerImpl::ClassifyNavigationWithoutPageID( | 1096 NavigationType NavigationControllerImpl::ClassifyNavigationWithoutPageID( |
| 1096 RenderFrameHostImpl* rfh, | 1097 RenderFrameHostImpl* rfh, |
| 1097 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) const { | 1098 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) const { |
| 1099 // Hack; remove once http://crbug.com/464014 is fixed. |
| 1100 if (rfh->IsCrossProcessSubframe()) |
| 1101 return NAVIGATION_TYPE_NEW_SUBFRAME; |
| 1102 |
| 1098 if (params.did_create_new_entry) { | 1103 if (params.did_create_new_entry) { |
| 1099 // A new entry. We may or may not have a pending entry for the page, and | 1104 // A new entry. We may or may not have a pending entry for the page, and |
| 1100 // this may or may not be the main frame. | 1105 // this may or may not be the main frame. |
| 1101 if (ui::PageTransitionIsMainFrame(params.transition)) { | 1106 if (ui::PageTransitionIsMainFrame(params.transition)) { |
| 1102 // TODO(avi): I want to use |if (!rfh->GetParent())| here but lots of unit | 1107 // TODO(avi): I want to use |if (!rfh->GetParent())| here but lots of unit |
| 1103 // tests fake auto subframe commits by sending the main frame a | 1108 // tests fake auto subframe commits by sending the main frame a |
| 1104 // PAGE_TRANSITION_AUTO_SUBFRAME transition. Fix those, and adjust here. | 1109 // PAGE_TRANSITION_AUTO_SUBFRAME transition. Fix those, and adjust here. |
| 1105 return NAVIGATION_TYPE_NEW_PAGE; | 1110 return NAVIGATION_TYPE_NEW_PAGE; |
| 1106 } | 1111 } |
| 1107 | 1112 |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1438 RenderFrameHostImpl* rfh, | 1443 RenderFrameHostImpl* rfh, |
| 1439 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { | 1444 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { |
| 1440 DCHECK(ui::PageTransitionCoreTypeIs(params.transition, | 1445 DCHECK(ui::PageTransitionCoreTypeIs(params.transition, |
| 1441 ui::PAGE_TRANSITION_AUTO_SUBFRAME)); | 1446 ui::PAGE_TRANSITION_AUTO_SUBFRAME)); |
| 1442 | 1447 |
| 1443 // We're guaranteed to have a previously committed entry, and we now need to | 1448 // We're guaranteed to have a previously committed entry, and we now need to |
| 1444 // handle navigation inside of a subframe in it without creating a new entry. | 1449 // handle navigation inside of a subframe in it without creating a new entry. |
| 1445 DCHECK(GetLastCommittedEntry()); | 1450 DCHECK(GetLastCommittedEntry()); |
| 1446 | 1451 |
| 1447 if (params.nav_entry_id) { | 1452 if (params.nav_entry_id) { |
| 1453 // If the |nav_entry_id| is non-zero, this is a browser-initiated navigation |
| 1454 // and is thus a "history auto" navigation. TODO(creis): Implement |
| 1455 // back/forward this way for site-per-process. |
| 1456 |
| 1448 int entry_index = GetEntryIndexWithUniqueID(params.nav_entry_id); | 1457 int entry_index = GetEntryIndexWithUniqueID(params.nav_entry_id); |
| 1458 if (entry_index == -1) { |
| 1459 NOTREACHED(); |
| 1460 return false; |
| 1461 } |
| 1449 | 1462 |
| 1450 // If the |nav_entry_id| is non-zero and matches an existing entry, this is | 1463 // Update the current navigation entry in case we're going back/forward. |
| 1451 // a history auto" navigation. Update the last committed index accordingly. | 1464 if (entry_index != last_committed_entry_index_) { |
| 1452 // If we don't recognize the |nav_entry_id|, it might be either a pending | |
| 1453 // entry for a transfer or a recently pruned entry. We'll handle it below. | |
| 1454 if (entry_index != -1 && entry_index != last_committed_entry_index_) { | |
| 1455 // Make sure that a subframe commit isn't changing the main frame's | 1465 // Make sure that a subframe commit isn't changing the main frame's |
| 1456 // origin. Otherwise the renderer process may be confused, leading to a | 1466 // origin. Otherwise the renderer process may be confused, leading to a |
| 1457 // URL spoof. We can't check the path since that may change | 1467 // URL spoof. We can't check the path since that may change |
| 1458 // (https://crbug.com/373041). | 1468 // (https://crbug.com/373041). |
| 1459 if (GetLastCommittedEntry()->GetURL().GetOrigin() != | 1469 if (GetLastCommittedEntry()->GetURL().GetOrigin() != |
| 1460 GetEntryAtIndex(entry_index)->GetURL().GetOrigin()) { | 1470 GetEntryAtIndex(entry_index)->GetURL().GetOrigin()) { |
| 1461 // TODO(creis): This is unexpectedly being encountered in practice. If | 1471 // TODO(creis): This is unexpectedly being encountered in practice. If |
| 1462 // you encounter this in practice, please post details to | 1472 // you encounter this in practice, please post details to |
| 1463 // https://crbug.com/486916. Once that's resolved, we'll change this to | 1473 // https://crbug.com/486916. Once that's resolved, we'll change this to |
| 1464 // kill the renderer process with bad_message::NC_AUTO_SUBFRAME. | 1474 // kill the renderer process with bad_message::NC_AUTO_SUBFRAME. |
| 1465 NOTREACHED() << "Unexpected main frame origin change on AUTO_SUBFRAME."; | 1475 NOTREACHED() << "Unexpected main frame origin change on AUTO_SUBFRAME."; |
| 1466 } | 1476 } |
| 1467 | |
| 1468 // TODO(creis): Update the FrameNavigationEntry in --site-per-process. | |
| 1469 last_committed_entry_index_ = entry_index; | 1477 last_committed_entry_index_ = entry_index; |
| 1470 DiscardNonCommittedEntriesInternal(); | 1478 DiscardNonCommittedEntriesInternal(); |
| 1471 return true; | 1479 return true; |
| 1472 } | 1480 } |
| 1473 } | 1481 } |
| 1474 | 1482 |
| 1475 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 1483 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 1476 switches::kSitePerProcess)) { | 1484 switches::kSitePerProcess)) { |
| 1477 // This may be a "new auto" case where we add a new FrameNavigationEntry, or | 1485 // This may be a "new auto" case where we add a new FrameNavigationEntry, or |
| 1478 // it may be a "history auto" case where we update an existing one. | 1486 // it may be a "history auto" case where we update an existing one. |
| 1479 NavigationEntryImpl* last_committed = GetLastCommittedEntry(); | 1487 NavigationEntryImpl* last_committed = GetLastCommittedEntry(); |
| 1480 last_committed->AddOrUpdateFrameEntry(rfh->frame_tree_node(), | 1488 last_committed->AddOrUpdateFrameEntry(rfh->frame_tree_node(), |
| 1481 rfh->GetSiteInstance(), params.url, | 1489 rfh->GetSiteInstance(), params.url, |
| 1482 params.referrer); | 1490 params.referrer); |
| 1483 | |
| 1484 // Cross-process subframe navigations may leave a pending entry around. | |
| 1485 // TODO(creis): Don't use pending entries for subframe navigations. | |
| 1486 DiscardNonCommittedEntriesInternal(); | |
| 1487 } | 1491 } |
| 1488 | 1492 |
| 1489 // We do not need to discard the pending entry in this case, since we will | 1493 // We do not need to discard the pending entry in this case, since we will |
| 1490 // not generate commit notifications for this auto-subframe navigation. | 1494 // not generate commit notifications for this auto-subframe navigation. |
| 1491 return false; | 1495 return false; |
| 1492 } | 1496 } |
| 1493 | 1497 |
| 1494 int NavigationControllerImpl::GetIndexOfEntry( | 1498 int NavigationControllerImpl::GetIndexOfEntry( |
| 1495 const NavigationEntryImpl* entry) const { | 1499 const NavigationEntryImpl* entry) const { |
| 1496 const NavigationEntries::const_iterator i(std::find( | 1500 const NavigationEntries::const_iterator i(std::find( |
| (...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2025 } | 2029 } |
| 2026 } | 2030 } |
| 2027 } | 2031 } |
| 2028 | 2032 |
| 2029 void NavigationControllerImpl::SetGetTimestampCallbackForTest( | 2033 void NavigationControllerImpl::SetGetTimestampCallbackForTest( |
| 2030 const base::Callback<base::Time()>& get_timestamp_callback) { | 2034 const base::Callback<base::Time()>& get_timestamp_callback) { |
| 2031 get_timestamp_callback_ = get_timestamp_callback; | 2035 get_timestamp_callback_ = get_timestamp_callback; |
| 2032 } | 2036 } |
| 2033 | 2037 |
| 2034 } // namespace content | 2038 } // namespace content |
| OLD | NEW |