Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(618)

Unified Diff: content/browser/frame_host/navigation_controller_impl.cc

Issue 1309323004: Create a NavigationEntry for the initial blank page. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix GetEntryCount, more tests Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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()));

Powered by Google App Engine
This is Rietveld 408576698