| 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..1f1f449305542bedda564c2a924a498f0f34d1eb 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).
|
| @@ -1778,9 +1816,55 @@ void NavigationControllerImpl::NavigateToPendingEntry(ReloadType reload_type) {
|
| // navigation to succeed. The interstitial will stay visible until the
|
| // resulting DidNavigate.
|
| if (delegate_->GetInterstitialPage()) {
|
| - static_cast<InterstitialPageImpl*>(delegate_->GetInterstitialPage())->
|
| - CancelForNavigation();
|
| - }
|
| + static_cast<InterstitialPageImpl*>(delegate_->GetInterstitialPage())
|
| + ->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;
|
|
|