| 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 0b0f411a1a041f52893e84357af935f7fe81c0df..eda129d5f155e334856105b2eed072061629bb1a 100644
|
| --- a/content/browser/frame_host/navigation_controller_impl.cc
|
| +++ b/content/browser/frame_host/navigation_controller_impl.cc
|
| @@ -801,6 +801,41 @@ bool NavigationControllerImpl::RendererDidNavigate(
|
|
|
| // Do navigation-type specific actions. These will make and commit an entry.
|
| details->type = ClassifyNavigation(rfh, params);
|
| + if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
|
| + switches::kSitePerProcess)) {
|
| + // For site-per-process, both ClassifyNavigation methods get it wrong (see
|
| + // http://crbug.com/464014) so don't worry about a mismatch if that's the
|
| + // case.
|
| + auto nt = [](NavigationType type) {
|
| + switch(type) {
|
| + case NAVIGATION_TYPE_UNKNOWN:
|
| + return "UNKNOWN";
|
| + case NAVIGATION_TYPE_NEW_PAGE:
|
| + return "NEW_PAGE";
|
| + case NAVIGATION_TYPE_EXISTING_PAGE:
|
| + return "EXISTING_PAGE";
|
| + case NAVIGATION_TYPE_SAME_PAGE:
|
| + return "SAME_PAGE";
|
| + case NAVIGATION_TYPE_IN_PAGE:
|
| + return "IN_PAGE";
|
| + case NAVIGATION_TYPE_NEW_SUBFRAME:
|
| + return "NEW_SUBFRAME";
|
| + case NAVIGATION_TYPE_AUTO_SUBFRAME:
|
| + return "AUTO_SUBFRAME";
|
| + case NAVIGATION_TYPE_NAV_IGNORE:
|
| + return "NAV_IGNORE";
|
| + default:
|
| + return "<invalid>";
|
| + }
|
| + };
|
| + NavigationType new_type = ClassifyNavigationWithoutPageID(rfh, params);
|
| + if (details->type != new_type) {
|
| + LOG(FATAL) << "old classify is " << nt(details->type)
|
| + << ", new classify is " << nt(new_type);
|
| + }
|
| + // Detailed logging above is temporary; will ship with vvvv below.
|
| + // DCHECK_EQ(details->type, ClassifyNavigationWithoutPageID(rfh, params));
|
| + }
|
|
|
| // is_in_page must be computed before the entry gets committed.
|
| details->is_in_page = AreURLsInPageNavigation(rfh->GetLastCommittedURL(),
|
| @@ -899,13 +934,14 @@ bool NavigationControllerImpl::RendererDidNavigate(
|
| NavigationType NavigationControllerImpl::ClassifyNavigation(
|
| RenderFrameHostImpl* rfh,
|
| const FrameHostMsg_DidCommitProvisionalLoad_Params& params) const {
|
| + LOG(ERROR) << "NavigationControllerImpl::ClassifyNavigation";
|
| if (params.page_id == -1) {
|
| - // TODO(nasko, creis): An out-of-process child frame has no way of
|
| - // knowing the page_id of its parent, so it is passing back -1. The
|
| - // semantics here should be re-evaluated during session history refactor
|
| - // (see http://crbug.com/236848). For now, we assume this means the
|
| - // child frame loaded and proceed. Note that this may do the wrong thing
|
| - // for cross-process AUTO_SUBFRAME navigations.
|
| + // TODO(nasko, creis): An out-of-process child frame has no way of knowing
|
| + // the page_id of its parent, so it is passing back -1. The semantics here
|
| + // should be re-evaluated during session history refactor (see
|
| + // http://crbug.com/236848 and in particular http://crbug.com/464014). For
|
| + // now, we assume this means the child frame loaded and proceed. Note that
|
| + // this may do the wrong thing for cross-process AUTO_SUBFRAME navigations.
|
| if (rfh->IsCrossProcessSubframe())
|
| return NAVIGATION_TYPE_NEW_SUBFRAME;
|
|
|
| @@ -927,11 +963,13 @@ NavigationType NavigationControllerImpl::ClassifyNavigation(
|
| // list.
|
| //
|
| // In these cases, there's nothing we can do with them, so ignore.
|
| + LOG(ERROR) << " > page id is -1; ignoring";
|
| return NAVIGATION_TYPE_NAV_IGNORE;
|
| }
|
|
|
| if (params.page_id > delegate_->GetMaxPageIDForSiteInstance(
|
| rfh->GetSiteInstance())) {
|
| + LOG(ERROR) << "larger page id (" << params.page_id << ") than we've seen before (" << delegate_->GetMaxPageIDForSiteInstance(rfh->GetSiteInstance()) << ")";
|
| // Greater page IDs than we've ever seen before are new pages. We may or may
|
| // not have a pending entry for the page, and this may or may not be the
|
| // main frame.
|
| @@ -1000,6 +1038,7 @@ NavigationType NavigationControllerImpl::ClassifyNavigation(
|
| NavigationEntryImpl* existing_entry = entries_[existing_entry_index].get();
|
|
|
| if (!ui::PageTransitionIsMainFrame(params.transition)) {
|
| + LOG(ERROR) << " > subframe transition; so it's auto";
|
| // All manual subframes would get new IDs and were handled above, so we
|
| // know this is auto. Since the current page was found in the navigation
|
| // entry list, we're guaranteed to have a last committed entry.
|
| @@ -1013,6 +1052,7 @@ NavigationType NavigationControllerImpl::ClassifyNavigation(
|
| existing_entry != pending_entry_ &&
|
| pending_entry_->GetPageID() == -1 &&
|
| existing_entry == GetLastCommittedEntry()) {
|
| + LOG(ERROR) << " > same page";
|
| // In this case, we have a pending entry for a URL but WebCore didn't do a
|
| // new navigation. This happens when you press enter in the URL bar to
|
| // reload. We will create a pending entry, but WebKit will convert it to
|
| @@ -1030,6 +1070,102 @@ NavigationType NavigationControllerImpl::ClassifyNavigation(
|
| // an encoding override (it always sends a navigation request).
|
| if (AreURLsInPageNavigation(existing_entry->GetURL(), params.url,
|
| params.was_within_same_page, rfh)) {
|
| + LOG(ERROR) << " > in page";
|
| + return NAVIGATION_TYPE_IN_PAGE;
|
| + }
|
| +
|
| + // Since we weeded out "new" navigations above, we know this is an existing
|
| + // (back/forward) navigation.
|
| + LOG(ERROR) << " > existing page";
|
| + return NAVIGATION_TYPE_EXISTING_PAGE;
|
| +}
|
| +
|
| +NavigationType NavigationControllerImpl::ClassifyNavigationWithoutPageID(
|
| + RenderFrameHostImpl* rfh,
|
| + const FrameHostMsg_DidCommitProvisionalLoad_Params& params) const {
|
| + LOG(ERROR) << "NavigationControllerImpl::ClassifyNavigationWithoutPageID"
|
| + << " nav_entry_id " << params.nav_entry_id;
|
| + 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()) {
|
| + // TODO(avi): Everyone does ui::PageTransitionIsMainFrame to determine
|
| + // main-frame-ness. I can get that consumers of page transitions would
|
| + // want to do that, but for code inside RenderFrameHost and NavController?
|
| + // Please.
|
| + 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;
|
| + }
|
| +
|
| + // We only clear the session history when navigating to a new page.
|
| + DCHECK(!params.history_list_was_cleared);
|
| +
|
| + if (rfh->GetParent()) {
|
| + // All manual subframes would be WebStandardCommit and handled above, so we
|
| + // know this is auto.
|
| + DCHECK(GetLastCommittedEntry());
|
| + return NAVIGATION_TYPE_AUTO_SUBFRAME;
|
| + }
|
| +
|
| + if (params.nav_entry_id == 0) {
|
| + // 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.
|
| + if (!GetLastCommittedEntry())
|
| + return NAVIGATION_TYPE_NAV_IGNORE;
|
| +
|
| + // This is a renderer-initiated navigation, but didn't create a new page.
|
| + if (params.was_within_same_page) {
|
| + // This is history.replaceState(), which is renderer-initiated yet within
|
| + // the same page.
|
| + return NAVIGATION_TYPE_IN_PAGE;
|
| + } else {
|
| + // This is history.reload() and client-side redirection.
|
| + return NAVIGATION_TYPE_EXISTING_PAGE;
|
| + }
|
| + }
|
| +
|
| + if (pending_entry_ && pending_entry_index_ == -1 &&
|
| + pending_entry_->GetUniqueID() == params.nav_entry_id) {
|
| + // In this case, we have a pending entry for a load of a new URL but Blink
|
| + // didn't do a new navigation (params.did_create_new_entry). This happens
|
| + // when you press enter in the URL bar to reload. We will create a pending
|
| + // entry, but Blink will convert it to a reload since it's the same page and
|
| + // not create a new entry for it (the user doesn't want to have a new
|
| + // back/forward entry when they do this). Therefore we want to just ignore
|
| + // the pending entry and go back to where we were (the "existing entry").
|
| + return NAVIGATION_TYPE_SAME_PAGE;
|
| + }
|
| +
|
| + // Now we know that the notification is for an existing page. Find that entry.
|
| + int existing_entry_index = GetEntryIndexWithUniqueID(params.nav_entry_id);
|
| + if (existing_entry_index == -1) {
|
| + // The page was not found. It could have been pruned because of the limit on
|
| + // back/forward entries (not likely since we'll usually tell it to navigate
|
| + // to such entries). It could also mean that the renderer is smoking crack.
|
| + NOTREACHED() << "Could not find nav entry with id " << params.nav_entry_id;
|
| + return NAVIGATION_TYPE_NAV_IGNORE;
|
| + }
|
| +
|
| + // Any top-level navigations with the same base (minus the reference fragment)
|
| + // are in-page navigations. (We weeded out subframe navigations above.) Most
|
| + // of the time this doesn't matter since Blink doesn't tell us about subframe
|
| + // navigations that don't actually navigate, but it can happen when there is
|
| + // an encoding override (it always sends a navigation request).
|
| + NavigationEntryImpl* existing_entry = entries_[existing_entry_index].get();
|
| + if (AreURLsInPageNavigation(existing_entry->GetURL(), params.url,
|
| + params.was_within_same_page, rfh)) {
|
| return NAVIGATION_TYPE_IN_PAGE;
|
| }
|
|
|
| @@ -1565,6 +1701,7 @@ int NavigationControllerImpl::GetPendingEntryIndex() const {
|
|
|
| void NavigationControllerImpl::InsertOrReplaceEntry(NavigationEntryImpl* entry,
|
| bool replace) {
|
| + LOG(ERROR) << "NavigationControllerImpl::InsertOrReplaceEntry";
|
| DCHECK(entry->GetTransitionType() != ui::PAGE_TRANSITION_AUTO_SUBFRAME);
|
|
|
| // Copy the pending entry's unique ID to the committed entry.
|
| @@ -1779,6 +1916,15 @@ int NavigationControllerImpl::GetEntryIndexWithPageID(
|
| return -1;
|
| }
|
|
|
| +int NavigationControllerImpl::GetEntryIndexWithUniqueID(
|
| + int nav_entry_id) const {
|
| + for (int i = static_cast<int>(entries_.size()) - 1; i >= 0; --i) {
|
| + if (entries_[i]->GetUniqueID() == nav_entry_id)
|
| + return i;
|
| + }
|
| + return -1;
|
| +}
|
| +
|
| NavigationEntryImpl* NavigationControllerImpl::GetTransientEntry() const {
|
| if (transient_entry_index_ == -1)
|
| return NULL;
|
|
|