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

Unified Diff: chrome/browser/navigation_controller.h

Issue 479: DidNavigate refactor of doom (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years, 3 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: chrome/browser/navigation_controller.h
===================================================================
--- chrome/browser/navigation_controller.h (revision 1840)
+++ chrome/browser/navigation_controller.h (working copy)
@@ -5,7 +5,7 @@
#ifndef CHROME_BROWSER_NAVIGATION_CONTROLLER_H_
#define CHROME_BROWSER_NAVIGATION_CONTROLLER_H_
-#include <hash_map>
+#include <map>
#include "base/linked_ptr.h"
#include "base/ref_counted.h"
@@ -21,24 +21,17 @@
class WebContents;
class TabContentsCollector;
struct TabNavigation;
+struct ViewHostMsg_FrameNavigate_Params;
-namespace printing {
-class PrintViewManager;
-}
-
-////////////////////////////////////////////////////////////////////////////////
+// A NavigationController maintains the back-forward list for a single tab and
+// manages all navigation within that list.
//
-// NavigationController class
-//
-// A NavigationController maintains navigation data. We have one
-// NavigationController instance per tab.
-//
// The NavigationController also owns all TabContents for the tab. This is to
// make sure that we have at most one TabContents instance per type.
-//
-////////////////////////////////////////////////////////////////////////////////
class NavigationController {
public:
+ // Notification details ------------------------------------------------------
+
// Provides the details for a NOTIFY_NAV_ENTRY_CHANGED notification.
struct EntryChangedDetails {
// The changed navigation entry after it has been updated.
@@ -48,6 +41,7 @@
int index;
};
+ // Provides the details for a NOTIFY_NAV_ENTRY_COMMITTED notification.
struct LoadCommittedDetails {
// By default, the entry will be filled according to a new main frame
// navigation.
@@ -88,7 +82,10 @@
}
};
+ // ---------------------------------------------------------------------------
+
NavigationController(TabContents* initial_contents, Profile* profile);
+
// Creates a NavigationController from the specified history. Processing
// for this is asynchronous and handled via the RestoreHelper (in
// navigation_controller.cc).
@@ -99,9 +96,25 @@
HWND parent);
~NavigationController();
- // Same as Reload, but doesn't check if current entry has POST data.
- void ReloadDontCheckForRepost();
+ // Begin the destruction sequence for this NavigationController and all its
+ // registered tabs. The sequence is as follows:
+ // 1. All tabs are asked to Destroy themselves.
+ // 2. When each tab is finished Destroying, it will notify the controller.
+ // 3. Once all tabs are Destroyed, the NavigationController deletes itself.
+ // This ensures that all the TabContents outlive the NavigationController.
+ void Destroy();
+ // Clone the receiving navigation controller. Only the active tab contents is
+ // duplicated. It is created as a child of the provided HWND.
+ NavigationController* Clone(HWND hwnd);
+
+ // Returns the profile for this controller. It can never be NULL.
+ Profile* profile() const {
+ return profile_;
+ }
+
+ // Active entry --------------------------------------------------------------
+
// Returns the active entry, which is the pending entry if a navigation is in
// progress or the last committed entry otherwise. NOTE: This can be NULL!!
//
@@ -115,19 +128,7 @@
// it is the pending_entry_index_.
int GetCurrentEntryIndex() const;
- // Returns the pending entry corresponding to the navigation that is
- // currently in progress, or null if there is none.
- NavigationEntry* GetPendingEntry() const {
- return pending_entry_;
- }
-
- // Returns the index of the pending entry or -1 if the pending entry
- // corresponds to a new navigation (created via LoadURL).
- int GetPendingEntryIndex() const {
- return pending_entry_index_;
- }
-
- // Returns the last committed entry, which may be null if there are no
+ // Returns the last committed entry, which may be null if there are no
// committed entries.
NavigationEntry* GetLastCommittedEntry() const;
@@ -136,6 +137,8 @@
return last_committed_entry_index_;
}
+ // Navigation list -----------------------------------------------------------
+
// Returns the number of entries in the NavigationControllerBase, excluding
// the pending entry if there is one.
int GetEntryCount() const {
@@ -150,86 +153,156 @@
// if out of bounds.
NavigationEntry* GetEntryAtOffset(int offset) const;
- bool CanStop() const;
+ // Returns the index of the specified entry, or -1 if entry is not contained
+ // in this NavigationControllerBase.
+ int GetIndexOfEntry(const NavigationEntry* entry) const;
- // Return whether this controller can go back.
+ // Return the index of the entry with the corresponding type, instance, and
+ // page_id, or -1 if not found. Use a NULL instance if the type is not
+ // TAB_CONTENTS_WEB.
+ int GetEntryIndexWithPageID(TabContentsType type,
+ SiteInstance* instance,
+ int32 page_id) const;
+
+ // Return the entry with the corresponding type, instance, and page_id, or
+ // NULL if not found. Use a NULL instance if the type is not
+ // TAB_CONTENTS_WEB.
+ NavigationEntry* GetEntryWithPageID(TabContentsType type,
+ SiteInstance* instance,
+ int32 page_id) const;
+
+ // Pending entry -------------------------------------------------------------
+
+ // Commits the current pending entry and issues the NOTIFY_NAV_ENTRY_COMMIT
+ // notification. No changes are made to the entry during this process, it is
+ // just moved from pending to committed. This is an alternative to
+ // RendererDidNavigate for simple TabContents types.
+ //
+ // When the pending entry is a new navigation, it will have a page ID of -1.
+ // The caller should leave this as-is. CommitPendingEntry will generate a
+ // new page ID for you and update the TabContents with that ID.
+ void CommitPendingEntry();
+
+ // Calling this may cause the active tab contents to switch if the current
+ // entry corresponds to a different tab contents type.
+ void DiscardPendingEntry();
+
+ // Returns the pending entry corresponding to the navigation that is
+ // currently in progress, or null if there is none.
+ NavigationEntry* GetPendingEntry() const {
+ return pending_entry_;
+ }
+
+ // Returns the index of the pending entry or -1 if the pending entry
+ // corresponds to a new navigation (created via LoadURL).
+ int GetPendingEntryIndex() const {
+ return pending_entry_index_;
+ }
+
+ // New navigations -----------------------------------------------------------
+
+ // Loads the specified URL.
+ void LoadURL(const GURL& url, PageTransition::Type type);
+
+ // Load the specified URL the next time it becomes active.
+ void LoadURLLazily(const GURL& url, PageTransition::Type type,
+ const std::wstring& title, SkBitmap* icon);
+
+ // Loads the current page if this NavigationController was restored from
+ // history and the current page has not loaded yet.
+ void LoadIfNecessary();
+
+ // Renavigation --------------------------------------------------------------
+
+ // Navigation relative to the "current entry"
bool CanGoBack() const;
-
- // Return whether this controller can go forward.
bool CanGoForward() const;
-
- // Causes the controller to go back.
void GoBack();
-
- // Causes the controller to go forward.
void GoForward();
- // Causes the controller to go to the specified index.
+ // Navigates to the specified absolute index.
void GoToIndex(int index);
- // Causes the controller to go to the specified offset from current. Does
- // nothing if out of bounds.
+ // Navigates to the specified offset from the "current entry". Does nothing if
+ // the offset is out of bounds.
void GoToOffset(int offset);
- // Causes the controller to stop a pending navigation if any.
- void Stop();
-
- // Causes the controller to reload the current entry. Will prompt the user if
- // reloading a URL with POST data and the active WebContents isn't showing the
- // POST interstitial page.
+ // Reloads the current entry. The user will be prompted if the URL has POST
+ // data and the active WebContents isn't showing the POST interstitial page.
void Reload();
- // Return the entry with the corresponding type, instance, and page_id, or
- // NULL if not found. Use a NULL instance if the type is not
- // TAB_CONTENTS_WEB.
- NavigationEntry* GetEntryWithPageID(TabContentsType type,
- SiteInstance* instance,
- int32 page_id) const;
+ // Same as Reload, but doesn't check if current entry has POST data.
+ void ReloadDontCheckForRepost();
- // Causes the controller to load the specified entry. The controller
- // assumes ownership of the entry.
- // NOTE: Do not pass an entry that the controller already owns!
- void LoadEntry(NavigationEntry* entry);
+ // TabContents ---------------------------------------------------------------
- // Ensure the given NavigationEntry has a valid state, so that WebKit does
- // not get confused.
- static void SetContentStateIfEmpty(NavigationEntry* entry);
-
- // Begin the destruction sequence for this NavigationController and all its
- // registered tabs. The sequence is as follows:
- // 1. All tabs are asked to Destroy themselves.
- // 2. When each tab is finished Destroying, it will notify the controller.
- // 3. Once all tabs are Destroyed, the NavigationController deletes itself.
- // This ensures that all the TabContents outlive the NavigationController.
- void Destroy();
-
// Notifies the controller that a TabContents that it owns has been destroyed.
// This is part of the NavigationController's Destroy sequence.
void TabContentsWasDestroyed(TabContentsType type);
+ // Returns the TabContents cached on this controller for the given type or
+ // NULL if there is none.
+ TabContents* GetTabContents(TabContentsType type);
+
// Returns the currently-active TabContents associated with this controller.
// You should use GetActiveEntry instead of this in most cases.
TabContents* active_contents() const {
return active_contents_;
}
- // This can never be null.
- Profile* profile() const {
- return profile_;
- }
+ // For use by TabContents ----------------------------------------------------
- // Returns the TabContents cached on this controller for the given type or
- // NULL if there is none.
- TabContents* GetTabContents(TabContentsType type);
+ // Handles updating the navigation state after the renderer has navigated.
+ // This is used by the WebContents. Simpler tab contents types can use
+ // CommitPendingEntry below.
+ //
+ // If a new entry is created, it will return true and will have filled the
+ // given details structure and broadcast the NOTIFY_NAV_ENTRY_COMMITTED
+ // notification. The caller can then use the details without worrying about
+ // listening for the notification.
+ //
+ // In the case that nothing has changed, the details structure is undefined
+ // and it will return false.
+ bool RendererDidNavigate(const ViewHostMsg_FrameNavigate_Params& params,
+ bool is_interstitial,
+ LoadCommittedDetails* details);
- // Causes the controller to load the specified URL.
- void LoadURL(const GURL& url, PageTransition::Type type);
+ // Inserts a new entry by making a copy of the given navigation entry. This is
+ // used by interstitials to create dummy entries that they will be in charge
+ // of removing later.
+ void AddDummyEntryForInterstitial(const NavigationEntry& clone_me);
- // Causes the controller to load the specified URL the next time it becomes
- // active.
- void LoadURLLazily(const GURL& url, PageTransition::Type type,
- const std::wstring& title, SkBitmap* icon);
+ // Removes the last entry in the list. This is used by the interstitial code
+ // to delete the dummy entry created by AddDummyEntryForInterstitial. If the
+ // last entry is the currently committed one, a ENTRY_COMMITTED notification
+ // will be broadcast.
+ void RemoveLastEntryForInterstitial();
+ // Notifies us that we just became active. This is used by the TabContents
+ // so that we know to load URLs that were pending as "lazy" loads.
+ void SetActive(bool is_active);
+
+ // Broadcasts the NOTIFY_NAV_ENTRY_CHANGED notification for the given entry
+ // (which must be at the given index). This will keep things in sync like
+ // the saved session.
+ void NotifyEntryChanged(const NavigationEntry* entry, int index);
+
+ // Returns true if the given URL would be an in-page navigation (i.e. only
+ // the reference fragment is different) from the "last committed entry". We do
+ // not compare it against the "active entry" since the active entry can be
+ // pending and in page navigations only happen on committed pages. If there
+ // is no last committed entry, then nothing will be in-page.
+ //
+ // Special note: if the URLs are the same, it does NOT count as an in-page
+ // navigation. Neither does an input URL that has no ref, even if the rest is
+ // the same. This may seem weird, but when we're considering whether a
+ // navigation happened without loading anything, the same URL would be a
+ // reload, while only a different ref would be in-page (pages can't clear
+ // refs without reload, only change to "#" which we don't count as empty).
+ bool IsURLInPageNavigation(const GURL& url) const;
+
+ // Random data ---------------------------------------------------------------
+
// Returns true if this NavigationController is is configured to load a URL
// lazily. If true, use GetLazyTitle() and GetLazyFavIcon() to discover the
// titles and favicons. Since no request was made, this is the only info
@@ -238,34 +311,10 @@
const std::wstring& GetLazyTitle() const;
const SkBitmap& GetLazyFavIcon() const;
+ // TODO(brettw) bug 1324500: move this out of here.
void SetAlternateNavURLFetcher(
AlternateNavURLFetcher* alternate_nav_url_fetcher);
- // --------------------------------------------------------------------------
- // For use by TabContents implementors:
-
- // Used to inform the NavigationControllerBase of a navigation being committed
- // 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.
- //
- // 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.
- void DiscardPendingEntry();
-
- // Inserts an entry after the current position, removing all entries after it.
- // The new entry will become the active one.
- void InsertEntry(NavigationEntry* entry);
-
// Returns the identifier used by session restore.
const SessionID& session_id() const { return session_id_; }
@@ -275,59 +324,98 @@
SSLManager* ssl_manager() { return &ssl_manager_; }
- // Broadcasts the NOTIFY_NAV_ENTRY_CHANGED notification for the
- // navigation corresponding to the given page. This will keep things in sync
- // like saved session.
- void NotifyEntryChangedByPageID(TabContentsType type,
- SiteInstance* instance,
- int32 page_id);
-
- void SetActive(bool is_active);
-
- // If this NavigationController was restored from history and the selected
- // page has not loaded, it is loaded.
- void LoadIfNecessary();
-
- // Clone the receiving navigation controller. Only the active tab contents is
- // duplicated. It is created as a child of the provided HWND.
- NavigationController* Clone(HWND hwnd);
-
// Returns true if a reload happens when activated (SetActive(true) is
// invoked). This is true for session/tab restore and cloned tabs.
bool needs_reload() const { return needs_reload_; }
- // Disables checking for a repost and prompting the user. This is used during
- // testing.
- static void DisablePromptOnRepost();
-
// Returns the largest restored page ID seen in this navigation controller,
// if it was restored from a previous session. (-1 otherwise)
int max_restored_page_id() const { return max_restored_page_id_; }
- // Returns the index of the specified entry, or -1 if entry is not contained
- // in this NavigationControllerBase.
- int GetIndexOfEntry(const NavigationEntry* entry) const;
+ // Disables checking for a repost and prompting the user. This is used during
+ // testing.
+ static void DisablePromptOnRepost();
- // Removes the last committed entry.
- void RemoveLastEntry();
-
private:
FRIEND_TEST(NavigationControllerTest, EnforceMaxNavigationCount);
-
class RestoreHelper;
friend class RestoreHelper;
+ friend class TabContents; // For invoking OnReservedPageIDRange.
- // For invoking OnReservedPageIDRange.
- friend class TabContents;
- // For invoking GetMaxPageID.
- friend class WebContents;
- // For invoking GetMaxPageID.
- friend class printing::PrintViewManager;
+ // Indicates different types of navigations that can occur that we will handle
+ // separately. This is computed by ClassifyNavigation.
+ enum NavClass {
+ // A new page was navigated in the main frame.
+ NAV_NEW_PAGE,
- // Returns the largest page ID seen. When PageIDs come in larger than
- // this (via DidNavigateToEntry), we know that we've navigated to a new page.
- int GetMaxPageID() const;
+ // Renavigating to an existing navigation entry. The entry is guaranteed to
+ // exist in the list, or else it would be a new page or IGNORE navigation.
+ NAV_EXISTING_PAGE,
+ // The same page has been reloaded as a result of the user requesting
+ // navigation to that same page (like pressing Enter in the URL bar). This
+ // is not the same as an in-page navigation because we'll actually have a
+ // pending entry for the load, which is then meaningless.
+ NAV_SAME_PAGE,
+
+ // In page navigations are when the reference fragment changes. This will
+ // be in the main frame only (we won't even get notified of in-page
+ // subframe navigations). It may be for any page, not necessarily the last
+ // committed one (for example, whey going back to a page with a ref).
+ NAV_IN_PAGE,
+
+ // A new subframe was manually navigated by the user. We will create a new
+ // NavigationEntry so they can go back to the previous subframe content
+ // using the back button.
+ NAV_NEW_SUBFRAME,
+
+ // A subframe in the page was automatically loaded or navigated to such that
+ // a new navigation entry should not be created. There are two cases:
+ // 1. Stuff like iframes containing ads that the page loads automatically.
+ // The user doesn't want to see these, so we just update the existing
+ // navigation entry.
+ // 2. Going back/forward to previous subframe navigations. We don't create
+ // a new entry here either, just update the last committed entry.
+ // These two cases are actually pretty different, they just happen to
+ // require almost the same code to handle.
+ NAV_AUTO_SUBFRAME,
+
+ // Nothing happened. This happens when we get information about a page we
+ // don't know anything about. It can also happen when an iframe in a popup
+ // navigated to about:blank is navigated. Nothing needs to be done.
+ NAV_IGNORE,
+ };
+
+ // Classifies the given renderer navigation (see the NavigationType enum).
+ NavClass ClassifyNavigation(
+ const ViewHostMsg_FrameNavigate_Params& params) const;
+
+ // Causes the controller to load the specified entry. The function assumes
+ // ownership of the pointer since it is put in the navigation list.
+ // NOTE: Do not pass an entry that the controller already owns!
+ void LoadEntry(NavigationEntry* entry);
+
+ // Handlers for the different types of navigation types. They will actually
+ // handle the navigations corresponding to the different NavClasses above.
+ // They will NOT broadcast the commit notification, that should be handled by
+ // the caller.
+ //
+ // RendererDidNavigateAutoSubframe is special, it may not actually change
+ // anything if some random subframe is loaded. It will return true if anything
+ // changed, or false if not.
+ void RendererDidNavigateToNewPage(
+ const ViewHostMsg_FrameNavigate_Params& params);
+ void RendererDidNavigateToExistingPage(
+ const ViewHostMsg_FrameNavigate_Params& params);
+ void RendererDidNavigateToSamePage(
+ const ViewHostMsg_FrameNavigate_Params& params);
+ void RendererDidNavigateInPage(
+ const ViewHostMsg_FrameNavigate_Params& params);
+ void RendererDidNavigateNewSubframe(
+ const ViewHostMsg_FrameNavigate_Params& params);
+ bool RendererDidNavigateAutoSubframe(
+ const ViewHostMsg_FrameNavigate_Params& params);
+
// Actually issues the navigation held in pending_entry.
void NavigateToPendingEntry(bool reload);
@@ -335,11 +423,6 @@
// 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,
- // and the user types in cnet, then digg and yahoo are pruned.
- void NotifyPrunedEntries();
-
// Invoked when the index of the active entry may have changed.
// The prev_commited_index parameter specifies the previous value
// of the last commited index before this navigation event happened
@@ -355,9 +438,6 @@
// and deleted by this navigation controller
void RegisterTabContents(TabContents* some_contents);
- // Broadcasts a notification that the given entry changed.
- void NotifyEntryChanged(const NavigationEntry* entry, int index);
-
// Removes the entry at the specified index. Note that you should not remove
// the pending entry or the last committed entry.
void RemoveEntryAtIndex(int index);
@@ -386,15 +466,14 @@
// contents.
void FinishRestore(HWND parent_hwnd, int selected_index);
+ // Inserts an entry after the current position, removing all entries after it.
+ // The new entry will become the active one.
+ void InsertEntry(NavigationEntry* entry);
+
// Discards the pending entry without updating active_contents_
void DiscardPendingEntryInternal();
- // Return the index of the entry with the corresponding type, instance, and
- // page_id, or -1 if not found. Use a NULL instance if the type is not
- // TAB_CONTENTS_WEB.
- int GetEntryIndexWithPageID(TabContentsType type,
- SiteInstance* instance,
- int32 page_id) const;
+ // ---------------------------------------------------------------------------
// The user profile associated with this controller
Profile* profile_;
@@ -421,7 +500,7 @@
// Tab contents. One entry per type used. The tab controller owns
// every tab contents used.
- typedef stdext::hash_map<TabContentsType, TabContents*> TabContentsMap;
+ typedef std::map<TabContentsType, TabContents*> TabContentsMap;
TabContentsMap tab_contents_map_;
// A map of TabContentsType -> TabContentsCollector containing all the
@@ -471,4 +550,3 @@
};
#endif // CHROME_BROWSER_NAVIGATION_CONTROLLER_H_
-

Powered by Google App Engine
This is Rietveld 408576698