Index: content/browser/frame_host/navigation_controller_impl.cc |
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc |
index 2d90ebb2f9db861d3fd425e46ce60d45039c25a8..c878fede04a349820acde6384ad4820a9074c0cd 100644 |
--- a/content/browser/frame_host/navigation_controller_impl.cc |
+++ b/content/browser/frame_host/navigation_controller_impl.cc |
@@ -135,6 +135,35 @@ bool ShouldKeepOverride(const NavigationEntry* last_entry) { |
return last_entry && last_entry->GetIsOverridingUserAgent(); |
} |
+// Returns true if the PageTransition in the |entry| require this navigation to |
+// be treated as a reload. For e.g. navigating to the last committed url via |
+// the address bar or clicking on a link which results in a navigation to the |
+// last committed or pending navigation, etc. |
+bool ShouldTreatNavigationAsReload(const NavigationEntry* entry) { |
+ if (!entry) |
+ return false; |
+ |
+ // We treat (PAGE_TRANSITION_RELOAD | PAGE_TRANSITION_FROM_ADDRESS_BAR), |
+ // PAGE_TRANSITION_TYPED or PAGE_TRANSITION_LINK transitions as navigations |
+ // which should be treated as reloads. |
+ if ((ui::PageTransitionCoreTypeIs(entry->GetTransitionType(), |
+ ui::PAGE_TRANSITION_RELOAD) && |
+ (entry->GetTransitionType() & ui::PAGE_TRANSITION_FROM_ADDRESS_BAR))) { |
+ return true; |
+ } |
+ |
+ if (ui::PageTransitionCoreTypeIs(entry->GetTransitionType(), |
+ ui::PAGE_TRANSITION_TYPED)) { |
+ return true; |
+ } |
+ |
+ if (ui::PageTransitionCoreTypeIs(entry->GetTransitionType(), |
+ ui::PAGE_TRANSITION_LINK)) { |
+ return true; |
+ } |
+ return false; |
+} |
+ |
} // namespace |
// NavigationControllerImpl ---------------------------------------------------- |
@@ -212,11 +241,14 @@ NavigationControllerImpl::NavigationControllerImpl( |
NavigationControllerDelegate* delegate, |
BrowserContext* browser_context) |
: browser_context_(browser_context), |
- pending_entry_(NULL), |
+ pending_entry_(nullptr), |
+ last_pending_entry_(nullptr), |
failed_pending_entry_id_(0), |
last_committed_entry_index_(-1), |
pending_entry_index_(-1), |
transient_entry_index_(-1), |
+ last_pending_entry_index_(-1), |
+ last_transient_entry_index_(-1), |
delegate_(delegate), |
ssl_manager_(this), |
needs_reload_(false), |
@@ -426,6 +458,12 @@ NavigationControllerImpl::GetEntryWithUniqueID(int nav_entry_id) const { |
void NavigationControllerImpl::LoadEntry( |
std::unique_ptr<NavigationEntryImpl> entry) { |
+ // Remember the last pending entry for which we haven't received a response |
+ // yet. This will be deleted in the NavigateToPendingEntry() function. |
+ last_pending_entry_ = pending_entry_; |
+ last_pending_entry_index_ = pending_entry_index_; |
+ last_transient_entry_index_ = transient_entry_index_; |
+ pending_entry_ = nullptr; |
// When navigating to a new page, we don't know for sure if we will actually |
// end up leaving the current page. The new page load could for example |
// result in a download or a 'no content' response (e.g., a mailto: URL). |
@@ -1758,10 +1796,10 @@ void NavigationControllerImpl::NavigateToPendingEntry(ReloadType reload_type) { |
// from happening, we drop the navigation here and stop the slow-to-commit |
// page from loading (which would normally happen during the navigation). |
if (pending_entry_index_ != -1 && |
- pending_entry_index_ == last_committed_entry_index_ && |
- (entries_[pending_entry_index_]->restore_type() == RestoreType::NONE) && |
- (entries_[pending_entry_index_]->GetTransitionType() & |
- ui::PAGE_TRANSITION_FORWARD_BACK)) { |
+ pending_entry_index_ == last_committed_entry_index_ && |
scottmg
2016/12/20 22:34:05
Indent got messed up here.
ananta
2016/12/20 23:14:10
Thanks fixed
|
+ (entries_[pending_entry_index_]->restore_type() == RestoreType::NONE) && |
+ (entries_[pending_entry_index_]->GetTransitionType() & |
+ ui::PAGE_TRANSITION_FORWARD_BACK)) { |
delegate_->Stop(); |
// If an interstitial page is showing, we want to close it to get back |
@@ -1779,8 +1817,54 @@ void NavigationControllerImpl::NavigateToPendingEntry(ReloadType reload_type) { |
// resulting DidNavigate. |
if (delegate_->GetInterstitialPage()) { |
static_cast<InterstitialPageImpl*>(delegate_->GetInterstitialPage())-> |
- CancelForNavigation(); |
- } |
+ CancelForNavigation(); |
+ } |
+ |
+ // The last navigation is the last pending navigation which hasn't been |
+ // committed yet, or the last committed navigation. |
+ NavigationEntryImpl* last_navigation = |
+ last_pending_entry_ ? last_pending_entry_ : GetLastCommittedEntry(); |
+ |
+ // Convert Enter-in-omnibox to a reload. This is what Blink does in |
+ // FrameLoader, but we want to handle it here so that if the navigation is |
+ // redirected or handled purely on the browser side in PlzNavigate we have the |
+ // same behaviour as Blink would. Note that we don't want to convert to a |
+ // reload for history navigations, so this must be above the retrieval of the |
+ // pending_entry_ below when pending_entry_index_ is used. |
+ if (reload_type == ReloadType::NONE && last_navigation && pending_entry_ && |
+ // Please refer to the ShouldTreatNavigationAsReload() function for info |
+ // on which navigations are treated as reloads. In general navigating to |
+ // the last committed or pending entry via the address bar, clicking on |
+ // a link, etc would be treated as reloads. |
+ ShouldTreatNavigationAsReload(pending_entry_) && |
+ // Skip entries with SSL errors. |
+ !last_navigation->ssl_error() && |
+ // Ignore interstitial pages |
+ last_transient_entry_index_ == -1 && |
+ pending_entry_->frame_tree_node_id() == -1 && |
+ pending_entry_->GetURL() == last_navigation->GetURL() && |
+ !pending_entry_->GetHasPostData() && !last_navigation->GetHasPostData() && |
+ // This check is required for cases like view-source:, etc. Here the URL |
+ // of the navigation entry would contain the url of the page, while the |
+ // virtual URL contains the full URL including the view-source prefix. |
+ last_navigation->GetVirtualURL() == pending_entry_->GetVirtualURL() && |
+ // This check is required for Android WebView loadDataWithBaseURL. Apps |
+ // can pass in anything in the base URL and we need to ensure that these |
+ // match before classifying it as a reload. |
+ (pending_entry_->GetURL().SchemeIs(url::kDataScheme) && |
+ pending_entry_->GetBaseURLForDataURL().is_valid() |
+ ? pending_entry_->GetBaseURLForDataURL() == |
+ last_navigation->GetBaseURLForDataURL() |
+ : true)) { |
+ reload_type = ReloadType::NORMAL; |
+ } |
+ |
+ if (last_pending_entry_index_ == -1 && last_pending_entry_) |
+ delete last_pending_entry_; |
+ |
+ last_transient_entry_index_ = -1; |
+ last_pending_entry_ = nullptr; |
+ last_pending_entry_index_ = -1; |
// For session history navigations only the pending_entry_index_ is set. |
if (!pending_entry_) { |
@@ -2024,6 +2108,11 @@ void NavigationControllerImpl::DiscardPendingEntry(bool was_failure) { |
pending_entry_index_ = -1; |
} |
+void NavigationControllerImpl::SetPendingNavigationSSLError(bool error) { |
+ if (pending_entry_) |
+ pending_entry_->set_ssl_error(error); |
+} |
+ |
void NavigationControllerImpl::DiscardTransientEntry() { |
if (transient_entry_index_ == -1) |
return; |