| 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 8a0c2071d62e92317fc55811882780ab5f859997..e3256686dd802b6414302d68431d47b65605eecd 100644
|
| --- a/content/browser/frame_host/navigation_controller_impl.cc
|
| +++ b/content/browser/frame_host/navigation_controller_impl.cc
|
| @@ -223,10 +223,10 @@ NavigationControllerImpl::NavigationControllerImpl(
|
| NavigationControllerDelegate* delegate,
|
| BrowserContext* browser_context)
|
| : browser_context_(browser_context),
|
| - pending_entry_(NULL),
|
| + pending_entry_(nullptr),
|
| failed_pending_entry_id_(0),
|
| failed_pending_entry_should_replace_(false),
|
| - last_committed_entry_index_(-1),
|
| + last_committed_entry_index_(0),
|
| pending_entry_index_(-1),
|
| transient_entry_index_(-1),
|
| delegate_(delegate),
|
| @@ -263,11 +263,13 @@ void NavigationControllerImpl::Restore(
|
| RestoreType type,
|
| ScopedVector<NavigationEntry>* entries) {
|
| // Verify that this controller is unused and that the input is valid.
|
| - DCHECK(GetEntryCount() == 0 && !GetPendingEntry());
|
| + DCHECK(IsInitialBlankNavigation() && GetEntryCount() == 1 &&
|
| + !GetPendingEntry());
|
| DCHECK(selected_navigation >= 0 &&
|
| selected_navigation < static_cast<int>(entries->size()));
|
|
|
| needs_reload_ = true;
|
| + entries_.clear();
|
| for (size_t i = 0; i < entries->size(); ++i) {
|
| NavigationEntryImpl* entry =
|
| NavigationEntryImpl::FromNavigationEntry((*entries)[i]);
|
| @@ -402,6 +404,14 @@ bool NavigationControllerImpl::IsInitialNavigation() const {
|
| return is_initial_navigation_;
|
| }
|
|
|
| +bool NavigationControllerImpl::IsInitialBlankNavigation() const {
|
| + // Only return true if the initial navigation is not marked as a restore, as
|
| + // it is during a clone.
|
| + return IsInitialNavigation() &&
|
| + GetEntryCount() == 1 &&
|
| + GetEntryAtIndex(0)->restore_type() == NavigationEntryImpl::RESTORE_NONE;
|
| +}
|
| +
|
| NavigationEntryImpl* NavigationControllerImpl::GetEntryWithPageID(
|
| SiteInstance* instance, int32 page_id) const {
|
| int index = GetEntryIndexWithPageID(instance, page_id);
|
| @@ -483,8 +493,8 @@ int NavigationControllerImpl::GetCurrentEntryIndex() const {
|
| }
|
|
|
| NavigationEntryImpl* NavigationControllerImpl::GetLastCommittedEntry() const {
|
| - if (last_committed_entry_index_ == -1)
|
| - return NULL;
|
| + DCHECK_GE(last_committed_entry_index_, 0);
|
| + DCHECK_LT(last_committed_entry_index_, GetEntryCount());
|
| return entries_[last_committed_entry_index_];
|
| }
|
|
|
| @@ -792,8 +802,6 @@ bool NavigationControllerImpl::RendererDidNavigate(
|
| RenderFrameHostImpl* rfh,
|
| const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
|
| LoadCommittedDetails* details) {
|
| - is_initial_navigation_ = false;
|
| -
|
| // Save the previous state before we clobber it.
|
| if (GetLastCommittedEntry()) {
|
| details->previous_url = GetLastCommittedEntry()->GetURL();
|
| @@ -827,6 +835,12 @@ bool NavigationControllerImpl::RendererDidNavigate(
|
| pending_entry_->should_replace_entry();
|
| }
|
|
|
| + // If this is the first navigation after the initial about:blank page, then it
|
| + // should replace the initial NavigationEntry, regardless of the checks above.
|
| + if (IsInitialBlankNavigation())
|
| + details->did_replace_entry = true;
|
| + is_initial_navigation_ = false;
|
| +
|
| // Do navigation-type specific actions. These will make and commit an entry.
|
| details->type = ClassifyNavigation(rfh, params);
|
|
|
| @@ -839,6 +853,9 @@ bool NavigationControllerImpl::RendererDidNavigate(
|
| RendererDidNavigateToNewPage(rfh, params, details->did_replace_entry);
|
| break;
|
| case NAVIGATION_TYPE_EXISTING_PAGE:
|
| + // TODO(creis): This is wrong. See
|
| + // https://codereview.chromium.org/1214073005. Shouldn't touch this value
|
| + // in most cases.
|
| details->did_replace_entry = details->is_in_page;
|
| RendererDidNavigateToExistingPage(rfh, params);
|
| break;
|
| @@ -852,16 +869,6 @@ bool NavigationControllerImpl::RendererDidNavigate(
|
| if (!RendererDidNavigateAutoSubframe(rfh, params))
|
| return false;
|
| break;
|
| - case NAVIGATION_TYPE_NAV_IGNORE:
|
| - // If a pending navigation was in progress, this canceled it. We should
|
| - // discard it and make sure it is removed from the URL bar. After that,
|
| - // there is nothing we can do with this navigation, so we just return to
|
| - // the caller that nothing has happened.
|
| - if (pending_entry_) {
|
| - DiscardNonCommittedEntries();
|
| - delegate_->NotifyNavigationStateChanged(INVALIDATE_TYPE_URL);
|
| - }
|
| - return false;
|
| default:
|
| NOTREACHED();
|
| }
|
| @@ -953,20 +960,9 @@ NavigationType NavigationControllerImpl::ClassifyNavigation(
|
| if (params.did_create_new_entry) {
|
| // A new entry. We may or may not have a pending entry for the page, and
|
| // this may or may not be the main frame.
|
| - if (!rfh->GetParent()) {
|
| - return NAVIGATION_TYPE_NEW_PAGE;
|
| - }
|
| -
|
| - // When this is a new subframe navigation, we should have a committed page
|
| - // in which it's a subframe. This may not be the case when an iframe is
|
| - // navigated on a popup navigated to about:blank (the iframe would be
|
| - // written into the popup by script on the main page). For these cases,
|
| - // there isn't any navigation stuff we can do, so just ignore it.
|
| - if (!GetLastCommittedEntry())
|
| - return NAVIGATION_TYPE_NAV_IGNORE;
|
| -
|
| - // Valid subframe navigation.
|
| - return NAVIGATION_TYPE_NEW_SUBFRAME;
|
| + return rfh->GetParent() ?
|
| + NAVIGATION_TYPE_NEW_SUBFRAME :
|
| + NAVIGATION_TYPE_NEW_PAGE;
|
| }
|
|
|
| // We only clear the session history when navigating to a new page.
|
| @@ -975,28 +971,13 @@ NavigationType NavigationControllerImpl::ClassifyNavigation(
|
| if (rfh->GetParent()) {
|
| // All manual subframes would be did_create_new_entry and handled above, so
|
| // we know this is auto.
|
| - if (GetLastCommittedEntry()) {
|
| - return NAVIGATION_TYPE_AUTO_SUBFRAME;
|
| - } else {
|
| - // We ignore subframes created in non-committed pages; we'd appreciate if
|
| - // people stopped doing that.
|
| - return NAVIGATION_TYPE_NAV_IGNORE;
|
| - }
|
| + return NAVIGATION_TYPE_AUTO_SUBFRAME;
|
| }
|
|
|
| if (params.nav_entry_id == 0) {
|
| // This is a renderer-initiated navigation (nav_entry_id == 0), but didn't
|
| - // create a new page.
|
| -
|
| - // Just like above in the did_create_new_entry case, it's possible to
|
| - // scribble onto an uncommitted page. Again, there isn't any navigation
|
| - // stuff that we can do, so ignore it here as well.
|
| - NavigationEntry* last_committed = GetLastCommittedEntry();
|
| - if (!last_committed)
|
| - return NAVIGATION_TYPE_NAV_IGNORE;
|
| -
|
| - // This is history.replaceState(), history.reload(), or a client-side
|
| - // redirect.
|
| + // create a new page. This happens for history.replaceState(),
|
| + // history.reload(), or a client-side redirect.
|
| return NAVIGATION_TYPE_EXISTING_PAGE;
|
| }
|
|
|
| @@ -1353,13 +1334,7 @@ bool NavigationControllerImpl::IsURLInPageNavigation(
|
| if (rfh->GetParent()) {
|
| last_committed_url = rfh->GetLastCommittedURL();
|
| } else {
|
| - NavigationEntry* last_committed = GetLastCommittedEntry();
|
| - // There must be a last-committed entry to compare URLs to. TODO(avi): When
|
| - // might Blink say that a navigation is in-page yet there be no last-
|
| - // committed entry?
|
| - if (!last_committed)
|
| - return false;
|
| - last_committed_url = last_committed->GetURL();
|
| + last_committed_url = GetLastCommittedEntry()->GetURL();
|
| }
|
|
|
| WebPreferences prefs = rfh->GetRenderViewHost()->GetWebkitPreferences();
|
| @@ -1387,12 +1362,13 @@ void NavigationControllerImpl::CopyStateFrom(
|
| const NavigationControllerImpl& source =
|
| static_cast<const NavigationControllerImpl&>(temp);
|
| // Verify that we look new.
|
| - DCHECK(GetEntryCount() == 0 && !GetPendingEntry());
|
| -
|
| - if (source.GetEntryCount() == 0)
|
| - return; // Nothing new to do.
|
| + DCHECK(IsInitialBlankNavigation() && GetEntryCount() == 1 &&
|
| + !GetPendingEntry());
|
| + DCHECK_GT(source.GetEntryCount(), 0);
|
|
|
| needs_reload_ = true;
|
| + // Drop the initial entry first.
|
| + entries_.pop_back();
|
| InsertEntriesFrom(source, source.GetEntryCount());
|
|
|
| for (SessionStorageNamespaceMap::const_iterator it =
|
| @@ -1469,7 +1445,7 @@ bool NavigationControllerImpl::CanPruneAllButLastCommitted() {
|
| // If there is no last committed entry, we cannot prune. Even if there is a
|
| // pending entry, it may not commit, leaving this WebContents blank, despite
|
| // possibly giving it new entries via CopyStateFromAndPrune.
|
| - if (last_committed_entry_index_ == -1)
|
| + if (IsInitialBlankNavigation())
|
| return false;
|
|
|
| // We cannot prune if there is a pending entry at an existing entry index.
|
| @@ -1537,9 +1513,28 @@ int32 NavigationControllerImpl::GetMaxRestoredPageID() const {
|
| return max_restored_page_id_;
|
| }
|
|
|
| +void NavigationControllerImpl::Init(SiteInstance* instance) {
|
| + DCHECK(IsInitialNavigation());
|
| +
|
| + // Start with an entry for the initial about:blank page, which will be
|
| + // replaced on first navigation.
|
| + scoped_ptr<NavigationEntryImpl> initial_entry =
|
| + make_scoped_ptr(new NavigationEntryImpl(
|
| + static_cast<SiteInstanceImpl*>(instance), -1,
|
| + GURL(url::kAboutBlankURL), Referrer(), base::string16(),
|
| + ui::PAGE_TRANSITION_LINK, false));
|
| +
|
| + // Make sure the initial RenderFrameHost knows about it.
|
| + RenderFrameHostImpl* main_frame =
|
| + delegate_->GetFrameTree()->root()->current_frame_host();
|
| + static_cast<RenderViewHostImpl*>(main_frame->GetRenderViewHost())->
|
| + set_nav_entry_id(initial_entry->GetUniqueID());
|
| +
|
| + entries_.push_back(initial_entry.Pass());
|
| +}
|
| +
|
| bool NavigationControllerImpl::IsUnmodifiedBlankTab() const {
|
| - return IsInitialNavigation() &&
|
| - !GetLastCommittedEntry() &&
|
| + return IsInitialBlankNavigation() &&
|
| !delegate_->HasAccessedInitialDocument();
|
| }
|
|
|
| @@ -1987,8 +1982,7 @@ void NavigationControllerImpl::SetTransientEntry(
|
| scoped_ptr<NavigationEntry> entry) {
|
| // Discard any current transient entry, we can only have one at a time.
|
| int index = 0;
|
| - if (last_committed_entry_index_ != -1)
|
| - index = last_committed_entry_index_ + 1;
|
| + index = last_committed_entry_index_ + 1;
|
| DiscardTransientEntry();
|
| entries_.insert(entries_.begin() + index,
|
| NavigationEntryImpl::FromNavigationEntry(entry.release()));
|
|
|