summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/native_ui_contents.cc5
-rw-r--r--chrome/browser/navigation_controller.cc23
-rw-r--r--chrome/browser/navigation_controller.h54
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_blocking_page.cc5
-rw-r--r--chrome/browser/ssl_blocking_page.cc5
-rw-r--r--chrome/browser/tab_contents.cc15
-rw-r--r--chrome/browser/tab_contents.h7
-rw-r--r--chrome/browser/views/info_bar_view.cc96
-rw-r--r--chrome/browser/views/info_bar_view.h23
-rw-r--r--chrome/browser/web_contents.cc290
-rw-r--r--chrome/browser/web_contents.h28
-rw-r--r--chrome/common/notification_types.h3
12 files changed, 299 insertions, 255 deletions
diff --git a/chrome/browser/native_ui_contents.cc b/chrome/browser/native_ui_contents.cc
index 2046ba0..73cd614 100644
--- a/chrome/browser/native_ui_contents.cc
+++ b/chrome/browser/native_ui_contents.cc
@@ -269,7 +269,10 @@ bool NativeUIContents::Navigate(const NavigationEntry& entry, bool reload) {
state_->GetByteRepresentation(&content_state);
new_entry->set_content_state(content_state);
const int32 page_id = new_entry->page_id();
- DidNavigateToEntry(new_entry);
+
+ // The default details is "new navigation", and that's OK with us.
+ NavigationController::LoadCommittedDetails details;
+ DidNavigateToEntry(new_entry, &details);
// This is not a WebContents, so we use a NULL SiteInstance.
controller()->NotifyEntryChangedByPageID(type(), NULL, page_id);
return true;
diff --git a/chrome/browser/navigation_controller.cc b/chrome/browser/navigation_controller.cc
index 715e33f7..c944d99 100644
--- a/chrome/browser/navigation_controller.cc
+++ b/chrome/browser/navigation_controller.cc
@@ -493,7 +493,8 @@ void NavigationController::SetAlternateNavURLFetcher(
alternate_nav_url_fetcher_entry_unique_id_ = pending_entry_->unique_id();
}
-void NavigationController::DidNavigateToEntry(NavigationEntry* entry) {
+void NavigationController::DidNavigateToEntry(NavigationEntry* entry,
+ LoadCommittedDetails* details) {
DCHECK(active_contents_);
DCHECK(entry->tab_type() == active_contents_->type());
@@ -501,6 +502,11 @@ void NavigationController::DidNavigateToEntry(NavigationEntry* entry) {
entry->set_restored(false);
+ // Update the details to list the last URL. Later, we'll update the current
+ // entry (after it's committed) and the details will be complete.
+ if (GetLastCommittedEntry())
+ details->previous_url = GetLastCommittedEntry()->url();
+
// If the entry is that of a page with PageID larger than any this Tab has
// seen before, then consider it a new navigation. Note that if the entry
// has a SiteInstance, it should be the same as the SiteInstance of the
@@ -508,7 +514,7 @@ void NavigationController::DidNavigateToEntry(NavigationEntry* entry) {
DCHECK(entry->page_id() >= 0) << "Page ID must be set before calling us.";
if (entry->page_id() > GetMaxPageID()) {
InsertEntry(entry);
- NotifyNavigationEntryCommitted();
+ NotifyNavigationEntryCommitted(details);
// It is now a safe time to schedule collection for any tab contents of a
// different type, because a navigation is necessary to get back to them.
ScheduleTabContentsCollectionForInactiveTabs();
@@ -566,7 +572,7 @@ void NavigationController::DidNavigateToEntry(NavigationEntry* entry) {
}
delete entry;
- NotifyNavigationEntryCommitted();
+ NotifyNavigationEntryCommitted(details);
if (alternate_nav_url_fetcher_.get()) {
// Because this call may synchronously show an infobar, we do it last, to
@@ -715,7 +721,8 @@ void NavigationController::NavigateToPendingEntry(bool reload) {
DiscardPendingEntry();
}
-void NavigationController::NotifyNavigationEntryCommitted() {
+void NavigationController::NotifyNavigationEntryCommitted(
+ LoadCommittedDetails* details) {
// Reset the Alternate Nav URL Fetcher if we're loading some page it doesn't
// care about. We must do this before calling Notify() below as that may
// result in the creation of a new fetcher.
@@ -735,9 +742,11 @@ void NavigationController::NotifyNavigationEntryCommitted() {
active_contents_->NotifyNavigationStateChanged(
TabContents::INVALIDATE_EVERYTHING);
- NotificationService::current()->Notify(NOTIFY_NAV_ENTRY_COMMITTED,
- Source<NavigationController>(this),
- NotificationService::NoDetails());
+ details->entry = GetActiveEntry();
+ NotificationService::current()->Notify(
+ NOTIFY_NAV_ENTRY_COMMITTED,
+ Source<NavigationController>(this),
+ Details<LoadCommittedDetails>(details));
}
void NavigationController::NotifyPrunedEntries() {
diff --git a/chrome/browser/navigation_controller.h b/chrome/browser/navigation_controller.h
index c2c517d..e43bfe1 100644
--- a/chrome/browser/navigation_controller.h
+++ b/chrome/browser/navigation_controller.h
@@ -48,6 +48,46 @@ class NavigationController {
int index;
};
+ struct LoadCommittedDetails {
+ // By default, the entry will be filled according to a new main frame
+ // navigation.
+ LoadCommittedDetails()
+ : entry(NULL),
+ is_auto(false),
+ is_in_page(false),
+ is_main_frame(true) {
+ }
+
+ // The committed entry. This will be the active entry in the controller.
+ NavigationEntry* entry;
+
+ // The previous URL that the user was on. This may be empty if none.
+ GURL previous_url;
+
+ // True when this load was non-user initated. This corresponds to a
+ // a NavigationGestureAuto call from WebKit (see webview_delegate.h).
+ // We also count reloads and meta-refreshes as "auto" to account for the
+ // fact that WebKit doesn't always set the user gesture properly in these
+ // cases (see bug 1051891).
+ bool is_auto;
+
+ // True if the navigation was in-page. This means that the active entry's
+ // URL and the |previous_url| are the same except for reference fragments.
+ bool is_in_page;
+
+ // True when the main frame was navigated. False means the navigation was a
+ // sub-frame.
+ bool is_main_frame;
+
+ // Returns whether the user probably felt like they navigated somewhere new.
+ // We often need this logic for showing or hiding something, and this
+ // returns true only for main frame loads that the user initiated, that go
+ // to a new page.
+ bool is_user_initiated_main_frame_load() const {
+ return !is_auto && !is_in_page && is_main_frame;
+ }
+ };
+
NavigationController(TabContents* initial_contents, Profile* profile);
// Creates a NavigationController from the specified history. Processing
// for this is asynchronous and handled via the RestoreHelper (in
@@ -208,7 +248,15 @@ class NavigationController {
// for a tab. The controller takes ownership of the entry. Any entry located
// forward to the current entry will be deleted. The new entry becomes the
// current entry.
- void DidNavigateToEntry(NavigationEntry* entry);
+ //
+ // The details are populated by the caller except for the new NavigationEntry
+ // pointer and the previous URL. We will fill these in before using it to
+ // broadcast notifications, so it can also be used by the caller.
+ //
+ // TODO(brettw) bug 1343146: The NavigationController should internally make
+ // the entry and the notification details.
+ void DidNavigateToEntry(NavigationEntry* entry,
+ LoadCommittedDetails* details);
// Calling this may cause the active tab contents to switch if the current
// entry corresponds to a different tab contents type.
@@ -284,8 +332,8 @@ class NavigationController {
void NavigateToPendingEntry(bool reload);
// Allows the derived class to issue notifications that a load has been
- // committed.
- void NotifyNavigationEntryCommitted();
+ // committed. This will fill in the active entry to the details structure.
+ void NotifyNavigationEntryCommitted(LoadCommittedDetails* details);
// Invoked when entries have been pruned, or removed. For example, if the
// current entries are [google, digg, yahoo], with the current entry google,
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
index c495952..8d39465 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
@@ -176,7 +176,10 @@ void SafeBrowsingBlockingPage::DisplayBlockingPage() {
nav_entry->set_page_id(tab_->GetMaxPageID() + 1);
nav_entry->set_page_type(NavigationEntry::INTERSTITIAL_PAGE);
nav_entry->set_url(url_);
- tab_->controller()->DidNavigateToEntry(nav_entry);
+
+ // The default details is "new navigation", and that's OK with us.
+ NavigationController::LoadCommittedDetails details;
+ tab_->controller()->DidNavigateToEntry(nav_entry, &details);
created_temporary_entry_ = true;
}
diff --git a/chrome/browser/ssl_blocking_page.cc b/chrome/browser/ssl_blocking_page.cc
index db0f684..a8f5152 100644
--- a/chrome/browser/ssl_blocking_page.cc
+++ b/chrome/browser/ssl_blocking_page.cc
@@ -153,7 +153,10 @@ void SSLBlockingPage::Show() {
nav_entry->ssl().set_cert_status(ssl_info.cert_status);
nav_entry->ssl().set_security_bits(ssl_info.security_bits);
// The controller will own the entry.
- tab_->controller()->DidNavigateToEntry(nav_entry);
+
+ // The default details is "new navigation", and that's OK with us.
+ NavigationController::LoadCommittedDetails details;
+ tab_->controller()->DidNavigateToEntry(nav_entry, &details);
tab->ShowInterstitialPage(html_text, NULL);
}
diff --git a/chrome/browser/tab_contents.cc b/chrome/browser/tab_contents.cc
index 27d7a0a..503c99e 100644
--- a/chrome/browser/tab_contents.cc
+++ b/chrome/browser/tab_contents.cc
@@ -256,11 +256,13 @@ void TabContents::SetIsLoading(bool is_loading,
NotificationService::NoDetails());
}
-void TabContents::DidNavigateToEntry(NavigationEntry* entry) {
+void TabContents::DidNavigateToEntry(
+ NavigationEntry* entry,
+ NavigationController::LoadCommittedDetails* details) {
// The entry may be deleted by DidNavigateToEntry...
int new_page_id = entry->page_id();
- controller_->DidNavigateToEntry(entry);
+ controller_->DidNavigateToEntry(entry, details);
// update after informing the navigation controller so it can check the
// previous value of the max page id.
@@ -275,7 +277,14 @@ bool TabContents::Navigate(const NavigationEntry& entry, bool reload) {
new_entry->set_page_id(0);
new_entry->set_title(GetDefaultTitle());
}
- DidNavigateToEntry(new_entry);
+
+ // When we're commanded to navigate like this, it's always a new main frame
+ // navigation (which is the default for the details).
+ NavigationController::LoadCommittedDetails details;
+ if (controller()->GetLastCommittedEntry())
+ details.previous_url = controller()->GetLastCommittedEntry()->url();
+
+ DidNavigateToEntry(new_entry, &details);
return true;
}
diff --git a/chrome/browser/tab_contents.h b/chrome/browser/tab_contents.h
index 9d117a5..7d0f784 100644
--- a/chrome/browser/tab_contents.h
+++ b/chrome/browser/tab_contents.h
@@ -489,8 +489,11 @@ class TabContents : public PageNavigator,
void SetIsLoading(bool is_loading, LoadNotificationDetails* details);
// Called by subclasses when a navigation occurs. Ownership of the entry
- // object is passed to this method.
- void DidNavigateToEntry(NavigationEntry* entry);
+ // object is passed to this method. The details object should be filled in
+ // *except* for the entry (which the NavigationController will set). This
+ // behaves the same as NavigationController::DidNavigate, see that for more.
+ void DidNavigateToEntry(NavigationEntry* entry,
+ NavigationController::LoadCommittedDetails* details);
// Called by a derived class when the TabContents is resized, causing
// suppressed constrained web popups to be repositioned to the new bounds
diff --git a/chrome/browser/views/info_bar_view.cc b/chrome/browser/views/info_bar_view.cc
index c10dfa9..56c2ecc 100644
--- a/chrome/browser/views/info_bar_view.cc
+++ b/chrome/browser/views/info_bar_view.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/views/info_bar_view.h"
#include "base/logging.h"
+#include "chrome/browser/navigation_controller.h"
#include "chrome/browser/navigation_entry.h"
#include "chrome/browser/tab_contents_delegate.h"
#include "chrome/browser/web_contents.h"
@@ -31,9 +32,16 @@ static const int kSeparatorHeight = 1;
InfoBarView::InfoBarView(WebContents* web_contents)
: web_contents_(web_contents) {
Init();
+ NotificationService::current()->AddObserver(
+ this, NOTIFY_NAV_ENTRY_COMMITTED,
+ Source<NavigationController>(web_contents_->controller()));
}
-InfoBarView::~InfoBarView() {}
+InfoBarView::~InfoBarView() {
+ NotificationService::current()->RemoveObserver(
+ this, NOTIFY_NAV_ENTRY_COMMITTED,
+ Source<NavigationController>(web_contents_->controller()));
+}
void InfoBarView::AppendInfoBarItem(ChromeViews::View* view, bool auto_expire) {
// AddChildView adds an entry to expire_map_ for view.
@@ -107,43 +115,6 @@ void InfoBarView::ChildAnimationEnded() {
web_contents_->ToolbarSizeChanged(false);
}
-void InfoBarView::DidNavigate(NavigationEntry* entry) {
- // Determine the views to remove first.
- std::vector<ChromeViews::View*> to_remove;
- NavigationEntry* pending_entry =
- web_contents_->controller()->GetPendingEntry();
- const int active_id = pending_entry ? pending_entry->unique_id() :
- entry->unique_id();
- for (std::map<View*,int>::iterator i = expire_map_.begin();
- i != expire_map_.end(); ++i) {
- if ((pending_entry &&
- pending_entry->transition_type() == PageTransition::RELOAD) ||
- i->second != active_id)
- to_remove.push_back(i->first);
- }
-
- if (to_remove.empty())
- return;
-
- // Remove the views.
- for (std::vector<ChromeViews::View*>::iterator i = to_remove.begin();
- i != to_remove.end(); ++i) {
- // RemoveChildView takes care of removing from expire_map for us.
- RemoveChildView(*i);
-
- // We own the child and we're removing it, need to delete it.
- delete *i;
- }
-
- if (GetChildViewCount() == 0) {
- // All our views have been removed, no need to stay visible.
- web_contents_->SetInfoBarVisible(false);
- } else if (web_contents_) {
- // This triggers a layout.
- web_contents_->ToolbarSizeChanged(false);
- }
-}
-
void InfoBarView::ViewHierarchyChanged(bool is_add, View *parent,
View *child) {
if (parent == this && child->GetParent() == this) {
@@ -220,3 +191,52 @@ void InfoBarView::PaintSeparator(ChromeCanvas* canvas,
GetWidth(),
kSeparatorHeight);
}
+
+void InfoBarView::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& in_details) {
+ // We should get only commit notifications from our controller.
+ DCHECK(type == NOTIFY_NAV_ENTRY_COMMITTED);
+ DCHECK(web_contents_->controller() ==
+ Source<NavigationController>(source).ptr());
+
+ NavigationController::LoadCommittedDetails& details =
+ *(Details<NavigationController::LoadCommittedDetails>(in_details).ptr());
+
+ // Only hide infobars when the user has done something that makes the main
+ // frame load. We don't want various automatic or subframe navigations making
+ // it disappear.
+ if (!details.is_user_initiated_main_frame_load())
+ return;
+
+ // Determine the views to remove first.
+ std::vector<ChromeViews::View*> to_remove;
+ for (std::map<View*,int>::iterator i = expire_map_.begin();
+ i != expire_map_.end(); ++i) {
+ if (PageTransition::StripQualifier(details.entry->transition_type()) ==
+ PageTransition::RELOAD ||
+ i->second != details.entry->unique_id())
+ to_remove.push_back(i->first);
+ }
+
+ if (to_remove.empty())
+ return;
+
+ // Remove the views.
+ for (std::vector<ChromeViews::View*>::iterator i = to_remove.begin();
+ i != to_remove.end(); ++i) {
+ // RemoveChildView takes care of removing from expire_map for us.
+ RemoveChildView(*i);
+
+ // We own the child and we're removing it, need to delete it.
+ delete *i;
+ }
+
+ if (GetChildViewCount() == 0) {
+ // All our views have been removed, no need to stay visible.
+ web_contents_->SetInfoBarVisible(false);
+ } else if (web_contents_) {
+ // This triggers a layout.
+ web_contents_->ToolbarSizeChanged(false);
+ }
+}
diff --git a/chrome/browser/views/info_bar_view.h b/chrome/browser/views/info_bar_view.h
index 8234c0a..0ff9b94 100644
--- a/chrome/browser/views/info_bar_view.h
+++ b/chrome/browser/views/info_bar_view.h
@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_BROWSER_VIEWS_INFO_BAR_VIEW_H__
-#define CHROME_BROWSER_VIEWS_INFO_BAR_VIEW_H__
+#ifndef CHROME_BROWSER_VIEWS_INFO_BAR_VIEW_H_
+#define CHROME_BROWSER_VIEWS_INFO_BAR_VIEW_H_
#include <map>
+#include "chrome/common/notification_service.h"
#include "chrome/views/view.h"
class NavigationEntry;
@@ -16,7 +17,8 @@ class WebContents;
//
// It will paint all of its children vertically, with the most recently
// added child displayed at the top of the info bar.
-class InfoBarView : public ChromeViews::View {
+class InfoBarView : public ChromeViews::View,
+ public NotificationObserver {
public:
explicit InfoBarView(WebContents* web_contents);
@@ -42,12 +44,6 @@ class InfoBarView : public ChromeViews::View {
virtual void DidChangeBounds(const CRect& previous, const CRect& current);
- // Notification that the user has done a navigation. Removes child views that
- // are set to be removed after a certain number of navigations and
- // potentially hides the info bar. |entry| is the new entry that we are
- // navigating to.
- void DidNavigate(NavigationEntry* entry);
-
WebContents* web_contents() { return web_contents_; }
protected:
@@ -74,14 +70,19 @@ class InfoBarView : public ChromeViews::View {
ChromeViews::View* v1,
ChromeViews::View* v2);
+ // NotificationObserver implementation.
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
WebContents* web_contents_;
// Map from view to number of navigations before it is removed. If a child
// doesn't have an entry in here, it is NOT removed on navigations.
std::map<View*,int> expire_map_;
- DISALLOW_EVIL_CONSTRUCTORS(InfoBarView);
+ DISALLOW_COPY_AND_ASSIGN(InfoBarView);
};
-#endif // CHROME_BROWSER_VIEWS_INFO_BAR_VIEW_H__
+#endif // CHROME_BROWSER_VIEWS_INFO_BAR_VIEW_H_
diff --git a/chrome/browser/web_contents.cc b/chrome/browser/web_contents.cc
index 45eec91..2367a9b 100644
--- a/chrome/browser/web_contents.cc
+++ b/chrome/browser/web_contents.cc
@@ -567,7 +567,7 @@ void WebContents::SavePage(const std::wstring& main_file,
// the ResourceDispatcherHost, who unpauses the response. Data is then sent
// to the pending RVH.
// - The pending renderer sends a FrameNavigate message that invokes the
-// WebContents::DidNavigate method. This replaces the current RVH with the
+// DidNavigate method. This replaces the current RVH with the
// pending RVH and goes back to the NORMAL RendererState.
bool WebContents::Navigate(const NavigationEntry& entry, bool reload) {
@@ -1194,46 +1194,59 @@ void WebContents::DidNavigate(RenderViewHost* rvh,
return;
}
+ // Generate the details for the notification.
+ // TODO(brettw) bug 1343146: Move into the NavigationController.
+ NavigationController::LoadCommittedDetails details;
+ // WebKit doesn't set the "auto" transition on meta refreshes properly (bug
+ // 1051891) so we manually set it for redirects which we normally treat as
+ // "non-user-gestures" where we want to update stuff after navigations.
+ //
+ // Note that the redirect check also checks for a pending entry to
+ // differentiate real redirects from browser initiated navigations to a
+ // redirected entry. This happens when you hit back to go to a page that was
+ // the destination of a redirect, we don't want to treat it as a redirect
+ // even though that's what its transition will be. See bug 1117048.
+ //
+ // TODO(brettw) write a test for this complicated logic.
+ details.is_auto = (PageTransition::IsRedirect(params.transition) &&
+ !controller()->GetPendingEntry()) ||
+ params.gesture == NavigationGestureAuto;
+ details.is_in_page = IsInPageNavigation(params.url);
+ details.is_main_frame = PageTransition::IsMainFrame(params.transition);
+
// DO NOT ADD MORE STUFF TO THIS FUNCTION! Don't make me come over there!
// =======================================================================
- // Add your code to DidNavigateAnyFramePreCommit if you have a helper object
+ // Add your code to DidNavigateAnyFramePostCommit if you have a helper object
// that needs to know about all navigations. If it needs to do it only for
// main frame or sub-frame navigations, add your code to
- // DidNavigateMainFrame or DidNavigateSubFrame. If you need to run it after
- // the navigation has been committed, put it in a *PostCommit version.
+ // DidNavigate*PostCommit.
// Create the new navigation entry for this navigation and do work specific to
// this frame type. The main frame / sub frame functions will do additional
// updates to the NavigationEntry appropriate for the navigation type (in
// addition to a lot of other stuff).
scoped_ptr<NavigationEntry> entry(CreateNavigationEntryForCommit(params));
- if (PageTransition::IsMainFrame(params.transition))
- DidNavigateMainFramePreCommit(params, entry.get());
- else
- DidNavigateSubFramePreCommit(params, entry.get());
-
- // Now we do non-frame-specific work in *AnyFramePreCommit (this depends on
- // the entry being completed appropriately in the frame-specific versions
- // above before the call).
- DidNavigateAnyFramePreCommit(params, entry.get());
// Commit the entry to the navigation controller.
- DidNavigateToEntry(entry.release());
+ DidNavigateToEntry(entry.release(), &details);
// WARNING: NavigationController will have taken ownership of entry at this
// point, and may have deleted it. As such, do NOT use entry after this.
// Run post-commit tasks.
- if (PageTransition::IsMainFrame(params.transition))
- DidNavigateMainFramePostCommit(params);
- DidNavigateAnyFramePostCommit(rvh, params);
+ if (details.is_main_frame)
+ DidNavigateMainFramePostCommit(details, params);
+ DidNavigateAnyFramePostCommit(rvh, details, params);
}
+// TODO(brettw) bug 1343146: This logic should be moved to NavigationController.
NavigationEntry* WebContents::CreateNavigationEntryForCommit(
const ViewHostMsg_FrameNavigate_Params& params) {
// This new navigation entry will represent the navigation. Note that we
// don't set the URL. This will happen in the DidNavigateMainFrame/SubFrame
// because the entry's URL should represent the toplevel frame only.
NavigationEntry* entry = new NavigationEntry(type());
+ if (PageTransition::IsMainFrame(params.transition))
+ entry->set_url(params.url);
entry->set_page_id(params.page_id);
entry->set_transition_type(params.transition);
entry->set_site_instance(site_instance());
@@ -1273,97 +1286,103 @@ NavigationEntry* WebContents::CreateNavigationEntryForCommit(
}
}
+ if (PageTransition::IsMainFrame(params.transition)) {
+ NavigationEntry* pending = controller()->GetPendingEntry();
+ if (pending) {
+ // Copy fields from the pending NavigationEntry into the actual
+ // NavigationEntry that we're committing to.
+ entry->set_user_typed_url(pending->user_typed_url());
+ if (pending->has_display_url())
+ entry->set_display_url(pending->display_url());
+ if (pending->url().SchemeIsFile())
+ entry->set_title(pending->title());
+ entry->set_content_state(pending->content_state());
+ }
+ entry->set_has_post_data(params.is_post);
+ } else {
+ NavigationEntry* last_committed = controller()->GetLastCommittedEntry();
+ if (last_committed) {
+ // In the case of a sub-frame navigation within a window that was created
+ // without an URL (window.open), we may not have a committed entry yet!
+
+ // Reset entry state to match that of the pending entry.
+ entry->set_unique_id(last_committed->unique_id());
+ entry->set_url(last_committed->url());
+ entry->set_transition_type(last_committed->transition_type());
+ entry->set_user_typed_url(last_committed->user_typed_url());
+ entry->set_content_state(last_committed->content_state());
+
+ // TODO(jcampan): when navigating to an insecure/unsafe inner frame, the
+ // main entry is the one that gets notified of the mixed/unsafe contents
+ // (see SSLPolicy::OnRequestStarted()). Here we are just transferring
+ // that state. We should find a better way to do this. Note that it is OK
+ // that the mixed/unsafe contents is set on the wrong navigation entry, as
+ // that state is reset when navigating back to it.
+ DCHECK(last_committed->ssl().content_status() == 0) << "We should never "
+ "be setting the status bits from 1 to 0 on navigate.";
+ entry->ssl() = last_committed->ssl();
+ }
+ }
+
return entry;
}
-void WebContents::DidNavigateMainFramePreCommit(
- const ViewHostMsg_FrameNavigate_Params& params,
- NavigationEntry* entry) {
- // Update contents MIME type of the main webframe.
- contents_mime_type_ = params.contents_mime_type;
-
- entry->set_url(params.url);
-
- NavigationEntry* pending = controller()->GetPendingEntry();
- if (pending) {
- // Copy fields from the pending NavigationEntry into the actual
- // NavigationEntry that we're committing to.
- entry->set_user_typed_url(pending->user_typed_url());
- if (pending->has_display_url())
- entry->set_display_url(pending->display_url());
- if (pending->url().SchemeIsFile())
- entry->set_title(pending->title());
- entry->set_content_state(pending->content_state());
+void WebContents::DidNavigateMainFramePostCommit(
+ const NavigationController::LoadCommittedDetails& details,
+ const ViewHostMsg_FrameNavigate_Params& params) {
+ // Hide the download shelf if all the following conditions are true:
+ // - there are no active downloads.
+ // - this is a navigation to a different TLD.
+ // - at least 5 seconds have elapsed since the download shelf was shown.
+ // TODO(jcampan): bug 1156075 when user gestures are reliable, they should
+ // be used to ensure we are hiding only on user initiated
+ // navigations.
+ DownloadManager* download_manager = profile()->GetDownloadManager();
+ // download_manager can be NULL in unit test context.
+ if (download_manager && download_manager->in_progress_count() == 0 &&
+ !details.previous_url.is_empty() &&
+ !net::RegistryControlledDomainService::SameDomainOrHost(
+ details.previous_url, details.entry->url())) {
+ TimeDelta time_delta(
+ TimeTicks::Now() - last_download_shelf_show_);
+ if (time_delta >
+ TimeDelta::FromMilliseconds(kDownloadShelfHideDelay)) {
+ SetDownloadShelfVisible(false);
+ }
}
- // We no longer know the title after this navigation.
- has_page_title_ = false;
-
- // Reset the starred button to false by default, but also request from
- // history whether it's actually starred.
- //
- // Only save the URL in the entry for top-level frames. This will appear in
- // the UI for the page, so we always want to use the toplevel URL.
- //
- // The |user_initiated_big_change| flag indicates whether we can tell the
- // infobar/password manager about this navigation. True for non-redirect,
- // non-in-page user initiated navigations; assume this is true and set false
- // below if not.
- //
- // TODO(pkasting): http://b/1048012 We should notify based on whether the
- // navigation was triggered by a user action rather than most of our current
- // heuristics. Be careful with SSL infobars, though.
- //
- // See bug 1051891 for reasons why we need both a redirect check and gesture
- // check; basically gesture checking is not always accurate.
- //
- // Note that the redirect check also checks for a pending entry to
- // differentiate real redirects from browser initiated navigations to a
- // redirected entry (like when you hit back to go to a page that was the
- // destination of a redirect, we don't want to treat it as a redirect
- // even though that's what its transition will be) http://b/1117048.
- bool user_initiated_big_change = true;
- if ((PageTransition::IsRedirect(entry->transition_type()) &&
- !controller()->GetPendingEntry()) ||
- (params.gesture == NavigationGestureAuto) ||
- IsInPageNavigation(params.url)) {
- user_initiated_big_change = false;
- } else {
+ if (details.is_user_initiated_main_frame_load()) {
// Clear the status bubble. This is a workaround for a bug where WebKit
// doesn't let us know that the cursor left an element during a
// transition (this is also why the mouse cursor remains as a hand after
// clicking on a link); see bugs 1184641 and 980803. We don't want to
// clear the bubble when a user navigates to a named anchor in the same
// page.
- UpdateTargetURL(params.page_id, GURL());
- }
+ UpdateTargetURL(details.entry->page_id(), GURL());
- // Let the infobar know about the navigation to give the infobar a chance
- // to remove any views on navigating. Only do so if this navigation was
- // initiated by the user, and we are not simply following a fragment to
- // relocate within the current page.
- //
- // We must do this after calling DidNavigateToEntry(), since the info bar
- // view checks the controller's active entry to determine whether to auto-
- // expire any children.
- if (user_initiated_big_change && IsInfoBarVisible()) {
- InfoBarView* info_bar = GetInfoBarView();
- DCHECK(info_bar);
- info_bar->DidNavigate(entry);
+ // UpdateHelpersForDidNavigate will handle the case where the password_form
+ // origin is valid.
+ // TODO(brettw) bug 1343111: Password manager stuff in here needs to be
+ // cleaned up and covered by tests.
+ if (!params.password_form.origin.is_valid())
+ GetPasswordManager()->DidNavigate();
}
- // UpdateHelpersForDidNavigate will handle the case where the password_form
- // origin is valid.
- if (user_initiated_big_change && !params.password_form.origin.is_valid())
- GetPasswordManager()->DidNavigate();
-
+ // The keyword generator uses the navigation entries, so must be called after
+ // the commit.
GenerateKeywordIfNecessary(params);
- // Close constrained popups if necessary.
- MaybeCloseChildWindows(params);
+ // We no longer know the title after this navigation.
+ has_page_title_ = false;
+
+ // Update contents MIME type of the main webframe.
+ contents_mime_type_ = params.contents_mime_type;
// Get the favicon, either from history or request it from the net.
- fav_icon_helper_.FetchFavIcon(entry->url());
+ fav_icon_helper_.FetchFavIcon(details.entry->url());
+
+ // Close constrained popups if necessary.
+ MaybeCloseChildWindows(params);
// We hide the FindInPage window when the user navigates away, except on
// reload.
@@ -1371,66 +1390,14 @@ void WebContents::DidNavigateMainFramePreCommit(
PageTransition::RELOAD)
SetFindInPageVisible(false);
- entry->set_has_post_data(params.is_post);
-}
-
-void WebContents::DidNavigateSubFramePreCommit(
- const ViewHostMsg_FrameNavigate_Params& params,
- NavigationEntry* entry) {
- NavigationEntry* last_committed = controller()->GetLastCommittedEntry();
- if (!last_committed) {
- // In the case of a sub-frame navigation within a window that was created
- // without an URL (via window.open), we may not have a committed entry yet!
- return;
- }
-
- // Reset entry state to match that of the pending entry.
- entry->set_unique_id(last_committed->unique_id());
- entry->set_url(last_committed->url());
- entry->set_transition_type(last_committed->transition_type());
- entry->set_user_typed_url(last_committed->user_typed_url());
- entry->set_content_state(last_committed->content_state());
-
- // TODO(jcampan): when navigating to an insecure/unsafe inner frame, the
- // main entry is the one that gets notified of the mixed/unsafe contents
- // (see SSLPolicy::OnRequestStarted()). Here we are just transferring that
- // state. We should find a better way to do this.
- // Note that it is OK that the mixed/unsafe contents is set on the wrong
- // navigation entry, as that state is reset when navigating back to it.
- DCHECK(last_committed->ssl().content_status() == 0) << "We should never be "
- "setting the status bits from 1 to 0 on navigate.";
- entry->ssl() = last_committed->ssl();
+ // Update the starred state.
+ UpdateStarredStateForCurrentURL();
}
-void WebContents::DidNavigateAnyFramePreCommit(
- const ViewHostMsg_FrameNavigate_Params& params,
- NavigationEntry* entry) {
-
- // Hide the download shelf if all the following conditions are true:
- // - there are no active downloads.
- // - this is a navigation to a different TLD.
- // - at least 5 seconds have elapsed since the download shelf was shown.
- // TODO(jcampan): bug 1156075 when user gestures are reliable, they should
- // be used to ensure we are hiding only on user initiated
- // navigations.
- NavigationEntry* current_entry = controller()->GetLastCommittedEntry();
- DownloadManager* download_manager = profile()->GetDownloadManager();
- // download_manager can be NULL in unit test context.
- if (download_manager && download_manager ->in_progress_count() == 0 &&
- current_entry && !net::RegistryControlledDomainService::SameDomainOrHost(
- current_entry->url(), entry->url())) {
- TimeDelta time_delta(
- TimeTicks::Now() - last_download_shelf_show_);
- if (time_delta >
- TimeDelta::FromMilliseconds(kDownloadShelfHideDelay)) {
- SetDownloadShelfVisible(false);
- }
- }
-
- // Notify the password manager of the navigation or form submit.
- if (params.password_form.origin.is_valid())
- GetPasswordManager()->ProvisionallySavePassword(params.password_form);
-
+void WebContents::DidNavigateAnyFramePostCommit(
+ RenderViewHost* render_view_host,
+ const NavigationController::LoadCommittedDetails& details,
+ const ViewHostMsg_FrameNavigate_Params& params) {
// If we navigate, start showing messages again. This does nothing to prevent
// a malicious script from spamming messages, since the script could just
// reload the page to stop blocking.
@@ -1441,27 +1408,20 @@ void WebContents::DidNavigateAnyFramePreCommit(
if (params.should_update_history) {
// Most of the time, the displayURL matches the loaded URL, but for about:
// URLs, we use a data: URL as the real value. We actually want to save
- // the about: URL to the history db and keep the data: URL hidden.
- UpdateHistoryForNavigation(entry->display_url(), params);
+ // the about: URL to the history db and keep the data: URL hidden. This is
+ // what the TabContents' URL getter does.
+ UpdateHistoryForNavigation(GetURL(), params);
}
-}
-void WebContents::DidNavigateMainFramePostCommit(
- const ViewHostMsg_FrameNavigate_Params& params) {
- // The keyword generator uses the navigation entries, so must be called after
- // the commit.
- GenerateKeywordIfNecessary(params);
-
- // Update the starred state.
- UpdateStarredStateForCurrentURL();
-}
-
-void WebContents::DidNavigateAnyFramePostCommit(
- RenderViewHost* render_view_host,
- const ViewHostMsg_FrameNavigate_Params& params) {
// Have the controller save the current session.
controller()->NotifyEntryChangedByPageID(type(), site_instance(),
- params.page_id);
+ details.entry->page_id());
+
+ // Notify the password manager of the navigation or form submit.
+ // TODO(brettw) bug 1343111: Password manager stuff in here needs to be
+ // cleaned up and covered by tests.
+ if (params.password_form.origin.is_valid())
+ GetPasswordManager()->ProvisionallySavePassword(params.password_form);
BroadcastProvisionalLoadCommit(render_view_host, params);
}
diff --git a/chrome/browser/web_contents.h b/chrome/browser/web_contents.h
index 87acbd5..43ba2e8 100644
--- a/chrome/browser/web_contents.h
+++ b/chrome/browser/web_contents.h
@@ -555,34 +555,16 @@ class WebContents : public TabContents,
NavigationEntry* CreateNavigationEntryForCommit(
const ViewHostMsg_FrameNavigate_Params& params);
- // Handles post-navigation tasks specific to some set of frames. DidNavigate()
- // calls these with newly created navigation entry for this navigation BEFORE
- // that entry has been committed to the navigation controller. The functions
- // can update the entry as needed.
- //
- // First the frame-specific version (main or sub) will be called to update the
- // entry as needed after it was created by CreateNavigationEntryForCommit.
- //
- // Then DidNavigateAnyFramePreCommit will be called with the now-complete
- // entry for further processing that is not specific to the type of frame.
- void DidNavigateMainFramePreCommit(
- const ViewHostMsg_FrameNavigate_Params& params,
- NavigationEntry* entry);
- void DidNavigateSubFramePreCommit(
- const ViewHostMsg_FrameNavigate_Params& params,
- NavigationEntry* entry);
- void DidNavigateAnyFramePreCommit(
- const ViewHostMsg_FrameNavigate_Params& params,
- NavigationEntry* entry);
-
// Handles post-navigation tasks in DidNavigate AFTER the entry has been
- // committed to the navigation controller. See WillNavigate* above. Note that
- // the navigation entry is not provided since it may be invalid/changed after
- // being committed.
+ // committed to the navigation controller. Note that the navigation entry is
+ // not provided since it may be invalid/changed after being committed. The
+ // current navigation entry is in the NavigationController at this point.
void DidNavigateMainFramePostCommit(
+ const NavigationController::LoadCommittedDetails& details,
const ViewHostMsg_FrameNavigate_Params& params);
void DidNavigateAnyFramePostCommit(
RenderViewHost* render_view_host,
+ const NavigationController::LoadCommittedDetails& details,
const ViewHostMsg_FrameNavigate_Params& params);
// Called when navigating the main frame to close all child windows if the
diff --git a/chrome/common/notification_types.h b/chrome/common/notification_types.h
index 7bd9bb1..cff0655 100644
--- a/chrome/common/notification_types.h
+++ b/chrome/common/notification_types.h
@@ -43,6 +43,9 @@ enum NotificationType {
// A new non-pending navigation entry has been created. This will correspond
// to one NavigationController entry being created (in the case of new
// navigations) or renavigated to (for back/forward navigations).
+ //
+ // The source will be the navigation controller doing the commit. The details
+ // will be NavigationController::LoadCommittedDetails.
NOTIFY_NAV_ENTRY_COMMITTED,
// Indicates that the NavigationController given in the Source has decreased