blob: 7d890d5d555e7778a0ee7a0adf71c99c621d1c5d [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <map>
#include <string>
#include <vector>
#include "base/memory/ref_counted.h"
#include "base/strings/string16.h"
#include "content/common/content_export.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/session_storage_namespace.h"
#include "content/public/browser/site_instance.h"
#include "content/public/common/referrer.h"
#include "ui/base/page_transition_types.h"
#include "url/gurl.h"
namespace base {
class RefCountedMemory;
} // namespace base
namespace content {
class BrowserContext;
class NavigationEntry;
class WebContents;
// A NavigationController maintains the back-forward list for a WebContents and
// manages all navigation within that list.
// Each NavigationController belongs to one WebContents; each WebContents has
// exactly one NavigationController.
class NavigationController {
enum ReloadType {
NO_RELOAD, // Normal load.
RELOAD, // Normal (cache-validating) reload.
RELOAD_IGNORING_CACHE, // Reload bypassing the cache (shift-reload).
RELOAD_ORIGINAL_REQUEST_URL // Reload using the original request URL.
// Load type used in LoadURLParams.
// A Java counterpart will be generated for this enum.
// org.chromium.content_public.browser.navigation_controller)
enum LoadURLType {
// For loads that do not fall into any types below.
// An http post load request initiated from browser side.
// The post data is passed in |browser_initiated_post_data|.
// Loads a 'data:' scheme URL with specified base URL and a history entry
// URL. This is only safe to be used for browser-initiated data: URL
// navigations, since it shows arbitrary content as if it comes from
// |virtual_url_for_data_url|.
// Adding new LoadURLType? Also update static constants.
// User agent override type used in LoadURLParams.
// A Java counterpart will be generated for this enum.
// org.chromium.content_public.browser.navigation_controller)
enum UserAgentOverrideOption {
// Use the override value from the previous NavigationEntry in the
// NavigationController.
// Use the default user agent.
// Use the user agent override, if it's available.
// Adding new UserAgentOverrideOption? Also update
// static constants.
enum RestoreType {
// Indicates the restore is from the current session. For example, restoring
// a closed tab.
// Restore from the previous session.
// Creates a navigation entry and translates the virtual url to a real one.
// This is a general call; prefer LoadURL[FromRenderer]/TransferURL below.
// Extra headers are separated by \n.
CONTENT_EXPORT static NavigationEntry* CreateNavigationEntry(
const GURL& url,
const Referrer& referrer,
ui::PageTransition transition,
bool is_renderer_initiated,
const std::string& extra_headers,
BrowserContext* browser_context);
// Extra optional parameters for LoadURLWithParams.
struct CONTENT_EXPORT LoadURLParams {
// The url to load. This field is required.
GURL url;
// SiteInstance of the frame that initiated the navigation or null if we
// don't know it.
scoped_refptr<SiteInstance> source_site_instance;
// See LoadURLType comments above.
LoadURLType load_type;
// PageTransition for this load. See PageTransition for details.
// Note the default value in constructor below.
ui::PageTransition transition_type;
// The FrameTreeNode ID for the frame to navigate, or -1 for the main frame.
int frame_tree_node_id;
// Referrer for this load. Empty if none.
Referrer referrer;
// Any redirect URLs that occurred for this navigation before |url|.
// Defaults to an empty vector.
std::vector<GURL> redirect_chain;
// Extra headers for this load, separated by \n.
std::string extra_headers;
// True for renderer-initiated navigations. This is
// important for tracking whether to display pending URLs.
bool is_renderer_initiated;
// User agent override for this load. See comments in
// UserAgentOverrideOption definition.
UserAgentOverrideOption override_user_agent;
// Marks the new navigation as being transferred from one RVH to another.
// In this case the browser can recycle the old request once the new
// renderer wants to navigate. Identifies the request ID of the old request.
GlobalRequestID transferred_global_request_id;
// Used in LOAD_TYPE_DATA loads only. Used for specifying a base URL
// for pages loaded via data URLs.
GURL base_url_for_data_url;
// Used in LOAD_TYPE_DATA loads only. URL displayed to the user for
// data loads.
GURL virtual_url_for_data_url;
// Used in LOAD_TYPE_BROWSER_INITIATED_HTTP_POST loads only. Carries the
// post data of the load. Ownership is transferred to NavigationController
// after LoadURLWithParams call.
scoped_refptr<base::RefCountedMemory> browser_initiated_post_data;
// True if this URL should be able to access local resources.
bool can_load_local_resources;
// Indicates whether this navigation should replace the current
// navigation entry.
bool should_replace_current_entry;
// Used to specify which frame to navigate. If empty, the main frame is
// navigated. This is currently only used in tests.
std::string frame_name;
// Indicates that during this navigation, the session history should be
// cleared such that the resulting page is the first and only entry of the
// session history.
// The clearing is done asynchronously, and completes when this navigation
// commits.
bool should_clear_history_list;
#if defined(OS_ANDROID)
// On Android, for a load triggered by an intent, the time Chrome received
// the original intent that prompted the load (in milliseconds active time
// since boot).
int64 intent_received_timestamp;
explicit LoadURLParams(const GURL& url);
// Allows copying of LoadURLParams struct.
LoadURLParams(const LoadURLParams& other);
LoadURLParams& operator=(const LoadURLParams& other);
// Disables checking for a repost and prompting the user. This is used during
// testing.
CONTENT_EXPORT static void DisablePromptOnRepost();
virtual ~NavigationController() {}
// Returns the web contents associated with this controller. It can never be
// nullptr.
virtual WebContents* GetWebContents() const = 0;
// Get/set the browser context for this controller. It can never be nullptr.
virtual BrowserContext* GetBrowserContext() const = 0;
virtual void SetBrowserContext(BrowserContext* browser_context) = 0;
// Initializes this NavigationController with the given saved navigations,
// using |selected_navigation| as the currently loaded entry. Before this call
// the controller should be unused (there should be no current entry). |type|
// indicates where the restor comes from. This takes ownership of the
// NavigationEntrys in |entries| and clears it out. This is used for session
// restore.
virtual void Restore(int selected_navigation,
RestoreType type,
std::vector<NavigationEntry*>* entries) = 0;
// Entries -------------------------------------------------------------------
// There are two basic states for entries: pending and committed. When an
// entry is navigated to, a request is sent to the server. While that request
// has not been responded to, the NavigationEntry is pending. Once data is
// received for that entry, that NavigationEntry is committed.
// A transient entry is an entry that, when the user navigates away, is
// removed and discarded rather than being added to the back-forward list.
// Transient entries are useful for interstitial pages and the like.
// Active entry --------------------------------------------------------------
// THIS IS DEPRECATED. DO NOT USE. Use GetVisibleEntry instead.
// See
// Returns the active entry, which is the transient entry if any, the pending
// entry if a navigation is in progress or the last committed entry otherwise.
// NOTE: This can be nullptr!!
virtual NavigationEntry* GetActiveEntry() const = 0;
// Returns the entry that should be displayed to the user in the address bar.
// This is the transient entry if any, the pending entry if a navigation is
// in progress *and* is safe to display to the user (see below), or the last
// committed entry otherwise.
// NOTE: This can be nullptr if no entry has committed!
// A pending entry is safe to display if it started in the browser process or
// if it's a renderer-initiated navigation in a new tab which hasn't been
// accessed by another tab. (If it has been accessed, it risks a URL spoof.)
virtual NavigationEntry* GetVisibleEntry() const = 0;
// Returns the index from which we would go back/forward or reload. This is
// the last_committed_entry_index_ if pending_entry_index_ is -1. Otherwise,
// it is the pending_entry_index_.
virtual int GetCurrentEntryIndex() const = 0;
// Returns the last committed entry, which may be null if there are no
// committed entries.
virtual NavigationEntry* GetLastCommittedEntry() const = 0;
// Returns the index of the last committed entry.
virtual int GetLastCommittedEntryIndex() const = 0;
// Returns true if the source for the current entry can be viewed.
virtual bool CanViewSource() const = 0;
// Navigation list -----------------------------------------------------------
// Returns the number of entries in the NavigationController, excluding
// the pending entry if there is one, but including the transient entry if
// any.
virtual int GetEntryCount() const = 0;
virtual NavigationEntry* GetEntryAtIndex(int index) const = 0;
// Returns the entry at the specified offset from current. Returns nullptr
// if out of bounds.
virtual NavigationEntry* GetEntryAtOffset(int offset) const = 0;
// Pending entry -------------------------------------------------------------
// Discards the pending and transient entries if any.
virtual void DiscardNonCommittedEntries() = 0;
// Returns the pending entry corresponding to the navigation that is
// currently in progress, or null if there is none.
virtual NavigationEntry* GetPendingEntry() const = 0;
// Returns the index of the pending entry or -1 if the pending entry
// corresponds to a new navigation (created via LoadURL).
virtual int GetPendingEntryIndex() const = 0;
// Transient entry -----------------------------------------------------------
// Returns the transient entry if any. This is an entry which is removed and
// discarded if any navigation occurs. Note that the returned entry is owned
// by the navigation controller and may be deleted at any time.
virtual NavigationEntry* GetTransientEntry() const = 0;
// Adds an entry that is returned by GetActiveEntry(). The entry is
// transient: any navigation causes it to be removed and discarded. The
// NavigationController becomes the owner of |entry| and deletes it when
// it discards it. This is useful with interstitial pages that need to be
// represented as an entry, but should go away when the user navigates away
// from them.
// Note that adding a transient entry does not change the active contents.
virtual void SetTransientEntry(NavigationEntry* entry) = 0;
// New navigations -----------------------------------------------------------
// Loads the specified URL, specifying extra http headers to add to the
// request. Extra headers are separated by \n.
virtual void LoadURL(const GURL& url,
const Referrer& referrer,
ui::PageTransition type,
const std::string& extra_headers) = 0;
// More general version of LoadURL. See comments in LoadURLParams for
// using |params|.
virtual void LoadURLWithParams(const LoadURLParams& params) = 0;
// Loads the current page if this NavigationController was restored from
// history and the current page has not loaded yet or if the load was
// explicitly requested using SetNeedsReload().
virtual void LoadIfNecessary() = 0;
// Renavigation --------------------------------------------------------------
// Navigation relative to the "current entry"
virtual bool CanGoBack() const = 0;
virtual bool CanGoForward() const = 0;
virtual bool CanGoToOffset(int offset) const = 0;
virtual void GoBack() = 0;
virtual void GoForward() = 0;
// Navigates to the specified absolute index.
virtual void GoToIndex(int index) = 0;
// Navigates to the specified offset from the "current entry". Does nothing if
// the offset is out of bounds.
virtual void GoToOffset(int offset) = 0;
// Reloads the current entry. If |check_for_repost| is true and the current
// entry has POST data the user is prompted to see if they really want to
// reload the page. In nearly all cases pass in true. If a transient entry
// is showing, initiates a new navigation to its URL.
virtual void Reload(bool check_for_repost) = 0;
// Like Reload(), but don't use caches (aka "shift-reload").
virtual void ReloadIgnoringCache(bool check_for_repost) = 0;
// Reloads the current entry using the original URL used to create it. This
// is used for cases where the user wants to refresh a page using a different
// user agent after following a redirect.
virtual void ReloadOriginalRequestURL(bool check_for_repost) = 0;
// Removing of entries -------------------------------------------------------
// Removes the entry at the specified |index|. If the index is the last
// committed index or the pending entry, this does nothing and returns false.
// Otherwise this call discards any transient or pending entries.
virtual bool RemoveEntryAtIndex(int index) = 0;
// Random --------------------------------------------------------------------
// Session storage depends on dom_storage that depends on blink::WebString,
// which cannot be used on iOS.
#if !defined(OS_IOS)
// Returns all the SessionStorageNamespace objects that this
// NavigationController knows about, the map key is a StoragePartition id.
virtual const SessionStorageNamespaceMap&
GetSessionStorageNamespaceMap() const = 0;
// TODO(ajwong): Remove this once prerendering, instant, and session restore
// are migrated.
virtual SessionStorageNamespace* GetDefaultSessionStorageNamespace() = 0;
// Sets the max restored page ID this NavigationController has seen, if it
// was restored from a previous session.
virtual void SetMaxRestoredPageID(int32 max_id) = 0;
// Returns the largest restored page ID seen in this navigation controller,
// if it was restored from a previous session. (-1 otherwise)
virtual int32 GetMaxRestoredPageID() const = 0;
// Returns true if a reload happens when activated (SetActive(true) is
// invoked). This is true for session/tab restore, cloned tabs and tabs that
// requested a reload (using SetNeedsReload()) after their renderer was
// killed.
virtual bool NeedsReload() const = 0;
// Request a reload to happen when activated. This can be used when a renderer
// backing a background tab is killed by the system on Android or ChromeOS.
virtual void SetNeedsReload() = 0;
// Cancels a repost that brought up a warning.
virtual void CancelPendingReload() = 0;
// Continues a repost that brought up a warning.
virtual void ContinuePendingReload() = 0;
// Returns true if we are navigating to the URL the tab is opened with.
// Returns false after the initial navigation has committed.
virtual bool IsInitialNavigation() const = 0;
// Broadcasts the NOTIFICATION_NAV_ENTRY_CHANGED notification for the given
// entry. This will keep things in sync like the saved session.
virtual void NotifyEntryChanged(const NavigationEntry* entry) = 0;
// Copies the navigation state from the given controller to this one. This
// one should be empty (just created).
virtual void CopyStateFrom(const NavigationController& source) = 0;
// A variant of CopyStateFrom. Removes all entries from this except the last
// committed entry, and inserts all entries from |source| before and including
// its last committed entry. For example:
// source: A B *C* D
// this: E F *G*
// result: A B C *G*
// If there is a pending entry after *G* in |this|, it is also preserved.
// If |replace_entry| is true, the current entry in |source| is replaced. So
// the result above would be A B *G*.
// This ignores any pending or transient entries in |source|. Callers must
// ensure that |CanPruneAllButLastCommitted| returns true before calling this,
// or it will crash.
virtual void CopyStateFromAndPrune(NavigationController* source,
bool replace_entry) = 0;
// Returns whether it is safe to call PruneAllButLastCommitted or
// CopyStateFromAndPrune. There must be a last committed entry, no transient
// entry, and if there is a pending entry, it must be new and not an existing
// entry.
// If there were no last committed entry, the pending entry might not commit,
// leaving us with a blank page. This is unsafe when used with
// |CopyStateFromAndPrune|, which would show an existing entry above the blank
// page.
// If there were a transient entry, we would not want to prune the other
// entries, which the transient entry could be referring to.
// If there were an existing pending entry, we could not prune the last
// committed entry, in case it did not commit. That would leave us with no
// sensible place to put the pending entry when it did commit, after all other
// entries are pruned. For example, it could be going back several entries.
// (New pending entries are safe, because they can always commit to the end.)
virtual bool CanPruneAllButLastCommitted() = 0;
// Removes all the entries except the last committed entry. If there is a new
// pending navigation it is preserved. Callers must ensure
// |CanPruneAllButLastCommitted| returns true before calling this, or it will
// crash.
virtual void PruneAllButLastCommitted() = 0;
// Clears all screenshots associated with navigation entries in this
// controller. Useful to reduce memory consumption in low-memory situations.
virtual void ClearAllScreenshots() = 0;
// This interface should only be implemented inside content.
friend class NavigationControllerImpl;
NavigationController() {}
} // namespace content