Chromium Code Reviews| 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; |